Use factions, leaders and genders manager in mp::connect.

This commit is contained in:
Andrius Silinskas 2013-08-23 20:20:51 +01:00
parent 54d776d236
commit 40c7cc8dbd
7 changed files with 206 additions and 280 deletions

View File

@ -55,9 +55,9 @@ flg_manager::flg_manager(const std::vector<const config*>& era_factions,
choosable_factions_(),
choosable_leaders_(),
choosable_genders_(),
current_faction_(),
current_leader_(),
current_gender_()
current_faction_(NULL),
current_leader_("null"),
current_gender_("null")
{
init_available_factions();
init_choosable_factions();
@ -72,17 +72,26 @@ flg_manager::~flg_manager()
void flg_manager::set_current_faction(const unsigned index)
{
assert(index < choosable_factions_.size());
set_current_faction(choosable_factions_[index]);
}
void flg_manager::set_current_faction(const config* faction)
{
current_faction_ = faction;
current_faction_ = choosable_factions_[index];
update_choosable_leaders();
set_current_leader(0);
}
void flg_manager::set_current_faction(const std::string& id)
{
unsigned index = 0;
BOOST_FOREACH(const config* faction, choosable_factions_) {
if ((*faction)["id"] == id) {
break;
}
index++;
}
set_current_faction(index);
}
void flg_manager::set_current_leader(const unsigned index)
{
assert(index < choosable_leaders_.size());
@ -156,6 +165,106 @@ void flg_manager::reset_gender_combo(gui::combo& combo_gender)
combo_gender.set_selected(current_gender_index());
}
void flg_manager::resolve_random() {
bool solved_random_faction = false;
if ((*current_faction_)["random_faction"].to_bool()) {
std::vector<std::string> faction_choices, faction_excepts;
faction_choices = utils::split((*current_faction_)["choices"]);
if (faction_choices.size() == 1 && faction_choices.front() == "") {
faction_choices.clear();
}
faction_excepts = utils::split((*current_faction_)["except"]);
if (faction_excepts.size() == 1 && faction_excepts.front() == "") {
faction_excepts.clear();
}
// Builds the list of factions eligible for choice
// (non-random factions).
std::vector<int> nonrandom_sides;
int num = -1;
BOOST_FOREACH(const config* i, available_factions_) {
++num;
if (!(*i)["random_faction"].to_bool()) {
const std::string& faction_id = (*i)["id"];
if (!faction_choices.empty() &&
std::find(faction_choices.begin(), faction_choices.end(),
faction_id) == faction_choices.end()) {
continue;
}
if (!faction_excepts.empty() &&
std::find(faction_excepts.begin(), faction_excepts.end(),
faction_id) != faction_excepts.end()) {
continue;
}
nonrandom_sides.push_back(num);
}
}
if (nonrandom_sides.empty()) {
throw config::error(_("Only random sides in the current era."));
}
const int faction_index =
nonrandom_sides[rand() % nonrandom_sides.size()];
current_faction_ = available_factions_[faction_index];
update_choosable_leaders();
set_current_leader(0);
solved_random_faction = true;
}
bool solved_random_leader = false;
if (current_leader_ == "random" || solved_random_faction) {
std::vector<std::string> nonrandom_leaders;
BOOST_FOREACH(const std::string& leader, choosable_leaders_) {
if (leader != "random") {
nonrandom_leaders.push_back(leader);
}
}
if (nonrandom_leaders.empty()) {
utils::string_map i18n_symbols;
i18n_symbols["faction"] = (*current_faction_)["name"];
throw config::error(vgettext(
"Unable to find a leader type for faction $faction",
i18n_symbols));
} else {
const int lchoice = rand() % nonrandom_leaders.size();
set_current_leader(nonrandom_leaders[lchoice]);
}
solved_random_leader = true;
}
// Resolve random genders "very much" like standard unit code.
if (current_gender_ == "random" || solved_random_leader) {
const unit_type *ut = unit_types.find(current_leader_);
if (ut && !choosable_genders_.empty()) {
std::vector<std::string> nonrandom_genders;
BOOST_FOREACH(const std::string& gender, choosable_genders_) {
if (gender != "random") {
nonrandom_genders.push_back(gender);
}
}
const int gchoice = rand() % nonrandom_genders.size();
set_current_gender(nonrandom_genders[gchoice]);
} else {
utils::string_map i18n_symbols;
i18n_symbols["leader"] = current_leader_;
throw config::error(vgettext(
"Cannot obtain genders for invalid leader $leader",
i18n_symbols));
}
}
}
void flg_manager::init_available_factions()
{
BOOST_FOREACH(const config* faction, era_factions_) {
@ -173,6 +282,8 @@ void flg_manager::init_available_factions()
available_factions_.push_back(faction);
}
assert(!available_factions_.empty());
}
void flg_manager::init_choosable_factions()
@ -368,19 +479,28 @@ void flg_manager::append_leaders_from_faction(const config* faction)
leaders_to_append.end());
}
int flg_manager::current_leader_index() const
int flg_manager::faction_index(const config* faction) const
{
std::vector<const config*>::const_iterator it = std::find(
choosable_factions_.begin(), choosable_factions_.end(), faction);
assert(it != choosable_factions_.end());
return std::distance(choosable_factions_.begin(), it);
}
int flg_manager::leader_index(const std::string& leader) const
{
std::vector<std::string>::const_iterator it = std::find(
choosable_leaders_.begin(), choosable_leaders_.end(), current_leader_);
choosable_leaders_.begin(), choosable_leaders_.end(), leader);
assert(it != choosable_leaders_.end());
return std::distance(choosable_leaders_.begin(), it);
}
int flg_manager::current_gender_index() const
int flg_manager::gender_index(const std::string& gender) const
{
std::vector<std::string>::const_iterator it = std::find(
choosable_genders_.begin(), choosable_genders_.end(), current_gender_);
choosable_genders_.begin(), choosable_genders_.end(), gender);
assert(it != choosable_genders_.end());
return std::distance(choosable_genders_.begin(), it);

