<commit_before>#ifndef ENTT_REGISTRY_HPP
#define ENTT_REGISTRY_HPP

#include <tuple>
#include <vector>
#include <bitset>
#include <utility>
#include <cstddef>
#include <iterator>
#include <cassert>
#include <type_traits>
#include "sparse_set.hpp"
#include "ident.hpp"

namespace entt {

template<typename, std::size_t...>
class View;

template<typename Pool, std::size_t Ident, std::size_t... Other>
class View<Pool, Ident, Other...> final {
    using pool_type = Pool;
    using mask_type = std::bitset<std::tuple_size<Pool>::value + 1>;
    using underlying_iterator_type = typename std::tuple_element_t<Ident, Pool>::iterator_type;

    class ViewIterator;

public:
    using iterator_type = ViewIterator;
    using entity_type = typename std::tuple_element_t<Ident, Pool>::index_type;
    using size_type = typename std::tuple_element_t<Ident, Pool>::size_type;

private:
    class ViewIterator {
        inline bool valid() const noexcept {
            return ((mask[*begin] & bitmask) == bitmask);
        }

    public:
        using value_type = entity_type;

        ViewIterator(underlying_iterator_type begin, underlying_iterator_type end, const mask_type &bitmask, const mask_type *mask) noexcept
            : begin{begin}, end{end}, bitmask{bitmask}, mask{mask}
        {
            if(begin != end && !valid()) {
                ++(*this);
            }
        }

        ViewIterator & operator++() noexcept {
            ++begin;
            while(begin != end && !valid()) { ++begin; }
            return *this;
        }

        ViewIterator operator++(int) noexcept {
            ViewIterator orig = *this;
            return ++(*this), orig;
        }

        bool operator==(const ViewIterator &other) const noexcept {
            return other.begin == begin;
        }

        bool operator!=(const ViewIterator &other) const noexcept {
            return !(*this == other);
        }

        value_type operator*() const noexcept {
            return *begin;
        }

    private:
        underlying_iterator_type begin;
        underlying_iterator_type end;
        const mask_type bitmask;
        const mask_type *mask;
    };

    template<std::size_t Idx>
    void prefer(size_type &size) noexcept {
        auto &&cpool = std::get<Idx>(*pool);
        auto sz = cpool.size();

        if(sz < size) {
            from = cpool.begin();
            to = cpool.end();
            size = sz;
        }
    }

public:
    explicit View(const pool_type *pool, const mask_type *mask) noexcept
        : from{std::get<Ident>(*pool).begin()},
          to{std::get<Ident>(*pool).end()},
          pool{pool},
          mask{mask}
    {
        using accumulator_type = int[];
        size_type size = std::get<Ident>(*pool).size();
        bitmask.set(Ident);
        accumulator_type types = { 0, (bitmask.set(Other), 0)... };
        accumulator_type pref = { 0, (prefer<Other>(size), 0)... };
        (void)types, (void)pref;
    }

    iterator_type begin() const noexcept {
        return ViewIterator{from, to, bitmask, mask};
    }

    iterator_type end() const noexcept {
        return ViewIterator{to, to, bitmask, mask};
    }

    void reset() noexcept {
        using accumulator_type = int[];
        auto &&cpool = std::get<Ident>(*pool);
        from = cpool.begin();
        to = cpool.end();
        size_type size = cpool.size();
        accumulator_type accumulator = { 0, (prefer<Other>(size), 0)... };
        (void)accumulator;
    }

private:
    underlying_iterator_type from;
    underlying_iterator_type to;
    const pool_type *pool;
    const mask_type *mask;
    mask_type bitmask;
};

template<typename Pool, std::size_t Ident>
class View<Pool, Ident> final {
    using pool_type = std::tuple_element_t<Ident, Pool>;

public:
    using iterator_type = typename pool_type::iterator_type;
    using entity_type = typename pool_type::index_type;
    using size_type = typename pool_type::size_type;
    using raw_type = typename pool_type::type;

    explicit View(const Pool *pool) noexcept
        : pool{&std::get<Ident>(*pool)}
    {}

    raw_type * raw() noexcept {
        return pool->raw();
    }

    const raw_type * raw() const noexcept {
        return pool->raw();
    }

    const entity_type * data() const noexcept {
        return pool->data();
    }

    size_type size() const noexcept {
        return pool->size();
    }

    iterator_type begin() const noexcept {
        return pool->begin();
    }

    iterator_type end() const noexcept {
        return pool->end();
    }

private:
    const pool_type *pool;
};

template<typename Entity, typename... Component>
class Registry {
    using pool_type = std::tuple<SparseSet<Entity, Component>...>;
    using mask_type = std::bitset<sizeof...(Component)+1>;

    static constexpr auto validity_bit = sizeof...(Component);

public:
    using entity_type = Entity;
    using size_type = typename std::vector<mask_type>::size_type;

    template<typename... Comp>
    using view_type = View<pool_type, ident<Component...>.template get<Comp>()...>;

private:
    template<typename Comp>
    void clone(entity_type to, entity_type from) {
        constexpr auto index = ident<Component...>.template get<Comp>();

        if(entities[from].test(index)) {
            assign<Comp>(to, std::get<index>(pool).get(from));
        }
    }

    template<typename Comp>
    void sync(entity_type to, entity_type from) {
        constexpr auto index = ident<Component...>.template get<Comp>();

        bool src = entities[from].test(index);
        bool dst = entities[to].test(index);

        if(src && dst) {
            copy<Comp>(to, from);
        } else if(src) {
            clone<Comp>(to, from);
        } else if(dst) {
            remove<Comp>(to);
        }
    }

public:
    template<typename... Args>
    Registry(Args&&... args)
        : pool{std::forward<Args>(args)...}
    {}

    Registry(const Registry &) = delete;
    Registry(Registry &&) = delete;

    Registry & operator=(const Registry &) = delete;
    Registry & operator=(Registry &&) = delete;

    size_type size() const noexcept {
        return entities.size() - available.size();
    }

    size_type capacity() const noexcept {
        return entities.size();
    }

    template<typename Comp>
    bool empty() const noexcept {
        constexpr auto index = ident<Component...>.template get<Comp>();
        return std::get<index>(pool).empty();
    }

    bool empty() const noexcept {
        return entities.empty();
    }

    bool valid(entity_type entity) const noexcept {
        return (entity < entities.size() && entities[entity].test(validity_bit));
    }

    template<typename... Comp>
    entity_type create() noexcept {
        using accumulator_type = int[];
        auto entity = create();
        accumulator_type accumulator = { 0, (assign<Comp>(entity), 0)... };
        (void)accumulator;
        return entity;
    }

    entity_type create() noexcept {
        entity_type entity;

        if(available.empty()) {
            entity = entity_type(entities.size());
            entities.emplace_back();
        } else {
            entity = available.back();
            available.pop_back();
        }

        entities[entity].set(validity_bit);

        return entity;
    }

    void destroy(entity_type entity) {
        assert(valid(entity));
        using accumulator_type = int[];
        accumulator_type accumulator = { 0, (reset<Component>(entity), 0)... };
        available.push_back(entity);
        entities[entity].reset();
        (void)accumulator;
    }

    template<typename Comp, typename... Args>
    Comp & assign(entity_type entity, Args... args) {
        assert(valid(entity));
        constexpr auto index = ident<Component...>.template get<Comp>();
        entities[entity].set(index);
        return std::get<index>(pool).construct(entity, args...);
    }

    template<typename Comp>
    void remove(entity_type entity) {
        assert(valid(entity));
        constexpr auto index = ident<Component...>.template get<Comp>();
        entities[entity].reset(index);
        std::get<index>(pool).destroy(entity);
    }

    template<typename... Comp>
    bool has(entity_type entity) const noexcept {
        assert(valid(entity));
        using accumulator_type = bool[];
        bool all = true;
        auto &mask = entities[entity];
        accumulator_type accumulator = { true, (all = all && mask.test(ident<Component...>.template get<Comp>()))... };
        (void)accumulator;
        return all;
    }

    template<typename Comp>
    const Comp & get(entity_type entity) const noexcept {
        constexpr auto index = ident<Component...>.template get<Comp>();
        return std::get<index>(pool).get(entity);
    }

    template<typename Comp>
    Comp & get(entity_type entity) noexcept {
        constexpr auto index = ident<Component...>.template get<Comp>();
        return std::get<index>(pool).get(entity);
    }

    template<typename Comp, typename... Args>
    Comp & replace(entity_type entity, Args... args) {
        constexpr auto index = ident<Component...>.template get<Comp>();
        return (std::get<index>(pool).get(entity) = Comp{args...});
    }

    template<typename Comp, typename... Args>
    Comp & accomodate(entity_type entity, Args... args) {
        assert(valid(entity));

        constexpr auto index = ident<Component...>.template get<Comp>();

        return (entities[entity].test(index)
                ? this->template replace<Comp>(entity, std::forward<Args>(args)...)
                : this->template assign<Comp>(entity, std::forward<Args>(args)...));
    }

    entity_type clone(entity_type from) {
        assert(valid(from));
        using accumulator_type = int[];
        auto to = create();
        accumulator_type accumulator = { 0, (clone<Component>(to, from), 0)... };
        (void)accumulator;
        return to;
    }

    template<typename Comp>
    Comp & copy(entity_type to, entity_type from) {
        constexpr auto index = ident<Component...>.template get<Comp>();
        auto &&cpool = std::get<index>(pool);
        return (cpool.get(to) = cpool.get(from));
    }

    void copy(entity_type to, entity_type from) {
        using accumulator_type = int[];
        accumulator_type accumulator = { 0, (sync<Component>(to, from), 0)... };
        (void)accumulator;
    }

    template<typename Comp>
    void swap(entity_type lhs, entity_type rhs) {
        std::get<ident<Component...>.template get<Comp>()>(pool).swap(lhs, rhs);
    }

    template<typename Comp, typename Compare>
    void sort(Compare compare) {
        std::get<ident<Component...>.template get<Comp>()>(pool).sort(std::move(compare));
    }

    template<typename To, typename From>
    void sort() {
        auto &&to = std::get<ident<Component...>.template get<To>()>(pool);
        auto &&from = std::get<ident<Component...>.template get<From>()>(pool);
        to.respect(from);
    }

    template<typename Comp>
    void reset(entity_type entity) {
        assert(valid(entity));

        constexpr auto index = ident<Component...>.template get<Comp>();

        if(entities[entity].test(index)) {
            remove<Comp>(entity);
        }
    }

    template<typename Comp>
    void reset() {
        constexpr auto index = ident<Component...>.template get<Comp>();

        for(entity_type entity = 0, last = entity_type(entities.size()); entity < last; ++entity) {
            if(entities[entity].test(index)) {
                remove<Comp>(entity);
            }
        }
    }

    void reset() {
        using accumulator_type = int[];
        accumulator_type acc = { 0, (std::get<ident<Component...>.template get<Component>()>(pool).reset(), 0)... };
        entities.clear();
        available.clear();
        (void)acc;
    }

    template<typename... Comp>
    std::enable_if_t<(sizeof...(Comp) == 1), view_type<Comp...>>
    view() noexcept { return view_type<Comp...>{&pool}; }

    template<typename... Comp>
    std::enable_if_t<(sizeof...(Comp) > 1), view_type<Comp...>>
    view() noexcept { return view_type<Comp...>{&pool, entities.data()}; }

private:
    std::vector<mask_type> entities;
    std::vector<entity_type> available;
    pool_type pool;
};

template<typename... Component>
using DefaultRegistry = Registry<std::uint32_t, Component...>;

}

#endif // ENTT_REGISTRY_HPP
<commit_msg>arguments are no longer accepted by the constructor<commit_after>#ifndef ENTT_REGISTRY_HPP
#define ENTT_REGISTRY_HPP

