Add a new field to the game state structure: completion,

...which may have the values 'running', 'victory', or 'defeat'.  It is
set by play_game() and check_victory().  It is loaded and saved.

Presently this is not yet used (though I have tested that it is set properly).
So there are no behavioral changes in the game yet.

What it does is give us a way of setting victory/defeat status that isn't 
tied to throwing an end-of-scenario exception.  This is a first step to 
allowing observer-like game browsing after victory/defeat notification,
with the user choosing to throw end-of-scenario after that.

Doing this required passing a game-state reference into two classes 
that didn't have it before, ai_interface and mouse_handler.
This commit is contained in:
Eric S. Raymond 2007-06-14 12:29:03 +00:00
parent df6be5bf47
commit 6e25c94423
12 changed files with 28 additions and 14 deletions

View File

@ -1566,7 +1566,8 @@ void advance_unit(const game_data& info,
}
void check_victory(unit_map& units,
std::vector<team>& teams)
std::vector<team>& teams,
game_state& gamestate)
{
std::vector<int> seen_leaders;
for(unit_map::const_iterator i = units.begin();
@ -1624,6 +1625,7 @@ void check_victory(unit_map& units,
std::cout << "\n";
}
gamestate.completion = found_player ? "victory" : "defeat";
LOG_NG << "throwing end level exception...\n";
throw end_level_exception(found_player ? VICTORY : DEFEAT);
}

View File

@ -248,7 +248,8 @@ gamemap::location under_leadership(const unit_map& units,
//checks to see if a side has won, and will throw an end_level_exception
//if one has. Will also remove control of villages from sides with dead leaders
void check_victory(unit_map& units,
std::vector<team>& teams);
std::vector<team>& teams,
game_state &gamestate);
//gets the time of day at a certain tile. Certain tiles may have a time of
//day that differs from 'the' time of day, if a unit that illuminates is

View File

@ -26,6 +26,7 @@
#include "replay.hpp"
#include "statistics.hpp"
#include "unit_display.hpp"
#include "playturn.hpp"
#include "wassert.hpp"
#define LOG_AI LOG_STREAM(info, ai)
@ -1081,7 +1082,7 @@ void ai_interface::attack_enemy(const location& u, const location& target, int w
}
}
check_victory(info_.units,info_.teams);
check_victory(info_.units,info_.teams,info_.game_state_);
raise_enemy_attacked();
}
}

View File

@ -33,9 +33,9 @@ public:
///that an AI might need access to in order to make and implement its decisions
struct info {
info(display& disp, const gamemap& map, const game_data& gameinfo, unit_map& units,
std::vector<team>& teams, unsigned int team_num, const gamestatus& state, class turn_info& turn_data)
std::vector<team>& teams, unsigned int team_num, const gamestatus& state, class turn_info& turn_data, class game_state& game_state)
: disp(disp), map(map), gameinfo(gameinfo), units(units), teams(teams),
team_num(team_num), state(state), turn_data_(turn_data) {}
team_num(team_num), state(state), turn_data_(turn_data), game_state_(game_state) {}
///the display object, used to draw the moves the AI makes.
display& disp;
@ -62,6 +62,10 @@ public:
///the object that allows the player to interact with the game.
///should not be used outside of ai_interface
class turn_info& turn_data_;
/// The global game state, because we may set the completion
/// field.
class game_state& game_state_;
};
///the constructor. All derived classes should take an argument of type info& which

View File

