use lazy-evaluation to auto-store units
This commit is contained in:
parent
b1e102291a
commit
31c41edcff
6 changed files with 135 additions and 41 deletions
|
@ -1057,8 +1057,8 @@ bool event_handler::handle_event_command(const queued_event& event_info,
|
|||
std::vector<std::string>::const_iterator si;
|
||||
for(si = sides.begin(); si != sides.end(); ++si) {
|
||||
int side_num = lexical_cast_default<int>(*si,1);
|
||||
|
||||
player_info* player=state_of_game->get_player((*teams)[side_num-1].save_id());
|
||||
const std::string player_id = (*teams)[side_num-1].save_id();
|
||||
player_info* player=state_of_game->get_player(player_id);
|
||||
|
||||
if(!player)
|
||||
continue;
|
||||
|
@ -1069,6 +1069,8 @@ bool event_handler::handle_event_command(const queued_event& event_info,
|
|||
ui != player->available_units.end(); ++ui) {
|
||||
wassert(game_data_ptr != NULL);
|
||||
ui->set_game_context(game_data_ptr,units,game_map,status_ptr,teams);
|
||||
scoped_recall_unit("this_unit", player_id,
|
||||
(ui - player->available_units.begin()));
|
||||
if(game_events::unit_matches_filter(*ui, filter,gamemap::location())) {
|
||||
ui->assign_role(cfg["role"]);
|
||||
found=true;
|
||||
|
@ -1086,6 +1088,8 @@ bool event_handler::handle_event_command(const queued_event& event_info,
|
|||
ui != pi->second.available_units.end(); ++ui) {
|
||||
wassert(game_data_ptr != NULL);
|
||||
ui->set_game_context(game_data_ptr,units,game_map,status_ptr,teams);
|
||||
scoped_recall_unit("this_unit", pi->first,
|
||||
(ui - pi->second.available_units.begin()));
|
||||
if(game_events::unit_matches_filter(*ui, filter,gamemap::location())) {
|
||||
ui->assign_role(cfg["role"]);
|
||||
found=true;
|
||||
|
@ -1319,7 +1323,8 @@ bool event_handler::handle_event_command(const queued_event& event_info,
|
|||
bool unit_recalled = false;
|
||||
for(int index = 0; !unit_recalled && index < int(teams->size()); ++index) {
|
||||
LOG_NG << "for side " << index << "...\n";
|
||||
player_info* const player = state_of_game->get_player((*teams)[index].save_id());
|
||||
const std::string player_id = (*teams)[index].save_id();
|
||||
player_info* const player = state_of_game->get_player(player_id);
|
||||
|
||||
if(player == NULL) {
|
||||
ERR_NG << "player not found!\n";
|
||||
|
@ -1332,6 +1337,7 @@ bool event_handler::handle_event_command(const queued_event& event_info,
|
|||
LOG_NG << "checking unit against filter...\n";
|
||||
wassert(game_data_ptr != NULL);
|
||||
u->set_game_context(game_data_ptr,units,game_map,status_ptr,teams);
|
||||
scoped_recall_unit("this_unit", player_id, u - avail.begin());
|
||||
if(game_events::unit_matches_filter(*u, cfg,gamemap::location())) {
|
||||
gamemap::location loc = cfg_to_loc(cfg);
|
||||
unit to_recruit(*u);
|
||||
|
@ -1652,6 +1658,7 @@ bool event_handler::handle_event_command(const queued_event& event_info,
|
|||
for(std::vector<unit>::iterator j = avail_units.begin(); j != avail_units.end();) {
|
||||
wassert(game_data_ptr != NULL);
|
||||
j->set_game_context(game_data_ptr,units,game_map,status_ptr,teams);
|
||||
scoped_recall_unit("this_unit", pi->first, j - avail_units.begin());
|
||||
if(game_events::unit_matches_filter(*j, cfg,gamemap::location())) {
|
||||
j = avail_units.erase(j);
|
||||
} else {
|
||||
|
@ -1715,6 +1722,7 @@ bool event_handler::handle_event_command(const queued_event& event_info,
|
|||
for(std::vector<unit>::iterator j = avail_units.begin(); j != avail_units.end();) {
|
||||
wassert(game_data_ptr != NULL);
|
||||
j->set_game_context(game_data_ptr,units,game_map,status_ptr,teams);
|
||||
scoped_recall_unit("this_unit", pi->first, j - avail_units.begin());
|
||||
if(game_events::unit_matches_filter(*j, filter,gamemap::location()) == false) {
|
||||
++j;
|
||||
continue;
|
||||
|
@ -2090,25 +2098,8 @@ bool process_event(event_handler& handler, const queued_event& ev)
|
|||
|
||||
unit_map::iterator unit1 = units->find(ev.loc1);
|
||||
unit_map::iterator unit2 = units->find(ev.loc2);
|
||||
config tmp_cfg;
|
||||
if(unit1!= units->end()) {
|
||||
unit1->second.write(tmp_cfg);
|
||||
tmp_cfg["x"] = lexical_cast<std::string,int>(ev.loc1.x+1);
|
||||
tmp_cfg["y"] = lexical_cast<std::string,int>(ev.loc1.y+1);
|
||||
} else {
|
||||
tmp_cfg = config();
|
||||
}
|
||||
scoped_wml_variable first_unit("unit",tmp_cfg);
|
||||
|
||||
if(unit2!= units->end()) {
|
||||
unit2->second.write(tmp_cfg);
|
||||
tmp_cfg["x"] = lexical_cast<std::string,int>(ev.loc2.x+1);
|
||||
tmp_cfg["y"] = lexical_cast<std::string,int>(ev.loc2.y+1);
|
||||
} else {
|
||||
tmp_cfg = config();
|
||||
}
|
||||
scoped_wml_variable second_unit("second_unit",tmp_cfg);
|
||||
|
||||
scoped_xy_unit first_unit("unit", ev.loc1.x, ev.loc1.y, *units);
|
||||
scoped_xy_unit second_unit("second_unit", ev.loc2.x, ev.loc2.y, *units);
|
||||
|
||||
const vconfig::child_list first_filters = handler.first_arg_filters();
|
||||
vconfig::child_list::const_iterator ffi;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "preferences.hpp"
|
||||
#include "statistics.hpp"
|
||||
#include "util.hpp"
|
||||
#include "variable.hpp"
|
||||
#include "wesconfig.h"
|
||||
#include "serialization/binary_or_text.hpp"
|
||||
#include "serialization/binary_wml.hpp"
|
||||
|
@ -991,6 +992,27 @@ namespace {
|
|||
const size_t MaxLoop = 1024;
|
||||
}
|
||||
|
||||
void game_state::activate_scope_variable(std::string var_name) const
|
||||
{
|
||||
if(recursive_)
|
||||
return;
|
||||
const std::string::iterator itor = std::find(var_name.begin(),var_name.end(),'.');
|
||||
if(itor != var_name.end()) {
|
||||
var_name.erase(itor, var_name.end());
|
||||
}
|
||||
std::vector<scoped_wml_variable*>::const_reverse_iterator rit;
|
||||
for(rit = scoped_variables.rbegin(); rit != scoped_variables.rend(); ++rit) {
|
||||
if((**rit).name() == var_name) {
|
||||
recursive_ = true;
|
||||
if(!(**rit).activated()) {
|
||||
(**rit).activate();
|
||||
}
|
||||
recursive_ = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void game_state::get_variable_internal_const(const std::string& key, const config& cfg,
|
||||
const t_string** varout) const
|
||||
{
|
||||
|
@ -1121,6 +1143,7 @@ void game_state::get_variable_internal(const std::string& key, config& cfg,
|
|||
t_string& game_state::get_variable(const std::string& key)
|
||||
{
|
||||
t_string* res = NULL;
|
||||
activate_scope_variable(key);
|
||||
get_variable_internal(key, variables, &res, NULL);
|
||||
if(res != NULL) {
|
||||
return *res;
|
||||
|
@ -1133,6 +1156,7 @@ t_string& game_state::get_variable(const std::string& key)
|
|||
const t_string& game_state::get_variable_const(const std::string& key) const
|
||||
{
|
||||
const t_string* res = NULL;
|
||||
activate_scope_variable(key);
|
||||
get_variable_internal_const(key, variables, &res);
|
||||
if(res != NULL) {
|
||||
return *res;
|
||||
|
@ -1145,6 +1169,7 @@ const t_string& game_state::get_variable_const(const std::string& key) const
|
|||
config& game_state::get_variable_cfg(const std::string& key)
|
||||
{
|
||||
config* res = NULL;
|
||||
activate_scope_variable(key);
|
||||
get_variable_internal(key + ".", variables, NULL, &res);
|
||||
|
||||
if(res != NULL) {
|
||||
|
@ -1157,11 +1182,13 @@ config& game_state::get_variable_cfg(const std::string& key)
|
|||
|
||||
void game_state::set_variable(const std::string& key, const t_string& value)
|
||||
{
|
||||
activate_scope_variable(key);
|
||||
variables[key] = value;
|
||||
}
|
||||
|
||||
config& game_state::add_variable_cfg(const std::string& key, const config& value)
|
||||
{
|
||||
activate_scope_variable(key);
|
||||
return variables.add_child(key, value);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class scoped_wml_variable;
|
||||
|
||||
//an object which defines the current time of day
|
||||
struct time_of_day
|
||||
{
|
||||
|
@ -61,7 +63,7 @@ struct player_info
|
|||
class game_state : public variable_set
|
||||
{
|
||||
public:
|
||||
game_state() : difficulty("NORMAL") {}
|
||||
game_state() : difficulty("NORMAL"), recursive_(false) {}
|
||||
std::string label; //name of the game (e.g. name of save file)
|
||||
std::string version; //version game was created with.
|
||||
std::string campaign_type; //type of the game - campaign, multiplayer etc
|
||||
|
@ -81,8 +83,12 @@ public:
|
|||
player_info* get_player(const std::string& id);
|
||||
|
||||
private:
|
||||
config variables; //variables that have been set
|
||||
mutable config variables; //mutable due to lazy-evaluation
|
||||
void activate_scope_variable(std::string var_name) const;
|
||||
mutable bool recursive_; //checks for recursion in activate_scope_variable()
|
||||
public:
|
||||
std::vector<scoped_wml_variable*> scoped_variables;
|
||||
|
||||
const config& get_variables() const { return variables; }
|
||||
void set_variables(const config& vars) { variables = vars; }
|
||||
|
||||
|
|
|
@ -714,9 +714,6 @@ bool unit::has_ability_by_id(const std::string& ability) const
|
|||
|
||||
bool unit::matches_filter(const config& orig_cfg,const gamemap::location& loc, bool use_flat_tod) const
|
||||
{
|
||||
config tmp_unit;
|
||||
write(tmp_unit); // <-- performance bottleneck (maxy)
|
||||
scoped_wml_variable this_unit("this_unit",tmp_unit);
|
||||
vconfig tmp_vconf(&orig_cfg);
|
||||
config cfg = tmp_vconf.get_parsed_config();
|
||||
const std::string& description = cfg["description"];
|
||||
|
|
|
@ -15,10 +15,14 @@
|
|||
|
||||
#include "global.hpp"
|
||||
|
||||
#include "variable.hpp"
|
||||
#include "config.hpp"
|
||||
#include "log.hpp"
|
||||
#include "variable.hpp"
|
||||
#include "wassert.hpp"
|
||||
#include <iostream>
|
||||
|
||||
#define ERR_NG LOG_STREAM(err, engine)
|
||||
|
||||
namespace
|
||||
{
|
||||
// FIXME: the variable repository should be a class of variable.hpp,
|
||||
|
@ -109,23 +113,65 @@ namespace variable
|
|||
}
|
||||
}
|
||||
|
||||
scoped_wml_variable::scoped_wml_variable(const std::string var_name,const config&var_value):
|
||||
var_name_(var_name)
|
||||
|
||||
scoped_wml_variable::scoped_wml_variable(const std::string& var_name)
|
||||
: var_name_(var_name), activated_(false)
|
||||
{
|
||||
//previous_val_;
|
||||
const config::child_list& children = repos->get_variables().get_children(var_name);
|
||||
repos->scoped_variables.push_back(this);
|
||||
}
|
||||
|
||||
void scoped_wml_variable::store(const config& var_value)
|
||||
{
|
||||
const config::child_list& children = repos->get_variables().get_children(var_name_);
|
||||
for(config::child_list::const_iterator i = children.begin(); i != children.end(); ++i) {
|
||||
previous_val_.append(**i);
|
||||
}
|
||||
repos->clear_variable_cfg(var_name);
|
||||
repos->add_variable_cfg(var_name, var_value);
|
||||
repos->clear_variable_cfg(var_name_);
|
||||
repos->add_variable_cfg(var_name_, var_value);
|
||||
activated_ = true;
|
||||
}
|
||||
|
||||
scoped_wml_variable::~scoped_wml_variable()
|
||||
{
|
||||
repos->clear_variable_cfg(var_name_);
|
||||
config::child_list old_val =previous_val_.get_children(var_name_);
|
||||
for(config::child_list::iterator j=old_val.begin(); j != old_val.end() ; j++){
|
||||
repos->add_variable_cfg(var_name_,**j);
|
||||
if(activated_) {
|
||||
repos->clear_variable_cfg(var_name_);
|
||||
config::child_list old_val =previous_val_.get_children(var_name_);
|
||||
for(config::child_list::iterator j=old_val.begin(); j != old_val.end() ; j++){
|
||||
repos->add_variable_cfg(var_name_,**j);
|
||||
}
|
||||
}
|
||||
wassert(repos->scoped_variables.back() == this);
|
||||
repos->scoped_variables.pop_back();
|
||||
}
|
||||
|
||||
void scoped_xy_unit::activate()
|
||||
{
|
||||
unit_map::const_iterator itor = umap_.find(gamemap::location(x_,y_));
|
||||
if(itor != umap_.end()) {
|
||||
config tmp_cfg;
|
||||
itor->second.write(tmp_cfg);
|
||||
tmp_cfg["x"] = lexical_cast<std::string,int>(x_ + 1);
|
||||
tmp_cfg["y"] = lexical_cast<std::string,int>(y_ + 1);
|
||||
store(tmp_cfg);
|
||||
} else {
|
||||
ERR_NG << "failed to auto-store $" << name() << " at (" << x_ << ',' << y_ << ")\n";
|
||||
}
|
||||
}
|
||||
|
||||
void scoped_recall_unit::activate()
|
||||
{
|
||||
player_info* const player = repos->get_player(player_);
|
||||
if(player != NULL) {
|
||||
if(player->available_units.size() > recall_index_) {
|
||||
config tmp_cfg;
|
||||
player->available_units[recall_index_].write(tmp_cfg);
|
||||
tmp_cfg["x"] = "recall";
|
||||
tmp_cfg["y"] = "recall";
|
||||
store(tmp_cfg);
|
||||
} else {
|
||||
ERR_NG << "failed to auto-store $" << name() << " for player: " << player_
|
||||
<< " at recall index: " << recall_index_ << '\n';
|
||||
}
|
||||
} else {
|
||||
ERR_NG << "failed to auto-store $" << name() << " for player: " << player_ << '\n';
|
||||
}
|
||||
}
|
|
@ -72,13 +72,40 @@ public:
|
|||
class scoped_wml_variable
|
||||
{
|
||||
public:
|
||||
scoped_wml_variable(const std::string var_name,const config&var_value);
|
||||
scoped_wml_variable(const std::string& var_name);
|
||||
~scoped_wml_variable();
|
||||
const std::string& name() const { return var_name_; }
|
||||
virtual void activate() = 0;
|
||||
void store(const config& var_value);
|
||||
bool activated() const { return activated_; }
|
||||
private:
|
||||
config previous_val_;
|
||||
std::string var_name_;
|
||||
const std::string var_name_;
|
||||
bool activated_;
|
||||
};
|
||||
|
||||
class scoped_xy_unit : public scoped_wml_variable
|
||||
{
|
||||
public:
|
||||
scoped_xy_unit(const std::string& var_name, const int x, const int y, const unit_map& umap)
|
||||
: scoped_wml_variable(var_name), x_(x), y_(y), umap_(umap) {}
|
||||
void activate();
|
||||
private:
|
||||
const int x_, y_;
|
||||
const unit_map& umap_;
|
||||
};
|
||||
|
||||
class scoped_recall_unit : public scoped_wml_variable
|
||||
{
|
||||
public:
|
||||
scoped_recall_unit(const std::string& var_name, const std::string& player,
|
||||
unsigned int recall_index) : scoped_wml_variable(var_name), player_(player),
|
||||
recall_index_(recall_index) {}
|
||||
void activate();
|
||||
private:
|
||||
const std::string player_;
|
||||
unsigned int recall_index_;
|
||||
};
|
||||
|
||||
// Here should go a class which servers as a variable repository
|
||||
#if 0
|
||||
|
|
Loading…
Add table
Reference in a new issue