#include <tuple>
#include <vector>
#include <bitset>
#include <utility>
#include <cstddef>
#include <iterator>
#include <cassert>
#include <type_traits>
#include "sparse_set.hpp"
#include "ident.hpp"

namespace entt {

template<typename, std::size_t...>
class View;

template<typename Pool, std::size_t Ident, std::size_t... Other>
class View<Pool, Ident, Other...> final {
    using pool_type = Pool;
    using mask_type = std::bitset<std::tuple_size<Pool>::value + 1>;
    using underlying_iterator_type = typename std::tuple_element_t<Ident, Pool>::iterator_type;

    class ViewIterator;

public:
    using iterator_type = ViewIterator;
    using entity_type = typename std::tuple_element_t<Ident, Pool>::index_type;
    using size_type = typename std::tuple_element_t<Ident, Pool>::size_type;

private:
    class ViewIterator {
        inline bool valid() const noexcept {
            return ((mask[*begin] & bitmask) == bitmask);
        }

    public:
        using value_type = entity_type;

        ViewIterator(underlying_iterator_type begin, underlying_iterator_type end, const mask_type &bitmask, const mask_type *mask) noexcept
            : begin{begin}, end{end}, bitmask{bitmask}, mask{mask}
        {
            if(begin != end && !valid()) {
                ++(*this);
            }
        }

        ViewIterator & operator++() noexcept {
            ++begin;
            while(begin != end && !valid()) { ++begin; }
            return *this;
        }

        ViewIterator operator++(int) noexcept {
            ViewIterator orig = *this;
            return ++(*this), orig;
        }

        bool operator==(const ViewIterator &other) const noexcept {
            return other.begin == begin;
        }

        bool operator!=(const ViewIterator &other) const noexcept {
            return !(*this == other);
        }

        value_type operator*() const noexcept {
            return *begin;
        }

    private:
        underlying_iterator_type begin;
        underlying_iterator_type end;
        const mask_type bitmask;
        const mask_type *mask;
    };

    template<std::size_t Idx>
    void prefer(size_type &size) noexcept {
        auto &&cpool = std::get<Idx>(*pool);
        auto sz = cpool.size();

        if(sz < size) {
            from = cpool.begin();
            to = cpool.end();
            size = sz;
        }
    }

public:
    explicit View(const pool_type *pool, const mask_type *mask) noexcept
        : from{std::get<Ident>(*pool).begin()},
          to{std::get<Ident>(*pool).end()},
          pool{pool},
          mask{mask}
    {
        using accumulator_type = int[];
        size_type size = std::get<Ident>(*pool).size();
        bitmask.set(Ident);
        accumulator_type types = { 0, (bitmask.set(Other), 0)... };
        accumulator_type pref = { 0, (prefer<Other>(size), 0)... };
        (void)types, (void)pref;
    }

    iterator_type begin() const noexcept {
        return ViewIterator{from, to, bitmask, mask};
    }

    iterator_type end() const noexcept {
        return ViewIterator{to, to, bitmask, mask};
    }

    void reset() noexcept {
        using accumulator_type = int[];
        auto &&cpool = std::get<Ident>(*pool);
        from = cpool.begin();
        to = cpool.end();
        size_type size = cpool.size();
        accumulator_type accumulator = { 0, (prefer<Other>(size), 0)... };
        (void)accumulator;
    }

private:
    underlying_iterator_type from;
    underlying_iterator_type to;
    const pool_type *pool;
    const mask_type *mask;
    mask_type bitmask;
};

template<typename Pool, std::size_t Ident>
class View<Pool, Ident> final {
    using pool_type = std::tuple_element_t<Ident, Pool>;

public:
    using iterator_type = typename pool_type::iterator_type;
    using entity_type = typename pool_type::index_type;
    using size_type = typename pool_type::size_type;
    using raw_type = typename pool_type::type;

    explicit View(const Pool *pool) noexcept
        : pool{&std::get<Ident>(*pool)}
    {}

    raw_type * raw() noexcept {
        return pool->raw();
    }

    const raw_type * raw() const noexcept {
        return pool->raw();
    }

    const entity_type * data() const noexcept {
        return pool->data();
    }

    size_type size() const noexcept {
        return pool->size();
    }

    iterator_type begin() const noexcept {
        return pool->begin();
    }

    iterator_type end() const noexcept {
        return pool->end();
    }

private:
    const pool_type *pool;
};

template<typename Entity, typename... Component>
class Registry {
    using pool_type = std::tuple<SparseSet<Entity, Component>...>;
    using mask_type = std::bitset<sizeof...(Component)+1>;

    static constexpr auto validity_bit = sizeof...(Component);

public:
    using entity_type = Entity;
    using size_type = typename std::vector<mask_type>::size_type;

    template<typename... Comp>
    using view_type = View<pool_type, ident<Component...>.template get<Comp>()...>;

private:
    template<typename Comp>
    void clone(entity_type to, entity_type from) {
        constexpr auto index = ident<Component...>.template get<Comp>();

        if(entities[from].test(index)) {
            assign<Comp>(to, std::get<index>(pool).get(from));
        }
    }

    template<typename Comp>
    void sync(entity_type to, entity_type from) {
        constexpr auto index = ident<Component...>.template get<Comp>();

        bool src = entities[from].test(index);
        bool dst = entities[to].test(index);

        if(src && dst) {
            copy<Comp>(to, from);
        } else if(src) {
            clone<Comp>(to, from);
        } else if(dst) {
            remove<Comp>(to);
        }
    }

public:
    explicit Registry() = default;
    ~Registry() = default;

    Registry(const Registry &) = delete;
    Registry(Registry &&) = delete;

    Registry & operator=(const Registry &) = delete;
    Registry & operator=(Registry &&) = delete;

    size_type size() const noexcept {
        return entities.size() - available.size();
    }

    size_type capacity() const noexcept {
        return entities.size();
    }

    template<typename Comp>
    bool empty() const noexcept {
        constexpr auto index = ident<Component...>.template get<Comp>();
        return std::get<index>(pool).empty();
    }

    bool empty() const noexcept {
        return entities.empty();
    }

    bool valid(entity_type entity) const noexcept {
        return (entity < entities.size() && entities[entity].test(validity_bit));
    }

    template<typename... Comp>
    entity_type create() noexcept {
        using accumulator_type = int[];
        auto entity = create();
        accumulator_type accumulator = { 0, (assign<Comp>(entity), 0)... };
        (void)accumulator;
        return entity;
    }

    entity_type create() noexcept {
        entity_type entity;

        if(available.empty()) {
            entity = entity_type(entities.size());
            entities.emplace_back();
        } else {
            entity = available.back();
            available.pop_back();
        }

        entities[entity].set(validity_bit);

        return entity;
    }

    void destroy(entity_type entity) {
        assert(valid(entity));
        using accumulator_type = int[];
        accumulator_type accumulator = { 0, (reset<Component>(entity), 0)... };
        available.push_back(entity);
        entities[entity].reset();
        (void)accumulator;
    }

    template<typename Comp, typename... Args>
    Comp & assign(entity_type entity, Args... args) {
        assert(valid(entity));
        constexpr auto index = ident<Component...>.template get<Comp>();
        entities[entity].set(index);
        return std::get<index>(pool).construct(entity, args...);
    }

    template<typename Comp>
    void remove(entity_type entity) {
        assert(valid(entity));
        constexpr auto index = ident<Component...>.template get<Comp>();
        entities[entity].reset(index);
        std::get<index>(pool).destroy(entity);
    }

    template<typename... Comp>
    bool has(entity_type entity) const noexcept {
        assert(valid(entity));
        using accumulator_type = bool[];
        bool all = true;
        auto &mask = entities[entity];
        accumulator_type accumulator = { true, (all = all && mask.test(ident<Component...>.template get<Comp>()))... };
        (void)accumulator;
        return all;
    }

    template<typename Comp>
    const Comp & get(entity_type entity) const noexcept {
        constexpr auto index = ident<Component...>.template get<Comp>();
        return std::get<index>(pool).get(entity);
    }

    template<typename Comp>
    Comp & get(entity_type entity) noexcept {
        constexpr auto index = ident<Component...>.template get<Comp>();
        return std::get<index>(pool).get(entity);
    }

    template<typename Comp, typename... Args>
    Comp & replace(entity_type entity, Args... args) {
        constexpr auto index = ident<Component...>.template get<Comp>();
        return (std::get<index>(pool).get(entity) = Comp{args...});
    }

    template<typename Comp, typename... Args>
    Comp & accomodate(entity_type entity, Args... args) {
        assert(valid(entity));

        constexpr auto index = ident<Component...>.template get<Comp>();

        return (entities[entity].test(index)
                ? this->template replace<Comp>(entity, std::forward<Args>(args)...)
                : this->template assign<Comp>(entity, std::forward<Args>(args)...));
    }

    entity_type clone(entity_type from) {
        assert(valid(from));
        using accumulator_type = int[];
        auto to = create();
        accumulator_type accumulator = { 0, (clone<Component>(to, from), 0)... };
        (void)accumulator;
        return to;
    }

    template<typename Comp>
    Comp & copy(entity_type to, entity_type from) {
        constexpr auto index = ident<Component...>.template get<Comp>();
        auto &&cpool = std::get<index>(pool);
        return (cpool.get(to) = cpool.get(from));
    }

    void copy(entity_type to, entity_type from) {
        using accumulator_type = int[];
        accumulator_type accumulator = { 0, (sync<Component>(to, from), 0)... };
        (void)accumulator;
    }

    template<typename Comp>
    void swap(entity_type lhs, entity_type rhs) {
        std::get<ident<Component...>.template get<Comp>()>(pool).swap(lhs, rhs);
    }

    template<typename Comp, typename Compare>
    void sort(Compare compare) {
        std::get<ident<Component...>.template get<Comp>()>(pool).sort(std::move(compare));
    }

    template<typename To, typename From>
    void sort() {
        auto &&to = std::get<ident<Component...>.template get<To>()>(pool);
        auto &&from = std::get<ident<Component...>.template get<From>()>(pool);
        to.respect(from);
    }

    template<typename Comp>
    void reset(entity_type entity) {
        assert(valid(entity));

        constexpr auto index = ident<Component...>.template get<Comp>();

        if(entities[entity].test(index)) {
            remove<Comp>(entity);
        }
    }

    template<typename Comp>
    void reset() {
        constexpr auto index = ident<Component...>.template get<Comp>();

        for(entity_type entity = 0, last = entity_type(entities.size()); entity < last; ++entity) {
            if(entities[entity].test(index)) {
                remove<Comp>(entity);
            }
        }
    }

    void reset() {
        using accumulator_type = int[];
        accumulator_type acc = { 0, (std::get<ident<Component...>.template get<Component>()>(pool).reset(), 0)... };
        entities.clear();
        available.clear();
        (void)acc;
    }

    template<typename... Comp>
    std::enable_if_t<(sizeof...(Comp) == 1), view_type<Comp...>>
    view() noexcept { return view_type<Comp...>{&pool}; }

    template<typename... Comp>
    std::enable_if_t<(sizeof...(Comp) > 1), view_type<Comp...>>
    view() noexcept { return view_type<Comp...>{&pool, entities.data()}; }

private:
    std::vector<mask_type> entities;
    std::vector<entity_type> available;
    pool_type pool;
};

template<typename... Component>
using DefaultRegistry = Registry<std::uint32_t, Component...>;

}

#endif // ENTT_REGISTRY_HPP
<|endoftext|>


<commit_before>/* Luwra
 * Minimal-overhead Lua wrapper for C++
 *
 * Copyright (C) 2015, Ole Krüger <ole@vprsm.de>
 */