View File

@ -32,24 +32,43 @@ public:
~flg_manager();
void set_current_faction(const unsigned index);
void set_current_faction(const config* faction);
void set_current_faction(const std::string& id);
void set_current_faction(const config* faction)
{ set_current_faction(faction_index(faction)); }
void set_current_leader(const unsigned index);
void set_current_leader(const std::string& leader)
{ set_current_leader(leader_index(leader)); }
void set_current_gender(const unsigned index);
void set_current_gender(const std::string& gender)
{ set_current_gender(gender_index(gender)); }
// Update the status of combo: items, selection and whether
// it should be enabled or not.
void reset_leader_combo(gui::combo& combo_leader);
void reset_gender_combo(gui::combo& combo_gender);
void resolve_random();
const std::vector<const config*> available_factions() const
{ return available_factions_; }
const std::vector<const config*> choosable_factions() const
{ return choosable_factions_; }
const std::vector<std::string>& choosable_leaders() const
{ return choosable_leaders_; }
const std::vector<std::string>& choosable_genders() const
{ return choosable_genders_; }
const config& current_faction() const
{ return *current_faction_; }
const std::string& current_leader() const
{ return current_leader_; }
const std::string& current_gender() const
{ return current_gender_; }
int current_faction_index() const
{ return faction_index(current_faction_); }
private:
flg_manager(const flg_manager&);
void operator=(const flg_manager&);
@ -67,8 +86,14 @@ private:
// to a choosable factions.
void append_leaders_from_faction(const config* faction);
int current_leader_index() const;
int current_gender_index() const;
int faction_index(const config* faction) const;
int leader_index(const std::string& leader) const;
int gender_index(const std::string& gender) const;
int current_leader_index() const
{ return leader_index(current_leader_); }
int current_gender_index() const
{ return gender_index(current_gender_); }
const std::vector<const config*>& era_factions_;
@ -80,7 +105,9 @@ private:
const int color_;
// All factions which could be played by a side (including Random).
std::vector<const config*> available_factions_;
std::vector<const config*> choosable_factions_;
std::vector<std::string> choosable_leaders_;
std::vector<std::string> choosable_genders_;

View File

