Skip to content

Commit

Permalink
Fixed utterly broken RNG due to improper serialization of seeds.
Browse files Browse the repository at this point in the history
(Issue spotted by isionous.)
  • Loading branch information
silene committed Dec 21, 2010
1 parent 742b794 commit 390713c
Show file tree
Hide file tree
Showing 9 changed files with 21 additions and 30 deletions.
2 changes: 1 addition & 1 deletion src/mouse_events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -995,7 +995,7 @@ void mouse_handler::attack_enemy_(const map_location& att_loc

void mouse_handler::perform_attack(
map_location attacker_loc, map_location defender_loc,
int attacker_weapon, int defender_weapon, rand_rng::seed_t seed)
int attacker_weapon, int defender_weapon, int seed)
{
// this function gets it's arguments by value because the calling function
// object might get deleted in the clear callback call below, invalidating
Expand Down
2 changes: 1 addition & 1 deletion src/mouse_events.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class mouse_handler : public mouse_handler_base {

// the perform attack function called after a random seed is obtained
void perform_attack(map_location attacker_loc, map_location defender_loc,
int attacker_weapon, int defender_weapon, rand_rng::seed_t seed);
int attacker_weapon, int defender_weapon, int seed);

void show_attack_options(const unit_map::const_iterator &u);
map_location current_unit_attacks_from(const map_location& loc);
Expand Down
2 changes: 1 addition & 1 deletion src/playturn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ turn_info::PROCESS_DATA_RESULT turn_info::process_network_data(const config& cfg
network::connection from, std::deque<config>& backlog, bool skip_replay)
{
if (const config &rnd_seed = cfg.child("random_seed")) {
rand_rng::set_seed(lexical_cast<rand_rng::seed_t>(rnd_seed["seed"]));
rand_rng::set_seed(rnd_seed["seed"]);
//may call a callback function, see rand_rng::set_seed_callback
}

Expand Down
14 changes: 7 additions & 7 deletions src/random.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ static lg::log_domain log_random("random");

namespace {
rand_rng::rng *random_generator = NULL ;
rand_rng::seed_t last_seed;
int last_seed;
bool seed_valid = false;
boost::function<void (rand_rng::seed_t)> new_seed_callback;
boost::function<void (int)> new_seed_callback;
}


Expand Down Expand Up @@ -94,7 +94,7 @@ void set_random_results(const config& cfg)
namespace rand_rng
{

void set_seed(seed_t seed)
void set_seed(int seed)
{
LOG_RND << "set_seed with " << seed << "\n";
assert(random_generator!=NULL);
Expand All @@ -111,7 +111,7 @@ void invalidate_seed()
{
LOG_RND << "invalidate_seed\n";
assert(random_generator!=NULL);
last_seed = rand();
last_seed = rand() & 0x7FFFFFFF;
if (has_valid_seed()) { //aka SRNG is disabled
random_generator->set_seed(last_seed);
}
Expand All @@ -124,12 +124,12 @@ bool has_valid_seed()
return (network::nconnections() == 0) || seed_valid;
}

seed_t get_last_seed()
int get_last_seed()
{
return last_seed;
}

void set_new_seed_callback(boost::function<void (seed_t)> f)
void set_new_seed_callback(boost::function<void (int)> f)
{
DBG_RND << "set_new_seed_callback\n";
new_seed_callback = f;
Expand Down Expand Up @@ -219,7 +219,7 @@ void rng::set_random(config* random)
return;
}

void rng::set_seed(seed_t seed)
void rng::set_seed(int seed)
{
LOG_RND << "Set random seed to " << seed << "\n";
generator_.seed_random(seed, 0);
Expand Down
2 changes: 0 additions & 2 deletions src/random.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ void set_random_results(const config& cfg);
namespace rand_rng
{

typedef unsigned int seed_t;

class rng;

struct set_random_generator {
Expand Down
17 changes: 5 additions & 12 deletions src/replay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,10 @@ void replay::add_attack(const map_location& a, const map_location& b,
add_unit_checksum(b,current_);
}

void replay::add_seed(const char* child_name, rand_rng::seed_t seed)
void replay::add_seed(const char* child_name, int seed)
{
LOG_REPLAY << "Setting seed for child type " << child_name << ": " << seed << "\n";
random()->child(child_name)["seed"] = lexical_cast<std::string>(seed);
random()->child(child_name)["seed"] = seed;
}

void replay::add_pos(const std::string& type,
Expand Down Expand Up @@ -1087,16 +1087,9 @@ bool do_replay_handle(int side_num, const std::string &do_untill)
continue;
}

try {
rand_rng::seed_t seed = lexical_cast<rand_rng::seed_t>(child["seed"]);
rand_rng::set_seed(seed);
LOG_REPLAY << "Replaying attack with seed " << seed << "\n";
} catch (bad_lexical_cast) {
std::stringstream errbuf;
errbuf << "illegal random seed for the attack " << src << " -> " << dst << '\n';
replay::process_error(errbuf.str());
continue;
}
int seed = child["seed"];
rand_rng::set_seed(child["seed"]);
LOG_REPLAY << "Replaying attack with seed " << seed << "\n";

DBG_REPLAY << "Attacker XP (before attack): " << u->experience() << "\n";

Expand Down
2 changes: 1 addition & 1 deletion src/replay.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class replay: public rand_rng::rng
int att_weapon, int def_weapon, const std::string& attacker_type_id,
const std::string& defender_type_id, int attacker_lvl,
int defender_lvl, const size_t turn, const time_of_day &t);
void add_seed(const char* child_name, rand_rng::seed_t seed);
void add_seed(const char* child_name, int seed);
void user_input(const std::string &, const config &);
void add_label(const terrain_label*);
void clear_labels(const std::string&, bool);
Expand Down
8 changes: 4 additions & 4 deletions src/rng.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class rng
const config* get_random_results();
void set_random_results(const config& cfg);

void set_seed(seed_t seed);
void set_seed(int seed);

protected:
int get_random_private(bool check);
Expand All @@ -64,7 +64,7 @@ class rng
* Set the random seed for the current random number generator, sets the seed
* as valid nd calls the new seed callback if set
*/
void set_seed(seed_t seed);
void set_seed(int seed);

/**
* Mark the RNG seed as invalid
Expand All @@ -80,15 +80,15 @@ bool has_valid_seed();
/**
* Get the last seed the RNG was seeded with in set_seed
*/
seed_t get_last_seed();
int get_last_seed();

/**
* Set the callback for a function that will be called on subsequent set_seed
* calls.
* @todo needs a reliable way of clearing the callback when things don't go as
* normal (e.g. player quit the game while the callback is set)
*/
void set_new_seed_callback(boost::function<void (seed_t)> f);
void set_new_seed_callback(boost::function<void (int)> f);

/**
* Clear the new seed callback
Expand Down
2 changes: 1 addition & 1 deletion src/server/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,7 @@ bool game::process_turn(simple_wml::document& data, const player_map::const_iter
}
for (command = commands.begin(); command != commands.end(); ++command) {
if (simple_wml::node* attack = (**command).child("attack")) {
int seed = rand();
int seed = rand() & 0x7FFFFFFF;
attack->set_attr_int("seed", seed);
simple_wml::document doc;
simple_wml::node& rs = doc.root().add_child("random_seed");
Expand Down

0 comments on commit 390713c

Please sign in to comment.