mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-11 09:34:34 +00:00
182 lines
5.3 KiB
C++
182 lines
5.3 KiB
C++
/*
|
|
Copyright (C) 2008 - 2013 by David White <dave@whitevine.net>
|
|
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY.
|
|
|
|
See the COPYING file for more details.
|
|
*/
|
|
|
|
#ifndef FORMULA_CALLABLE_HPP_INCLUDED
|
|
#define FORMULA_CALLABLE_HPP_INCLUDED
|
|
|
|
#include "reference_counted_object.hpp"
|
|
#include "variant.hpp"
|
|
|
|
namespace game_logic
|
|
{
|
|
|
|
enum FORMULA_ACCESS_TYPE { FORMULA_READ_ONLY, FORMULA_WRITE_ONLY, FORMULA_READ_WRITE };
|
|
struct formula_input {
|
|
std::string name;
|
|
FORMULA_ACCESS_TYPE access;
|
|
explicit formula_input(const std::string& name, FORMULA_ACCESS_TYPE access=FORMULA_READ_WRITE)
|
|
: name(name), access(access)
|
|
{}
|
|
};
|
|
|
|
//interface for objects that can have formulae run on them
|
|
class formula_callable : public reference_counted_object {
|
|
public:
|
|
explicit formula_callable(bool has_self=true) : type_(FORMULA_C), has_self_(has_self)
|
|
{}
|
|
|
|
variant query_value(const std::string& key) const {
|
|
if(has_self_ && key == "self") {
|
|
return variant(this);
|
|
}
|
|
return get_value(key);
|
|
}
|
|
|
|
void mutate_value(const std::string& key, const variant& value) {
|
|
set_value(key, value);
|
|
}
|
|
|
|
std::vector<formula_input> inputs() const {
|
|
std::vector<formula_input> res;
|
|
get_inputs(&res);
|
|
return res;
|
|
}
|
|
|
|
bool equals(const formula_callable* other) const {
|
|
return do_compare(other) == 0;
|
|
}
|
|
|
|
bool less(const formula_callable* other) const {
|
|
return do_compare(other) < 0;
|
|
}
|
|
|
|
virtual void get_inputs(std::vector<formula_input>* /*inputs*/) const {};
|
|
|
|
//note: this function should NOT overwrite str, but append text to it!
|
|
void serialize(std::string& str) const {
|
|
serialize_to_string(str);
|
|
}
|
|
|
|
bool has_key(const std::string& key) const
|
|
{ return !query_value(key).is_null(); }
|
|
|
|
protected:
|
|
virtual ~formula_callable() {}
|
|
|
|
virtual void set_value(const std::string& key, const variant& value);
|
|
virtual int do_compare(const formula_callable* callable) const {
|
|
if( type_ < callable->type_ )
|
|
return -1;
|
|
|
|
if( type_ > callable->type_ )
|
|
return 1;
|
|
|
|
return this < callable ? -1 : (this == callable ? 0 : 1);
|
|
}
|
|
|
|
//note: this function should NOT overwrite str, but append text to it!
|
|
virtual void serialize_to_string(std::string& /*str*/) const {
|
|
throw type_error("Tried to serialize type which cannot be serialized");
|
|
}
|
|
|
|
//priority for objects that are derived from this class, used in do_compare
|
|
//when comparing objects of different types
|
|
//for example: formula_callable < terrain_callable < unit_type_callable ...
|
|
enum TYPE { FORMULA_C, TERRAIN_C, LOCATION_C, UNIT_TYPE_C, UNIT_C,
|
|
ATTACK_TYPE_C, MOVE_PARTIAL_C, MOVE_C, ATTACK_C, MOVE_MAP_C };
|
|
|
|
TYPE type_;
|
|
private:
|
|
virtual variant get_value(const std::string& key) const = 0;
|
|
bool has_self_;
|
|
};
|
|
|
|
class formula_callable_no_ref_count : public formula_callable {
|
|
public:
|
|
formula_callable_no_ref_count() {
|
|
turn_reference_counting_off();
|
|
}
|
|
virtual ~formula_callable_no_ref_count() {}
|
|
};
|
|
|
|
class formula_callable_with_backup : public formula_callable {
|
|
const formula_callable& main_;
|
|
const formula_callable& backup_;
|
|
variant get_value(const std::string& key) const {
|
|
variant var = main_.query_value(key);
|
|
if(var.is_null()) {
|
|
return backup_.query_value(key);
|
|
}
|
|
|
|
return var;
|
|
}
|
|
|
|
void get_inputs(std::vector<formula_input>* inputs) const {
|
|
main_.get_inputs(inputs);
|
|
backup_.get_inputs(inputs);
|
|
}
|
|
public:
|
|
formula_callable_with_backup(const formula_callable& main, const formula_callable& backup) : formula_callable(false), main_(main), backup_(backup)
|
|
{}
|
|
};
|
|
|
|
class formula_variant_callable_with_backup : public formula_callable {
|
|
variant var_;
|
|
const formula_callable& backup_;
|
|
variant get_value(const std::string& key) const {
|
|
variant var = var_.get_member(key);
|
|
if(var.is_null()) {
|
|
return backup_.query_value(key);
|
|
}
|
|
|
|
return var;
|
|
}
|
|
|
|
void get_inputs(std::vector<formula_input>* inputs) const {
|
|
backup_.get_inputs(inputs);
|
|
}
|
|
|
|
public:
|
|
formula_variant_callable_with_backup(const variant& var, const formula_callable& backup) : formula_callable(false), var_(var), backup_(backup)
|
|
{}
|
|
};
|
|
|
|
class map_formula_callable : public formula_callable {
|
|
public:
|
|
explicit map_formula_callable(const formula_callable* fallback=NULL);
|
|
map_formula_callable& add(const std::string& key, const variant& value);
|
|
void set_fallback(const formula_callable* fallback) { fallback_ = fallback; }
|
|
bool empty() const { return values_.empty(); }
|
|
void clear() { values_.clear(); }
|
|
|
|
typedef std::map<std::string,variant>::const_iterator const_iterator;
|
|
|
|
const_iterator begin() const { return values_.begin(); }
|
|
const_iterator end() const { return values_.end(); }
|
|
|
|
private:
|
|
variant get_value(const std::string& key) const;
|
|
void get_inputs(std::vector<formula_input>* inputs) const;
|
|
void set_value(const std::string& key, const variant& value);
|
|
std::map<std::string,variant> values_;
|
|
const formula_callable* fallback_;
|
|
};
|
|
|
|
typedef boost::intrusive_ptr<map_formula_callable> map_formula_callable_ptr;
|
|
typedef boost::intrusive_ptr<const map_formula_callable> const_map_formula_callable_ptr;
|
|
|
|
}
|
|
|
|
#endif
|