checksum verification of recruitment provided by Xan

(only enabled when starting with --debug)
This commit is contained in:
Gunter Labes 2006-06-03 18:34:35 +00:00
parent 24528ae9ff
commit bd38112c4e
11 changed files with 85 additions and 13 deletions

View File

@ -305,6 +305,7 @@ bool ai_interface::recruit(const std::string& unit_name, location loc)
" gold=" << data.gold <<
((data.net_income < 0) ? "" : "+") <<
data.net_income << "\n";
recorder.add_checksum_check(loc);
return true;
} else {
const team_data data = calculate_team_data(current_team(),info_.team_num,info_.units);

View File

@ -203,6 +203,7 @@ game_controller::game_controller(int argc, char** argv)
test_mode_ = true;
} else if(val == "--debug" || val == "-d") {
game_config::debug = true;
game_config::mp_debug = true;
} else if (val.substr(0, 6) == "--log-") {
} else if(val == "--nosound") {
preferences::set_sound(false);

View File

@ -30,7 +30,7 @@ namespace game_config
int kill_experience = 8;
int leadership_bonus = 25;
const std::string version = VERSION;
bool debug = false, editor = false, ignore_replay_errors = false;
bool debug = false, editor = false, ignore_replay_errors = false, mp_debug = false;
std::string game_icon = "wesnoth-icon.png", game_title, game_logo, title_music, anonymous_music,
victory_music, defeat_music;

View File

@ -33,7 +33,7 @@ namespace game_config
extern int leadership_bonus;
extern const std::string version;
extern bool debug, editor, ignore_replay_errors;
extern bool debug, editor, ignore_replay_errors, mp_debug;
extern std::string path;

View File

@ -644,6 +644,7 @@ namespace events{
gui_->recalculate_minimap();
gui_->invalidate_game_status();
gui_->invalidate_all();
recorder.add_checksum_check(loc);
} else {
recorder.undo();
gui::show_dialog(*gui_,NULL,"",msg,gui::OK_ONLY);
@ -753,6 +754,7 @@ namespace events{
recall_list.erase(recall_list.begin()+res);
gui_->invalidate_game_status();
gui_->invalidate_all();
recorder.add_checksum_check(loc);
}
}
}
@ -895,6 +897,7 @@ namespace events{
gui_->invalidate(action.recall_loc);
gui_->draw();
recorder.add_checksum_check(action.recall_loc);
} else {
recorder.undo();
gui::show_dialog(*gui_,NULL,"",msg,gui::OK_ONLY);
@ -936,6 +939,7 @@ namespace events{
gui_->draw();
//gui_.invalidate_game_status();
//gui_.invalidate_all();
recorder.add_checksum_check(loc);
} else {
recorder.undo();
gui::show_dialog(*gui_,NULL,"",msg,gui::OK_ONLY);

View File

@ -214,6 +214,21 @@ void replay::save_game(const std::string& label, const config& snapshot,
saveInfo_.snapshot = config();
}
void replay::add_unit_checksum(const gamemap::location& loc,config* const cfg)
{
if(! game_config::mp_debug) {
return;
}
wassert(unit_map_ref);
config& cc = cfg->add_child("checksum");
loc.write(cc);
unit_map::const_iterator u = unit_map_ref->find(loc);
wassert(u != unit_map_ref->end());
std::string chk_value;
u->second.write_checksum(chk_value);
cc["value"] = chk_value;
}
void replay::add_start()
{
config* const cmd = add_command(true);
@ -286,6 +301,8 @@ void replay::add_attack(const gamemap::location& a, const gamemap::location& b,
char buf[100];
snprintf(buf,sizeof(buf),"%d",weapon);
current_->child("attack")->values["weapon"] = buf;
add_unit_checksum(a,current_);
add_unit_checksum(b,current_);
}
void replay::add_pos(const std::string& type,
@ -366,6 +383,14 @@ void replay::add_event(const std::string& name)
ev["raise"] = name;
(*cmd)["undo"] = "no";
}
void replay::add_checksum_check(const gamemap::location& loc)
{
if(! game_config::mp_debug) {
return;
}
config* const cmd = add_command();
add_unit_checksum(loc,cmd);
}
void replay::speak(const config& cfg)
{
config* const cmd = add_command(false);
@ -560,6 +585,32 @@ replay& get_replay_source()
}
}
namespace {
void check_checksums(display& disp,const unit_map& units,const config& cfg)
{
if(! game_config::mp_debug) {
return;
}
for(config::child_list::const_iterator ci = cfg.get_children("checksum").begin(); ci != cfg.get_children("checksum").end(); ++ci) {
gamemap::location loc(**ci);
unit_map::const_iterator u = units.find(loc);
if(u == units.end()) {
std::stringstream message;
message << "non existant unit to checksum at " << loc.x+1 << "," << loc.y+1 << "!";
disp.add_chat_message("verification",1,message.str(),display::MESSAGE_PRIVATE);
continue;
}
std::string check;
u->second.write_checksum(check);
if(check != (**ci)["value"]) {
std::stringstream message;
message << "checksum mismatch at " << loc.x+1 << "," << loc.y+1 << "!";
disp.add_chat_message("verification",1,message.str(),display::MESSAGE_PRIVATE);
}
}
}
}
bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
unit_map& units,
std::vector<team>& teams, int team_num, const gamestatus& state,
@ -618,7 +669,8 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
continue;
}
}
//if there is nothing more in the records
if(cfg == NULL) {
//replayer.set_skip(false);
@ -728,6 +780,7 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
current_team.spend_gold(u_type->second.cost());
LOG_NW << "-> " << (current_team.gold()) << "\n";
fix_shroud = !replayer.is_skipping();
check_checksums(disp,units,*cfg);
}
else if((child = cfg->child("recall")) != NULL) {
@ -755,6 +808,7 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
if (!game_config::ignore_replay_errors) throw replay::error();
}
fix_shroud = !replayer.is_skipping();
check_checksums(disp,units,*cfg);
}
else if((child = cfg->child("disband")) != NULL) {
@ -852,6 +906,7 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
up->first = dst;
units.add(up);
u = units.find(dst);
check_checksums(disp,units,*cfg);
if(map.is_village(dst)) {
const int orig_owner = village_owner(dst,teams) + 1;
if(orig_owner != team_num) {
@ -883,6 +938,7 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
else if((child = cfg->child("attack")) != NULL) {
const config* const destination = child->child("destination");
const config* const source = child->child("source");
check_checksums(disp,units,*cfg);
if(destination == NULL || source == NULL) {
ERR_NW << "no destination/source found in attack\n";
@ -938,8 +994,12 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
}
game_events::fire((*child)["raise"]);
} else {
ERR_NW << "unrecognized action\n";
if (!game_config::ignore_replay_errors) throw replay::error();
if(! cfg->child("checksum")) {
ERR_NW << "unrecognized action\n";
if (!game_config::ignore_replay_errors) throw replay::error();
} else {
check_checksums(disp,units,*cfg);
}
}
//Check if we should refresh the shroud, and redraw the minimap/map tiles.

View File

@ -58,6 +58,8 @@ public:
void add_rename(const std::string& name, const gamemap::location& loc);
void end_turn();
void add_event(const std::string& name);
void add_unit_checksum(const gamemap::location& loc,config* const cfg);
void add_checksum_check(const gamemap::location& loc);
void speak(const config& cfg);
std::string build_chat_log(const std::string& team) const;

View File

@ -203,7 +203,13 @@ void unit::set_game_context(const game_data* gamedata, unit_map* unitmap, const
gamestatus_ = game_status;
teams_ = teams;
}
void unit::write_checksum(std::string& str) const
{
config unit_config;
write(unit_config);
unit_config["controller"] = "";
str = unit_config.hash();
}
std::string unit::generate_description() const
{
@ -932,7 +938,6 @@ void unit::read(const config& cfg)
bool type_set = false;
id_ = "";
traits_description_ = cfg["traits_description"];
if(cfg["type"] != "" && cfg["type"] != cfg["id"]) {
wassert(gamedata_ != NULL);
std::map<std::string,unit_type>::const_iterator i = gamedata_->unit_types.find(cfg["type"]);
@ -1159,8 +1164,6 @@ void unit::write(config& cfg) const
cfg["user_description"] = custom_unit_description_;
cfg["description"] = underlying_description_;
cfg["traits_description"] = traits_description_;
if(can_recruit())
cfg["canrecruit"] = "1";

View File

@ -59,6 +59,7 @@ class unit
virtual ~unit();
void set_game_context(const game_data* gamedata, unit_map* unitmap, const gamemap* map, const gamestatus* game_status, const std::vector<team>* teams);
void write_checksum(std::string& str) const;
// Advances this unit to another type
void advance_to(const unit_type* t);

View File

@ -954,11 +954,11 @@ const std::string& unit_type::image_profile() const
return val;
}
const std::string& unit_type::unit_description() const
const t_string& unit_type::unit_description() const
{
static const std::string default_val("No description available");
static const t_string default_val("No description available");
const std::string& desc = cfg_["unit_description"];
const t_string& desc = cfg_["unit_description"];
if(desc.empty())
return default_val;
else

View File

@ -188,7 +188,7 @@ public:
const std::string& image() const;
const std::string& image_profile() const;
const std::string& unit_description() const;
const t_string& unit_description() const;
const std::vector<Uint32>& flag_rgb() const;