various tweaks of ai handling of map changes

solve some problems which might arise if map changes in the middle of
the turn thanks to WML events
This commit is contained in:
Iurii Chernyi 2009-12-02 23:53:49 +00:00
parent 8c157b38e7
commit 08ac3d103d
7 changed files with 105 additions and 8 deletions

View File

@ -21,6 +21,8 @@
{FOREACH MOVE_UNIT_store unit}
{VARIABLE_OP MOVE_UNIT_store[$unit].x add {X_OFFSET}}
{VARIABLE_OP MOVE_UNIT_store[$unit].y add {Y_OFFSET}}
{VARIABLE_OP MOVE_UNIT_store[$unit].goto_x add {X_OFFSET}}
{VARIABLE_OP MOVE_UNIT_store[$unit].goto_y add {Y_OFFSET}}
{NEXT unit}
{FOREACH villages village}

View File

@ -204,6 +204,7 @@ readonly_context_impl::readonly_context_impl(side_context &context, const config
add_known_aspect("support_villages",support_villages_);
add_known_aspect("village_value",village_value_);
add_known_aspect("villages_per_scout",villages_per_scout_);
keeps_.init(get_info().map);
}
@ -797,6 +798,12 @@ void readonly_context_impl::invalidate_keeps_cache() const
}
void keeps_cache::handle_generic_event(const std::string &/*event_name*/)
{
clear();
}
void readonly_context_impl::invalidate_move_maps() const
{
move_maps_valid_ = false;
@ -806,18 +813,47 @@ void readonly_context_impl::invalidate_move_maps() const
const std::set<map_location>& readonly_context_impl::keeps() const
{
gamemap &map_ = get_info().map;
return keeps_.get();
}
keeps_cache::keeps_cache()
{
ai::manager::add_turn_started_observer(this);
ai::manager::add_map_changed_observer(this);
}
keeps_cache::~keeps_cache()
{
ai::manager::remove_turn_started_observer(this);
ai::manager::remove_map_changed_observer(this);
}
void keeps_cache::clear()
{
keeps_.clear();
}
void keeps_cache::init(gamemap &map)
{
map_ = &map;
}
const std::set<map_location>& keeps_cache::get()
{
if(keeps_.empty()) {
// Generate the list of keeps:
// iterate over the entire map and find all keeps.
for(size_t x = 0; x != size_t(map_.w()); ++x) {
for(size_t y = 0; y != size_t(map_.h()); ++y) {
for(size_t x = 0; x != size_t(map_->w()); ++x) {
for(size_t y = 0; y != size_t(map_->h()); ++y) {
const map_location loc(x,y);
if(map_.is_keep(loc)) {
if(map_->is_keep(loc)) {
map_location adj[6];
get_adjacent_tiles(loc,adj);
for(size_t n = 0; n != 6; ++n) {
if(map_.is_castle(adj[n])) {
if(map_->is_castle(adj[n])) {
keeps_.insert(loc);
break;
}

View File

@ -96,6 +96,20 @@ struct defensive_position {
double vulnerability, support;
};
// keeps cache
class keeps_cache : public events::observer
{
public:
keeps_cache();
~keeps_cache();
void handle_generic_event(const std::string& event_name);
void clear();
const std::set<map_location>& get();
void init(gamemap &map);
private:
gamemap *map_;
std::set<map_location> keeps_;
};
// side context
@ -1323,7 +1337,7 @@ private:
mutable move_map enemy_srcdst_;
aspect_type< std::string >::typesafe_ptr grouping_;
std::vector< goal_ptr > goals_;
mutable std::set<map_location> keeps_;
mutable keeps_cache keeps_;
aspect_type<double>::typesafe_ptr leader_aggression_;
aspect_type< config >::typesafe_ptr leader_goal_;
aspect_type< double >::typesafe_ptr leader_value_;

View File

@ -2010,12 +2010,18 @@ void ai_default::move_leader_after_recruit()
leader_paths.destinations.contains(adj[n]) &&
!is_accessible(adj[n], get_enemy_dstsrc()))
{
move_result_ptr move_res = check_move_action(keep,adj[n],true);
if (!move_res->is_ok())
{
continue;
}
bool gamestate_changed = false;
map_location new_loc = move_unit(keep,adj[n],gamestate_changed);
move_res->execute();
gamestate_changed |= move_res->is_gamestate_changed();
if (!gamestate_changed) {
ERR_AI << "moving leader after recruit failed" << std::endl;
}
if (new_loc!=keep) {
if (!move_res->is_ok()) {
return;
}
}

View File

@ -311,6 +311,7 @@ events::generic_event manager::sync_network_("ai_sync_network");
events::generic_event manager::gamestate_changed_("ai_gamestate_changed");
events::generic_event manager::turn_started_("ai_turn_started");
events::generic_event manager::recruit_list_changed_("ai_recruit_list_changed");
events::generic_event manager::map_changed_("ai_map_changed");
int manager::last_interact_ = 0;
int manager::num_interact_ = 0;
@ -352,16 +353,24 @@ void manager::remove_observer(events::observer* event_observer){
void manager::add_gamestate_observer( events::observer* event_observer){
gamestate_changed_.attach_handler(event_observer);
turn_started_.attach_handler(event_observer);
map_changed_.attach_handler(event_observer);
}
void manager::remove_gamestate_observer(events::observer* event_observer){
gamestate_changed_.detach_handler(event_observer);
turn_started_.detach_handler(event_observer);
map_changed_.detach_handler(event_observer);
}
void manager::add_map_changed_observer( events::observer* event_observer )
{
map_changed_.attach_handler(event_observer);
}
void manager::add_recruit_list_changed_observer( events::observer* event_observer )
{
recruit_list_changed_.attach_handler(event_observer);
@ -398,6 +407,12 @@ void manager::remove_user_interact_observer( events::observer* event_observer )
}
void manager::remove_map_changed_observer( events::observer* event_observer )
{
map_changed_.detach_handler(event_observer);
}
void manager::delete_sync_network_observer( events::observer* event_observer )
{
sync_network_.detach_handler(event_observer);
@ -443,6 +458,11 @@ void manager::raise_recruit_list_changed() {
}
void manager::raise_map_changed() {
map_changed_.notify_observers();
}
// =======================================================================
// EVALUATION
// =======================================================================

View File

@ -210,6 +210,17 @@ public:
static void raise_turn_started();
/**
* Notifies all observers of 'ai_map_changed' event.
*/
static void raise_map_changed();
/**
* Adds an observer of 'ai_map_changed' event.
*/
static void add_map_changed_observer( events::observer* event_observer );
/**
* Adds an observer of 'ai_recruit_list_changed' event.
@ -235,6 +246,12 @@ public:
static void add_turn_started_observer( events::observer* event_observer );
/**
* Deletes an observer of 'ai_map_changed' event.
*/
static void remove_map_changed_observer( events::observer* event_observer );
/**
* Deletes an observer of 'ai_recruit_list_changed' event.
@ -451,6 +468,7 @@ private:
static long history_item_counter_;
static game_info *ai_info_;
static events::generic_event map_changed_;
static events::generic_event recruit_list_changed_;
static events::generic_event user_interact_;
static events::generic_event sync_network_;

View File

@ -3446,6 +3446,7 @@ WML_HANDLER_FUNCTION(replace_map, /*event_info*/, cfg)
*game_map = map;
resources::screen->reload_map();
screen_needs_rebuild = true;
ai::manager::raise_map_changed();
}
WML_HANDLER_FUNCTION(unit_worth, /*event_info*/, cfg)