use enums instead of strings for controllers in wesnothd::game
This is not only faster, it is also easier to understand, becasue it is now obvious that every enement of side_controllers_ can only be 'human', 'ai' or 'null'. This also makes enum::parse() in MAKE_ENUM a template. This way it also works with other string classes, specially string_span from simple_wml.
This commit is contained in:
parent
4d14482159
commit
1b9c72d319
3 changed files with 33 additions and 30 deletions
|
@ -161,7 +161,8 @@ struct NAME : public enum_tag \
|
|||
PP_SEQ_FOR_EACH_I_PAIR(EXPAND_ENUMFUNC_NORMAL, str , CONTENT) \
|
||||
throw bad_enum_cast( #NAME , str); \
|
||||
} \
|
||||
bool parse (const std::string& str) \
|
||||
template<typename TStr> \
|
||||
bool parse (const TStr& str) \
|
||||
{ \
|
||||
PP_SEQ_FOR_EACH_I_PAIR(EXPAND_ENUMPARSE_NORMAL, str , CONTENT) \
|
||||
return false; \
|
||||
|
@ -207,9 +208,9 @@ struct NAME : public enum_tag \
|
|||
is >> temp; \
|
||||
try { \
|
||||
val = string_to_enum(temp); \
|
||||
} catch (const bad_enum_cast & e) {\
|
||||
} catch (const bad_enum_cast & /*e*/) {\
|
||||
is.setstate(std::ios::failbit); \
|
||||
make_enum_detail::debug_conversion_error(temp, e); \
|
||||
/*make_enum_detail::debug_conversion_error(temp, e); */\
|
||||
} \
|
||||
return is; \
|
||||
} \
|
||||
|
|
|
@ -435,14 +435,14 @@ void game::update_side_data()
|
|||
//we found invalid [side] data. Some message would be cool.
|
||||
continue;
|
||||
}
|
||||
side_controllers_[side_index] = controller.to_string();
|
||||
side_controllers_[side_index].parse(controller);
|
||||
sides_[side_index] = *user;
|
||||
side_found = true;
|
||||
}
|
||||
else if (*user == owner_ && (controller == "null")) {
|
||||
//the *user == owner_ check has no effect,
|
||||
//it's just an optimisation so that we only do this once.
|
||||
side_controllers_[side_index] = controller.to_string();
|
||||
side_controllers_[side_index].parse(controller);
|
||||
}
|
||||
}
|
||||
if (side_found) {
|
||||
|
@ -553,7 +553,7 @@ void game::change_controller(const size_t side_index,
|
|||
const std::string& side = lexical_cast_default<std::string, size_t>(side_index + 1);
|
||||
sides_[side_index] = sock;
|
||||
|
||||
if (player_left && side_controllers_[side_index] == "ai") {
|
||||
if (player_left && side_controllers_[side_index] == CONTROLLER::AI) {
|
||||
// Automatic AI side transfer.
|
||||
} else {
|
||||
if (started_) {
|
||||
|
@ -568,7 +568,7 @@ void game::change_controller(const size_t side_index,
|
|||
change.set_attr("player", player_name.c_str());
|
||||
|
||||
// Tell everyone but the new player that this side's controller changed.
|
||||
change.set_attr("controller", (side_controllers_[side_index] == "ai" ? "ai" : "human"));
|
||||
change.set_attr("controller", side_controllers_[side_index].to_cstring());
|
||||
change.set_attr("is_local", "no");
|
||||
|
||||
send_data(response, sock);
|
||||
|
@ -1010,25 +1010,25 @@ void game::handle_random_choice(const simple_wml::node&)
|
|||
void game::handle_controller_choice(const simple_wml::node& req)
|
||||
{
|
||||
const size_t side_index = req["side"].to_int() - 1;
|
||||
const std::string new_controller = req["new_controller"].to_string();
|
||||
const std::string old_controller = req["old_controller"].to_string();
|
||||
if(new_controller != "human" && new_controller != "ai" && new_controller != "null") {
|
||||
send_and_record_server_message("Could not handle [request_choice] [change_controller] with invalid controller '" + new_controller + "'");
|
||||
CONTROLLER new_controller;
|
||||
CONTROLLER old_controller;
|
||||
if(!new_controller.parse(req["new_controller"])) {
|
||||
send_and_record_server_message("Could not handle [request_choice] [change_controller] with invalid controller '" + req["new_controller"].to_string() + "'");
|
||||
return;
|
||||
}
|
||||
if(old_controller != "human" && old_controller != "ai" && old_controller != "null") {
|
||||
send_and_record_server_message("Could not handle [request_choice] [change_controller] with invalid controller '" + old_controller + "'");
|
||||
if(!old_controller.parse(req["old_controller"])) {
|
||||
send_and_record_server_message("Could not handle [request_choice] [change_controller] with invalid controller '" + req["old_controller"].to_string() + "'");
|
||||
return;
|
||||
}
|
||||
if(old_controller != this->side_controllers_[side_index]) {
|
||||
send_and_record_server_message("Found unexpected old_controller= '" + old_controller + "' in [request_choice] [change_controller]");
|
||||
send_and_record_server_message("Found unexpected old_controller= '" + old_controller.to_string() + "' in [request_choice] [change_controller]");
|
||||
}
|
||||
if(side_index >= sides_.size()) {
|
||||
send_and_record_server_message("Could not handle [request_choice] [change_controller] with invalid side '" + req["side"].to_string() + "'");
|
||||
return;
|
||||
}
|
||||
const bool was_null = this->side_controllers_[side_index] == "null";
|
||||
const bool becomes_null = new_controller == "null";
|
||||
const bool was_null = this->side_controllers_[side_index] == CONTROLLER::EMPTY;
|
||||
const bool becomes_null = new_controller == CONTROLLER::EMPTY;
|
||||
if(was_null) {
|
||||
assert(sides_[side_index] == 0);
|
||||
sides_[side_index] = current_player();
|
||||
|
@ -1042,15 +1042,15 @@ void game::handle_controller_choice(const simple_wml::node& req)
|
|||
simple_wml::node& turn = mdata->root().add_child("turn");
|
||||
simple_wml::node& command = turn.add_child("command");
|
||||
simple_wml::node& change_controller_wml = command.add_child("change_controller_wml");
|
||||
change_controller_wml.set_attr_dup("controller", new_controller.c_str());
|
||||
change_controller_wml.set_attr_dup("is_local", "yes");
|
||||
change_controller_wml.set_attr("controller", new_controller.to_cstring());
|
||||
change_controller_wml.set_attr("is_local", "yes");
|
||||
command.set_attr("from_side", "server");
|
||||
command.set_attr("dependent", "yes");
|
||||
if(sides_[side_index] != 0) {
|
||||
//calling send_to_one to 0 connect causes the package to be sended to all clients.
|
||||
wesnothd::send_to_one(*mdata, sides_[side_index], "game replay");
|
||||
}
|
||||
change_controller_wml.set_attr_dup("is_local", "no");
|
||||
change_controller_wml.set_attr("is_local", "no");
|
||||
send_data(*mdata, sides_[side_index], "game replay");
|
||||
record_data(mdata);
|
||||
}
|
||||
|
@ -1142,7 +1142,7 @@ bool game::end_turn() {
|
|||
turn_ended = true;
|
||||
}
|
||||
// Skip over empty sides.
|
||||
for (int i = 0; i < nsides_ && side_controllers_[current_side()] == "null"; ++i) {
|
||||
for (int i = 0; i < nsides_ && side_controllers_[current_side()] == CONTROLLER::EMPTY; ++i) {
|
||||
++end_turn_;
|
||||
if (current_side() == 0) {
|
||||
turn_ended = true;
|
||||
|
@ -1289,7 +1289,7 @@ bool game::remove_player(const network::connection player, const bool disconnect
|
|||
for (side_vector::iterator side = sides_.begin(); side != sides_.end(); ++side) {
|
||||
size_t side_index = side - sides_.begin();
|
||||
if (*side != player) continue;
|
||||
if (side_controllers_[side_index] == "ai") ai_transfer = true;
|
||||
if (side_controllers_[side_index] == CONTROLLER::AI) ai_transfer = true;
|
||||
|
||||
player_map::iterator o = player_info_->find(owner_);
|
||||
change_controller(side_index, owner_, username(o));
|
||||
|
@ -1306,7 +1306,7 @@ bool game::remove_player(const network::connection player, const bool disconnect
|
|||
const std::string side_drop = lexical_cast_default<std::string, size_t>(side_index + 1);
|
||||
simple_wml::document drop;
|
||||
drop.root().set_attr("side_drop", side_drop.c_str());
|
||||
drop.root().set_attr("controller", side_controllers_[side_index].c_str());
|
||||
drop.root().set_attr("controller", side_controllers_[side_index].to_cstring());
|
||||
|
||||
DBG_GAME << "*** sending side drop: \n" << drop.output() << std::endl;
|
||||
|
||||
|
@ -1654,7 +1654,7 @@ std::string game::debug_sides_info() const {
|
|||
result << "\t\t level, server\n";
|
||||
for(simple_wml::node::child_list::const_iterator s = sides.begin(); s != sides.end(); ++s) {
|
||||
result << "side " << (**s)["side"].to_int() << " :\t" << (**s)["controller"].to_string()
|
||||
<< "\t, " << side_controllers_[(**s)["side"].to_int() - 1]
|
||||
<< "\t, " << side_controllers_[(**s)["side"].to_int() - 1].to_cstring()
|
||||
<< "\t( " << sides_[(**s)["side"].to_int()-1] << ",\t"
|
||||
<< (**s)["current_player"].to_string() << " )\n";
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "../mt_rng.hpp"
|
||||
#include "../make_enum.hpp"
|
||||
|
||||
#include <boost/ptr_container/ptr_vector.hpp>
|
||||
//class player;
|
||||
|
@ -37,6 +38,13 @@ typedef std::vector<network::connection> side_vector;
|
|||
class game
|
||||
{
|
||||
public:
|
||||
MAKE_ENUM(CONTROLLER,
|
||||
(HUMAN, "human")
|
||||
(AI, "ai")
|
||||
/* NULL is alreaddy the name of a standart c++ macro */
|
||||
(EMPTY, "null")
|
||||
)
|
||||
|
||||
game(player_map& players, const network::connection host=0,
|
||||
const std::string& name="", bool save_replays=false,
|
||||
const std::string& replay_save_path="");
|
||||
|
@ -360,13 +368,7 @@ private:
|
|||
/** A vector of side owners. */
|
||||
side_vector sides_;
|
||||
|
||||
/**
|
||||
* A vector of controller strings indicating the type.
|
||||
* "human" - a side controlled by a human
|
||||
* "ai" - a side controlled by an AI
|
||||
* "null" - an empty side
|
||||
*/
|
||||
std::vector<std::string> side_controllers_;
|
||||
std::vector<CONTROLLER> side_controllers_;
|
||||
|
||||
/** Number of sides in the current scenario. */
|
||||
int nsides_;
|
||||
|
|
Loading…
Add table
Reference in a new issue