#ifndef LUWRA_TYPES_H_
#define LUWRA_TYPES_H_

#include "common.hpp"

#include <utility>
#include <tuple>
#include <string>
#include <type_traits>
#include <limits>

LUWRA_NS_BEGIN

/* Lua types */
using Integer = lua_Integer;
using Number = lua_Number;
using State = lua_State;
using CFunction = lua_CFunction;

/**
 * A value on the stack
 */
template <typename T>
struct Value {
	static_assert(sizeof(T) == -1, "You must not use an unspecialized version of Value");

	/**
	 * Retrieve the value at position `n`.
	 */
	static
	T read(State*, int);

	/**
	 * push the value onto the stack.
	 */
	static
	int push(State*, T);
};

/**
 * Convenient wrapped for `Value<T>::push`.
 */
template <typename T> static inline
int push(State* state, T value) {
	return Value<T>::push(state, value);
}

/**
 * Define a template specialization of `Value` for `type` with a `retrf(State*, int)` which
 * extracts it from the stack and a `pushf(State*, type)` which pushes the value on the stack again.
 * This assumes that only one value will be pushed onto the stack.
 */
#define LUWRA_DEF_VALUE(type, retrf, pushf)                          \
	template <>                                                      \
	struct Value<type> {                                             \
		static inline                                                \
		type read(State* state, int n) {                             \
			return retrf(state, n);                                  \
		}                                                            \
                                                                     \
		static inline                                                \
		int push(State* state, type value) {                         \
			pushf(state, value);                                     \
			return 1;                                                \
		}                                                            \
	}

#ifndef luaL_checkboolean
	/**
	 * Check if the value at index `n` is a boolean and retrieve its value.
	 */
	#define luaL_checkboolean(state, n) \
		(luaL_checktype(state, n, LUA_TBOOLEAN), lua_toboolean(state, n))
#endif

#ifndef luaL_checkcfunction
	/**
	 * Check if the value at index `n` is a C function and retrieve it.
	 */
	#define luaL_checkcfunction(state, n) \
		(luaL_checktype(state, n, LUA_TCFUNCTION), lua_toboolean(state, n))
#endif

#ifndef luaL_pushstdstring
	/**
	 * push a `std::string` as string onto the stack.
	 */
	#define luaL_pushstdstring(state, stdstring) \
		(lua_pushstring(state, (stdstring).c_str()))
#endif

namespace internal {
	template <typename>
	struct NumericTransportValue;

	// Transport unit `Integer`
	template <>
	struct NumericTransportValue<Integer> {
		static inline
		Integer read(State* state, int index) {
			return luaL_checkinteger(state, index);
		}

		static inline
		int push(State* state, Integer value) {
			lua_pushinteger(state, value);
			return 1;
		}
	};

	// Transport unit `Number`
	template <>
	struct NumericTransportValue<Number> {
		static inline
		Number read(State* state, int index) {
			return luaL_checknumber(state, index);
		}

		static inline
		int push(State* state, Number value) {
			lua_pushnumber(state, value);
			return 1;
		}
	};

	// Base for `Value<I>` specializations which uses `B` as transport unit, where `I` is smaller
	// than `B`.
	template <typename I, typename B>
	struct NumericContainedValueBase {
		static constexpr
		bool qualifies =
			// TODO: Remove warning about comparsion between signed and unsigned integers
			std::numeric_limits<I>::max() <= std::numeric_limits<B>::max()
			&& std::numeric_limits<I>::lowest() >= std::numeric_limits<B>::lowest();

		static inline
		I read(State* state, int index) {
			return
				std::max<B>(
					std::numeric_limits<I>::lowest(),
					std::min<B>(
						std::numeric_limits<I>::max(),
						NumericTransportValue<B>::read(state, index)
					)
				);
		}

		static inline
		int push(State* state, I value) {
			NumericTransportValue<B>::push(state, static_cast<B>(value));
			return 1;
		}
	};

	// Base for `Value<I>` specializations which uses `B` as transport unit, where `I` is bigger
	// than `B`.
	template <typename I, typename B>
	struct NumericTruncatingValueBase {
		static inline
		I read(State* state, int index) {
			return static_cast<I>(NumericTransportValue<B>::read(state, index));
		}

		static inline
		int push(State*, I) {
			static_assert(
				sizeof(I) == -1,
				"You must not use 'Value<I>::push' specializations which inherit from NumericTruncatingValueBase"
			);

			return -1;
		}
	};

	// Base for `Value<I>` specializations which uses `B` as transport unit
	template <typename I, typename B>
	using NumericValueBase =
		typename std::conditional<
			std::is_same<I, B>::value,
			NumericTransportValue<B>,
			typename std::conditional<
				NumericContainedValueBase<I, B>::qualifies,
				NumericContainedValueBase<I, B>,
				NumericTruncatingValueBase<I, B>
			>::type
		>::type;
}

/**
 * Define an integral type which will be transported via `base`.
 */
#define LUWRA_DEF_NUMERIC(base, type) \
	template <> \
	struct Value<type>: internal::NumericValueBase<type, base> {};

// Lua-dependent types
LUWRA_DEF_NUMERIC(Number, float)
LUWRA_DEF_NUMERIC(Number, double)
LUWRA_DEF_NUMERIC(Number, long double)

// Integral types
LUWRA_DEF_NUMERIC(Integer, signed   short)
LUWRA_DEF_NUMERIC(Integer, unsigned short)
LUWRA_DEF_NUMERIC(Integer, signed   int)
LUWRA_DEF_NUMERIC(Integer, unsigned int)
LUWRA_DEF_NUMERIC(Integer, signed   long int)
LUWRA_DEF_NUMERIC(Integer, unsigned long int)
LUWRA_DEF_NUMERIC(Integer, signed   long long int)
LUWRA_DEF_NUMERIC(Integer, unsigned long long int)

// C/C++ types
LUWRA_DEF_VALUE(bool,        luaL_checkboolean, lua_pushboolean);
LUWRA_DEF_VALUE(const char*, luaL_checkstring,  lua_pushstring);
LUWRA_DEF_VALUE(std::string, luaL_checkstring,  luaL_pushstdstring);

// Do not export these macros
#undef LUWRA_DEF_VALUE
#undef LUWRA_DEF_NUMERIC

/**
 * C Functions may be pushed aswell.
 */
template <>
struct Value<CFunction> {
	static inline
	int push(State* state, CFunction fun) {
		lua_pushcfunction(state, fun);
		return 1;
	}
};

/**
 * An arbitrary value on an execution stack.
 * Note: this value is only available as long as it exists on its originating stack.
 */
struct Arbitrary {
	State* state;
	int index;
};

template <>
struct Value<Arbitrary> {
	static inline
	Arbitrary read(State* state, int index) {
		if (index < 0)
			index = lua_gettop(state) + (index + 1);

		return Arbitrary {state, index};
	}

	static inline
	int push(State* state, const Arbitrary& value) {
		lua_pushvalue(value.state, value.index);

		if (value.state != state)
			lua_xmove(value.state, state, 1);

		return 1;
	}
};

namespace internal {
	template <typename>
	struct StackPusher;

	template <size_t I>
	struct StackPusher<std::index_sequence<I>> {
		template <typename... T> static inline
		int push(State* state, const std::tuple<T...>& package) {
			using R = typename std::tuple_element<I, std::tuple<T...>>::type;
			return std::max(0, Value<R>::push(state, std::get<I>(package)));
		}
	};

	template <size_t I, size_t... Is>
	struct StackPusher<std::index_sequence<I, Is...>> {
		template <typename... T> static inline
		int push(State* state, const std::tuple<T...>& package) {
			return
				StackPusher<std::index_sequence<I>>::push(state, package)
				+ StackPusher<std::index_sequence<Is...>>::push(state, package);
		}
	};
}

/**
 * Allows you to use multiple return values.
 */
template <typename... A>
struct Value<std::tuple<A...>> {
	static inline
	int push(State* state, const std::tuple<A...>& value) {
		return internal::StackPusher<std::make_index_sequence<sizeof...(A)>>::push(state, value);
	}
};

LUWRA_NS_END

#endif
<commit_msg>Do not limit bounds of numeric values before casting them<commit_after>/* Luwra
 * Minimal-overhead Lua wrapper for C++
 *
 * Copyright (C) 2015, Ole Krüger <ole@vprsm.de>
 */

#ifndef LUWRA_TYPES_H_
#define LUWRA_TYPES_H_

#include "common.hpp"

#include <utility>
#include <tuple>
#include <string>
#include <type_traits>
#include <limits>

LUWRA_NS_BEGIN

/* Lua types */
using Integer = lua_Integer;
using Number = lua_Number;
using State = lua_State;
using CFunction = lua_CFunction;

/**
 * A value on the stack
 */
template <typename T>
struct Value {
	static_assert(sizeof(T) == -1, "You must not use an unspecialized version of Value");

	/**
	 * Retrieve the value at position `n`.
	 */
	static
	T read(State*, int);

	/**
	 * push the value onto the stack.
	 */
	static
	int push(State*, T);
};

/**
 * Convenient wrapped for `Value<T>::push`.
 */
template <typename T> static inline
int push(State* state, T value) {
	return Value<T>::push(state, value);
}

/**
 * Define a template specialization of `Value` for `type` with a `retrf(State*, int)` which
 * extracts it from the stack and a `pushf(State*, type)` which pushes the value on the stack again.
 * This assumes that only one value will be pushed onto the stack.
 */
#define LUWRA_DEF_VALUE(type, retrf, pushf)                          \
	template <>                                                      \
	struct Value<type> {                                             \
		static inline                                                \
		type read(State* state, int n) {                             \
			return retrf(state, n);                                  \
		}                                                            \
                                                                     \
		static inline                                                \
		int push(State* state, type value) {                         \
			pushf(state, value);                                     \
			return 1;                                                \
		}                                                            \
	}

#ifndef luaL_checkboolean
	/**
	 * Check if the value at index `n` is a boolean and retrieve its value.
	 */
	#define luaL_checkboolean(state, n) \
		(luaL_checktype(state, n, LUA_TBOOLEAN), lua_toboolean(state, n))
#endif

#ifndef luaL_checkcfunction
	/**
	 * Check if the value at index `n` is a C function and retrieve it.
	 */
	#define luaL_checkcfunction(state, n) \
		(luaL_checktype(state, n, LUA_TCFUNCTION), lua_toboolean(state, n))
#endif

#ifndef luaL_pushstdstring
	/**
	 * push a `std::string` as string onto the stack.
	 */
	#define luaL_pushstdstring(state, stdstring) \
		(lua_pushstring(state, (stdstring).c_str()))
#endif

namespace internal {
	template <typename>
	struct NumericTransportValue;

	// Transport unit `Integer`
	template <>
	struct NumericTransportValue<Integer> {
		static inline
		Integer read(State* state, int index) {
			return luaL_checkinteger(state, index);
		}

		static inline
		int push(State* state, Integer value) {
			lua_pushinteger(state, value);
			return 1;
		}
	};

	// Transport unit `Number`
	template <>
	struct NumericTransportValue<Number> {
		static inline
		Number read(State* state, int index) {
			return luaL_checknumber(state, index);
		}

		static inline
		int push(State* state, Number value) {
			lua_pushnumber(state, value);
			return 1;
		}
	};

	// Base for `Value<I>` specializations which uses `B` as transport unit, where `I` is smaller
	// than `B`.
	template <typename I, typename B>
	struct NumericContainedValueBase {
		static constexpr
		bool qualifies =
			// TODO: Remove warning about comparsion between signed and unsigned integers
			std::numeric_limits<I>::max() <= std::numeric_limits<B>::max()
			&& std::numeric_limits<I>::lowest() >= std::numeric_limits<B>::lowest();

