Skip to content

Commit

Permalink
implement the random faction options in the connect engine, flg man
Browse files Browse the repository at this point in the history
This is essentially the same implementation used in the
"Rushed By Yetis" add-on no mirror modification.
  • Loading branch information
cbeck88 committed Mar 12, 2015
1 parent d7cb138 commit 8146c42
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 7 deletions.
27 changes: 24 additions & 3 deletions src/game_initialization/connect_engine.cpp
Expand Up @@ -394,7 +394,28 @@ void connect_engine::start_game(LOAD_USERS load_users)
// Resolves the "random faction", "random gender" and "random message"
// Must be done before shuffle sides, or some cases will cause errors
BOOST_FOREACH(side_engine_ptr side, side_engines_) {
side->resolve_random();
std::vector<std::string> avoid_faction_ids;

// If we aren't resolving random factions independently at random, calculate which factions should not appear for this side.
if (params_.random_faction_mode != 0) {
BOOST_FOREACH(side_engine_ptr side2, side_engines_) {
if (!side2->flg().is_random_faction()) {
switch(params_.random_faction_mode) {
case 1: //no mirror
avoid_faction_ids.push_back(side2->flg().current_faction()["id"].str());
break;
case 2: //no ally mirror
if (side2->team() == side->team()) {// TODO: When the connect engines are fixed to allow multiple teams, this should be changed to "if side1 and side2 are allied, i.e. their list of teams has nonempty intersection"
avoid_faction_ids.push_back(side2->flg().current_faction()["id"].str());
}
break;
default:
break; // assert(false);
}
}
}
}
side->resolve_random(avoid_faction_ids);
}

// Shuffle sides (check settings and if it is a re-loaded game).
Expand Down Expand Up @@ -1168,15 +1189,15 @@ bool side_engine::swap_sides_on_drop_target(const unsigned drop_target) {
return true;
}

void side_engine::resolve_random()
void side_engine::resolve_random(const std::vector<std::string> & avoid_faction_ids)
{
if (parent_.params_.saved_game) {
return;
}

chose_random_ = flg_.is_random_faction();

flg_.resolve_random();
flg_.resolve_random(avoid_faction_ids);

LOG_MP << "side " << (index_ + 1) << ": faction=" <<
(flg_.current_faction())["name"] << ", leader=" <<
Expand Down
2 changes: 1 addition & 1 deletion src/game_initialization/connect_engine.hpp
Expand Up @@ -157,7 +157,7 @@ class side_engine

bool swap_sides_on_drop_target(const unsigned drop_target);

void resolve_random();
void resolve_random(const std::vector<std::string> & avoid_faction_ids = std::vector<std::string>());

// Resets this side to its default state.
void reset();
Expand Down
26 changes: 24 additions & 2 deletions src/game_initialization/flg_manager.cpp
Expand Up @@ -206,7 +206,16 @@ bool flg_manager::is_random_faction()
return (*current_faction_)["random_faction"].to_bool();
}

void flg_manager::resolve_random() {
// When we use a random mode like "no mirror", "no ally mirror", the list of
// faction ids to avoid is past as an argument.
// It may be that for some scenario configuration, a strict no mirror
// assignment is not possible, because there are too many sides, or some users
// have forced their faction choices to be matching, etc.
// In that case we gracefully continue by ignoring the no mirror rule and
// assigning as we would have if it were off.
// If there is still no options we throw a config error because it means the
// era is misconfigured.
void flg_manager::resolve_random(const std::vector<std::string> & avoid) {
if (is_random_faction()) {
std::vector<std::string> faction_choices, faction_excepts;

Expand All @@ -223,6 +232,7 @@ void flg_manager::resolve_random() {
// Builds the list of factions eligible for choice
// (non-random factions).
std::vector<int> nonrandom_sides;
std::vector<int> fallback_nonrandom_sides;
int num = -1;
BOOST_FOREACH(const config* i, available_factions_) {
++num;
Expand All @@ -241,10 +251,22 @@ void flg_manager::resolve_random() {
continue;
}

nonrandom_sides.push_back(num);
fallback_nonrandom_sides.push_back(num); //This side is consistent with this random faction, remember as a fallback.

if (!avoid.empty() &&
std::find(avoid.begin(), avoid.end(),
faction_id) != avoid.end()) {
continue;
}

nonrandom_sides.push_back(num); //This side is consistent with this random faction, and the avoid factions argument.
}
}

if (nonrandom_sides.empty()) {
nonrandom_sides = fallback_nonrandom_sides; // There was no way to succeed consistently with the avoid factions argument, so ignore it as a fallback.
}

if (nonrandom_sides.empty()) {
throw config::error(_("Only random sides in the current era."));
}
Expand Down
2 changes: 1 addition & 1 deletion src/game_initialization/flg_manager.hpp
Expand Up @@ -55,7 +55,7 @@ class flg_manager
void reset_gender_combo(gui::combo& combo_gender) const;

bool is_random_faction();
void resolve_random();
void resolve_random(const std::vector<std::string> & avoid); //Argument is a list of faction ids we don't want to match, used to implement random faction modes. If it is not possible to resolve then we just proceed anyways rather than give an error.

// Picks the first faction with the greater amount of data
// matching the criteria.
Expand Down

0 comments on commit 8146c42

Please sign in to comment.