diff options
Diffstat (limited to 'src/include/tome')
-rw-r--r-- | src/include/tome/enum_string_map.hpp | 55 | ||||
-rw-r--r-- | src/include/tome/make_array.hpp | 13 | ||||
-rw-r--r-- | src/include/tome/pp/global_constexpr.hpp | 21 | ||||
-rw-r--r-- | src/include/tome/squelch/automatizer.hpp | 154 | ||||
-rw-r--r-- | src/include/tome/squelch/automatizer_fwd.hpp | 10 | ||||
-rw-r--r-- | src/include/tome/squelch/condition.hpp | 632 | ||||
-rw-r--r-- | src/include/tome/squelch/condition_fwd.hpp | 15 | ||||
-rw-r--r-- | src/include/tome/squelch/condition_metadata.hpp | 12 | ||||
-rw-r--r-- | src/include/tome/squelch/condition_metadata_fwd.hpp | 14 | ||||
-rw-r--r-- | src/include/tome/squelch/cursor.hpp | 50 | ||||
-rw-r--r-- | src/include/tome/squelch/cursor_fwd.hpp | 10 | ||||
-rw-r--r-- | src/include/tome/squelch/object_status.hpp | 28 | ||||
-rw-r--r-- | src/include/tome/squelch/object_status_fwd.hpp | 12 | ||||
-rw-r--r-- | src/include/tome/squelch/rule.hpp | 162 | ||||
-rw-r--r-- | src/include/tome/squelch/rule_fwd.hpp | 16 | ||||
-rw-r--r-- | src/include/tome/squelch/tree_printer.hpp | 51 | ||||
-rw-r--r-- | src/include/tome/squelch/tree_printer_fwd.hpp | 10 |
17 files changed, 1265 insertions, 0 deletions
diff --git a/src/include/tome/enum_string_map.hpp b/src/include/tome/enum_string_map.hpp new file mode 100644 index 00000000..814827fe --- /dev/null +++ b/src/include/tome/enum_string_map.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include <boost/bimap.hpp> +#include <boost/noncopyable.hpp> +#include <string> +#include <cassert> + +/** + * Bidirectional mapping between enumerated values + * and strings. + */ +template <class E> +class EnumStringMap : boost::noncopyable { + +private: + typedef boost::bimap< E, std::string > bimap_type; + typedef typename bimap_type::value_type value_type; + + bimap_type bimap; + +public: + explicit EnumStringMap(std::initializer_list< std::pair<E, const char *> > in) { + for (auto es : in) + { + bimap.insert(value_type(es.first, es.second)); + } + // Sanity check that there were no + // duplicate mappings. + assert(bimap.size() == in.size()); + } + + const char *stringify(E e) const { + auto i = bimap.left.find(e); + assert(i != bimap.left.end() && "Missing mapping for enumerated value"); + return i->second.c_str(); + } + + E parse(const char *s) const { + E e; + bool result = parse(s, &e); + assert(result && "Missing string->enum mapping"); + return e; + } + + bool parse(const char *s, E *e) const { + auto i = bimap.right.find(s); + if (i == bimap.right.end()) + { + return false; + } + + *e = i->second; + return true; + } +}; diff --git a/src/include/tome/make_array.hpp b/src/include/tome/make_array.hpp new file mode 100644 index 00000000..23cb8ac0 --- /dev/null +++ b/src/include/tome/make_array.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include <type_traits> + +/* + * Make an array of a POD type. + */ +template <typename T> T *make_array(std::size_t n) { + static_assert(std::is_pod<T>::value, "Type parameter must be POD type"); + T *array = new T[n]; + memset(array, 0, n*sizeof(T)); + return array; +} diff --git a/src/include/tome/pp/global_constexpr.hpp b/src/include/tome/pp/global_constexpr.hpp new file mode 100644 index 00000000..83168c59 --- /dev/null +++ b/src/include/tome/pp/global_constexpr.hpp @@ -0,0 +1,21 @@ +#pragma once + +/** + * Macro for declaring a global constexpr variable without + * violating the ODR and without running into the SIOF. + * + * Shamelessly cribbed from http://stackoverflow.com/a/20374473 + */ +#define PP_GLOBAL_CONSTEXPR_CONST(type, var, value) \ +namespace global_constexpr { namespace var { \ +template<class = void> \ +struct wrapper \ +{ \ + static constexpr type var = value; \ +}; \ +template<class T> \ +constexpr type wrapper<T>::var; \ +} } \ +namespace { \ +auto const& var = global_constexpr::var::wrapper<>::var; \ +} diff --git a/src/include/tome/squelch/automatizer.hpp b/src/include/tome/squelch/automatizer.hpp new file mode 100644 index 00000000..833b5648 --- /dev/null +++ b/src/include/tome/squelch/automatizer.hpp @@ -0,0 +1,154 @@ +#pragma once + +#include <boost/noncopyable.hpp> +#include <memory> +#include <jsoncons/json.hpp> +#include <vector> + +#include "tome/squelch/rule_fwd.hpp" +#include "tome/squelch/cursor_fwd.hpp" +#include "tome/squelch/tree_printer_fwd.hpp" +#include "tome/squelch/condition_fwd.hpp" +#include "../object_type_fwd.hpp" + +namespace squelch { + +/** + * Automatizer + */ +class Automatizer : public boost::noncopyable +{ +public: + Automatizer(std::shared_ptr<TreePrinter> tree_printer, + std::shared_ptr<Cursor> cursor) + : m_selected_rule(0) + , m_begin(0) + , m_tree_printer(tree_printer) + , m_cursor(cursor) + , m_rules() { + } + + /** + * Append a rule + */ + int append_rule(std::shared_ptr<Rule> rule); + + /** + * Swap two rules + */ + void swap_rules(int i, int j); + + /** + * Apply all rules to the given object + */ + bool apply_rules(object_type *o_ptr, int item_idx) const; + + /** + * Build a JSON document to represent all the rules. + */ + jsoncons::json to_json() const; + + /** + * Load rules from a JSON document. + */ + void load_json(jsoncons::json const &); + + /** + * Remove currently selected condition or rule. + */ + int remove_current_selection(); + + /** + * Reset view. + */ + void reset_view(); + + /** + * Show current rule + */ + void show_current() const; + + /** + * Scroll view up + */ + void scroll_up(); + + /** + * Scroll view down + */ + void scroll_down(); + + /** + * Scroll view left + */ + void scroll_left(); + + /** + * Scroll view right + */ + void scroll_right(); + + /** + * Move selection up + */ + void move_up(); + + /** + * Move selection down + */ + void move_down(); + + /** + * Move selection left + */ + void move_left(); + + /** + * Move selection right + */ + void move_right(); + + /** + * Add new condition to selected rule + */ + void add_new_condition(std::function<std::shared_ptr<Condition> ()> factory); + + /** + * Get rule names. + */ + std::vector<std::string> get_rule_names() const; + + /** + * Get current number of rules. + */ + int rules_count() const; + + /** + * Get the "beginning" rule. + */ + int rules_begin() const; + + /** + * Select a new rule. + */ + void select_rule(int selected_rule); + + /** + * Return selected rule index + */ + int selected_rule() const; + + /** + * Return selected rule + */ + std::shared_ptr<Rule> current_rule(); + +private: + int m_selected_rule; + int m_begin; + std::shared_ptr<TreePrinter> m_tree_printer; + std::shared_ptr<Cursor> m_cursor; + std::vector < std::shared_ptr < Rule > > m_rules; +}; + +} // namespace diff --git a/src/include/tome/squelch/automatizer_fwd.hpp b/src/include/tome/squelch/automatizer_fwd.hpp new file mode 100644 index 00000000..068f297a --- /dev/null +++ b/src/include/tome/squelch/automatizer_fwd.hpp @@ -0,0 +1,10 @@ +#ifndef H_cbf79126_fd24_4f80_8f2d_9dd69cb7010f +#define H_cbf79126_fd24_4f80_8f2d_9dd69cb7010f + +namespace squelch { + +class Automatizer; + +} // namespace + +#endif diff --git a/src/include/tome/squelch/condition.hpp b/src/include/tome/squelch/condition.hpp new file mode 100644 index 00000000..584ecb0e --- /dev/null +++ b/src/include/tome/squelch/condition.hpp @@ -0,0 +1,632 @@ +#pragma once + +#include "tome/squelch/condition_fwd.hpp" + +#include <boost/noncopyable.hpp> +#include <cstdint> +#include <functional> +#include <memory> +#include <jsoncons/json.hpp> + +#include "tome/squelch/cursor_fwd.hpp" +#include "tome/squelch/tree_printer_fwd.hpp" +#include "tome/squelch/object_status_fwd.hpp" +#include "tome/enum_string_map.hpp" +#include "../object_type_fwd.hpp" + +namespace squelch { + +/** + * Types of matches used for conditions. + */ +enum class match_type { + AND , OR , NOT , NAME , CONTAIN , + INSCRIBED, DISCOUNT, SYMBOL , STATE , STATUS , + TVAL , SVAL , RACE , SUBRACE , CLASS , + LEVEL , SKILL , ABILITY, INVENTORY, EQUIPMENT }; + +/** + * Bidirectional map between enumeration values and strings. + */ +EnumStringMap<match_type> &match_mapping(); + +/** + * Identification states an object can have: identified or not + * identified. + */ +enum class identification_state { + IDENTIFIED, NOT_IDENTIFIED }; + +/** + * Biredectional map between identification_state values and strings. + */ +EnumStringMap<identification_state> &identification_state_mapping(); + +/** + * Condition represents a tree of checks which + * can be applied to objects, the player, etc. + */ +class Condition : public boost::noncopyable +{ +public: + Condition(match_type match_) : match(match_) { + } + + void display(TreePrinter *, Cursor *) const; + + virtual bool is_match(object_type *) const = 0; + + virtual ~Condition() { + } + +public: + jsoncons::json to_json() const; + + virtual void add_child(ConditionFactory const &factory) { + // Default is to not support children. + }; + + virtual void remove_child(Condition *c) { + // Nothing to do by default. + } + + virtual std::shared_ptr<Condition> first_child() { + // No children. + return nullptr; + } + + virtual std::shared_ptr<Condition> previous_child(Condition *) { + // Default no children, so no predecessor. + return nullptr; + } + + virtual std::shared_ptr<Condition> next_child(Condition *) { + // Default no children, so no successor. + return nullptr; + } + + /** + * Parse condition from JSON + */ + static std::shared_ptr<Condition> parse_condition(jsoncons::json const &); + + /** + * Convert an (optional) condition to JSON. + */ + static jsoncons::json optional_to_json(std::shared_ptr<Condition> condition); + +protected: + virtual void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const = 0; + virtual void to_json(jsoncons::json &) const = 0; + + // What do we want to match? + match_type match; +}; + +/** + * Check for a specific TVAL + */ +class TvalCondition : public Condition +{ +public: + TvalCondition(uint8_t tval) + : Condition(match_type::TVAL) + , m_tval(tval) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(jsoncons::json &) const override; + +private: + uint8_t m_tval; +}; + +/** + * Check for object name + */ +class NameCondition : public Condition +{ +public: + NameCondition(std::string name) : + Condition(match_type::NAME), + m_name(name) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(jsoncons::json &) const override; + +private: + std::string m_name; +}; + +/** + * Check for infix of object name + */ +class ContainCondition : public Condition +{ +public: + ContainCondition(std::string contain) : + Condition(match_type::CONTAIN), + m_contain(contain) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(jsoncons::json &) const override; + +private: + std::string m_contain; +}; + +/** + * Check for specific SVAL + */ +class SvalCondition : public Condition +{ +public: + SvalCondition(uint8_t min, uint8_t max) + : Condition(match_type::SVAL) + , m_min(min) + , m_max(max) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(jsoncons::json &) const override; + +private: + uint8_t m_min; + uint8_t m_max; +}; + +/** + * Groupings of subconditions + */ +class GroupingCondition : public Condition +{ +public: + GroupingCondition(match_type match, + std::vector< std::shared_ptr<Condition> > conditions = std::vector< std::shared_ptr<Condition> >()) + : Condition(match) + , m_conditions(conditions) { + } + + virtual void add_condition(std::shared_ptr<Condition> condition) { + if (condition) + { + m_conditions.push_back(condition); + } + } + + // Child manipulation + virtual void add_child(ConditionFactory const &factory) override; + virtual void remove_child(Condition *condition) override; + virtual std::shared_ptr<Condition> first_child() override; + virtual std::shared_ptr<Condition> previous_child(Condition *) override; + virtual std::shared_ptr<Condition> next_child(Condition *current) override; + + // Parse a list of conditions from JSON property + static std::vector< std::shared_ptr<Condition> > parse_conditions(jsoncons::json const &); + +protected: + void to_json(jsoncons::json &) const override; + +protected: + std::vector< std::shared_ptr<Condition> > m_conditions; +}; + +/** + * Conditions that are AND'ed together + */ +class AndCondition : public GroupingCondition +{ +public: + AndCondition() : GroupingCondition(match_type::AND) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; +}; + +/** + * Conditions that are OR'ed together + */ +class OrCondition : public GroupingCondition +{ +public: + OrCondition() : GroupingCondition(match_type::OR) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; +}; + +/** + * Check for object status + */ +class StatusCondition : public Condition +{ +public: + StatusCondition(status_type status) + : Condition(match_type::STATUS) + , m_status(status) { + } + +public: + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(jsoncons::json &) const override; + +private: + status_type m_status; +}; + +/** + * Check for player race + */ +class RaceCondition : public Condition +{ +public: + RaceCondition(std::string race) + : Condition(match_type::RACE) + , m_race(race) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(jsoncons::json &) const override; + +private: + std::string m_race; +}; + +/** + * Check player subrace + */ +class SubraceCondition : public Condition +{ +public: + SubraceCondition(std::string subrace) + : Condition(match_type::SUBRACE) + , m_subrace(subrace) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(jsoncons::json &) const override; + +private: + std::string m_subrace; +}; + +/** + * Check player class + */ +class ClassCondition : public Condition +{ +public: + ClassCondition(std::string klass) + : Condition(match_type::CLASS) + , m_class(klass) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(jsoncons::json &) const override; + +private: + std::string m_class; +}; + +/** + * Check object inscription + */ +class InscriptionCondition : public Condition +{ +public: + InscriptionCondition(std::string inscription) + : Condition(match_type::INSCRIBED) + , m_inscription(inscription) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(jsoncons::json &) const override; + +private: + std::string m_inscription; +}; + +/** + * Check object discount + */ +class DiscountCondition : public Condition +{ +public: + DiscountCondition(int min, int max) + : Condition(match_type::DISCOUNT) + , m_min(min) + , m_max(max) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(jsoncons::json &) const override; + +private: + int m_min; + int m_max; +}; + +/** + * Check player level + */ +class LevelCondition : public Condition +{ +public: + LevelCondition(int min, int max) + : Condition(match_type::LEVEL) + , m_min(min) + , m_max(max) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(jsoncons::json &) const override; + +private: + int m_min; + int m_max; +}; + +/** + * Check player's skill level + */ +class SkillCondition : public Condition +{ +public: + SkillCondition(uint16_t skill_idx, uint16_t min, uint16_t max) + : Condition(match_type::SKILL) + , m_skill_idx(skill_idx) + , m_min(min) + , m_max(max) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(jsoncons::json &) const override; + +private: + uint16_t m_skill_idx; + uint16_t m_min; + uint16_t m_max; +}; + +/** + * Check identification state + */ +class StateCondition : public Condition +{ +public: + StateCondition(identification_state state) + : Condition(match_type::STATE) + , m_state(state) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(jsoncons::json &) const override; + +private: + identification_state m_state; +}; + +/** + * Check object symbol + */ +class SymbolCondition : public Condition +{ +public: + SymbolCondition(char symbol) + : Condition(match_type::SYMBOL) + , m_symbol(symbol) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(jsoncons::json &) const override; + +private: + char m_symbol; +}; + +/** + * Check if player has a particular ability + */ +class AbilityCondition : public Condition +{ +public: + AbilityCondition(uint16_t ability_idx) + : Condition(match_type::ABILITY) + , m_ability_idx(ability_idx) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(jsoncons::json &) const override; + +private: + uint16_t m_ability_idx; +}; + +/** + * Condition with a single subcondition + */ +class SingleSubconditionCondition : public Condition +{ +public: + SingleSubconditionCondition(match_type match, + std::shared_ptr<Condition> subcondition) + : Condition(match) + , m_subcondition(subcondition) { + } + + virtual void add_child(std::function< std::shared_ptr<Condition> () > const &factory) override; + + virtual void remove_child(Condition *c) override; + + virtual std::shared_ptr<Condition> first_child() override; + +protected: + void to_json(jsoncons::json &) const override; + + static std::shared_ptr<Condition> parse_single_subcondition( + jsoncons::json const &condition_json); + +protected: + std::shared_ptr<Condition> m_subcondition; +}; + +/** + * Condition which negates another condition + */ +class NotCondition : public SingleSubconditionCondition +{ +public: + NotCondition(std::shared_ptr<Condition> subcondition = nullptr) + : SingleSubconditionCondition(match_type::NOT, subcondition) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; +}; + +/** + * Condition which checks if player inventory contains object(s) + * satisfying another condition. + */ +class InventoryCondition : public SingleSubconditionCondition +{ +public: + InventoryCondition(std::shared_ptr<Condition> subcondition = nullptr) + : SingleSubconditionCondition(match_type::INVENTORY, subcondition) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; +}; + +/** + * Condition which checks if player equipment contains object(s) + * satisfying another condition. + */ +class EquipmentCondition : public SingleSubconditionCondition +{ +public: + EquipmentCondition(std::shared_ptr<Condition> subcondition = nullptr) + : SingleSubconditionCondition(match_type::EQUIPMENT, subcondition) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr<Condition> from_json(jsoncons::json const &); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; +}; + +} // namespace diff --git a/src/include/tome/squelch/condition_fwd.hpp b/src/include/tome/squelch/condition_fwd.hpp new file mode 100644 index 00000000..744e7884 --- /dev/null +++ b/src/include/tome/squelch/condition_fwd.hpp @@ -0,0 +1,15 @@ +#ifndef H_1122f873_e83d_4af8_b6a8_a9e8db195473 +#define H_1122f873_e83d_4af8_b6a8_a9e8db195473 + +#include <functional> +#include <memory> + +namespace squelch { + +enum class match_type : int; +class Condition; +typedef std::function< std::shared_ptr<Condition> () > ConditionFactory; + +} // namespace + +#endif diff --git a/src/include/tome/squelch/condition_metadata.hpp b/src/include/tome/squelch/condition_metadata.hpp new file mode 100644 index 00000000..fbb26bc3 --- /dev/null +++ b/src/include/tome/squelch/condition_metadata.hpp @@ -0,0 +1,12 @@ +#ifndef H_787198a1_aa3e_45c9_bc9f_fd7f490db78c +#define H_787198a1_aa3e_45c9_bc9f_fd7f490db78c + +#include "tome/squelch/condition_metadata_fwd.hpp" + +namespace squelch { + +std::shared_ptr<Condition> new_condition_interactive(); + +} // namespace + +#endif diff --git a/src/include/tome/squelch/condition_metadata_fwd.hpp b/src/include/tome/squelch/condition_metadata_fwd.hpp new file mode 100644 index 00000000..1f57481b --- /dev/null +++ b/src/include/tome/squelch/condition_metadata_fwd.hpp @@ -0,0 +1,14 @@ +#ifndef H_7922f591_bdfd_491d_8561_b11225285fea +#define H_7922f591_bdfd_491d_8561_b11225285fea + +#include "tome/squelch/condition_fwd.hpp" + +#include <memory> + +namespace squelch { + +std::shared_ptr<Condition> new_condition_interactive(); + +} // namespace + +#endif diff --git a/src/include/tome/squelch/cursor.hpp b/src/include/tome/squelch/cursor.hpp new file mode 100644 index 00000000..8dbfc6bf --- /dev/null +++ b/src/include/tome/squelch/cursor.hpp @@ -0,0 +1,50 @@ +#ifndef H_8a10111d_64a1_4af9_a85b_24ec8922d3fa +#define H_8a10111d_64a1_4af9_a85b_24ec8922d3fa + +#include <boost/noncopyable.hpp> +#include <deque> + +#include "tome/squelch/condition_fwd.hpp" + +namespace squelch { + +/** + * Cursor which maintains selected condition(s) + */ +class Cursor : public boost::noncopyable +{ +public: + bool is_selected(Condition const *condition) const; + + void push(Condition *condition) { + m_conditions.push_back(condition); + } + + Condition *pop(); + + Condition *current(); + + void clear() { + m_conditions.clear(); + } + + bool empty() const { + return m_conditions.empty(); + } + + std::size_t size() const { + return m_conditions.size(); + } + + void move_left(); + void move_right(); + void move_up(); + void move_down(); + +private: + std::deque<Condition *> m_conditions; +}; + +} // namespace + +#endif diff --git a/src/include/tome/squelch/cursor_fwd.hpp b/src/include/tome/squelch/cursor_fwd.hpp new file mode 100644 index 00000000..f07e9aa9 --- /dev/null +++ b/src/include/tome/squelch/cursor_fwd.hpp @@ -0,0 +1,10 @@ +#ifndef H_a4caa98a_1044_4192_b1af_27c2e8790cae +#define H_a4caa98a_1044_4192_b1af_27c2e8790cae + +namespace squelch { + +class Cursor; + +} // namespace + +#endif diff --git a/src/include/tome/squelch/object_status.hpp b/src/include/tome/squelch/object_status.hpp new file mode 100644 index 00000000..c52a35ea --- /dev/null +++ b/src/include/tome/squelch/object_status.hpp @@ -0,0 +1,28 @@ +#ifndef H_e3f9ebbe_ff9a_4687_a847_6101f094b483 +#define H_e3f9ebbe_ff9a_4687_a847_6101f094b483 + +#include "tome/enum_string_map.hpp" + +namespace squelch { + +/** + * Types of statuses for objects, e.g. "special" for artifacts and + * "average" for plain objects with no plusses. + */ +enum class status_type { + BAD , VERY_BAD, AVERAGE, GOOD, VERY_GOOD, + SPECIAL, TERRIBLE, NONE, CHEST_EMPTY, CHEST_DISARMED }; + +/** + * Bidirectional map between status_type values and strings. + */ +EnumStringMap<status_type> &status_mapping(); + +/** + * Find the status of an object + */ +status_type object_status(object_type *o_ptr); + +} // namespace + +#endif diff --git a/src/include/tome/squelch/object_status_fwd.hpp b/src/include/tome/squelch/object_status_fwd.hpp new file mode 100644 index 00000000..361ea2fe --- /dev/null +++ b/src/include/tome/squelch/object_status_fwd.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "../object_type_fwd.hpp" +#include "tome/enum_string_map.hpp" + +namespace squelch { + +enum class status_type; +EnumStringMap<status_type> &status_mapping(); +status_type object_status(object_type *o_ptr); + +} // namespace diff --git a/src/include/tome/squelch/rule.hpp b/src/include/tome/squelch/rule.hpp new file mode 100644 index 00000000..af86dfc8 --- /dev/null +++ b/src/include/tome/squelch/rule.hpp @@ -0,0 +1,162 @@ +#pragma once + +#include <memory> +#include <jsoncons/json.hpp> + +#include "tome/squelch/condition_fwd.hpp" +#include "tome/squelch/cursor_fwd.hpp" +#include "tome/squelch/tree_printer_fwd.hpp" +#include "tome/enum_string_map.hpp" +#include "../object_type_fwd.hpp" + +namespace squelch { + +/** + * Types of automatizer actions: destroy, pick up, and inscribe. + */ +enum class action_type { AUTO_DESTROY, AUTO_PICKUP, AUTO_INSCRIBE }; + +/** + * Bidirectional map between rule actions and strings. + */ +EnumStringMap<action_type> &action_mapping(); + +/** + * Rules are the representation of "when condition X is true, do Y". + */ +class Rule : public boost::noncopyable +{ +public: + Rule(std::string name, + action_type action, + int module_idx, + std::shared_ptr<Condition> condition) + : m_name(name) + , m_action(action) + , m_module_idx(module_idx) + , m_condition(condition) { + } + + /** + * Set the name of the rule + */ + void set_name(const std::string &new_name); + + /** + * Get the name of the rule + */ + std::string get_name() const; + + /** + * Get condition + */ + std::shared_ptr<Condition> get_condition() const; + + /** + * Add new condition using a factory to instantiate the + * condition only if the rule permits adding a condition. + */ + void add_new_condition(Cursor *cursor, + ConditionFactory const &factory); + + /** + * Remove currently selected condition + */ + void delete_selected_condition(Cursor *cursor); + + /** + * Write out tree representing rule + */ + void write_tree(TreePrinter *p, Cursor *cursor) const; + + /** + * Apply rule to object + */ + bool apply_rule(object_type *o_ptr, int item_idx) const; + + /** + * Convert rule to JSON. + */ + virtual jsoncons::json to_json() const; + + /** + * Parse rule from JSON + */ + static std::shared_ptr<Rule> parse_rule(jsoncons::json const &); + +protected: + virtual bool do_apply_rule(object_type *, int) const = 0; + virtual void do_write_tree(TreePrinter *p) const = 0; + +protected: + // Rule name + std::string m_name; + // What does the rule do? + action_type m_action; + // Which module does this rule apply to? + int m_module_idx; + // Condition to check + std::shared_ptr<Condition> m_condition; +}; + +/** + * Rule for destroying matching objects + */ +class DestroyRule : public Rule +{ +public: + DestroyRule(std::string name, + int module_idx, + std::shared_ptr<Condition> condition) + : Rule(name, action_type::AUTO_DESTROY, module_idx, condition) { + } + +protected: + virtual bool do_apply_rule(object_type *o_ptr, int item_idx) const override; + virtual void do_write_tree(TreePrinter *p) const override; +}; + +/** + * Rule for picking up matching objects + */ +class PickUpRule : public Rule +{ +public: + + PickUpRule(std::string name, + int module_idx, + std::shared_ptr<Condition> condition) + : Rule(name, action_type::AUTO_PICKUP, module_idx, condition) { + } + +protected: + virtual void do_write_tree(TreePrinter *p) const override; + virtual bool do_apply_rule(object_type *o_ptr, int item_idx) const override; +}; + +/** + * Rule for inscribing matching objects + */ +class InscribeRule : public Rule +{ +public: + InscribeRule(std::string name, + int module_idx, + std::shared_ptr<Condition> condition, + std::string inscription) + : Rule(name, action_type::AUTO_INSCRIBE, module_idx, condition) + , m_inscription(inscription) { + } + + jsoncons::json to_json() const override; + +protected: + virtual void do_write_tree(TreePrinter *p) const override; + virtual bool do_apply_rule(object_type *o_ptr, int) const override; + +private: + // Inscription to use for inscription rules. + std::string m_inscription; +}; + +} // namespace diff --git a/src/include/tome/squelch/rule_fwd.hpp b/src/include/tome/squelch/rule_fwd.hpp new file mode 100644 index 00000000..091e77ef --- /dev/null +++ b/src/include/tome/squelch/rule_fwd.hpp @@ -0,0 +1,16 @@ +#ifndef H_4a8d2cfb_182c_4138_983d_606a9ac70784 +#define H_4a8d2cfb_182c_4138_983d_606a9ac70784 + +#include "tome/enum_string_map.hpp" + +namespace squelch { + +enum class action_type; + +EnumStringMap<action_type> &action_mapping(); + +class Rule; + +} // namespace + +#endif diff --git a/src/include/tome/squelch/tree_printer.hpp b/src/include/tome/squelch/tree_printer.hpp new file mode 100644 index 00000000..c9e79af2 --- /dev/null +++ b/src/include/tome/squelch/tree_printer.hpp @@ -0,0 +1,51 @@ +#ifndef H_3d6cc652_c674_4a84_911d_e8ec35cc992a +#define H_3d6cc652_c674_4a84_911d_e8ec35cc992a + +#include <boost/noncopyable.hpp> +#include <cstdint> +#include <string> + +namespace squelch { + +/** + * Printing trees. + */ +class TreePrinter : boost::noncopyable +{ +public: + TreePrinter(); + + void indent(); + + void dedent(); + + void reset(); + + void reset_scroll(); + + void scroll_up(); + + void scroll_down(); + + void scroll_left(); + + void scroll_right(); + + void write(uint8_t color, const char *); + void write(uint8_t color, std::string const &); + +private: + int m_indent; + int m_write_out_y; + int m_write_out_x; + int m_write_out_h; + int m_write_out_w; + int m_write_y; + int m_write_x; + int m_write_off_x; + int m_write_off_y; +}; + +} // namespace + +#endif diff --git a/src/include/tome/squelch/tree_printer_fwd.hpp b/src/include/tome/squelch/tree_printer_fwd.hpp new file mode 100644 index 00000000..d7d75453 --- /dev/null +++ b/src/include/tome/squelch/tree_printer_fwd.hpp @@ -0,0 +1,10 @@ +#ifndef H_4ce68eb3_c475_4fc4_8a70_0590c16dc684 +#define H_4ce68eb3_c475_4fc4_8a70_0590c16dc684 + +namespace squelch { + +class TreePrinter; + +} // namespace + +#endif |