made it so non-interactive mode works well with eras

This commit is contained in:
Dave White 2004-04-29 01:49:51 +00:00
parent ab34166bb2
commit f50ee653d3
9 changed files with 79 additions and 36 deletions

View file

@ -452,6 +452,7 @@ int play_game(int argc, char** argv)
//it is all handled inside this 'if' statement
if(multiplayer_mode) {
std::string era = "era_default";
std::string scenario = "multiplayer_test";
std::map<int,std::string> side_types, side_controllers, side_algorithms;
std::map<int,string_map> side_parameters;
@ -484,6 +485,8 @@ int play_game(int argc, char** argv)
if(name == "--scenario") {
scenario = value;
} else if(name == "--era") {
era = value;
} else if(last_digit && name_head == "--controller") {
side_controllers[side] = value;
} else if(last_digit && name_head == "--algorithm") {
@ -518,9 +521,15 @@ int play_game(int argc, char** argv)
config level = *lvl;
std::vector<config*> story;
const config* const side = game_config.child("multiplayer_side");
const config* const era_cfg = game_config.find_child("era","id",era);
if(era_cfg == NULL) {
std::cerr << "Could not find era '" << era << "'\n";
return 0;
}
const config* const side = era_cfg->child("multiplayer_side");
if(side == NULL) {
std::cerr << "Could not find side\n";
std::cerr << "Could not find multiplayer side\n";
return 0;
}
@ -535,8 +544,8 @@ int play_game(int argc, char** argv)
controller = side_controllers.find(side_num),
algorithm = side_algorithms.find(side_num);
const config* side = type == side_types.end() ? game_config.child("multiplayer_side") :
game_config.find_child("multiplayer_side","type",type->second);
const config* side = type == side_types.end() ? era_cfg->child("multiplayer_side") :
era_cfg->find_child("multiplayer_side","type",type->second);
if(side == NULL) {
std::string side_name = (type == side_types.end() ? "default" : type->second);
std::cerr << "Could not find side '" << side_name << "' for side " << side_num << "\n";

View file

@ -107,6 +107,8 @@ std::set<network::connection> bad_sockets;
namespace network {
const connection null_connection = 0;
error::error(const std::string& msg, connection sock) : message(msg), socket(sock)
{
if(socket) {

View file

@ -35,6 +35,8 @@ private:
typedef int connection;
extern const connection null_connection;
//the number of peers we are connected to
size_t nconnections();

View file

@ -339,6 +339,8 @@ LEVEL_RESULT play_level(game_data& gameinfo, const config& game_config,
int player_number = 0;
std::deque<config> data_backlog;
try {
for(bool first_time = true; true; first_time = false, first_player = 0) {
player_number = 0;
@ -491,15 +493,27 @@ redo_turn:
for(;;) {
bool have_data = false;
config cfg;
const network::connection res = network::receive_data(cfg);
network::connection from = network::null_connection;
const turn_info::PROCESS_DATA_RESULT result = turn_data.process_network_data(cfg,res);
if(result == turn_info::PROCESS_RESTART_TURN) {
goto redo_turn;
} else if(result == turn_info::PROCESS_END_TURN) {
break;
if(data_backlog.empty() == false) {
have_data = true;
cfg = data_backlog.front();
data_backlog.pop_front();
} else {
from = network::receive_data(cfg);
have_data = from != network::null_connection;
}
if(have_data) {
const turn_info::PROCESS_DATA_RESULT result = turn_data.process_network_data(cfg,from,data_backlog);
if(result == turn_info::PROCESS_RESTART_TURN) {
goto redo_turn;
} else if(result == turn_info::PROCESS_END_TURN) {
break;
}
}
const int ncommand = recorder.ncommands();

View file

@ -134,7 +134,11 @@ void play_turn(game_data& gameinfo, game_state& state_of_game,
try {
config cfg;
const network::connection res = network::receive_data(cfg);
turn_data.process_network_data(cfg,res);
std::deque<config> backlog;
if(res != network::null_connection) {
turn_data.process_network_data(cfg,res,backlog);
}
turn_data.turn_slice();
} catch(end_level_exception& e) {
@ -2063,12 +2067,8 @@ unit_map::const_iterator turn_info::current_unit() const
return i;
}
turn_info::PROCESS_DATA_RESULT turn_info::process_network_data(const config& cfg, network::connection from)
turn_info::PROCESS_DATA_RESULT turn_info::process_network_data(const config& cfg, network::connection from, std::deque<config>& backlog)
{
if(from == 0) {
return PROCESS_CONTINUE;
}
if(cfg.child("observer") != NULL) {
const config::child_list& observers = cfg.get_children("observer");
for(config::child_list::const_iterator ob = observers.begin(); ob != observers.end(); ++ob) {
@ -2090,26 +2090,34 @@ turn_info::PROCESS_DATA_RESULT turn_info::process_network_data(const config& cfg
bool turn_end = false;
const config::child_list& turns = cfg.get_children("turn");
if(turns.empty() == false) {
if(turns.empty() == false && from != network::null_connection) {
//forward the data to other peers
network::send_data_all_except(cfg,from);
}
for(config::child_list::const_iterator t = turns.begin(); t != turns.end(); ++t) {
replay replay_obj(**t);
replay_obj.start_replay();
if(turn_end == false) {
replay replay_obj(**t);
replay_obj.start_replay();
try {
turn_end |= do_replay(gui_,map_,gameinfo_,units_,teams_,
team_num_,status_,state_of_game_,&replay_obj);
} catch(replay::error& e) {
save_game(string_table["network_sync_error"]);
try {
turn_end = do_replay(gui_,map_,gameinfo_,units_,teams_,
team_num_,status_,state_of_game_,&replay_obj);
} catch(replay::error& e) {
save_game(string_table["network_sync_error"]);
//throw e;
//throw e;
}
recorder.add_config(**t,replay::MARK_AS_SENT);
} else {
//this turn has finished, so push the remaining moves
//into the backlog
backlog.push_back(config());
backlog.back().add_child("turn",**t);
}
recorder.add_config(**t,replay::MARK_AS_SENT);
}
//if a side has dropped out of the game.

View file

@ -32,6 +32,7 @@
#include "unit.hpp"
#include "video.hpp"
#include <deque>
#include <map>
#include <vector>
@ -77,8 +78,14 @@ public:
enum PROCESS_DATA_RESULT { PROCESS_CONTINUE, PROCESS_RESTART_TURN, PROCESS_END_TURN };
//function which will process incoming network data, and act on it.
PROCESS_DATA_RESULT process_network_data(const config& cfg, network::connection from);
//function which will process incoming network data, and act on it. If there is
//more data than a single turn's worth, excess data will be placed into 'backlog'.
//No more than one turn's worth of data will be placed into a single backlog item,
//so it is safe to assume that backlog won't be touched if cfg is a member of a previous
//backlog.
//data will be forwarded to all peers other than 'from', unless 'from' is null, in
//which case data will not be forwarded
PROCESS_DATA_RESULT process_network_data(const config& cfg,network::connection from,std::deque<config>& backlog);
private:

View file

@ -142,6 +142,11 @@ void game::add_player(network::connection player)
observer_join.add_child("observer").values["name"] = info->second.name();
send_data(observer_join);
}
//tell this player that the game has started
config cfg;
cfg.add_child("start_game");
network::send_data(cfg,player);
}
//if the player is already in the game, don't add them.
@ -154,10 +159,7 @@ void game::add_player(network::connection player)
send_user_list();
//send the player the history of the game to-date
for(std::vector<config>::const_iterator i = history_.begin();
i != history_.end(); ++i) {
network::send_data(*i,player);
}
network::send_data(history_,player);
}
void game::remove_player(network::connection player)
@ -247,7 +249,7 @@ void game::send_data_team(const config& data, const std::string& team, network::
void game::record_data(const config& data)
{
history_.push_back(data);
history_.append(data);
}
bool game::level_init() const

View file

@ -82,7 +82,7 @@ private:
config level_;
std::vector<config> history_;
config history_;
config* description_;

View file

@ -301,7 +301,6 @@ void server::run()
//g->start_game() will send data that assumes the [start_game]
//message has been sent
g->send_data(data,sock);
g->record_data(data);
g->start_game();
lobby_players_.send_data(sync_initial_response());