various AI improvements, tweaks to the campaign
This commit is contained in:
parent
effdcfdc1e
commit
187adbcf9b
10 changed files with 167 additions and 98 deletions
|
@ -1,30 +1,30 @@
|
|||
gggggggrrgggccsssssssssssssssssssssccg
|
||||
gCCCgggrrgggccsssssssssssssssssssssctg
|
||||
gC3Cgtgrrgggccsssssssssssssssssssscggg
|
||||
gCCCgggrrgggccssssssssssssssssssssscvg
|
||||
gC3Cgvgrrgggccsssssssssssssssssssscggg
|
||||
ggCggggrrggggcssssssssccccsssssssccCgg
|
||||
gggggggrrgggggcsssssscctccssssssccg2Cg
|
||||
gggggggrrgggggcssssssccvccssssssccg2Cg
|
||||
ggggggrrrgggggcsssssccccccscccsccggggr
|
||||
ggggggrrggtgggccsssccccccccccccccggrrr
|
||||
ggtggrrrgggggggfcccccccccccccccggrrrrg
|
||||
gggggrrgggggffffcccccccccccccggrrrrggg
|
||||
gggggrrfffgfffffffcfcfffcfgggggrrfgtgg
|
||||
gggggrrffffffffftffffffffftggrrrrffffg
|
||||
gggggrrrrrffffffffffffffffffrrrfffffff
|
||||
gggtggrrrrrrrrfrfffffffffffrrrffffffff
|
||||
ggggggggggrfrrrrrrfffffffffrrfffffffff
|
||||
gggggggggggfffrfrrrrfffffrrrrfffffffff
|
||||
gggggggggggfffffffrrrrfrrrrfffffffffff
|
||||
gfffffggtgffffffftffrrrrrfffffffffffff
|
||||
fffffffffffffffffffffrrrrrffffffffffff
|
||||
fffffffffffffffrrrrrrrrfrrrffffffftfff
|
||||
ffftfffffffrfrrrrrrrrrfffrrfffffffffff
|
||||
rrfffffrfrrrrrrffffffffffrrfffffffffff
|
||||
rrrrrrrrrrrfrffffffffffffrrfffffffffff
|
||||
ffrrrrrfrfffffftfffffftffrrfffffffffff
|
||||
ffffffffffffffffffffffffrrrffffffffffg
|
||||
fffgfffffffffffffffffffrrrfffgggfgfggg
|
||||
ffftggfffffffffffffffffrrgfgggggggggtg
|
||||
ffffgffffgfgfgfffffffffrrggggggCgggggg
|
||||
ggfffffggggtggggfgggfffrrgggggC1Cggggg
|
||||
gggggggggggggggggggfffrrrgtgggCCCggggg
|
||||
gggggggggggggggggggffrrrgggggggggggggg
|
||||
ggggggrrggvgggccsssccccccccccccccggrrr
|
||||
ggvggrrrggggggghcccccccccccccccggrrrrg
|
||||
gggggrrggggghhhhcccccccccccccggrrrrggg
|
||||
gggggrrhhhghhhhhhhchchhhchgggggrrhgvgg
|
||||
gggggrrhhhhhhhhhvhhhhhhhhhvggrrrrhhhhg
|
||||
gggggrrrrrhhhhhhhhhhhhhhhhhhrrrhhhhhhh
|
||||
gggvggrrrrrrrrhrhhhhhhhhhhhrrrhhhhhhhh
|
||||
ggggggggggrhrrrrrrhhhhhhhhhrrhhhhhhhhh
|
||||
ggggggggggghhhrhrrrrhhhhhrrrrhhhhhhhhh
|
||||
ggggggggggghhhhhhhrrrrhrrrrhhhhhhhhhhh
|
||||
ghhhhhggvghhhhhhhvhhrrrrrhhhhhhhhhhhhh
|
||||
hhhhhhhhhhhhhhhhhhhhhrrrrrhhhhhhhhhhhh
|
||||
hhhhhhhhhhhhhhhrrrrrrrrhrrrhhhhhhhvhhh
|
||||
hhhvhhhhhhhrhrrrrrrrrrhhhrrhhhhhhhhhhh
|
||||
rrhhhhhrhrrrrrrhhhhhhhhhhrrhhhhhhhhhhh
|
||||
rrrrrrrrrrrhrhhhhhhhhhhhhrrhhhhhhhhhhh
|
||||
hhrrrrrhrhhhhhhvhhhhhhvhhrrhhhhhhhhhhh
|
||||
hhhhhhhhhhhhhhhhhhhhhhhhrrrhhhhhhhhhhg
|
||||
hhhghhhhhhhhhhhhhhhhhhhrrrhhhggghghggg
|
||||
hhhvgghhhhhhhhhhhhhhhhhrrghgggggggggvg
|
||||
hhhhghhhhghghghhhhhhhhhrrggggggCgggggg
|
||||
gghhhhhggggvgggghggghhhrrgggggC1Cggggg
|
||||
ggggggggggggggggggghhhrrrgvgggCCCggggg
|
||||
ggggggggggggggggggghhrrrgggggggggggggg
|
||||
|
|
|
@ -87,7 +87,7 @@ Defeat
|
|||
[message]
|
||||
id=msgcrossroads4
|
||||
description=Kalenz
|
||||
message="Beware! These forests are not safe! The roads are important to Asheviere's strategy, and she has hired Orcs to guard them. We shall have to fight to travel them."
|
||||
message="Beware! These hills are not safe! The roads are important to Asheviere's strategy, and she has hired Orcs to guard them. We shall have to fight to travel them."
|
||||
[/message]
|
||||
[message]
|
||||
id=msgcrossroads5
|
||||
|
@ -127,7 +127,7 @@ Defeat
|
|||
[message]
|
||||
id=msgcrossroads1
|
||||
description=Niodien
|
||||
message="Stay on the path! The forests here are not safe!"
|
||||
message="Stay on the path! The hills here are not safe!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
||||
|
@ -153,7 +153,7 @@ Defeat
|
|||
[message]
|
||||
description=Loflar
|
||||
id=msgcrossroads2
|
||||
message="Beware the forest! There are many Orcs in hiding, preparing to ambush you!"
|
||||
message="Beware the hills! There are many Orcs in hiding, preparing to ambush you!"
|
||||
[/message]
|
||||
[/event]
|
||||
|
||||
|
|
|
@ -22,6 +22,12 @@ Defeat:
|
|||
#Death of Konrad
|
||||
#Turns run out"
|
||||
|
||||
[label]
|
||||
x,y=11,17
|
||||
text="Elensefar"
|
||||
id=elensefar
|
||||
[/label]
|
||||
|
||||
[bigmap]
|
||||
image=misc/map.png
|
||||
{DOT 131 332}
|
||||
|
|
103
src/ai.cpp
103
src/ai.cpp
|
@ -445,6 +445,8 @@ void ai::do_move()
|
|||
{
|
||||
log_scope("doing ai move");
|
||||
|
||||
invalidate_defensive_position_cache();
|
||||
|
||||
user_interact();
|
||||
|
||||
typedef paths::route route;
|
||||
|
@ -791,16 +793,22 @@ bool ai::get_healing(std::map<gamemap::location,paths>& possible_moves, const mo
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ai::should_retreat(const gamemap::location& loc, const move_map& srcdst, const move_map& dstsrc, const move_map& enemy_srcdst, const move_map& enemy_dstsrc) const
|
||||
bool ai::should_retreat(const gamemap::location& loc, const unit_map::const_iterator un, const move_map& srcdst, const move_map& dstsrc, const move_map& enemy_srcdst, const move_map& enemy_dstsrc) const
|
||||
{
|
||||
const double caution = current_team().caution();
|
||||
if(caution <= 0.0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const double optimal_terrain = best_defensive_position(un->first,dstsrc,srcdst,enemy_dstsrc,enemy_srcdst).chance_to_hit/100.0;
|
||||
const double proposed_terrain = un->second.defense_modifier(map_,map_.get_terrain(loc))/100.0;
|
||||
|
||||
//the 'exposure' is the additional % chance to hit this unit receives from being on a sub-optimal defensive terrain
|
||||
const double exposure = proposed_terrain - optimal_terrain;
|
||||
|
||||
const double our_power = power_projection(loc,srcdst,dstsrc);
|
||||
const double their_power = power_projection(loc,enemy_srcdst,enemy_dstsrc);
|
||||
return caution*their_power > 2.0*our_power + our_power*current_team().aggression();
|
||||
return caution*their_power*(1.0+exposure) > our_power;
|
||||
}
|
||||
|
||||
bool ai::retreat_units(std::map<gamemap::location,paths>& possible_moves, const move_map& srcdst, const move_map& dstsrc, const move_map& enemy_srcdst, const move_map& enemy_dstsrc, unit_map::const_iterator leader)
|
||||
|
@ -821,7 +829,7 @@ bool ai::retreat_units(std::map<gamemap::location,paths>& possible_moves, const
|
|||
|
||||
//this unit still has movement left, and is a candidate to retreat. We see the amount
|
||||
//of power of each side on the situation, and decide whether it should retreat.
|
||||
if(should_retreat(i->first,fullmove_srcdst,fullmove_dstsrc,enemy_srcdst,enemy_dstsrc)) {
|
||||
if(should_retreat(i->first,i,fullmove_srcdst,fullmove_dstsrc,enemy_srcdst,enemy_dstsrc)) {
|
||||
|
||||
bool can_reach_leader = false;
|
||||
|
||||
|
@ -1269,48 +1277,9 @@ void ai::move_leader_to_keep(const move_map& enemy_dstsrc)
|
|||
}
|
||||
}
|
||||
|
||||
void ai::leader_attack()
|
||||
{
|
||||
std::cerr << "leader attack analysis...\n";
|
||||
const unit_map::iterator leader = find_leader(units_,team_num_);
|
||||
if(leader == units_.end() || leader->second.stone() || leader->second.can_attack() == false)
|
||||
return;
|
||||
|
||||
gamemap::location choice;
|
||||
double rating = 0.0;
|
||||
int weapon = -1;
|
||||
|
||||
gamemap::location adj[6];
|
||||
get_adjacent_tiles(leader->first,adj);
|
||||
for(size_t n = 0; n != 6; ++n) {
|
||||
const unit_map::const_iterator u = units_.find(adj[n]);
|
||||
if(u != units_.end() && current_team().is_enemy(u->second.side()) && u->second.stone() == false) {
|
||||
attack_analysis analysis;
|
||||
analysis.target = adj[n];
|
||||
analysis.movements.push_back(std::pair<location,location>(leader->first,leader->first));
|
||||
analysis.analyze(map_,units_,state_,gameinfo_,20,*this);
|
||||
const double value = analysis.chance_to_kill*analysis.target_value - analysis.avg_losses*10.0 - analysis.avg_damage_taken;
|
||||
if(value >= rating) {
|
||||
rating = value;
|
||||
choice = adj[n];
|
||||
|
||||
assert(analysis.weapons.size() == 1);
|
||||
weapon = analysis.weapons.front();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(choice.valid()) {
|
||||
attack_enemy(leader->first,choice,weapon);
|
||||
}
|
||||
|
||||
std::cerr << "end leader attack analysis...\n";
|
||||
}
|
||||
|
||||
void ai::move_leader_after_recruit(const move_map& enemy_dstsrc)
|
||||
{
|
||||
std::cerr << "moving leader after recruit...\n";
|
||||
leader_attack();
|
||||
|
||||
const unit_map::iterator leader = find_leader(units_,team_num_);
|
||||
if(leader == units_.end() || leader->second.stone())
|
||||
|
@ -1391,3 +1360,53 @@ int ai::rate_terrain(const unit& u, const gamemap::location& loc)
|
|||
|
||||
return rating;
|
||||
}
|
||||
|
||||
const ai::defensive_position& ai::best_defensive_position(const gamemap::location& loc,
|
||||
const move_map& dstsrc, const move_map& srcdst,
|
||||
const move_map& enemy_dstsrc, const move_map& enemy_srcdst) const
|
||||
{
|
||||
const unit_map::const_iterator itor = units_.find(loc);
|
||||
if(itor == units_.end()) {
|
||||
static defensive_position pos;
|
||||
pos.chance_to_hit = 0;
|
||||
pos.vulnerability = pos.support = 0;
|
||||
return pos;
|
||||
}
|
||||
|
||||
const std::map<location,defensive_position>::const_iterator position = defensive_position_cache_.find(loc);
|
||||
if(position != defensive_position_cache_.end()) {
|
||||
return position->second;
|
||||
}
|
||||
|
||||
defensive_position pos;
|
||||
pos.chance_to_hit = 100;
|
||||
pos.vulnerability = 10000.0;
|
||||
pos.support = 0.0;
|
||||
|
||||
typedef move_map::const_iterator Itor;
|
||||
const std::pair<Itor,Itor> itors = srcdst.equal_range(loc);
|
||||
for(Itor i = itors.first; i != itors.second; ++i) {
|
||||
const int defense = itor->second.defense_modifier(map_,map_.get_terrain(i->second));
|
||||
if(defense > pos.chance_to_hit) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const double vulnerability = power_projection(i->second,enemy_srcdst,enemy_dstsrc);
|
||||
const double support = power_projection(i->second,srcdst,dstsrc);
|
||||
|
||||
if(defense < pos.chance_to_hit || support - vulnerability > pos.support - pos.vulnerability) {
|
||||
pos.loc = i->second;
|
||||
pos.chance_to_hit = defense;
|
||||
pos.vulnerability = vulnerability;
|
||||
pos.support = support;
|
||||
}
|
||||
}
|
||||
|
||||
defensive_position_cache_.insert(std::pair<location,defensive_position>(loc,pos));
|
||||
return defensive_position_cache_[loc];
|
||||
}
|
||||
|
||||
void ai::invalidate_defensive_position_cache()
|
||||
{
|
||||
defensive_position_cache_.clear();
|
||||
}
|
23
src/ai.hpp
23
src/ai.hpp
|
@ -305,8 +305,20 @@ public:
|
|||
double value;
|
||||
};
|
||||
|
||||
struct defensive_position {
|
||||
location loc;
|
||||
int chance_to_hit;
|
||||
double vulnerability, support;
|
||||
};
|
||||
|
||||
const defensive_position& best_defensive_position(const location& unit, const move_map& dstsrc, const move_map& srcdst,
|
||||
const move_map& enemy_dstsrc, const move_map& enemy_srcdst) const;
|
||||
void invalidate_defensive_position_cache();
|
||||
|
||||
protected:
|
||||
|
||||
mutable std::map<location,defensive_position> defensive_position_cache_;
|
||||
|
||||
virtual void do_move();
|
||||
|
||||
virtual bool do_combat(std::map<gamemap::location,paths>& possible_moves, const move_map& srcdst, const move_map& dstsrc, const move_map& enemy_srcdst, const move_map& enemy_dstsrc);
|
||||
|
@ -315,13 +327,12 @@ protected:
|
|||
virtual bool retreat_units(std::map<gamemap::location,paths>& possible_moves, const move_map& srcdst, const move_map& dstsrc, const move_map& enemy_srcdst, const move_map& enemy_dstsrc, unit_map::const_iterator leader);
|
||||
virtual bool move_to_targets(std::map<gamemap::location,paths>& possible_moves, move_map& srcdst, move_map& dstsrc, const move_map& enemy_srcdst, const move_map& enemy_dstsrc, unit_map::const_iterator leader);
|
||||
|
||||
virtual bool should_retreat(const gamemap::location& loc, const move_map& srcdst, const move_map& dstsrc, const move_map& enemy_srcdst, const move_map& enemy_dstsrc) const;
|
||||
virtual bool should_retreat(const gamemap::location& loc, unit_map::const_iterator un, const move_map& srcdst, const move_map& dstsrc, const move_map& enemy_srcdst, const move_map& enemy_dstsrc) const;
|
||||
|
||||
virtual void do_recruitment();
|
||||
|
||||
virtual void move_leader_to_keep(const move_map& enemy_dstsrc);
|
||||
virtual void move_leader_after_recruit(const move_map& enemy_dstsrc);
|
||||
virtual void leader_attack();
|
||||
|
||||
virtual bool recruit_usage(const std::string& usage);
|
||||
|
||||
|
@ -343,7 +354,8 @@ protected:
|
|||
{
|
||||
void analyze(const gamemap& map, std::map<location,unit>& units,
|
||||
const gamestatus& status, const game_data& info, int sims,
|
||||
class ai& ai_obj);
|
||||
class ai& ai_obj, const move_map& dstsrc, const move_map& srcdst,
|
||||
const move_map& enemy_dstsrc, const move_map& enemy_srcdst);
|
||||
|
||||
double rating(double aggression) const;
|
||||
|
||||
|
@ -374,6 +386,11 @@ protected:
|
|||
//the weighted average of the % chance to hit each attacking unit
|
||||
double terrain_quality;
|
||||
|
||||
//the weighted average of the % defense of the best possible terrain
|
||||
//that the attacking units could reach this turn, without attacking
|
||||
//(good for comparison to see just how good/bad 'terrain_quality' is)
|
||||
double alternative_terrain_quality;
|
||||
|
||||
//the ratio of the attacks the unit being attacked will get to
|
||||
//the strength of its most powerful attack
|
||||
double counter_strength_ratio;
|
||||
|
|
|
@ -168,7 +168,7 @@ void ai::do_attack_analysis(
|
|||
|
||||
cur_analysis.support += best_support;
|
||||
|
||||
cur_analysis.analyze(map_,units_,state_,gameinfo_,50,*this);
|
||||
cur_analysis.analyze(map_,units_,state_,gameinfo_,50,*this,dstsrc,srcdst,enemy_dstsrc,enemy_srcdst);
|
||||
|
||||
if(cur_analysis.rating(0.0) > rating_to_beat) {
|
||||
|
||||
|
@ -292,7 +292,9 @@ int ai::choose_weapon(const location& att, const location& def,
|
|||
void ai::attack_analysis::analyze(const gamemap& map,
|
||||
unit_map& units,
|
||||
const gamestatus& status,
|
||||
const game_data& info, int num_sims, ai& ai_obj)
|
||||
const game_data& info, int num_sims, ai& ai_obj,
|
||||
const ai::move_map& dstsrc, const ai::move_map& srcdst,
|
||||
const ai::move_map& enemy_dstsrc, const ai::move_map& enemy_srcdst)
|
||||
{
|
||||
const unit_map::const_iterator defend_it = units.find(target);
|
||||
assert(defend_it != units.end());
|
||||
|
@ -463,12 +465,32 @@ void ai::attack_analysis::analyze(const gamemap& map,
|
|||
avg_damage_inflicted += target_hp - defhp;
|
||||
}
|
||||
|
||||
//calculate the 'alternative_terrain_quality' -- the best possible defensive values
|
||||
//the attacking units could hope to achieve if they didn't attack and moved somewhere.
|
||||
//this is could for comparative purposes to see just how vulnerable the AI is
|
||||
//making itself
|
||||
|
||||
alternative_terrain_quality = 0.0;
|
||||
double cost_sum = 0.0;
|
||||
for(size_t i = 0; i != movements.size(); ++i) {
|
||||
const unit_map::const_iterator att = units.find(movements[i].first);
|
||||
const double cost = att->second.type().cost();
|
||||
cost_sum += cost;
|
||||
alternative_terrain_quality += cost*ai_obj.best_defensive_position(att->first,dstsrc,srcdst,enemy_dstsrc,enemy_srcdst).chance_to_hit;
|
||||
}
|
||||
|
||||
alternative_terrain_quality /= cost_sum*100;
|
||||
|
||||
chance_to_kill /= num_sims;
|
||||
avg_damage_inflicted /= num_sims;
|
||||
avg_damage_taken /= num_sims;
|
||||
terrain_quality /= resources_used;
|
||||
resources_used /= num_sims;
|
||||
avg_losses /= num_sims;
|
||||
|
||||
if(uses_leader) {
|
||||
leader_threat = false;
|
||||
}
|
||||
}
|
||||
|
||||
double ai::attack_analysis::rating(double aggression) const
|
||||
|
@ -479,12 +501,24 @@ double ai::attack_analysis::rating(double aggression) const
|
|||
|
||||
//only use the leader if we do a serious amount of damage
|
||||
//compared to how much they do to us.
|
||||
if(uses_leader && aggression > -1.0) {
|
||||
aggression = -1.0;
|
||||
if(uses_leader && aggression > -4.0) {
|
||||
std::cerr << "uses leader..\n";
|
||||
aggression = -4.0;
|
||||
}
|
||||
|
||||
double value = chance_to_kill*target_value - avg_losses;
|
||||
|
||||
if(terrain_quality > alternative_terrain_quality) {
|
||||
//this situation looks like it might be a bad move: we are moving our attackers out
|
||||
//of their optimal terrain into sub-optimal terrain.
|
||||
//calculate the 'exposure' of our units to risk
|
||||
|
||||
const double exposure = resources_used*(terrain_quality - alternative_terrain_quality);
|
||||
std::cerr << "attack option has base value " << value << " with exposure " << exposure << "\n";
|
||||
|
||||
value -= exposure;
|
||||
}
|
||||
|
||||
//prefer to attack already damaged targets
|
||||
value += ((target_starting_damage/3 + avg_damage_inflicted)*
|
||||
(target_value/resources_used) -
|
||||
|
@ -500,6 +534,8 @@ double ai::attack_analysis::rating(double aggression) const
|
|||
value *= 5.0;
|
||||
}
|
||||
|
||||
std::cerr << "value: " << value << " vulnerability: " << vulnerability << " quality: " << terrain_quality << " alternative quality: " << alternative_terrain_quality << "\n";
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
|
@ -302,7 +302,7 @@ std::pair<gamemap::location,gamemap::location> ai::choose_move(std::vector<targe
|
|||
std::pair<Itor,Itor> its = dstsrc.equal_range(*ri);
|
||||
while(its.first != its.second) {
|
||||
if(its.first->second == best->first) {
|
||||
if(!should_retreat(its.first->first,fullmove_srcdst,fullmove_dstsrc,enemy_srcdst,enemy_dstsrc)) {
|
||||
if(!should_retreat(its.first->first,best,fullmove_srcdst,fullmove_dstsrc,enemy_srcdst,enemy_dstsrc)) {
|
||||
const double value = best_target->value - best->second.type().cost()/20.0;
|
||||
|
||||
if(value > 0.0) {
|
||||
|
|
23
src/game.cpp
23
src/game.cpp
|
@ -65,9 +65,9 @@ LEVEL_RESULT play_game(display& disp, game_state& state, config& game_config,
|
|||
config* scenario = NULL;
|
||||
|
||||
//'starting_pos' will contain the position we start the game from.
|
||||
//'replay_starting_pos' will contain the position as at the start of the scenario
|
||||
//which is useful for saving replays
|
||||
config starting_pos, replay_starting_pos;
|
||||
config starting_pos;
|
||||
|
||||
recorder.set_save_info(state);
|
||||
|
||||
//see if we load the scenario from the scenario data -- if there is
|
||||
//no snapshot data available from a save, or if the user has selected
|
||||
|
@ -79,7 +79,6 @@ LEVEL_RESULT play_game(display& disp, game_state& state, config& game_config,
|
|||
std::cerr << "loading starting position: '" << state.starting_pos.write() << "'\n";
|
||||
starting_pos = state.starting_pos;
|
||||
scenario = &starting_pos;
|
||||
replay_starting_pos = state.starting_pos;
|
||||
} else {
|
||||
scenario = game_config.find_child(type,"id",state.scenario);
|
||||
}
|
||||
|
@ -91,7 +90,6 @@ LEVEL_RESULT play_game(display& disp, game_state& state, config& game_config,
|
|||
std::cerr << "loading snapshot...\n";
|
||||
//load from a save-snapshot.
|
||||
starting_pos = state.snapshot;
|
||||
replay_starting_pos = state.starting_pos;
|
||||
scenario = &starting_pos;
|
||||
state = read_game(units_data,&state.snapshot);
|
||||
}
|
||||
|
@ -102,18 +100,9 @@ LEVEL_RESULT play_game(display& disp, game_state& state, config& game_config,
|
|||
const std::string current_scenario = state.scenario;
|
||||
|
||||
try {
|
||||
LEVEL_RESULT res = REPLAY;
|
||||
|
||||
state.label = translate_string_default((*scenario)["id"],(*scenario)["name"]);
|
||||
|
||||
recorder.set_save_info(state);
|
||||
|
||||
while(res == REPLAY) {
|
||||
state = recorder.get_save_info();
|
||||
|
||||
res = play_level(units_data,game_config,scenario,
|
||||
video,state,story);
|
||||
}
|
||||
const LEVEL_RESULT res = play_level(units_data,game_config,scenario,video,state,story);
|
||||
|
||||
state.snapshot = config();
|
||||
|
||||
|
@ -137,7 +126,7 @@ LEVEL_RESULT play_game(display& disp, game_state& state, config& game_config,
|
|||
try {
|
||||
config snapshot;
|
||||
|
||||
recorder.save_game(units_data,label,snapshot,replay_starting_pos);
|
||||
recorder.save_game(units_data,label,snapshot,state.starting_pos);
|
||||
} catch(gamestatus::save_game_failed& e) {
|
||||
gui::show_dialog(disp,NULL,"",string_table["save_game_failed"],gui::MESSAGE);
|
||||
retry = true;
|
||||
|
@ -202,6 +191,8 @@ LEVEL_RESULT play_game(display& disp, game_state& state, config& game_config,
|
|||
|
||||
state.starting_pos = *scenario;
|
||||
}
|
||||
|
||||
recorder.set_save_info(state);
|
||||
}
|
||||
|
||||
if(state.scenario != "" && state.scenario != "null") {
|
||||
|
|
|
@ -606,7 +606,7 @@ redo_turn:
|
|||
return end_level.result;
|
||||
}
|
||||
|
||||
if(end_level.result == QUIT || end_level.result == REPLAY) {
|
||||
if(end_level.result == QUIT) {
|
||||
return end_level.result;
|
||||
} else if(end_level.result == DEFEAT) {
|
||||
try {
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
enum LEVEL_RESULT { VICTORY, DEFEAT, QUIT, REPLAY, CONTINUE };
|
||||
enum LEVEL_RESULT { VICTORY, DEFEAT, QUIT, CONTINUE };
|
||||
|
||||
struct end_level_exception {
|
||||
end_level_exception(LEVEL_RESULT res, bool bonus=true)
|
||||
|
|
Loading…
Add table
Reference in a new issue