		static inline
		I read(State* state, int index) {
			return
				static_cast<I>(NumericTransportValue<B>::read(state, index));
		}

		static inline
		int push(State* state, I value) {
			NumericTransportValue<B>::push(state, static_cast<B>(value));
			return 1;
		}
	};

	// Base for `Value<I>` specializations which uses `B` as transport unit, where `I` is bigger
	// than `B`.
	template <typename I, typename B>
	struct NumericTruncatingValueBase {
		static inline
		I read(State* state, int index) {
			return static_cast<I>(NumericTransportValue<B>::read(state, index));
		}

		static inline
		int push(State*, I) {
			static_assert(
				sizeof(I) == -1,
				"You must not use 'Value<I>::push' specializations which inherit from NumericTruncatingValueBase"
			);

			return -1;
		}
	};

	// Base for `Value<I>` specializations which uses `B` as transport unit
	template <typename I, typename B>
	using NumericValueBase =
		typename std::conditional<
			std::is_same<I, B>::value,
			NumericTransportValue<B>,
			typename std::conditional<
				NumericContainedValueBase<I, B>::qualifies,
				NumericContainedValueBase<I, B>,
				NumericTruncatingValueBase<I, B>
			>::type
		>::type;
}

/**
 * Define an integral type which will be transported via `base`.
 */
#define LUWRA_DEF_NUMERIC(base, type) \
	template <> \
	struct Value<type>: internal::NumericValueBase<type, base> {};

// Lua-dependent types
LUWRA_DEF_NUMERIC(Number, float)
LUWRA_DEF_NUMERIC(Number, double)
LUWRA_DEF_NUMERIC(Number, long double)

// Integral types
LUWRA_DEF_NUMERIC(Integer, signed   short)
LUWRA_DEF_NUMERIC(Integer, unsigned short)
LUWRA_DEF_NUMERIC(Integer, signed   int)
LUWRA_DEF_NUMERIC(Integer, unsigned int)
LUWRA_DEF_NUMERIC(Integer, signed   long int)
LUWRA_DEF_NUMERIC(Integer, unsigned long int)
LUWRA_DEF_NUMERIC(Integer, signed   long long int)
LUWRA_DEF_NUMERIC(Integer, unsigned long long int)

// C/C++ types
LUWRA_DEF_VALUE(bool,        luaL_checkboolean, lua_pushboolean);
LUWRA_DEF_VALUE(const char*, luaL_checkstring,  lua_pushstring);
LUWRA_DEF_VALUE(std::string, luaL_checkstring,  luaL_pushstdstring);

// Do not export these macros
#undef LUWRA_DEF_VALUE
#undef LUWRA_DEF_NUMERIC

/**
 * C Functions may be pushed aswell.
 */
template <>
struct Value<CFunction> {
	static inline
	int push(State* state, CFunction fun) {
		lua_pushcfunction(state, fun);
		return 1;
	}
};

/**
 * An arbitrary value on an execution stack.
 * Note: this value is only available as long as it exists on its originating stack.
 */
struct Arbitrary {
	State* state;
	int index;
};

template <>
struct Value<Arbitrary> {
	static inline
	Arbitrary read(State* state, int index) {
		if (index < 0)
			index = lua_gettop(state) + (index + 1);

		return Arbitrary {state, index};
	}

	static inline
	int push(State* state, const Arbitrary& value) {
		lua_pushvalue(value.state, value.index);

		if (value.state != state)
			lua_xmove(value.state, state, 1);

		return 1;
	}
};

namespace internal {
	template <typename>
	struct StackPusher;

	template <size_t I>
	struct StackPusher<std::index_sequence<I>> {
		template <typename... T> static inline
		int push(State* state, const std::tuple<T...>& package) {
			using R = typename std::tuple_element<I, std::tuple<T...>>::type;
			return std::max(0, Value<R>::push(state, std::get<I>(package)));
		}
	};

	template <size_t I, size_t... Is>
	struct StackPusher<std::index_sequence<I, Is...>> {
		template <typename... T> static inline
		int push(State* state, const std::tuple<T...>& package) {
			return
				StackPusher<std::index_sequence<I>>::push(state, package)
				+ StackPusher<std::index_sequence<Is...>>::push(state, package);
		}
	};
}

/**
 * Allows you to use multiple return values.
 */
template <typename... A>
struct Value<std::tuple<A...>> {
	static inline
	int push(State* state, const std::tuple<A...>& value) {
		return internal::StackPusher<std::make_index_sequence<sizeof...(A)>>::push(state, value);
	}
};

LUWRA_NS_END

#endif
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "LoginMenu.h"

/* common implementation headers */
#include "FontManager.h"

/* local implementation headers */
#include "MainMenu.h"
#include "MenuDefaultKey.h"
#include "ClientAuthentication.h"

LoginMenu::LoginMenu()
{
  // cache font face ID
  int fontFace = MainMenu::getFontFace();

  // add controls
  std::vector<HUDuiControl*>& list = getControls();

  HUDuiLabel* label = new HUDuiLabel;
  label->setFontFace(fontFace);
  label->setString("Login");
  list.push_back(label);

  username = new HUDuiTypeIn;
  username->setFontFace(fontFace);
  username->setLabel("Username:");
  username->setMaxLength(20);
  list.push_back(username);

  password = new HUDuiTypeIn;
  password->setFontFace(fontFace);
  password->setLabel("Password:");
  password->setMaxLength(20);
  list.push_back(password);

  login = new HUDuiLabel;
  login->setFontFace(fontFace);
  login->setString("Login");
  list.push_back(login);

  initNavigation(list, 1, list.size() - 1);
}

LoginMenu::~LoginMenu()
{
}

HUDuiDefaultKey* LoginMenu::getDefaultKey()
{
  return MenuDefaultKey::getInstance();
}

void LoginMenu::execute()
{
  HUDuiControl* focus = HUDui::getFocus();
  if (focus == login) {
    // Initializing Authentication
    ClientAuthentication::login(username->getString().c_str(),
				password->getString().c_str());
  }
}

