Extending the "actions" namespace.

This commit is contained in:
J. Tyne 2013-02-08 05:33:07 +00:00
parent c57b546b41
commit f0d0ee3084
6 changed files with 140 additions and 137 deletions

View file

@ -51,34 +51,33 @@ static lg::log_domain log_engine("engine");
namespace {
struct castle_cost_calculator : pathfind::cost_calculator
{
castle_cost_calculator(const gamemap& map, const team & view_team) :
map_(map),
viewer_(view_team),
use_shroud_(view_team.uses_shroud())
{}
virtual double cost(const map_location& loc, const double) const
struct castle_cost_calculator : pathfind::cost_calculator
{
if(!map_.is_castle(loc))
return 10000;
castle_cost_calculator(const gamemap& map, const team & view_team) :
map_(map),
viewer_(view_team),
use_shroud_(view_team.uses_shroud())
{}
if ( use_shroud_ && viewer_.shrouded(loc) )
return 10000;
virtual double cost(const map_location& loc, const double) const
{
if(!map_.is_castle(loc))
return 10000;
return 1;
}
if ( use_shroud_ && viewer_.shrouded(loc) )
return 10000;
private:
const gamemap& map_;
const team& viewer_;
const bool use_shroud_; // Allows faster checks when shroud is disabled.
};
return 1;
}
private:
const gamemap& map_;
const team& viewer_;
const bool use_shroud_; // Allows faster checks when shroud is disabled.
};
}//anonymous namespace
unit_creator::unit_creator(team &tm, const map_location &start_pos)
: add_to_recall_(false),discover_(false),get_village_(false),invalidate_(false), rename_side_(false), show_(false), start_pos_(start_pos), team_(tm)
{
@ -325,7 +324,11 @@ bool can_recruit_on(const map_location& leader_loc, const map_location& recruit_
return !rt.steps.empty();
}
const std::set<std::string> get_recruits_for_location(int side, const map_location &recruit_loc)
namespace actions {
const std::set<std::string> get_recruits(int side, const map_location &recruit_loc)
{
const team & current_team = (*resources::teams)[side -1];
@ -388,41 +391,42 @@ const std::set<std::string> get_recruits_for_location(int side, const map_locati
}
/**
* Adds to @a result those units that @a leader (assumed a leader) can recall.
* If @a already_added is supplied, it contains the underlying IDs of units
* that can be skipped (because they are already in @a result), and the
* underlying ID of units added to @a result will be added to @a already_added.
*/
static void add_leader_filtered_recalls(const unit & leader,
std::vector<const unit*> & result,
std::set<size_t> * already_added = NULL)
{
const team& leader_team = (*resources::teams)[leader.side()-1];
const std::vector<unit>& recall_list = leader_team.recall_list();
const std::string& save_id = leader_team.save_id();
BOOST_FOREACH(const unit& recall_unit, recall_list)
namespace { // Helpers for get_recalls_for_location()
/**
* Adds to @a result those units that @a leader (assumed a leader) can recall.
* If @a already_added is supplied, it contains the underlying IDs of units
* that can be skipped (because they are already in @a result), and the
* underlying ID of units added to @a result will be added to @a already_added.
*/
void add_leader_filtered_recalls(const unit & leader,
std::vector<const unit*> & result,
std::set<size_t> * already_added = NULL)
{
// Do not add a unit twice.
size_t underlying_id = recall_unit.underlying_id();
if ( !already_added || already_added->count(underlying_id) == 0 )
{
// Only units that match the leader's recall filter are valid.
scoped_recall_unit this_unit("this_unit", save_id, &recall_unit - &recall_list[0]);
const team& leader_team = (*resources::teams)[leader.side()-1];
const std::vector<unit>& recall_list = leader_team.recall_list();
const std::string& save_id = leader_team.save_id();
if ( recall_unit.matches_filter(vconfig(leader.recall_filter()), map_location::null_location) )
BOOST_FOREACH(const unit& recall_unit, recall_list)
{
// Do not add a unit twice.
size_t underlying_id = recall_unit.underlying_id();
if ( !already_added || already_added->count(underlying_id) == 0 )
{
result.push_back(&recall_unit);
if ( already_added != NULL )
already_added->insert(underlying_id);
// Only units that match the leader's recall filter are valid.
scoped_recall_unit this_unit("this_unit", save_id, &recall_unit - &recall_list[0]);
if ( recall_unit.matches_filter(vconfig(leader.recall_filter()), map_location::null_location) )
{
result.push_back(&recall_unit);
if ( already_added != NULL )
already_added->insert(underlying_id);
}
}
}
}
}
}// anonymous namespace
const std::vector<const unit*> get_recalls_for_location(int side, const map_location &recall_loc)
const std::vector<const unit*> get_recalls(int side, const map_location &recall_loc)
{
LOG_NG << "getting recall list for side " << side << " at location " << recall_loc << "\n";
@ -655,82 +659,83 @@ std::string find_recruit_location(const int side, map_location& recruit_location
}
/**
* Performs a checksum check on a newly recruited/recalled unit.
*/
static void recruit_checksums(const unit &new_unit, bool wml_triggered)
{
const config* ran_results = get_random_results();
if ( ran_results != NULL ) {
// When recalling from WML there should be no random results, if we use
// random we might get the replay out of sync.
assert(!wml_triggered);
const std::string checksum = get_checksum(new_unit);
const std::string rc = (*ran_results)["checksum"];
if ( rc != checksum ) {
std::stringstream error_msg;
error_msg << "SYNC: In recruit " << new_unit.type_id() <<
": has checksum " << checksum <<
" while datasource has checksum " << rc << "\n";
ERR_NG << error_msg.str();
namespace { // Helpers for place_recruit()
/**
* Performs a checksum check on a newly recruited/recalled unit.
*/
void recruit_checksums(const unit &new_unit, bool wml_triggered)
{
const config* ran_results = get_random_results();
if ( ran_results != NULL ) {
// When recalling from WML there should be no random results, if we
// use random we might get the replay out of sync.
assert(!wml_triggered);
const std::string checksum = get_checksum(new_unit);
const std::string rc = (*ran_results)["checksum"];
if ( rc != checksum ) {
std::stringstream error_msg;
error_msg << "SYNC: In recruit " << new_unit.type_id() <<
": has checksum " << checksum <<
" while datasource has checksum " << rc << "\n";
ERR_NG << error_msg.str();
config cfg_unit1;
new_unit.write(cfg_unit1);
DBG_NG << cfg_unit1;
replay::process_error(error_msg.str());
config cfg_unit1;
new_unit.write(cfg_unit1);
DBG_NG << cfg_unit1;
replay::process_error(error_msg.str());
}
} else if ( wml_triggered == false ) {
config cfg;
cfg["checksum"] = get_checksum(new_unit);
set_random_results(cfg);
}
} else if ( wml_triggered == false ) {
config cfg;
cfg["checksum"] = get_checksum(new_unit);
set_random_results(cfg);
}
}
/**
* Locates a leader on side @a side who can recruit at @a recruit_location.
* A leader at @a recruited_from is chosen in preference to others.
*/
static const map_location & find_recruit_leader(int side,
const map_location &recruit_location, const map_location &recruited_from)
{
const unit_map & units = *resources::units;
/**
* Locates a leader on side @a side who can recruit at @a recruit_location.
* A leader at @a recruited_from is chosen in preference to others.
*/
const map_location & find_recruit_leader(int side,
const map_location &recruit_location, const map_location &recruited_from)
{
const unit_map & units = *resources::units;
// See if the preferred location is an option.
unit_map::const_iterator leader = units.find(recruited_from);
if ( leader != units.end() && leader->can_recruit() &&
leader->side() == side && can_recruit_on(*leader, recruit_location) )
return leader->get_location();
// Check all units.
for ( leader = units.begin(); leader != units.end(); ++leader )
if ( leader->can_recruit() && leader->side() == side &&
can_recruit_on(*leader, recruit_location) )
// See if the preferred location is an option.
unit_map::const_iterator leader = units.find(recruited_from);
if ( leader != units.end() && leader->can_recruit() &&
leader->side() == side && can_recruit_on(*leader, recruit_location) )
return leader->get_location();
// No usable leader found.
return map_location::null_location;
}
// Check all units.
for ( leader = units.begin(); leader != units.end(); ++leader )
if ( leader->can_recruit() && leader->side() == side &&
can_recruit_on(*leader, recruit_location) )
return leader->get_location();
/**
* Tries to make @a un_it valid, and updates @a current_loc.
* Used by place_recruit() after WML might have changed something.
* @returns true if the iterator was made valid.
*/
static bool validate_recruit_iterator(unit_map::iterator & un_it,
map_location & current_loc)
{
if ( !un_it.valid() ) {
// Maybe WML provided a replacement?
un_it = resources::units->find(current_loc);
if ( un_it == resources::units->end() )
// The unit is gone.
return false;
// No usable leader found.
return map_location::null_location;
}
current_loc = un_it->get_location();
return true;
}
/**
* Tries to make @a un_it valid, and updates @a current_loc.
* Used by place_recruit() after WML might have changed something.
* @returns true if the iterator was made valid.
*/
bool validate_recruit_iterator(unit_map::iterator & un_it,
map_location & current_loc)
{
if ( !un_it.valid() ) {
// Maybe WML provided a replacement?
un_it = resources::units->find(current_loc);
if ( un_it == resources::units->end() )
// The unit is gone.
return false;
}
current_loc = un_it->get_location();
return true;
}
}// anonymous namespace
bool place_recruit(const unit &u, const map_location &recruit_location, const map_location& recruited_from,
int cost, bool is_recall, bool show, bool fire_event, bool full_movement,
@ -816,9 +821,6 @@ bool place_recruit(const unit &u, const map_location &recruit_location, const ma
}
namespace actions {
/**
* Recruits a unit of the given type for the given side.
*/

View file

@ -83,6 +83,9 @@ bool can_recruit_on(const map_location& leader_loc, const map_location& recruit_
inline bool can_recruit_on(const unit& leader, const map_location& recruit_loc)
{ return can_recruit_on(leader.get_location(), recruit_loc, leader.side()); }
namespace actions {
/**
* Finds a location on which to place a unit.
* A leader of the @a side must be on a keep
@ -125,7 +128,7 @@ std::string find_recall_location(const int side, map_location& recall_location,
* @param recruit_location the hex field being part of the castle the player wants to recruit on or from.
* @return a set of units that can be recruited either by the leader on @a recruit_location or by leaders on keeps connected by castle tiles to @a recruit_location.
*/
const std::set<std::string> get_recruits_for_location(int side, const map_location &recruit_location);
const std::set<std::string> get_recruits(int side, const map_location &recruit_location);
/**
* Gets the recallable units for a side, restricted by that side's leaders' personal abilities to recall on or from a specific hex field.
@ -134,7 +137,7 @@ const std::set<std::string> get_recruits_for_location(int side, const map_locati
* @param recall_loc the hex field being part of the castle the player wants to recruit on or from.
* @return a set of units that can be recalled by @a side on (or from) @a recall_loc or the full recall list of @a side.
*/
const std::vector<const unit*> get_recalls_for_location(int side, const map_location &recall_loc);
const std::vector<const unit*> get_recalls(int side, const map_location &recall_loc);
/**
* Place a unit into the game.
@ -146,9 +149,6 @@ bool place_recruit(const unit &u, const map_location &recruit_location, const ma
int cost, bool is_recall, bool show = false, bool fire_event = true, bool full_movement = false,
bool wml_triggered = false);
namespace actions {
/**
* Recruits a unit of the given type for the given side.
* This is the point at which the code merges for recruits originating from players,

View file

@ -669,7 +669,7 @@ void recall_result::do_execute()
std::vector<unit>::iterator rec = find_if_matches_id(my_team.recall_list(), unit_id_);
assert(rec != my_team.recall_list().end());
const std::string &err = find_recall_location(get_side(), recall_location_, recall_from_, *rec);
const std::string &err = ::actions::find_recall_location(get_side(), recall_location_, recall_from_, *rec);
if(!err.empty()) {
set_error(AI_ACTION_FAILURE);
return;
@ -863,7 +863,7 @@ void recruit_result::do_execute()
const unit_type *u = unit_types.find(unit_name_);
const events::command_disabler disable_commands;
const std::string recruit_err = find_recruit_location(get_side(), recruit_location_, recruit_from_, u->id());
const std::string recruit_err = ::actions::find_recruit_location(get_side(), recruit_location_, recruit_from_, u->id());
if(recruit_err.empty()) {
recorder.add_recruit(num_,recruit_location_,recruit_from_);
::actions::recruit_unit(*u, get_side(), recruit_location_, recruit_from_, preferences::show_ai_moves(), true);

View file

@ -1957,8 +1957,9 @@ WML_HANDLER_FUNCTION(recall, /*event_info*/, cfg)
if(resources::game_map->on_board(loc)) {
DBG_NG << "...valid location for the recall found. Recalling.\n";
avail.erase(u); // Erase before recruiting, since recruiting can fire more events
place_recruit(to_recruit, loc, leader->get_location(), 0, true,
cfg["show"].to_bool(true), cfg["fire_event"].to_bool(false), true, true);
actions::place_recruit(to_recruit, loc, leader->get_location(), 0, true,
cfg["show"].to_bool(true), cfg["fire_event"].to_bool(false),
true, true);
return;
}
}
@ -1972,8 +1973,8 @@ WML_HANDLER_FUNCTION(recall, /*event_info*/, cfg)
DBG_NG << "No usable leader found, but found usable location. Recalling.\n";
avail.erase(u); // Erase before recruiting, since recruiting can fire more events
map_location null_location = map_location::null_location;
place_recruit(to_recruit, loc, null_location, 0, true,
cfg["show"].to_bool(true), cfg["fire_event"].to_bool(false), true, true);
actions::place_recruit(to_recruit, loc, null_location, 0, true, cfg["show"].to_bool(true),
cfg["fire_event"].to_bool(false), true, true);
return;
}
}

View file

@ -739,7 +739,7 @@ void menu_handler::recruit(int side_num, const map_location &last_hex)
std::vector<std::string> item_keys;
std::vector<std::string> items;
std::set<std::string> recruits = get_recruits_for_location(side_num, last_hex);
std::set<std::string> recruits = actions::get_recruits(side_num, last_hex);
for(std::set<std::string>::const_iterator it = recruits.begin(); it != recruits.end(); ++it) {
const unit_type *type = unit_types.find(*it);
@ -819,7 +819,7 @@ bool menu_handler::do_recruit(const std::string &name, int side_num,
//search for the unit to be recruited in recruits
int recruit_num = 0;
std::set<std::string> recruits = get_recruits_for_location(side_num, last_hex);
std::set<std::string> recruits = actions::get_recruits(side_num, last_hex);
for(std::set<std::string>::const_iterator r = recruits.begin(); ; ++r) {
if (r == recruits.end()) {
@ -848,7 +848,7 @@ bool menu_handler::do_recruit(const std::string &name, int side_num,
map_location recruited_from = map_location::null_location;
std::string msg;
{ wb::future_map_if_active future; //< start planned unit map scope if in planning mode
msg = find_recruit_location(side_num, loc, recruited_from, u_type->id());
msg = actions::find_recruit_location(side_num, loc, recruited_from, u_type->id());
} // end planned unit map scope
if (!msg.empty()) {
gui2::show_transient_message(gui_->video(), "", msg);
@ -890,7 +890,7 @@ void menu_handler::recall(int side_num, const map_location &last_hex)
std::vector<const unit*> recall_list_team;
{ wb::future_map future; // ensures recall list has planned recalls removed
recall_list_team = get_recalls_for_location(side_num, last_hex);
recall_list_team = actions::get_recalls(side_num, last_hex);
}
gui_->draw(); //clear the old menu
@ -1039,7 +1039,7 @@ void menu_handler::recall(int side_num, const map_location &last_hex)
map_location recall_from = map_location::null_location;
std::string err;
{ wb::future_map_if_active future; // future unit map removes invisible units from map, don't do this outside of planning mode
err = find_recall_location(side_num, recall_location, recall_from, *(recall_list_team[res]));
err = actions::find_recall_location(side_num, recall_location, recall_from, *(recall_list_team[res]));
} // end planned unit map scope
if(!err.empty()) {
gui2::show_transient_message(gui_->video(), "", err);

View file

@ -1015,7 +1015,7 @@ bool do_replay_handle(int side_num, const std::string &do_untill)
continue;
}
const std::string res = find_recruit_location(side_num, loc, from, u_type->id());
const std::string res = actions::find_recruit_location(side_num, loc, from, u_type->id());
const int beginning_gold = current_team.gold();
if (res.empty()) {