@ -168,15 +168,14 @@ void connect::side::process_event()
if (combo_color_.changed() && combo_color_.selected() >= 0) {
engine_->set_color(combo_color_.selected());
update_faction_combo();
update_leader_combo();
update_gender_combo();
engine_->flg().reset_leader_combo(combo_leader_);
engine_->flg().reset_gender_combo(combo_gender_);
changed_ = true;
}
if (combo_faction_.changed() && combo_faction_.selected() >= 0) {
engine_->set_current_faction(engine_->
choosable_factions()[combo_faction_.selected()]);
update_leader_combo();
update_gender_combo();
engine_->flg().set_current_faction(combo_faction_.selected());
engine_->flg().reset_leader_combo(combo_leader_);
engine_->flg().reset_gender_combo(combo_gender_);
changed_ = true;
}
if (combo_ai_algorithm_.changed() && combo_ai_algorithm_.selected() >= 0) {
@ -185,14 +184,12 @@ void connect::side::process_event()
changed_ = true;
}
if (combo_leader_.changed() && combo_leader_.selected() >= 0) {
engine_->set_current_leader(engine_->
choosable_leaders()[combo_leader_.selected()]);
update_gender_combo();
engine_->flg().set_current_leader(combo_leader_.selected());
engine_->flg().reset_gender_combo(combo_gender_);
changed_ = true;
}
if (combo_gender_.changed() && combo_gender_.selected() >= 0) {
engine_->set_current_gender(engine_->
choosable_genders()[combo_gender_.selected()]);
engine_->flg().set_current_gender(combo_gender_.selected());
changed_ = true;
}
if (combo_team_.changed() && combo_team_.selected() >= 0) {
@ -232,8 +229,8 @@ bool connect::side::changed()
void connect::side::update_ui()
{
update_faction_combo();
update_leader_combo();
update_gender_combo();
engine_->flg().reset_leader_combo(combo_leader_);
engine_->flg().reset_gender_combo(combo_gender_);
update_controller_ui();
@ -276,7 +273,7 @@ void connect::side::add_widgets_to_scrollpane(gui::scrollpane& pane, int pos)
void connect::side::update_faction_combo()
{
std::vector<std::string> factions;
BOOST_FOREACH(const config* faction, engine_->choosable_factions()) {
BOOST_FOREACH(const config* faction, engine_->flg().choosable_factions()) {
const std::string& name = (*faction)["name"];
const std::string& icon = (*faction)["image"];
if (!icon.empty()) {
@ -295,21 +292,7 @@ void connect::side::update_faction_combo()
combo_faction_.enable(factions.size() > 1 && !parent_->params().saved_game);
combo_faction_.set_items(factions);
combo_faction_.set_selected(engine_->current_faction_index());
}
void connect::side::update_leader_combo()
{
reset_leader_combo(&combo_leader_, engine_->choosable_leaders(),
engine_->current_leader(), engine_->color(),
parent_->params().saved_game);
}
void connect::side::update_gender_combo()
{
reset_gender_combo(&combo_gender_, engine_->choosable_genders(),
engine_->current_leader(), engine_->current_gender(),
engine_->color(), parent_->params().saved_game);
combo_faction_.set_selected(engine_->flg().current_faction_index());
}
void connect::side::update_controller_ui()

View File

@ -60,8 +60,6 @@ public:
private:
// Update UI methods and their helper(s).
void update_faction_combo();
void update_leader_combo();
void update_gender_combo();
void update_controller_ui();
// The mp::connect widget owning this mp::connect::side.

View File

@ -746,14 +746,7 @@ side_engine::side_engine(const config& cfg, connect_engine& parent_engine,
parent_(parent_engine),
controller_(CNTR_NETWORK),
current_controller_index_(0),
available_factions_(),
choosable_factions_(),
choosable_leaders_(),
choosable_genders_(),
controller_options_(),
current_faction_(NULL),
current_leader_("null"),
current_gender_("null"),
allow_player_(cfg["controller"] == "ai" && cfg["allow_player"].empty() ?
false : cfg["allow_player"].to_bool(true)),
allow_changes_(cfg["allow_changes"].to_bool(true)),
@ -765,7 +758,9 @@ side_engine::side_engine(const config& cfg, connect_engine& parent_engine,
income_(cfg["income"]),
current_player_(cfg["current_player"]),
player_id_(cfg["player_id"]),
ai_algorithm_()
ai_algorithm_(),
flg_(parent_.era_factions_, cfg_, parent_.params_.use_map_settings,
parent_.params_.saved_game, parent_.first_scenario_, color_)
{
update_controller_options();
@ -830,10 +825,6 @@ side_engine::side_engine(const config& cfg, connect_engine& parent_engine,
color_ = game_config::color_info(cfg["color"]).index() - 1;
}
// Initialize faction lists.
available_factions_ = init_available_factions(parent_.era_factions_, cfg_,
parent_.params_.use_map_settings, parent_.first_scenario_);
const bool has_any_recruits =
!cfg["recruit"].empty() || !cfg["previous_recruits"].empty();
if ((!cfg_.has_attribute("faction") || !parent_.first_scenario_) &&
@ -846,17 +837,14 @@ side_engine::side_engine(const config& cfg, connect_engine& parent_engine,
cfg_["faction"] = "Custom";
}
choosable_factions_ = init_choosable_factions(available_factions_, cfg_,
parent_.params_.use_map_settings, parent_.first_scenario_);
assert(!choosable_factions_.empty());
int faction_index = 0;
if (parent_.params_.use_map_settings || parent_.params_.saved_game) {
// Explicitly assign a faction, if possible.
if (choosable_factions_.size() > 1) {
faction_index = find_suitable_faction(choosable_factions_, cfg_);
if (faction_index < 0) {
faction_index = 0;
if (flg_.choosable_factions().size() > 1) {
faction_index = find_suitable_faction(flg_.choosable_factions(),
cfg_);
if (faction_index >= 0) {
flg_.set_current_faction(faction_index);
}
}
}
@ -865,9 +853,6 @@ side_engine::side_engine(const config& cfg, connect_engine& parent_engine,
if (const config& ai = cfg.child("ai")) {
ai_algorithm_ = ai["ai_algorithm"].str();
}
// Initializes leader and gender lists.
set_current_faction(choosable_factions_[faction_index]);
}
side_engine::~side_engine()
@ -882,7 +867,7 @@ config side_engine::new_config() const
// then import their new values in the config.
if (!parent_.params_.saved_game) {
// Merge the faction data to res.
res.append(*current_faction_);
res.append(flg_.current_faction());
res["faction_name"] = res["name"];
}
@ -967,9 +952,8 @@ config side_engine::new_config() const
res["allow_changes"] = !parent_.params_.saved_game && allow_changes_;
if (!parent_.params_.saved_game) {
res["type"] = (current_leader_ != "null") ? current_leader_ : "random";
res["gender"] = (current_gender_ != "null") ? current_gender_ :
"random";
res["type"] = flg_.current_leader();
res["gender"] = flg_.current_gender();
res["team_name"] = parent_.team_names_[team_];
res["user_team_name"] = parent_.user_team_names_[team_];
@ -1096,105 +1080,11 @@ void side_engine::resolve_random()
return;
}
if ((*current_faction_)["random_faction"].to_bool()) {
// Choose a random faction, and force leader to be random.
current_leader_ = "random";
flg_.resolve_random();
std::vector<std::string> faction_choices, faction_excepts;
faction_choices = utils::split((*current_faction_)["choices"]);
if (faction_choices.size() == 1 && faction_choices.front() == "") {
faction_choices.clear();
}
faction_excepts = utils::split((*current_faction_)["except"]);
if (faction_excepts.size() == 1 && faction_excepts.front() == "") {
faction_excepts.clear();
}
// Builds the list of factions eligible for choice
// (non-random factions).
std::vector<int> nonrandom_sides;
int num = -1;
BOOST_FOREACH(const config* i, available_factions_) {
++num;
if (!(*i)["random_faction"].to_bool()) {
const std::string& faction_id = (*i)["id"];
if (!faction_choices.empty() &&
std::find(faction_choices.begin(), faction_choices.end(),
faction_id) == faction_choices.end()) {
continue;
}
if (!faction_excepts.empty() &&
std::find(faction_excepts.begin(), faction_excepts.end(),
faction_id) != faction_excepts.end()) {
continue;
}
nonrandom_sides.push_back(num);
}
}
if (nonrandom_sides.empty()) {
throw config::error(_("Only random sides in the current era."));
}
const int faction_index =
nonrandom_sides[rand() % nonrandom_sides.size()];
set_current_faction(available_factions_[faction_index]);
}
LOG_MP << "FACTION" << (index_ + 1) << ": " << (*current_faction_)["name"]
<< std::endl;
bool solved_random_leader = false;
if (current_leader_ == "random") {
// Choose a random leader type, and force gender to be random.
current_gender_ = "random";
std::vector<std::string> nonrandom_leaders;
BOOST_FOREACH(const std::string& leader, choosable_leaders_) {
if (leader != "random") {
nonrandom_leaders.push_back(leader);
}
}
if (nonrandom_leaders.empty()) {
utils::string_map i18n_symbols;
i18n_symbols["faction"] = (*current_faction_)["name"];
throw config::error(vgettext(
"Unable to find a leader type for faction $faction",
i18n_symbols));
} else {
const int lchoice = rand() % nonrandom_leaders.size();
set_current_leader(nonrandom_leaders[lchoice]);
}
solved_random_leader = true;
}
// Resolve random genders "very much" like standard unit code.
if (current_gender_ == "random" || solved_random_leader) {
const unit_type *ut = unit_types.find(current_leader_);
if (ut && !choosable_genders_.empty()) {
std::vector<std::string> nonrandom_genders;
BOOST_FOREACH(const std::string& gender, choosable_genders_) {
if (gender != "random") {
nonrandom_genders.push_back(gender);
}
}
const int gchoice = rand() % nonrandom_genders.size();
set_current_gender(nonrandom_genders[gchoice]);
} else {
ERR_CF << "cannot obtain genders for invalid leader '" <<
current_leader_ << "'.\n";
current_gender_ = "null";
}
}
LOG_MP << "side " << (index_ + 1) << ": faction=" <<
(flg_.current_faction())["name"] << ", leader=" <<
flg_.current_leader() << ", gender=" << flg_.current_gender() << "\n";
}
void side_engine::reset()
@ -1203,9 +1093,7 @@ void side_engine::reset()
set_controller(parent_.default_controller_);
if (!parent_.params_.saved_game) {
set_current_faction(choosable_factions_[0]);
set_current_leader(choosable_leaders_[0]);
set_current_gender(choosable_genders_[0]);
flg_.set_current_faction((unsigned) 0);
}
}
@ -1222,16 +1110,12 @@ void side_engine::place_user(const config& data)
player_id_ = data["name"].str();
set_controller(parent_.default_controller_);
if (data.has_attribute("faction")) {
if (data["change_faction"].to_bool()) {
// Network user's data carry information about chosen
// faction, leader and genders.
BOOST_FOREACH(const config* faction, choosable_factions_) {
if ((*faction)["id"] == data["faction"]) {
set_current_faction(faction);
}
}
set_current_leader(data["leader"]);
set_current_gender(data["gender"]);
flg_.set_current_faction(data["faction"].str());
flg_.set_current_leader(data["leader"].str());
flg_.set_current_gender(data["gender"].str());
}
}
@ -1300,49 +1184,9 @@ void side_engine::set_controller(mp::controller controller)
update_current_controller_index();
}
void side_engine::set_current_faction(const config* current_faction)
{
current_faction_ = current_faction;
update_choosable_leaders();
set_current_leader(choosable_leaders_[0]);
}
void side_engine::set_current_leader(const std::string& current_leader)
{
current_leader_ = current_leader;
update_choosable_genders();
set_current_gender(choosable_genders_[0]);
}
void side_engine::set_current_gender(const std::string& current_gender)
{
current_gender_ = current_gender;
}
int side_engine::current_faction_index() const
{
int index = 0;
BOOST_FOREACH(const config* faction, choosable_factions_) {
if ((*faction)["id"] == (*current_faction_)["id"]) {
return index;
}
index++;
}
return 0;
}
void side_engine::set_faction_commandline(const std::string& faction_name)
{
BOOST_FOREACH(const config* faction, choosable_factions_) {
if ((*faction)["name"] == faction_name) {
current_faction_ = faction;
break;
}
}
flg_.set_current_faction(faction_name);
}
void side_engine::set_controller_commandline(const std::string& controller_name)
@ -1359,20 +1203,4 @@ void side_engine::set_controller_commandline(const std::string& controller_name)
player_id_.clear();
}
void side_engine::update_choosable_leaders()
{
choosable_leaders_.clear();
choosable_leaders_ = init_choosable_leaders(cfg_, current_faction_,
available_factions_, parent_.params_.use_map_settings,
parent_.params_.saved_game, parent_.first_scenario_);
}
void side_engine::update_choosable_genders()
{
choosable_genders_.clear();
choosable_genders_ = init_choosable_genders(cfg_, current_leader_,
parent_.params_.use_map_settings, parent_.params_.saved_game,
parent_.first_scenario_);
}
} // end namespace mp

View File

@ -16,6 +16,7 @@
#include "commandline_options.hpp"
#include "config.hpp"
#include "flg_manager.hpp"
#include "gamestatus.hpp"
#include "multiplayer_ui.hpp"
@ -150,12 +151,6 @@ public:
bool controller_changed(const int selection);
void set_controller(mp::controller controller);
void set_current_faction(const config* current_faction);
void set_current_leader(const std::string& current_leader);
void set_current_gender(const std::string& current_gender);
int current_faction_index() const;
// Game set up from command line helpers.
void set_faction_commandline(const std::string& faction_name);
void set_controller_commandline(const std::string& controller_name);
@ -163,17 +158,9 @@ public:
/* Setters & Getters */
std::string save_id() const { return cfg_["save_id"]; }
const std::vector<const config*>& choosable_factions()
{ return choosable_factions_; }
const std::vector<std::string>& choosable_leaders()
{ return choosable_leaders_; }
const std::vector<std::string>& choosable_genders()
{ return choosable_genders_; }
const std::vector<controller_option>& controller_options()
{ return controller_options_; }
const config& cfg() const { return cfg_; }
const std::string& current_leader() const { return current_leader_; }
const std::string& current_gender() const { return current_gender_; }
mp::controller controller() const { return controller_; }
unsigned current_controller_index() const
{ return current_controller_index_; }
@ -199,33 +186,19 @@ public:
{ return parent_.player_teams_; }
bool side_configurations_lock() const
{ return parent_.side_configurations_lock_; }
flg_manager& flg() { return flg_; }
private:
side_engine(const side_engine& engine);
void operator=(const side_engine&);
void update_choosable_leaders();
void update_choosable_genders();
config cfg_;
connect_engine& parent_;
mp::controller controller_;
unsigned current_controller_index_;
// All factions which could be played by a side (including Random).
std::vector<const config*> available_factions_;
std::vector<const config*> choosable_factions_;
std::vector<std::string> choosable_leaders_;
std::vector<std::string> choosable_genders_;
std::vector<controller_option> controller_options_;
const config* current_faction_;
std::string current_leader_;
std::string current_gender_;
const bool allow_player_;
const bool allow_changes_;
const std::string leader_id_;
@ -238,6 +211,8 @@ private:
std::string current_player_;
std::string player_id_;
std::string ai_algorithm_;
flg_manager flg_;
};
} // end namespace mp

View File

@ -87,10 +87,9 @@ void wait::leader_preview_pane::draw_contents()
loc.h - leader_pane_border * 2);
const clip_rect_setter clipper(screen, &area);
const config& side = *flg_.choosable_factions()[selection_];
std::string faction = side["faction"];
std::string faction = flg_.current_faction()["faction"];
const std::string recruits = side["recruit"];
const std::string recruits = flg_.current_faction()["recruit"];
const std::vector<std::string> recruit_list = utils::split(recruits);
std::ostringstream recruit_string;
@ -256,8 +255,6 @@ void wait::join_game(bool observe)
//if the client is allowed to choose their team, instead of having
//it set by the server, do that here.
std::string leader_choice, gender_choice;
if(allow_changes) {
events::event_context context;
@ -320,16 +317,14 @@ void wait::join_game(bool observe)
set_result(QUIT);
return;
}
leader_choice = flg.current_leader();
gender_choice = flg.current_gender();
config faction;
config& change = faction.add_child("change_faction");
change["change_faction"] = true;
change["name"] = preferences::login();
change["faction"] =
(*flg.choosable_factions()[faction_choice])["id"];
change["leader"] = leader_choice;
change["gender"] = gender_choice;
change["faction"] = flg.current_faction()["id"];
change["leader"] = flg.current_leader();
change["gender"] = flg.current_gender();
network::send_data(faction, 0);
}