void LoginMenu::resize(int width, int height)
{
  int i;
  HUDDialog::resize(width, height);

  // use a big font for title, smaller font for the rest
  const float titleFontSize = (float)height / 15.0f;
  const float fontSize = (float)height / 30.0f;

  FontManager &fm = FontManager::instance();

  // reposition title
  std::vector<HUDuiControl*>& list = getControls();
  HUDuiLabel* title = (HUDuiLabel*)list[0];
  title->setFontSize(titleFontSize);
  const float titleWidth = fm.getStrLength(MainMenu::getFontFace(),
					   titleFontSize, title->getString());
  const float titleHeight = fm.getStrHeight(MainMenu::getFontFace(),
					    titleFontSize, "");
  float x = 0.5f * ((float)width - titleWidth);
  float y = (float)height - titleHeight;
  title->setPosition(x, y);

  // reposition options
  x  = 0.5f * ((float)width - 0.5f * titleWidth);
  y -= 0.6f * titleHeight;
  const int count = list.size();
  const float h = fm.getStrHeight(MainMenu::getFontFace(), fontSize, " ");
  for (i = 1; i < count; i++) {
    list[i]->setFontSize(fontSize);
    list[i]->setPosition(x, y);
    y -= 1.0f * h;
  }
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>this actually compiled for you?<commit_after>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "LoginMenu.h"

/* common implementation headers */
#include "FontManager.h"

/* local implementation headers */
#include "HUDui.h"
#include "MainMenu.h"
#include "MenuDefaultKey.h"
#include "ClientAuthentication.h"

LoginMenu::LoginMenu()
{
  // cache font face ID
  int fontFace = MainMenu::getFontFace();

  // add controls
  std::vector<HUDuiControl*>& list = getControls();

  HUDuiLabel* label = new HUDuiLabel;
  label->setFontFace(fontFace);
  label->setString("Login");
  list.push_back(label);

  username = new HUDuiTypeIn;
  username->setFontFace(fontFace);
  username->setLabel("Username:");
  username->setMaxLength(20);
  list.push_back(username);

  password = new HUDuiTypeIn;
  password->setFontFace(fontFace);
  password->setLabel("Password:");
  password->setMaxLength(20);
  list.push_back(password);

  login = new HUDuiLabel;
  login->setFontFace(fontFace);
  login->setString("Login");
  list.push_back(login);

  initNavigation(list, 1, list.size() - 1);
}

LoginMenu::~LoginMenu()
{
}

HUDuiDefaultKey* LoginMenu::getDefaultKey()
{
  return MenuDefaultKey::getInstance();
}

void LoginMenu::execute()
{
  HUDuiControl* focus = HUDui::getFocus();
  if (focus == login) {
    // Initializing Authentication
    ClientAuthentication::login(username->getString().c_str(),
				password->getString().c_str());
  }
}

void LoginMenu::resize(int width, int height)
{
  int i;
  HUDDialog::resize(width, height);

  // use a big font for title, smaller font for the rest
  const float titleFontSize = (float)height / 15.0f;
  const float fontSize = (float)height / 30.0f;

  FontManager &fm = FontManager::instance();

  // reposition title
  std::vector<HUDuiControl*>& list = getControls();
  HUDuiLabel* title = (HUDuiLabel*)list[0];
  title->setFontSize(titleFontSize);
  const float titleWidth = fm.getStrLength(MainMenu::getFontFace(),
					   titleFontSize, title->getString());
  const float titleHeight = fm.getStrHeight(MainMenu::getFontFace(),
					    titleFontSize, "");
  float x = 0.5f * ((float)width - titleWidth);
  float y = (float)height - titleHeight;
  title->setPosition(x, y);

  // reposition options
  x  = 0.5f * ((float)width - 0.5f * titleWidth);
  y -= 0.6f * titleHeight;
  const int count = list.size();
  const float h = fm.getStrHeight(MainMenu::getFontFace(), fontSize, " ");
  for (i = 1; i < count; i++) {
    list[i]->setFontSize(fontSize);
    list[i]->setPosition(x, y);
    y -= 1.0f * h;
  }
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>// vw_explore.cpp : Defines the entry point for the console application.
//

#include "MWTExplorer.h"
#include <chrono>
#include <tuple>
#include <iostream>

using namespace std;
using namespace std::chrono;
using namespace MultiWorldTesting;

class MyContext
{

};

class MyPolicy : public IPolicy<MyContext>
{
public:
	u32 Choose_Action(MyContext& context)
	{
		return (u32)1;
	}
};

class MySimplePolicy : public IPolicy<SimpleContext>
{
public:
	u32 Choose_Action(SimpleContext& context)
	{
		return (u32)1;
	}
};

class MyScorer : public IScorer<MyContext>
{
public:
	MyScorer(u32 num_actions) : m_num_actions(num_actions)
	{

	}
	vector<float> Score_Actions(MyContext& context)
	{
		vector<float> scores;
		for (size_t i = 0; i < m_num_actions; i++)
		{
			scores.push_back(.1f);
		}
		return scores;
	}
private:
	u32 m_num_actions;
};

class MyRecorder : public IRecorder<MyContext>
{
public:
	virtual void Record(MyContext& context, u32 action, float probability, string unique_key)
	{

	}
};

int main(int argc, char* argv[])
{
	if (argc < 2)
	{
		cerr << "arguments: {greedy,tau-first,bagging,softmax,generic} [stateful]" << endl;
		exit(1);
	}

	//arguments for individual explorers
	if (strcmp(argv[1], "greedy") == 0)
	{
		//Initialize Epsilon-Greedy explore algorithm using MyPolicy
		vector<Feature> features;
		features.push_back({ 0.5f, 1 });
		features.push_back({ 1.3f, 11 });
		features.push_back({ -.95f, 413 });
		SimpleContext context(features);

		StringRecorder<SimpleContext> recorder;
		MySimplePolicy default_policy;
		MwtExplorer<SimpleContext> mwt("appid", recorder);

		u32 num_actions = 10;
		float epsilon = .2f;
		EpsilonGreedyExplorer<SimpleContext> explorer(default_policy, epsilon, num_actions);

		string unique_key = "eventid";
		u32 action = mwt.Choose_Action(explorer, unique_key, context);

		cout << "action = " << action << " recorder = " << recorder.Get_Recording();
	}
	else if (strcmp(argv[1], "tau-first") == 0)
	{
		//Initialize Tau-First explore algorithm using MyPolicy
		MyRecorder recorder;
		MwtExplorer<MyContext> mwt("appid", recorder);

		int num_actions = 10;
		u32 tau = 5;
		MyPolicy default_policy;
		TauFirstExplorer<MyContext> explorer(default_policy, tau, num_actions);
		MyContext ctx;
		string unique_key = "eventid";
		u32 action = mwt.Choose_Action(explorer, unique_key, ctx);

		cout << "action = " << action << endl;
	}
	else if (strcmp(argv[1], "bagging") == 0)
	{
		//Initialize Bagging explore algorithm using MyPolicy
		MyRecorder recorder;
		MwtExplorer<MyContext> mwt("appid", recorder);

		u32 num_bags = 2;
		vector<unique_ptr<IPolicy<MyContext>>> policy_functions;
		for (size_t i = 0; i < num_bags; i++)
		{
			policy_functions.push_back(unique_ptr<IPolicy<MyContext>>(new MyPolicy()));
		}
		int num_actions = 10;
		BaggingExplorer<MyContext> explorer(policy_functions, num_bags, num_actions);
		MyContext ctx;
		string unique_key = "eventid";
		u32 action = mwt.Choose_Action(explorer, unique_key, ctx);

		cout << "action = " << action << endl;
	}
	else if (strcmp(argv[1], "softmax") == 0)
	{
		//Initialize Softmax explore algorithm using MyScorer
		MyRecorder recorder;
		MwtExplorer<MyContext> mwt("salt", recorder);

		u32 num_actions = 10;
		MyScorer scorer(num_actions);
		float lambda = 0.5f;
		SoftmaxExplorer<MyContext> explorer(scorer, lambda, num_actions);

		MyContext ctx;
		string unique_key = "eventid";
		u32 action = mwt.Choose_Action(explorer, unique_key, ctx);

		cout << "action = " << action << endl;
	}
	else if (strcmp(argv[1], "generic") == 0)
	{
		//Initialize Generic explore algorithm using MyScorer
		MyRecorder recorder;
		MwtExplorer<MyContext> mwt("appid", recorder);

		int num_actions = 10;
		MyScorer scorer(num_actions);
		GenericExplorer<MyContext> explorer(scorer, num_actions);
		MyContext ctx;
		string unique_key = "eventid";
		u32 action = mwt.Choose_Action(explorer, unique_key, ctx);

		cout << "action = " << action << endl;
	}
	else
	{
		cerr << "unknown exploration type: " << argv[1] << endl;
		exit(1);
	}

	return 0;
}
<commit_msg>Added Interaction<Ctx> class to c++ sample code<commit_after>// vw_explore.cpp : Defines the entry point for the console application.
//

#include "MWTExplorer.h"
#include <chrono>
#include <tuple>
#include <iostream>

using namespace std;
using namespace std::chrono;
using namespace MultiWorldTesting;

class MyContext
{

};

class MyPolicy : public IPolicy<MyContext>
{
public:
	u32 Choose_Action(MyContext& context)
	{
		return (u32)1;
	}
};

class MySimplePolicy : public IPolicy<SimpleContext>
{
public:
	u32 Choose_Action(SimpleContext& context)
	{
		return (u32)1;
	}
};

class MyScorer : public IScorer<MyContext>
{
public:
	MyScorer(u32 num_actions) : m_num_actions(num_actions)
	{

	}
	vector<float> Score_Actions(MyContext& context)
	{
		vector<float> scores;
		for (size_t i = 0; i < m_num_actions; i++)
		{
			scores.push_back(.1f);
		}
		return scores;
	}
private:
	u32 m_num_actions;
};

template <class Ctx>
struct MyInteraction
{
	Ctx& Context;
	u32 Action;
	float Probability;
	string Unique_Key;
};

class MyRecorder : public IRecorder<MyContext>
{
public:
	virtual void Record(MyContext& context, u32 action, float probability, string unique_key)
	{
		m_interactions.push_back({ context, action, probability, unique_key });
	}
private:
	vector<MyInteraction<MyContext>> m_interactions;
};

int main(int argc, char* argv[])
{
	if (argc < 2)
	{
		cerr << "arguments: {greedy,tau-first,bagging,softmax,generic}" << endl;
		exit(1);
	}

	//arguments for individual explorers
	if (strcmp(argv[1], "greedy") == 0)
	{
		//Initialize Epsilon-Greedy explore algorithm using MyPolicy
		vector<Feature> features;
		features.push_back({ 0.5f, 1 });
		features.push_back({ 1.3f, 11 });
		features.push_back({ -.95f, 413 });
		SimpleContext context(features);

		StringRecorder<SimpleContext> recorder;
		MySimplePolicy default_policy;
		MwtExplorer<SimpleContext> mwt("appid", recorder);

		u32 num_actions = 10;
		float epsilon = .2f;
		EpsilonGreedyExplorer<SimpleContext> explorer(default_policy, epsilon, num_actions);

		string unique_key = "eventid";
		u32 action = mwt.Choose_Action(explorer, unique_key, context);

		cout << "action = " << action << " recorder = " << recorder.Get_Recording();
	}
	else if (strcmp(argv[1], "tau-first") == 0)
	{
		//Initialize Tau-First explore algorithm using MyPolicy
		MyRecorder recorder;
		MwtExplorer<MyContext> mwt("appid", recorder);

		int num_actions = 10;
		u32 tau = 5;
		MyPolicy default_policy;
		TauFirstExplorer<MyContext> explorer(default_policy, tau, num_actions);
		MyContext ctx;
		string unique_key = "eventid";
		u32 action = mwt.Choose_Action(explorer, unique_key, ctx);

		cout << "action = " << action << endl;
	}
	else if (strcmp(argv[1], "bagging") == 0)
	{
		//Initialize Bagging explore algorithm using MyPolicy
		MyRecorder recorder;
		MwtExplorer<MyContext> mwt("appid", recorder);

		u32 num_bags = 2;
		vector<unique_ptr<IPolicy<MyContext>>> policy_functions;
		for (size_t i = 0; i < num_bags; i++)
		{
			policy_functions.push_back(unique_ptr<IPolicy<MyContext>>(new MyPolicy()));
		}
		int num_actions = 10;
		BaggingExplorer<MyContext> explorer(policy_functions, num_bags, num_actions);
		MyContext ctx;
		string unique_key = "eventid";
		u32 action = mwt.Choose_Action(explorer, unique_key, ctx);

		cout << "action = " << action << endl;
	}
	else if (strcmp(argv[1], "softmax") == 0)
	{
		//Initialize Softmax explore algorithm using MyScorer
		MyRecorder recorder;
		MwtExplorer<MyContext> mwt("salt", recorder);

		u32 num_actions = 10;
		MyScorer scorer(num_actions);
		float lambda = 0.5f;
		SoftmaxExplorer<MyContext> explorer(scorer, lambda, num_actions);

		MyContext ctx;
		string unique_key = "eventid";
		u32 action = mwt.Choose_Action(explorer, unique_key, ctx);

		cout << "action = " << action << endl;
	}
	else if (strcmp(argv[1], "generic") == 0)
	{
		//Initialize Generic explore algorithm using MyScorer
		MyRecorder recorder;
		MwtExplorer<MyContext> mwt("appid", recorder);

		int num_actions = 10;
		MyScorer scorer(num_actions);
		GenericExplorer<MyContext> explorer(scorer, num_actions);
		MyContext ctx;
		string unique_key = "eventid";
		u32 action = mwt.Choose_Action(explorer, unique_key, ctx);

		cout << "action = " << action << endl;
	}
	else
	{
		cerr << "unknown exploration type: " << argv[1] << endl;
		exit(1);
	}

	return 0;
}
<|endoftext|>


<commit_before>/*********************************************************************
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2013, PAL Robotics, S.L.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the Willow Garage nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *********************************************************************/

/*
 * Author: Bence Magyar
 */

#include <controller_interface/controller.h>
#include <hardware_interface/joint_command_interface.h>
#include <pluginlib/class_list_macros.h>

#include <nav_msgs/Odometry.h>
#include <tf/tfMessage.h>
#include <tf/transform_datatypes.h>

#include <urdf_parser/urdf_parser.h>

#include <realtime_tools/realtime_buffer.h>
#include <realtime_tools/realtime_publisher.h>

#include <boost/assign.hpp>

#include <diff_drive_controller/odometry.h>

namespace diff_drive_controller{

  class DiffDriveController : public controller_interface::Controller<hardware_interface::VelocityJointInterface>
  {
  public:
    bool init(hardware_interface::VelocityJointInterface* hw,
              ros::NodeHandle& root_nh,
              ros::NodeHandle &controller_nh)
    {
      ROS_INFO("Init DiffDriveController.");

      name_ = getLeafNamespace(controller_nh);
      // get joint names from the parameter server
      std::string left_wheel_name, right_wheel_name;

      bool res = controller_nh.hasParam("left_wheel");
      if(!res || !controller_nh.getParam("left_wheel", left_wheel_name))
      {
        ROS_ERROR("Couldn't retrieve left wheel name from param server.");
        return false;
      }
      res = controller_nh.hasParam("right_wheel");
      if(!res || !controller_nh.getParam("right_wheel", right_wheel_name))
      {
        ROS_ERROR("Couldn't retrieve right wheel name from param server.");
        return false;
      }

      // parse robot description
      const std::string model_param_name = "/robot_description";
      res = root_nh.hasParam(model_param_name);
      std::string robot_model_str="";
      if(!res || !root_nh.getParam(model_param_name,robot_model_str))
      {
        ROS_ERROR("Robot descripion couldn't be retrieved from param server.");
        return false;
      }

      boost::shared_ptr<urdf::ModelInterface> model_ptr(urdf::parseURDF(robot_model_str));
      boost::shared_ptr<const urdf::Joint> wheelJointPtr(model_ptr->getJoint(left_wheel_name));
      if(!wheelJointPtr.get())
      {
        ROS_ERROR_STREAM(left_wheel_name << " couldn't be retrieved from model description");
        return false;
      }

      wheel_radius_ = fabs(wheelJointPtr->parent_to_joint_origin_transform.position.z);
      wheel_separation_ = 2.0 * fabs(wheelJointPtr->parent_to_joint_origin_transform.position.y);
      ROS_INFO_STREAM("Odometry params : wheel separation " << wheel_separation_
                      << ", wheel radius " << wheel_radius_);

      // get the joint object to use in the realtime loop
      ROS_INFO_STREAM("Adding left wheel with joint name: " << left_wheel_name
                      << " and right wheel with joint name: " << right_wheel_name);
      left_wheel_joint_ = hw->getHandle(left_wheel_name);  // throws on failure
      right_wheel_joint_ = hw->getHandle(right_wheel_name);  // throws on failure

      // setup odometry realtime publisher + odom message constant fields
      odom_pub_.reset(new realtime_tools::RealtimePublisher<nav_msgs::Odometry>(controller_nh, "odom", 100));
      odom_pub_->msg_.header.frame_id = "odom";
      odom_pub_->msg_.pose.pose.position.z = 0;
      odom_pub_->msg_.pose.covariance = boost::assign::list_of
          (1e-3) (0)   (0)  (0)  (0)  (0)
          (0) (1e-3)  (0)  (0)  (0)  (0)
          (0)   (0)  (1e6) (0)  (0)  (0)
          (0)   (0)   (0) (1e6) (0)  (0)
          (0)   (0)   (0)  (0) (1e6) (0)
          (0)   (0)   (0)  (0)  (0)  (1e3);
      odom_pub_->msg_.twist.twist.linear.y  = 0;
      odom_pub_->msg_.twist.twist.linear.z  = 0;
      odom_pub_->msg_.twist.twist.angular.x = 0;
      odom_pub_->msg_.twist.twist.angular.y = 0;
      odom_pub_->msg_.twist.covariance = boost::assign::list_of
          (1e-3) (0)   (0)  (0)  (0)  (0)
          (0) (1e-3)  (0)  (0)  (0)  (0)
          (0)   (0)  (1e6) (0)  (0)  (0)
          (0)   (0)   (0) (1e6) (0)  (0)
          (0)   (0)   (0)  (0) (1e6) (0)
          (0)   (0)   (0)  (0)  (0)  (1e3);
      tf_odom_pub_.reset(new realtime_tools::RealtimePublisher<tf::tfMessage>(controller_nh, "/tf", 100));
      odom_frame.transform.translation.z = 0.0;
      odom_frame.child_frame_id = "base_footprint";
      odom_frame.header.frame_id = "odom";

      sub_command_ = controller_nh.subscribe("cmd_vel", 1, &DiffDriveController::cmdVelCallback, this);

      return true;
    }

    void update(const ros::Time& time, const ros::Duration& period)
    {
      // MOVE ROBOT
      // command the wheels according to the messages from the cmd_vel topic
      const Commands curr_cmd = *(command_.readFromRT());
      const double vel_right =
          (curr_cmd.lin + curr_cmd.ang * wheel_separation_ / 2.0)/wheel_radius_;
      const double vel_left =
          (curr_cmd.lin - curr_cmd.ang * wheel_separation_ / 2.0)/wheel_radius_;
      left_wheel_joint_.setCommand(vel_left);
      right_wheel_joint_.setCommand(vel_right);

      // PUBLISH ODOMETRY
      // try to publish
      if(odom_pub_->trylock())// && tf_odom_pub_->trylock()) // this blocks the publish of tf, wonder why
      {
        // estimate linear and angular velocity using joint information
        //----------------------------
        // get current wheel joint positions
        left_wheel_cur_pos_ = left_wheel_joint_.getPosition()*wheel_radius_;
        right_wheel_cur_pos_ = right_wheel_joint_.getPosition()*wheel_radius_;
        // estimate velocity of wheels using old and current position
        left_wheel_est_vel_ = left_wheel_cur_pos_ - left_wheel_old_pos_;
        right_wheel_est_vel_ = right_wheel_cur_pos_ - right_wheel_old_pos_;
        // update old position with current
        left_wheel_old_pos_ = left_wheel_cur_pos_;
        right_wheel_old_pos_ = right_wheel_cur_pos_;

        // compute linear and angular velocity
        const double linear = (left_wheel_est_vel_ + right_wheel_est_vel_) * 0.5 ;
        const double angular = (right_wheel_est_vel_ - left_wheel_est_vel_) / wheel_separation_;

        if(!(fabs(angular) > 1e-15) && !(fabs(linear)< 1e-15))
          return;

        if(!odometryReading_.integrate(linear, angular, time))
          return;
        // estimate speeds
        speedEstimation(odometryReading_.getLinear(), odometryReading_.getAngular());

        //----------------------------

        // populate message
        odom_pub_->msg_.header.stamp = time;
        odom_pub_->msg_.pose.pose.position.x = odometryReading_.getPos().x;
        odom_pub_->msg_.pose.pose.position.y = odometryReading_.getPos().y;
        odom_pub_->msg_.pose.pose.orientation = tf::createQuaternionMsgFromYaw(odometryReading_.getHeading());
        odom_pub_->msg_.twist.twist.linear.x  = linear_est_speed_;
        odom_pub_->msg_.twist.twist.angular.z = angular_est_speed_;

        //publish odom tf
        odom_frame.header.stamp = time;
        odom_frame.transform.translation.x = odometryReading_.getPos().x;
        odom_frame.transform.translation.y = odometryReading_.getPos().y;
        odom_frame.transform.rotation = odom_pub_->msg_.pose.pose.orientation;
        //tf_odom_pub_->msg_.transforms.clear();
        tf_odom_pub_->msg_.transforms.push_back(odom_frame);

        // release locks and publish
        odom_pub_->unlockAndPublish();
        tf_odom_pub_->unlockAndPublish();
      }
    }

    void starting(const ros::Time& time)
    {
      // set velocity to 0
      const double vel = 0.0;
      left_wheel_joint_.setCommand(vel);
      right_wheel_joint_.setCommand(vel);
    }

    void stopping(const ros::Time& time)
    {
      // set velocity to 0
      const double vel = 0.0;
      left_wheel_joint_.setCommand(vel);
      right_wheel_joint_.setCommand(vel);
    }

  private:
    std::string name_;

    struct Commands
    {
      double lin;
      double ang;
    };
    realtime_tools::RealtimeBuffer<Commands> command_;
    Commands command_struct_;
    ros::Subscriber sub_command_;

    hardware_interface::JointHandle left_wheel_joint_;
    hardware_interface::JointHandle right_wheel_joint_;

    boost::shared_ptr<realtime_tools::RealtimePublisher<nav_msgs::Odometry> > odom_pub_;
    boost::shared_ptr<realtime_tools::RealtimePublisher<tf::tfMessage> > tf_odom_pub_;

    Odometry odometryReading_;
    double wheel_separation_;
    double wheel_radius_;
    double left_wheel_old_pos_, right_wheel_old_pos_;
    double left_wheel_cur_pos_, right_wheel_cur_pos_;
    double left_wheel_est_vel_, right_wheel_est_vel_;
    double linear_est_speed_, angular_est_speed_;
    geometry_msgs::TransformStamped odom_frame;
    std::list<geometry_msgs::Point> lastSpeeds;

  private:
    void cmdVelCallback(const geometry_msgs::Twist& command)
    {
      if(isRunning())
      {
        command_struct_.ang = command.angular.z;
        command_struct_.lin = command.linear.x;
        command_.writeFromNonRT (command_struct_);
        ROS_INFO_STREAM("Added values to command. Ang: " << command_struct_.ang
                        << ", Lin: " << command_struct_.lin);
      }
      else
      {
        ROS_ERROR_NAMED(name_, "Can't accept new commands. Controller is not running.");
      }
    }

    std::string getLeafNamespace(const ros::NodeHandle& nh)
    {
      const std::string complete_ns = nh.getNamespace();
      std::size_t id = complete_ns.find_last_of("/");
      return complete_ns.substr(id + 1);
    }

    void speedEstimation(const double &linear, double const &angular)
    {
      if(lastSpeeds.size()> 10)
        lastSpeeds.pop_front();

      geometry_msgs::Point speed;
      speed.x = linear;
      speed.y = angular;
      lastSpeeds.push_back(speed);

      double averageLinearSpeed = 0.0, averageAngularSpeed = 0.0;
      std::list<geometry_msgs::Point>::const_iterator it;

      for(it=lastSpeeds.begin();it!= lastSpeeds.end(); ++it)
      {
        averageLinearSpeed += it->x;
        averageAngularSpeed += it->y;
      }

      linear_est_speed_  =  averageLinearSpeed/lastSpeeds.size();
      angular_est_speed_ =  averageAngularSpeed/lastSpeeds.size();
    }
  };

  PLUGINLIB_DECLARE_CLASS(diff_drive_controller, DiffDriveController, diff_drive_controller::DiffDriveController, controller_interface::ControllerBase);
}//namespace
<commit_msg>Moved ROS_INFO-s to ROS_DEBUG or removed. Added typedef for iterator type.<commit_after>/*********************************************************************
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2013, PAL Robotics, S.L.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the Willow Garage nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *********************************************************************/

/*
 * Author: Bence Magyar
 */

#include <controller_interface/controller.h>
#include <hardware_interface/joint_command_interface.h>
#include <pluginlib/class_list_macros.h>

#include <nav_msgs/Odometry.h>
#include <tf/tfMessage.h>
#include <tf/transform_datatypes.h>

#include <urdf_parser/urdf_parser.h>

#include <realtime_tools/realtime_buffer.h>
#include <realtime_tools/realtime_publisher.h>

#include <boost/assign.hpp>

#include <diff_drive_controller/odometry.h>

namespace diff_drive_controller{

  class DiffDriveController : public controller_interface::Controller<hardware_interface::VelocityJointInterface>
  {
  public:
    bool init(hardware_interface::VelocityJointInterface* hw,
              ros::NodeHandle& root_nh,
              ros::NodeHandle &controller_nh)
    {
      name_ = getLeafNamespace(controller_nh);
      // get joint names from the parameter server
      std::string left_wheel_name, right_wheel_name;

      bool res = controller_nh.hasParam("left_wheel");
      if(!res || !controller_nh.getParam("left_wheel", left_wheel_name))
      {
        ROS_ERROR("Couldn't retrieve left wheel name from param server.");
        return false;
      }
      res = controller_nh.hasParam("right_wheel");
      if(!res || !controller_nh.getParam("right_wheel", right_wheel_name))
      {
        ROS_ERROR("Couldn't retrieve right wheel name from param server.");
        return false;
      }

      // parse robot description
      const std::string model_param_name = "/robot_description";
      res = root_nh.hasParam(model_param_name);
      std::string robot_model_str="";
      if(!res || !root_nh.getParam(model_param_name,robot_model_str))
      {
        ROS_ERROR("Robot descripion couldn't be retrieved from param server.");
        return false;
      }

      boost::shared_ptr<urdf::ModelInterface> model_ptr(urdf::parseURDF(robot_model_str));
      boost::shared_ptr<const urdf::Joint> wheelJointPtr(model_ptr->getJoint(left_wheel_name));
      if(!wheelJointPtr.get())
      {
        ROS_ERROR_STREAM(left_wheel_name << " couldn't be retrieved from model description");
        return false;
      }

      wheel_radius_ = fabs(wheelJointPtr->parent_to_joint_origin_transform.position.z);
      wheel_separation_ = 2.0 * fabs(wheelJointPtr->parent_to_joint_origin_transform.position.y);
      ROS_DEBUG_STREAM("Odometry params : wheel separation " << wheel_separation_
                      << ", wheel radius " << wheel_radius_);

      // get the joint object to use in the realtime loop
      ROS_DEBUG_STREAM("Adding left wheel with joint name: " << left_wheel_name
                      << " and right wheel with joint name: " << right_wheel_name);
      left_wheel_joint_ = hw->getHandle(left_wheel_name);  // throws on failure
      right_wheel_joint_ = hw->getHandle(right_wheel_name);  // throws on failure

      // setup odometry realtime publisher + odom message constant fields
      odom_pub_.reset(new realtime_tools::RealtimePublisher<nav_msgs::Odometry>(controller_nh, "odom", 100));
      odom_pub_->msg_.header.frame_id = "odom";
      odom_pub_->msg_.pose.pose.position.z = 0;
      odom_pub_->msg_.pose.covariance = boost::assign::list_of
          (1e-3) (0)   (0)  (0)  (0)  (0)
          (0) (1e-3)  (0)  (0)  (0)  (0)
          (0)   (0)  (1e6) (0)  (0)  (0)
          (0)   (0)   (0) (1e6) (0)  (0)
          (0)   (0)   (0)  (0) (1e6) (0)
          (0)   (0)   (0)  (0)  (0)  (1e3);
      odom_pub_->msg_.twist.twist.linear.y  = 0;
      odom_pub_->msg_.twist.twist.linear.z  = 0;
      odom_pub_->msg_.twist.twist.angular.x = 0;
      odom_pub_->msg_.twist.twist.angular.y = 0;
      odom_pub_->msg_.twist.covariance = boost::assign::list_of
          (1e-3) (0)   (0)  (0)  (0)  (0)
          (0) (1e-3)  (0)  (0)  (0)  (0)
          (0)   (0)  (1e6) (0)  (0)  (0)
          (0)   (0)   (0) (1e6) (0)  (0)
          (0)   (0)   (0)  (0) (1e6) (0)
          (0)   (0)   (0)  (0)  (0)  (1e3);
      tf_odom_pub_.reset(new realtime_tools::RealtimePublisher<tf::tfMessage>(controller_nh, "/tf", 100));
      odom_frame.transform.translation.z = 0.0;
      odom_frame.child_frame_id = "base_footprint";
      odom_frame.header.frame_id = "odom";

      sub_command_ = controller_nh.subscribe("cmd_vel", 1, &DiffDriveController::cmdVelCallback, this);

      return true;
    }

    void update(const ros::Time& time, const ros::Duration& period)
    {
      // MOVE ROBOT
      // command the wheels according to the messages from the cmd_vel topic
      const Commands curr_cmd = *(command_.readFromRT());
      const double vel_right =
          (curr_cmd.lin + curr_cmd.ang * wheel_separation_ / 2.0)/wheel_radius_;
      const double vel_left =
          (curr_cmd.lin - curr_cmd.ang * wheel_separation_ / 2.0)/wheel_radius_;
      left_wheel_joint_.setCommand(vel_left);
      right_wheel_joint_.setCommand(vel_right);

      // PUBLISH ODOMETRY
      // try to publish
      if(odom_pub_->trylock())// && tf_odom_pub_->trylock()) // this blocks the publish of tf, wonder why
      {
        // estimate linear and angular velocity using joint information
        //----------------------------
        // get current wheel joint positions
        left_wheel_cur_pos_ = left_wheel_joint_.getPosition()*wheel_radius_;
        right_wheel_cur_pos_ = right_wheel_joint_.getPosition()*wheel_radius_;
        // estimate velocity of wheels using old and current position
        left_wheel_est_vel_ = left_wheel_cur_pos_ - left_wheel_old_pos_;
        right_wheel_est_vel_ = right_wheel_cur_pos_ - right_wheel_old_pos_;
        // update old position with current
        left_wheel_old_pos_ = left_wheel_cur_pos_;
        right_wheel_old_pos_ = right_wheel_cur_pos_;

        // compute linear and angular velocity
        const double linear = (left_wheel_est_vel_ + right_wheel_est_vel_) * 0.5 ;
        const double angular = (right_wheel_est_vel_ - left_wheel_est_vel_) / wheel_separation_;

        if(!(fabs(angular) > 1e-15) && !(fabs(linear)< 1e-15))
          return;

        if(!odometryReading_.integrate(linear, angular, time))
          return;
        // estimate speeds
        speedEstimation(odometryReading_.getLinear(), odometryReading_.getAngular());

        //----------------------------

        // populate message
        odom_pub_->msg_.header.stamp = time;
        odom_pub_->msg_.pose.pose.position.x = odometryReading_.getPos().x;
        odom_pub_->msg_.pose.pose.position.y = odometryReading_.getPos().y;
        odom_pub_->msg_.pose.pose.orientation = tf::createQuaternionMsgFromYaw(odometryReading_.getHeading());
        odom_pub_->msg_.twist.twist.linear.x  = linear_est_speed_;
        odom_pub_->msg_.twist.twist.angular.z = angular_est_speed_;

        //publish odom tf
        odom_frame.header.stamp = time;
        odom_frame.transform.translation.x = odometryReading_.getPos().x;
        odom_frame.transform.translation.y = odometryReading_.getPos().y;
        odom_frame.transform.rotation = odom_pub_->msg_.pose.pose.orientation;
        //tf_odom_pub_->msg_.transforms.clear();
        tf_odom_pub_->msg_.transforms.push_back(odom_frame);

        // release locks and publish
        odom_pub_->unlockAndPublish();
        tf_odom_pub_->unlockAndPublish();
      }
    }

    void starting(const ros::Time& time)
    {
      // set velocity to 0
      const double vel = 0.0;
      left_wheel_joint_.setCommand(vel);
      right_wheel_joint_.setCommand(vel);
    }

    void stopping(const ros::Time& time)
    {
      // set velocity to 0
      const double vel = 0.0;
      left_wheel_joint_.setCommand(vel);
      right_wheel_joint_.setCommand(vel);
    }

  private:
    std::string name_;

    struct Commands
    {
      double lin;
      double ang;
    };
    realtime_tools::RealtimeBuffer<Commands> command_;
    Commands command_struct_;
    ros::Subscriber sub_command_;

    hardware_interface::JointHandle left_wheel_joint_;
    hardware_interface::JointHandle right_wheel_joint_;

    boost::shared_ptr<realtime_tools::RealtimePublisher<nav_msgs::Odometry> > odom_pub_;
    boost::shared_ptr<realtime_tools::RealtimePublisher<tf::tfMessage> > tf_odom_pub_;

    Odometry odometryReading_;
    double wheel_separation_;
    double wheel_radius_;
    double left_wheel_old_pos_, right_wheel_old_pos_;
    double left_wheel_cur_pos_, right_wheel_cur_pos_;
    double left_wheel_est_vel_, right_wheel_est_vel_;
    double linear_est_speed_, angular_est_speed_;
    geometry_msgs::TransformStamped odom_frame;
    std::list<geometry_msgs::Point> lastSpeeds;
    typedef std::list<geometry_msgs::Point>::const_iterator speeds_it;

  private:
    void cmdVelCallback(const geometry_msgs::Twist& command)
    {
      if(isRunning())
      {
        command_struct_.ang = command.angular.z;
        command_struct_.lin = command.linear.x;
        command_.writeFromNonRT (command_struct_);
        ROS_DEBUG_STREAM("Added values to command. Ang: " << command_struct_.ang
                        << ", Lin: " << command_struct_.lin);
      }
      else
      {
        ROS_ERROR_NAMED(name_, "Can't accept new commands. Controller is not running.");
      }
    }

    std::string getLeafNamespace(const ros::NodeHandle& nh)
    {
      const std::string complete_ns = nh.getNamespace();
      std::size_t id = complete_ns.find_last_of("/");
      return complete_ns.substr(id + 1);
    }

    void speedEstimation(const double &linear, double const &angular)
    {
      if(lastSpeeds.size()> 10)
        lastSpeeds.pop_front();

      geometry_msgs::Point speed;
      speed.x = linear;
      speed.y = angular;
      lastSpeeds.push_back(speed);

      double averageLinearSpeed = 0.0, averageAngularSpeed = 0.0;
      for(speeds_it it=lastSpeeds.begin();it!= lastSpeeds.end(); ++it)
      {
        averageLinearSpeed += it->x;
        averageAngularSpeed += it->y;
      }

      linear_est_speed_  =  averageLinearSpeed/lastSpeeds.size();
      angular_est_speed_ =  averageAngularSpeed/lastSpeeds.size();
    }
  };

  PLUGINLIB_DECLARE_CLASS(diff_drive_controller, DiffDriveController, diff_drive_controller::DiffDriveController, controller_interface::ControllerBase);
}//namespace
<|endoftext|>


<commit_before>#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#define F_CPU 1000000L
#include <util/delay.h>
#include <common.hpp>
#include <am2302.hpp>
#include <sensor.hpp>
#include <vcc.hpp>
#include <interrupt/WDT.hpp>

typedef AM2302< Pin<Port<B>, 4> > Tsensor1;

unsigned char id;

static unsigned char read_eeprom(int addr)
{
	loop_until_bit_is_clear(EECR, EEPE);

	EEAR = addr;

	EECR |= _BV(EERE);

	return EEDR;
}

void send()
{
	union {
		struct {
			unsigned char len;
			unsigned char id;
			unsigned char data[0];
		};
		unsigned char raw[16];
	} data;

	VCC vccreader;
	unsigned char* dp = data.data;

	short hum, temp;
	if (Tsensor1::read(hum, temp)) {
		dp += SensorValue<Humidity>::encode(hum, dp);
		dp += SensorValue<Temperature>::encode(temp, dp);
	}

	int voltage = vccreader.read_voltage();
	dp += SensorValue<Power>::encode(voltage, dp);

	data.len = dp - data.data + 1;
	data.id = id;

	radio::select();
	radio::write_txfifo(data.raw, data.len + 1);
	radio::select();
	radio::wcmd<radio::STX>();
	radio::release();
}

static void loop();

static void radio_off()
{
	radio::select();
	radio::wcmd<radio::SPWD>();
	radio::release();

	WDTCR = _BV(WDIE) | _BV(WDP3) | _BV(WDP0);
	WDTInterrupt::set(loop);
}

static void loop()
{
	static unsigned char counter = 0;

	counter++;

	if (counter == 3) {
		short thum, ttemp;
		Tsensor1::read(thum, ttemp);
		WDTCR = _BV(WDIE) | _BV(WDP3);
	} else if (counter == 4) {
		counter = 0;
		send();
		wdt_reset();
		WDTCR = _BV(WDIE);
		WDTInterrupt::set(radio_off);
	}
}

int main()
{
	id = read_eeprom(511);

	radio::setup();
	radio_reset();

	sei();

	radio_off();

	for (;;) {
		set_sleep_mode(SLEEP_MODE_PWR_DOWN);
		sleep_mode();
		WDTInterrupt::pending();
	}
}
<commit_msg>sensor: macro for primary timeout<commit_after>#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#define F_CPU 1000000L
#include <util/delay.h>
#include <common.hpp>
#include <am2302.hpp>
#include <sensor.hpp>
#include <vcc.hpp>
#include <interrupt/WDT.hpp>

typedef AM2302< Pin<Port<B>, 4> > Tsensor1;

unsigned char id;

static unsigned char read_eeprom(int addr)
{
	loop_until_bit_is_clear(EECR, EEPE);

	EEAR = addr;

	EECR |= _BV(EERE);

	return EEDR;
}

void send()
{
	union {
		struct {
			unsigned char len;
			unsigned char id;
			unsigned char data[0];
		};
		unsigned char raw[16];
	} data;

	VCC vccreader;
	unsigned char* dp = data.data;

	short hum, temp;
	if (Tsensor1::read(hum, temp)) {
		dp += SensorValue<Humidity>::encode(hum, dp);
		dp += SensorValue<Temperature>::encode(temp, dp);
	}

	int voltage = vccreader.read_voltage();
	dp += SensorValue<Power>::encode(voltage, dp);

	data.len = dp - data.data + 1;
	data.id = id;

	radio::select();
	radio::write_txfifo(data.raw, data.len + 1);
	radio::select();
	radio::wcmd<radio::STX>();
	radio::release();
}

static void loop();

static void radio_off()
{
	radio::select();
	radio::wcmd<radio::SPWD>();
	radio::release();

	WDTCR = _BV(WDIE) | _BV(WDP3) | _BV(WDP0);
	WDTInterrupt::set(loop);
}

#define P_TIMEOUTS 3

static void loop()
{
	static unsigned char counter = 0;

	counter++;

	if (counter == P_TIMEOUTS) {
		short thum, ttemp;
		Tsensor1::read(thum, ttemp);
		WDTCR = _BV(WDIE) | _BV(WDP3);
	} else if (counter == P_TIMEOUTS+1) {
		counter = 0;
		send();
		wdt_reset();
		WDTCR = _BV(WDIE);
		WDTInterrupt::set(radio_off);
	}
}

int main()
{
	id = read_eeprom(511);

	radio::setup();
	radio_reset();

	sei();

	radio_off();

	for (;;) {
		set_sleep_mode(SLEEP_MODE_PWR_DOWN);
		sleep_mode();
		WDTInterrupt::pending();
	}
}
<|endoftext|>


<commit_before>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkFlattenable.h"
#include "SkTypeface.h"

SK_DEFINE_INST_COUNT(SkFlattenable)

///////////////////////////////////////////////////////////////////////////////

void SkFlattenable::flatten(SkFlattenableWriteBuffer&) const
{
    /*  we don't write anything at the moment, but this allows our subclasses
        to not know that, since we want them to always call INHERITED::flatten()
        in their code.
    */
}

///////////////////////////////////////////////////////////////////////////////

SkFlattenableReadBuffer::SkFlattenableReadBuffer() {
    fRCArray = NULL;
    fRCCount = 0;

    fTFArray = NULL;
    fTFCount = 0;

    fFactoryTDArray = NULL;
    fFactoryArray = NULL;
    fFactoryCount = 0;

    // Set default values. These should be explicitly set by our client
    // via setFlags() if the buffer came from serialization.
    fFlags = 0;
#ifdef SK_SCALAR_IS_FLOAT
    fFlags |= kScalarIsFloat_Flag;
#endif
    if (8 == sizeof(void*)) {
        fFlags |= kPtrIs64Bit_Flag;
    }
}

///////////////////////////////////////////////////////////////////////////////

SkFlattenableWriteBuffer::SkFlattenableWriteBuffer() {
    fFlags = (Flags)0;
    fRCSet = NULL;
    fTFSet = NULL;
    fFactorySet = NULL;
}

SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() {
    SkSafeUnref(fRCSet);
    SkSafeUnref(fTFSet);
    SkSafeUnref(fFactorySet);
}

SkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) {
    SkRefCnt_SafeAssign(fRCSet, rec);
    return rec;
}

SkRefCntSet* SkFlattenableWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
    SkRefCnt_SafeAssign(fTFSet, rec);
    return rec;
}

SkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
    SkRefCnt_SafeAssign(fFactorySet, rec);
    return rec;
}

void SkFlattenableWriteBuffer::writeRefCnt(SkRefCnt* obj) {
    SkASSERT(!isCrossProcess());
    if (NULL == obj || NULL == fRCSet) {
        this->write32(0);
    } else {
        this->write32(fRCSet->add(obj));
    }
}

void SkFlattenableWriteBuffer::writeTypeface(SkTypeface* obj) {
    if (NULL == obj || NULL == fTFSet) {
        this->write32(0);
    } else {
        this->write32(fTFSet->add(obj));
    }
}

///////////////////////////////////////////////////////////////////////////////

SkRefCntSet::~SkRefCntSet() {
    // call this now, while our decPtr() is sill in scope
    this->reset();
}

void SkRefCntSet::incPtr(void* ptr) {
    ((SkRefCnt*)ptr)->ref();
}

void SkRefCntSet::decPtr(void* ptr) {
    ((SkRefCnt*)ptr)->unref();
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

#define MAX_PAIR_COUNT  64

struct Pair {
    const char*             fName;
    SkFlattenable::Factory  fFactory;
};

static int gCount;
static Pair gPairs[MAX_PAIR_COUNT];

void SkFlattenable::Register(const char name[], Factory factory) {
    SkASSERT(name);
    SkASSERT(factory);

    static bool gOnce;
    if (!gOnce) {
        gCount = 0;
        gOnce = true;
    }

    SkASSERT(gCount < MAX_PAIR_COUNT);

    gPairs[gCount].fName = name;
    gPairs[gCount].fFactory = factory;
    gCount += 1;
}

#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
static void report_no_entries(const char* functionName) {
    if (!gCount) {
        SkDebugf("%s has no registered name/factory pairs."
                 " Call SkGraphics::Init() at process initialization time.",
                 functionName);
    }
}
#endif

SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
    report_no_entries(__FUNCTION__);
#endif
    const Pair* pairs = gPairs;
    for (int i = gCount - 1; i >= 0; --i) {
        if (strcmp(pairs[i].fName, name) == 0) {
            return pairs[i].fFactory;
        }
    }
    return NULL;
}

