use lazy-evaluation to auto-store units

This commit is contained in:
Patrick Parker 2007-02-24 08:57:38 +00:00
parent b1e102291a
commit 31c41edcff
6 changed files with 135 additions and 41 deletions

View file

@ -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;

View file

@ -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);
}

View file

@ -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; }

View file

@ -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"];

View file

@ -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';
}
}

View file

@ -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