@ -426,6 +426,7 @@ game_state::game_state(const game_data& data, const config& cfg)
label = cfg["label"];
version = cfg["version"];
scenario = cfg["scenario"];
completion = cfg["completion"];
campaign = cfg["campaign"];
const config* snapshot = cfg.child("snapshot");
@ -669,6 +670,7 @@ void write_game(config_writer &out, const game_state& gamestate, WRITE_GAME_MODE
out.write_key_val("label", gamestate.label);
out.write_key_val("version", game_config::version);
out.write_key_val("scenario", gamestate.scenario);
out.write_key_val("completion", gamestate.completion);
out.write_key_val("campaign", gamestate.campaign);
out.write_key_val("campaign_type", gamestate.campaign_type);
out.write_key_val("difficulty", gamestate.difficulty);

View File

@ -95,6 +95,7 @@ public:
std::string campaign; //the campaign being played
std::string scenario; //the scenario being played
std::string completion; // running. victory, or defeat
// information about campaign players who carry resources from
// previous levels, indexed by a string identifier (which is

View File

@ -673,9 +673,9 @@ namespace{
} //end anonymous namespace
mouse_handler::mouse_handler(display* gui, std::vector<team>& teams, unit_map& units, gamemap& map,
gamestatus& status, const game_data& gameinfo, undo_list& undo_stack, undo_list& redo_stack):
gamestatus& status, const game_data& gameinfo, undo_list& undo_stack, undo_list& redo_stack, game_state& game_state):
gui_(gui), teams_(teams), units_(units), map_(map), status_(status), gameinfo_(gameinfo),
undo_stack_(undo_stack), redo_stack_(redo_stack)
undo_stack_(undo_stack), redo_stack_(redo_stack), game_state_(game_state)
{
minimap_scrolling_ = false;
dragging_ = false;
@ -1397,7 +1397,7 @@ bool mouse_handler::attack_enemy_(unit_map::iterator attacker, unit_map::iterato
current_route_.steps.clear();
gui_->set_route(NULL);
check_victory(units_,teams_);
check_victory(units_,teams_,game_state_);
gui_->invalidate_all();
gui_->draw(); //clear the screen

View File

@ -37,7 +37,7 @@ struct command_disabler
class mouse_handler{
public:
mouse_handler(display* gui, std::vector<team>& teams, unit_map& units, gamemap& map,
gamestatus& status, const game_data& gameinfo, undo_list& undo_stack, undo_list& redo_stack);
gamestatus& status, const game_data& gameinfo, undo_list& undo_stack, undo_list& redo_stack, game_state& gamestate);
void set_team(const int team_number);
void mouse_motion(const SDL_MouseMotionEvent& event, const bool browse);
// update the mouse with a fake mouse motion
@ -92,6 +92,7 @@ private:
const game_data& gameinfo_;
undo_list& undo_stack_;
undo_list& redo_stack_;
game_state& game_state_;
bool minimap_scrolling_;
bool dragging_;

View File

@ -30,7 +30,7 @@ play_controller::play_controller(const config& level, const game_data& gameinfo,
int ticks, int num_turns, const config& game_config, CVideo& video, bool skip_replay) :
verify_manager_(units_), team_manager_(teams_), labels_manager_(),
help_manager_(&game_config, &gameinfo, &map_),
mouse_handler_(gui_, teams_, units_, map_, status_, gameinfo, undo_stack_, redo_stack_),
mouse_handler_(gui_, teams_, units_, map_, status_, gameinfo, undo_stack_, redo_stack_, state_of_game),
menu_handler_(gui_, units_, teams_, level, gameinfo, map_, game_config, status_, state_of_game, undo_stack_, redo_stack_),
generator_setter(&recorder), statistics_context_(level["name"]), gameinfo_(gameinfo), level_(level), game_config_(game_config),
gamestate_(state_of_game), status_(level, num_turns, &state_of_game),

View File

@ -276,6 +276,8 @@ LEVEL_RESULT play_game(display& disp, game_state& gamestate, const config& game_
sound::play_no_music();
gamestate.completion = "running";
switch (io_type){
case IO_NONE:
res = playsingle_scenario(units_data,game_config,scenario,video,gamestate,story,log, skip_replay);

View File

@ -406,7 +406,7 @@ void playsingle_controller::play_turn(bool save)
}
finish_side_turn();
check_victory(units_,teams_);
check_victory(units_,teams_,gamestate_);
}
}
@ -529,7 +529,7 @@ void playsingle_controller::play_ai_turn(){
turn_info turn_data(gameinfo_,gamestate_,status_,*gui_,
map_,teams_,player_number_,units_, replay_sender_, undo_stack_);
ai_interface::info ai_info(*gui_,map_,gameinfo_,units_,teams_,player_number_,status_, turn_data);
ai_interface::info ai_info(*gui_,map_,gameinfo_,units_,teams_,player_number_,status_, turn_data, gamestate_);
util::scoped_ptr<ai_interface> ai_obj(create_ai(current_team().ai_algorithm(),ai_info));
ai_obj->user_interact().attach_handler(this);
ai_obj->unit_recruited().attach_handler(this);

View File

@ -647,7 +647,7 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
//if there are no more advancing units, then we check for victory,
//in case the battle that led to advancement caused the end of scenario
if(advancing_units.empty()) {
check_victory(units,teams);
check_victory(units,teams,state_of_game);
}
continue;
@ -1004,7 +1004,7 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
//check victory now if we don't have any advancements. If we do have advancements,
//we don't check until the advancements are processed.
if(advancing_units.empty()) {
check_victory(units,teams);
check_victory(units,teams,state_of_game);
}
fix_shroud = !replayer.is_skipping();
} else if((child = cfg->child("fire_event")) != NULL) {