const char* SkFlattenable::FactoryToName(Factory fact) {
#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
    report_no_entries(__FUNCTION__);
#endif
    const Pair* pairs = gPairs;
    for (int i = gCount - 1; i >= 0; --i) {
        if (pairs[i].fFactory == fact) {
            return pairs[i].fName;
        }
    }
    return NULL;
}
<commit_msg>Bump max flattenable from 64 to 1024. Ran into limit on Mac.<commit_after>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkFlattenable.h"
#include "SkTypeface.h"

SK_DEFINE_INST_COUNT(SkFlattenable)

///////////////////////////////////////////////////////////////////////////////

void SkFlattenable::flatten(SkFlattenableWriteBuffer&) const
{
    /*  we don't write anything at the moment, but this allows our subclasses
        to not know that, since we want them to always call INHERITED::flatten()
        in their code.
    */
}

///////////////////////////////////////////////////////////////////////////////

SkFlattenableReadBuffer::SkFlattenableReadBuffer() {
    fRCArray = NULL;
    fRCCount = 0;

    fTFArray = NULL;
    fTFCount = 0;

    fFactoryTDArray = NULL;
    fFactoryArray = NULL;
    fFactoryCount = 0;

    // Set default values. These should be explicitly set by our client
    // via setFlags() if the buffer came from serialization.
    fFlags = 0;
#ifdef SK_SCALAR_IS_FLOAT
    fFlags |= kScalarIsFloat_Flag;
#endif
    if (8 == sizeof(void*)) {
        fFlags |= kPtrIs64Bit_Flag;
    }
}

///////////////////////////////////////////////////////////////////////////////

SkFlattenableWriteBuffer::SkFlattenableWriteBuffer() {
    fFlags = (Flags)0;
    fRCSet = NULL;
    fTFSet = NULL;
    fFactorySet = NULL;
}

SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() {
    SkSafeUnref(fRCSet);
    SkSafeUnref(fTFSet);
    SkSafeUnref(fFactorySet);
}

SkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) {
    SkRefCnt_SafeAssign(fRCSet, rec);
    return rec;
}

SkRefCntSet* SkFlattenableWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
    SkRefCnt_SafeAssign(fTFSet, rec);
    return rec;
}

SkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
    SkRefCnt_SafeAssign(fFactorySet, rec);
    return rec;
}

void SkFlattenableWriteBuffer::writeRefCnt(SkRefCnt* obj) {
    SkASSERT(!isCrossProcess());
    if (NULL == obj || NULL == fRCSet) {
        this->write32(0);
    } else {
        this->write32(fRCSet->add(obj));
    }
}

void SkFlattenableWriteBuffer::writeTypeface(SkTypeface* obj) {
    if (NULL == obj || NULL == fTFSet) {
        this->write32(0);
    } else {
        this->write32(fTFSet->add(obj));
    }
}

///////////////////////////////////////////////////////////////////////////////

SkRefCntSet::~SkRefCntSet() {
    // call this now, while our decPtr() is sill in scope
    this->reset();
}

void SkRefCntSet::incPtr(void* ptr) {
    ((SkRefCnt*)ptr)->ref();
}

void SkRefCntSet::decPtr(void* ptr) {
    ((SkRefCnt*)ptr)->unref();
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

#define MAX_PAIR_COUNT  1024

struct Pair {
    const char*             fName;
    SkFlattenable::Factory  fFactory;
};

static int gCount;
static Pair gPairs[MAX_PAIR_COUNT];

void SkFlattenable::Register(const char name[], Factory factory) {
    SkASSERT(name);
    SkASSERT(factory);

    static bool gOnce;
    if (!gOnce) {
        gCount = 0;
        gOnce = true;
    }

    SkASSERT(gCount < MAX_PAIR_COUNT);

    gPairs[gCount].fName = name;
    gPairs[gCount].fFactory = factory;
    gCount += 1;
}

#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
static void report_no_entries(const char* functionName) {
    if (!gCount) {
        SkDebugf("%s has no registered name/factory pairs."
                 " Call SkGraphics::Init() at process initialization time.",
                 functionName);
    }
}
#endif

SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
    report_no_entries(__FUNCTION__);
#endif
    const Pair* pairs = gPairs;
    for (int i = gCount - 1; i >= 0; --i) {
        if (strcmp(pairs[i].fName, name) == 0) {
            return pairs[i].fFactory;
        }
    }
    return NULL;
}

const char* SkFlattenable::FactoryToName(Factory fact) {
#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
    report_no_entries(__FUNCTION__);
#endif
    const Pair* pairs = gPairs;
    for (int i = gCount - 1; i >= 0; --i) {
        if (pairs[i].fFactory == fact) {
            return pairs[i].fName;
        }
    }
    return NULL;
}
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2003 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "callbacks.h"
#include "LocalPlayer.h"
#include "HUDRenderer.h"

extern LocalPlayer*	myTank;
extern HUDRenderer*	hud;

void setFlagHelp(const std::string& name, void*)
{
  if (myTank == NULL)
    return;
  static const float FlagHelpDuration = 60.0f;
  if (BZDB.isTrue(name))
    hud->setFlagHelp(myTank->getFlag(), FlagHelpDuration);
  else
    hud->setFlagHelp(Flags::Null, 0.0);
}

void setDepthBuffer(const std::string& name, void*)
{
  if (BZDB.isTrue(name)) {
    GLint value;
    glGetIntegerv(GL_DEPTH_BITS, &value);
    if (value == 0) {
      // temporarily remove ourself
      BZDB.removeCallback(name, setDepthBuffer, NULL);
      BZDB.set(name, "0");
      // add it again
      BZDB.addCallback(name, setDepthBuffer, NULL);
    }
  }
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<commit_msg>if evil dust bunnies are going to commit code for me, they could at least try to commit the right code... fixed bug where setting zbuffer var in config file would crash client -- cannot perform callback until opengl context is created and active<commit_after>/* bzflag
 * Copyright (c) 1993 - 2003 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "callbacks.h"
#include "LocalPlayer.h"
#include "HUDRenderer.h"

extern LocalPlayer*	myTank;
extern HUDRenderer*	hud;

void setFlagHelp(const std::string& name, void*)
{
  if (myTank == NULL)
    return;
  static const float FlagHelpDuration = 60.0f;
  if (BZDB.isTrue(name))
    hud->setFlagHelp(myTank->getFlag(), FlagHelpDuration);
  else
    hud->setFlagHelp(Flags::Null, 0.0);
}

void setDepthBuffer(const std::string& name, void*)
{
  /* FIXME - time dependant callback is not safe.  cannot make
   * ogl call until the pipeline/context is initialized, whereas
   * this callback is made when zbuffer is set in config file.
   * that can crash a client.
   */
#if 0
  /* if zbuffer was set and not available, unset it */
  if (BZDB.isTrue(name)) {
    GLint value;
    glGetIntegerv(GL_DEPTH_BITS, &value);
    if (value == 0) {
      // temporarily remove ourself
      BZDB.removeCallback(name, setDepthBuffer, NULL);
      BZDB.set(name, "0");
      // add it again
      BZDB.addCallback(name, setDepthBuffer, NULL);
    }
  }
#endif
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<|endoftext|>