Merge branch 'reference_count_units'

This commit is contained in:
Chris Beck 2014-06-15 15:04:29 -04:00
commit 35180b82d1
76 changed files with 533 additions and 414 deletions

View file

@ -21,9 +21,11 @@
#include "construct_dialog.hpp"
#include "display.hpp"
#include "formula_string_utils.hpp"
#include "gettext.hpp"
#include "marked-up_text.hpp"
#include "sdl/alpha.hpp"
#include "util.hpp"
#include <boost/foreach.hpp>

View file

@ -41,6 +41,7 @@
#include "../synced_checkup.hpp"
#include "../synced_context.hpp"
#include "../team.hpp"
#include "../unit.hpp"
#include "../unit_display.hpp"
#include "../variable.hpp"
#include "../whiteboard/manager.hpp"
@ -189,10 +190,11 @@ void unit_creator::add_unit(const config &cfg, const vconfig* vcfg)
bool animate = temp_cfg["animate"].to_bool();
temp_cfg.remove_attribute("animate");
std::vector<unit> &recall_list = team_.recall_list();
std::vector<unit>::iterator recall_list_element = find_if_matches_id(recall_list, id);
std::vector<UnitPtr > &recall_list = team_.recall_list();
std::vector<UnitPtr >::iterator recall_list_it = find_if_matches_id(recall_list, id);
UnitPtr & recall_list_element = *recall_list_it;
if ( recall_list_element == recall_list.end() ) {
if ( recall_list_it == recall_list.end() ) {
//make a temporary unit
boost::scoped_ptr<unit> temp_unit(new unit(temp_cfg, true, vcfg));
map_location loc = find_location(temp_cfg, temp_unit.get());
@ -206,7 +208,8 @@ void unit_creator::add_unit(const config &cfg, const vconfig* vcfg)
else if ( add_to_recall_ ) {
//add to recall list
unit *new_unit = temp_unit.get();
recall_list.push_back(*new_unit);
UnitPtr temp_ptr = UnitPtr(new unit(*new_unit));
recall_list.push_back(temp_ptr);
DBG_NG << "inserting unit with id=["<<id<<"] on recall list for side " << new_unit->side() << "\n";
preferences::encountered_units().insert(new_unit->type_id());
}
@ -286,6 +289,12 @@ bool can_recruit_from(const map_location& leader_loc, int side)
!= map_location::null_location();
}
bool can_recruit_from(const unit& leader)
{
return can_recruit_from(leader.get_location(), leader.side());
}
/**
* Checks to see if a leader at @a leader_loc could recruit on @a recruit_loc.
* This takes into account terrain, shroud (for side @a side), and whether or
@ -328,6 +337,11 @@ bool can_recruit_on(const map_location& leader_loc, const map_location& recruit_
return !rt.steps.empty();
}
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 {
@ -402,26 +416,29 @@ namespace { // Helpers for get_recalls()
* 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,
void add_leader_filtered_recalls(const UnitConstPtr leader,
std::vector< UnitConstPtr > & 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 team& leader_team = (*resources::teams)[leader->side()-1];
const std::vector<UnitPtr >& recall_list = leader_team.recall_list();
const std::string& save_id = leader_team.save_id();
BOOST_FOREACH(const unit& recall_unit, recall_list)
BOOST_FOREACH(const UnitConstPtr & recall_unit_ptr, recall_list)
{
const unit & recall_unit = *recall_unit_ptr;
// 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 std::vector<UnitPtr >::const_iterator rit = find_if_matches_id(recall_list, recall_unit.id());
if ( recall_unit.matches_filter(vconfig(leader.recall_filter()), map_location::null_location()) )
scoped_recall_unit this_unit("this_unit", save_id, rit - recall_list.begin());
if ( recall_unit.matches_filter(vconfig(leader->recall_filter()), map_location::null_location()) )
{
result.push_back(&recall_unit);
result.push_back(recall_unit_ptr);
if ( already_added != NULL )
already_added->insert(underlying_id);
}
@ -430,11 +447,11 @@ namespace { // Helpers for get_recalls()
}
}// anonymous namespace
const std::vector<const unit*> get_recalls(int side, const map_location &recall_loc)
std::vector<UnitConstPtr > get_recalls(int side, const map_location &recall_loc)
{
LOG_NG << "getting recall list for side " << side << " at location " << recall_loc << "\n";
std::vector<const unit*> result;
std::vector<UnitConstPtr > result;
/*
* We have three use cases:
@ -449,14 +466,14 @@ const std::vector<const unit*> get_recalls(int side, const map_location &recall_
// Check for a leader at recall_loc (means we are recalling from there,
// rather than to there).
unit_map::const_iterator find_it = resources::units->find(recall_loc);
const unit_map::const_iterator find_it = resources::units->find(recall_loc);
if ( find_it != resources::units->end() ) {
if ( find_it->can_recruit() && find_it->side() == side &&
resources::gameboard->map().is_keep(recall_loc) )
{
// We have been requested to get the recalls for this
// particular leader.
add_leader_filtered_recalls(*find_it, result);
add_leader_filtered_recalls(find_it.get_shared_ptr(), result);
return result;
}
else if ( find_it->is_visible_to_team((*resources::teams)[side-1], resources::gameboard->map(), false) )
@ -482,17 +499,17 @@ const std::vector<const unit*> get_recalls(int side, const map_location &recall_
continue;
leader_in_place= true;
add_leader_filtered_recalls(*u, result, &valid_local_recalls);
add_leader_filtered_recalls(u.get_shared_ptr(), result, &valid_local_recalls);
}
}
if ( !leader_in_place )
{
// Return the full recall list.
const std::vector<unit>& recall_list = (*resources::teams)[side-1].recall_list();
BOOST_FOREACH(const unit &recall, recall_list)
const std::vector< UnitPtr >& recall_list = (*resources::teams)[side-1].recall_list();
BOOST_FOREACH(const UnitConstPtr & recall, recall_list)
{
result.push_back(&recall);
result.push_back(recall);
}
}
@ -515,9 +532,10 @@ namespace { // Helpers for check_recall_location()
return RECRUIT_NO_LEADER;
// Make sure the recalling unit can recall this specific unit.
const team& recall_team = (*resources::teams)[recaller.side()-1];
team& recall_team = (*resources::teams)[recaller.side()-1];
std::vector<UnitPtr >::iterator it = find_if_matches_id(recall_team.recall_list(), recall_unit.id());
scoped_recall_unit this_unit("this_unit", recall_team.save_id(),
&recall_unit - &recall_team.recall_list()[0]);
it - recall_team.recall_list().begin());
if ( !recall_unit.matches_filter(vconfig(recaller.recall_filter()),
map_location::null_location()) )
return RECRUIT_NO_ABLE_LEADER;
@ -966,12 +984,12 @@ bool place_recruit(const unit &u, const map_location &recruit_location, const ma
void recruit_unit(const unit_type & u_type, int side_num, const map_location & loc,
const map_location & from, bool show, bool use_undo)
{
const unit new_unit(u_type, side_num, true);
const UnitPtr new_unit = UnitPtr( new unit(u_type, side_num, true));
// Place the recruit.
bool mutated = place_recruit(new_unit, loc, from, u_type.cost(), false, show);
statistics::recruit_unit(new_unit);
bool mutated = place_recruit(*new_unit, loc, from, u_type.cost(), false, show);
statistics::recruit_unit(*new_unit);
// To speed things a bit, don't bother with the undo stack during
// an AI turn. The AI will not undo nor delay shroud updates.
@ -999,16 +1017,16 @@ bool recall_unit(const std::string & id, team & current_team,
const map_location & loc, const map_location & from,
bool show, bool use_undo)
{
std::vector<unit> & recall_list = current_team.recall_list();
std::vector<UnitPtr > & recall_list = current_team.recall_list();
// Find the unit to recall.
std::vector<unit>::iterator recall_it = find_if_matches_id(recall_list, id);
std::vector<UnitPtr >::iterator recall_it = find_if_matches_id(recall_list, id);
if ( recall_it == recall_list.end() )
return false;
// Make a copy of the unit before erasing it from the list.
unit recall(*recall_it);
UnitPtr recall(*recall_it);
recall_list.erase(recall_it);
// ** IMPORTANT: id might become invalid at this point!
// (Use recall.id() instead, if needed.)
@ -1017,15 +1035,15 @@ bool recall_unit(const std::string & id, team & current_team,
// We also check to see if a custom unit level recall has been set if not,
// we use the team's recall cost otherwise the unit's.
bool mutated;
if (recall.recall_cost() < 0) {
mutated = place_recruit(recall, loc, from, current_team.recall_cost(),
if (recall->recall_cost() < 0) {
mutated = place_recruit(*recall, loc, from, current_team.recall_cost(),
true, show);
}
else {
mutated = place_recruit(recall, loc, from, recall.recall_cost(),
mutated = place_recruit(*recall, loc, from, recall->recall_cost(),
true, show);
}
statistics::recall_unit(recall);
statistics::recall_unit(*recall);
// To speed things a bit, don't bother with the undo stack during
// an AI turn. The AI will not undo nor delay shroud updates.

View file

@ -21,12 +21,13 @@
#ifndef ACTIONS_CREATE_H_INCLUDED
#define ACTIONS_CREATE_H_INCLUDED
class config;
class team;
class vconfig;
class config;
class team;
class unit_type;
class vconfig;
#include "../map_location.hpp"
#include "../unit.hpp"
#include "../unit_ptr.hpp"
class unit_creator {
@ -71,16 +72,14 @@ private:
bool can_recruit_from(const map_location& leader_loc, int side);
/// Checks to see if @a leader (assumed a leader) can recruit somewhere.
/// This takes into account terrain, shroud, and the presence of visible units.
inline bool can_recruit_from(const unit& leader)
{ return can_recruit_from(leader.get_location(), leader.side()); }
bool can_recruit_from(const unit& leader);
/// Checks to see if a leader at @a leader_loc could recruit on @a recruit_loc.
bool can_recruit_on(const map_location& leader_loc, const map_location& recruit_loc, int side);
/// Checks to see if @a leader (assumed a leader) can recruit on @a recruit_loc.
/// This takes into account terrain, shroud, and whether or not there is already
/// a visible unit at recruit_loc.
inline bool can_recruit_on(const unit& leader, const map_location& recruit_loc)
{ return can_recruit_on(leader.get_location(), recruit_loc, leader.side()); }
bool can_recruit_on(const unit& leader, const map_location& recruit_loc);
namespace actions {
@ -190,7 +189,7 @@ const std::set<std::string> get_recruits(int side, const map_location &recruit_l
* @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(int side, const map_location &recall_loc);
std::vector<UnitConstPtr > get_recalls(int side, const map_location &recall_loc);
/**
* Place a unit into the game.

View file

@ -1073,7 +1073,7 @@ namespace { // Private helpers for move_unit()
if ( mover_valid ) {
// MP_COUNTDOWN: added param
undo_stack->add_move(
*move_it_, begin_, real_end_, orig_moves_,
move_it_.get_shared_ptr(), begin_, real_end_, orig_moves_,
action_time_bonus, orig_village_owner, orig_dir_);
}

View file

@ -56,14 +56,14 @@ undo_list::undo_action::~undo_action()
struct undo_list::dismiss_action : undo_list::undo_action {
unit dismissed_unit;
UnitPtr dismissed_unit;
explicit dismiss_action(const unit& dismissed) : undo_action(),
dismissed_unit(dismissed)
explicit dismiss_action(const UnitConstPtr dismissed) : undo_action(),
dismissed_unit(new unit(*dismissed))
{}
explicit dismiss_action(const config & unit_cfg) : undo_action(),
dismissed_unit(unit_cfg)
dismissed_unit(new unit(unit_cfg))
{}
virtual ~dismiss_action();
@ -86,7 +86,7 @@ struct undo_list::move_action : undo_list::undo_action {
map_location goto_hex;
move_action(const unit& moved,
move_action(const UnitConstPtr moved,
const std::vector<map_location>::const_iterator & begin,
const std::vector<map_location>::const_iterator & end,
int sm, int timebonus, int orig, const map_location::DIRECTION dir) :
@ -94,8 +94,8 @@ struct undo_list::move_action : undo_list::undo_action {
starting_moves(sm),
original_village_owner(orig),
countdown_time_bonus(timebonus),
starting_dir(dir == map_location::NDIRECTIONS ? moved.facing() : dir),
goto_hex(moved.get_goto())
starting_dir(dir == map_location::NDIRECTIONS ? moved->facing() : dir),
goto_hex(moved->get_goto())
{}
move_action(const config & unit_cfg, const config & route_cfg,
int sm, int timebonus, int orig, const map_location::DIRECTION dir) :
@ -127,10 +127,10 @@ struct undo_list::recall_action : undo_list::undo_action {
map_location recall_from;
recall_action(const unit& recalled, const map_location& loc,
recall_action(const UnitConstPtr recalled, const map_location& loc,
const map_location& from) :
undo_action(recalled, loc),
id(recalled.id()),
id(recalled->id()),
recall_from(from)
{}
recall_action(const config & unit_cfg, const map_location & loc,
@ -157,10 +157,10 @@ struct undo_list::recruit_action : undo_list::undo_action {
map_location recruit_from;
recruit_action(const unit& recruited, const map_location& loc,
recruit_action(const UnitConstPtr recruited, const map_location& loc,
const map_location& from) :
undo_action(recruited, loc),
u_type(recruited.type()),
u_type(recruited->type()),
recruit_from(from)
{}
recruit_action(const config & unit_cfg, const unit_type & type,
@ -291,7 +291,7 @@ void undo_list::dismiss_action::write(config & cfg) const
{
cfg.add_child("replay_data", replay_data);
cfg["type"] = "dismiss";
dismissed_unit.write(cfg.add_child("unit"));
dismissed_unit->write(cfg.add_child("unit"));
}
/**
@ -399,7 +399,7 @@ void undo_list::add_auto_shroud(bool turned_on)
/**
* Adds a dismissal to the undo stack.
*/
void undo_list::add_dismissal(const unit & u)
void undo_list::add_dismissal(const UnitConstPtr u)
{
add(new dismiss_action(u));
}
@ -407,7 +407,7 @@ void undo_list::add_dismissal(const unit & u)
/**
* Adds a move to the undo stack.
*/
void undo_list::add_move(const unit& u,
void undo_list::add_move(const UnitConstPtr u,
const std::vector<map_location>::const_iterator & begin,
const std::vector<map_location>::const_iterator & end,
int start_moves, int timebonus, int village_owner,
@ -419,7 +419,7 @@ void undo_list::add_move(const unit& u,
/**
* Adds a recall to the undo stack.
*/
void undo_list::add_recall(const unit& u, const map_location& loc,
void undo_list::add_recall(const UnitConstPtr u, const map_location& loc,
const map_location& from)
{
add(new recall_action(u, loc, from));
@ -428,7 +428,7 @@ void undo_list::add_recall(const unit& u, const map_location& loc,
/**
* Adds a recruit to the undo stack.
*/
void undo_list::add_recruit(const unit& u, const map_location& loc,
void undo_list::add_recruit(const UnitConstPtr u, const map_location& loc,
const map_location& from)
{
add(new recruit_action(u, loc, from));
@ -648,9 +648,13 @@ bool undo_list::recall_action::undo(int side, undo_list & /*undos*/)
return false;
}
const unit &un = *un_it;
statistics::un_recall_unit(un);
int cost = statistics::un_recall_unit_cost(un);
UnitPtr un = un_it.get_shared_ptr();
if (!un) {
return false;
}
statistics::un_recall_unit(*un);
int cost = statistics::un_recall_unit_cost(*un);
if (cost < 0) {
current_team.spend_gold(-current_team.recall_cost());
}
@ -829,9 +833,7 @@ bool undo_list::dismiss_action::redo(int side)
}
recorder.redo(replay_data);
replay_data.clear();
std::vector<unit>::iterator unit_it =
find_if_matches_id(current_team.recall_list(), dismissed_unit.id());
current_team.recall_list().erase(unit_it);
erase_if_matches_id(current_team.recall_list(), dismissed_unit->id());
return true;
}
@ -853,15 +855,15 @@ bool undo_list::recall_action::redo(int side)
map_location loc = route.front();
map_location from = recall_from;
const std::vector<unit> & recalls = current_team.recall_list();
std::vector<unit>::const_iterator unit_it = find_if_matches_id(recalls, id);
const std::vector<UnitPtr > & recalls = current_team.recall_list();
std::vector<UnitPtr >::const_iterator unit_it = find_if_matches_id(recalls, id);
if ( unit_it == recalls.end() ) {
ERR_NG << "Trying to redo a recall of '" << id
<< "', but that unit is not in the recall list.";
return false;
}
const std::string &msg = find_recall_location(side, loc, from, *unit_it);
const std::string &msg = find_recall_location(side, loc, from, **unit_it);
if ( msg.empty() ) {
recorder.redo(replay_data);
replay_data.clear();

View file

@ -22,13 +22,12 @@
#include "vision.hpp"
#include "../map_location.hpp"
#include "../unit_ptr.hpp"
#include <boost/noncopyable.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <vector>
class unit;
namespace actions {
@ -39,18 +38,18 @@ class undo_list : boost::noncopyable {
/// Each type of action gets its own derived type.
struct undo_action : boost::noncopyable {
/// Constructor for move actions.
undo_action(const unit& u,
undo_action(const UnitConstPtr u,
const std::vector<map_location>::const_iterator & begin,
const std::vector<map_location>::const_iterator & end) :
route(begin, end),
view_info(new clearer_info(u))
view_info(new clearer_info(*u))
{
}
/// Constructor for recruit and recall actions.
/// These types of actions are guaranteed to have a non-empty route.
undo_action(const unit& u, const map_location& loc) :
undo_action(const UnitConstPtr u, const map_location& loc) :
route(1, loc),
view_info(new clearer_info(u))
view_info(new clearer_info(*u))
{}
/// Constructor from a config storing the view info.
/// Does not set @a route.
@ -125,18 +124,18 @@ public:
/// Adds an auto-shroud toggle to the undo stack.
void add_auto_shroud(bool turned_on);
/// Adds a dismissal to the undo stack.
void add_dismissal(const unit & u);
void add_dismissal(const UnitConstPtr u);
/// Adds a move to the undo stack.
void add_move(const unit& u,
void add_move(const UnitConstPtr u,
const std::vector<map_location>::const_iterator & begin,
const std::vector<map_location>::const_iterator & end,
int start_moves, int timebonus=0, int village_owner=-1,
const map_location::DIRECTION dir=map_location::NDIRECTIONS);
/// Adds a recall to the undo stack.
void add_recall(const unit& u, const map_location& loc,
void add_recall(const UnitConstPtr u, const map_location& loc,
const map_location& from);
/// Adds a recruit to the undo stack.
void add_recruit(const unit& u, const map_location& loc,
void add_recruit(const UnitConstPtr u, const map_location& loc,
const map_location& from);
private:
/// Adds a shroud update to the undo stack.

View file

@ -501,12 +501,12 @@ recall_result::recall_result(side_number side,
const unit * recall_result::get_recall_unit(const team &my_team)
{
const std::vector<unit>::const_iterator rec = find_if_matches_id(my_team.recall_list(), unit_id_);
const std::vector<UnitPtr >::const_iterator rec = find_if_matches_id(my_team.recall_list(), unit_id_);
if (rec == my_team.recall_list().end()) {
set_error(E_NOT_AVAILABLE_FOR_RECALLING);
return NULL;
}
return &*rec;
return rec->get();
}
bool recall_result::test_enough_gold(const team &my_team)

View file

@ -22,6 +22,7 @@
#include "property_handler.hpp"
#include "../../config.hpp"
#include "../../log.hpp"
#include "../../unit.hpp"
#include "../formula/ai.hpp"

View file

@ -25,6 +25,7 @@
#include "../formula/stage_side_formulas.hpp"
#include "../formula/stage_unit_formulas.hpp"
#include "../../log.hpp"
#include "../../unit.hpp"
namespace ai {

View file

@ -168,7 +168,7 @@ public:
, bound_unit_()
{
map_location loc(cfg["unit_x"] - 1, cfg["unit_y"] - 1); // lua and c++ coords differ by one
bound_unit_ = boost::shared_ptr<unit>(new unit(*resources::units->find(loc)));
bound_unit_ = UnitPtr(new unit(*resources::units->find(loc)));
}
virtual double evaluate()
@ -190,7 +190,7 @@ public:
this->disable(); // we do not want to execute the same sticky CA twice -> will be moved out to Lua later
}
private:
boost::shared_ptr<unit> bound_unit_;
UnitPtr bound_unit_;
};

View file

@ -39,6 +39,7 @@
#include "../mouse_handler_base.hpp"
#include "../resources.hpp"
#include "../tod_manager.hpp"
#include "../unit.hpp"
#include <boost/foreach.hpp>
@ -775,9 +776,9 @@ const moves_map& readonly_context_impl::get_possible_moves() const
}
const std::vector<unit>& readonly_context_impl::get_recall_list() const
const std::vector<UnitPtr>& readonly_context_impl::get_recall_list() const
{
static std::vector<unit> dummy_units;
static std::vector<UnitPtr> dummy_units;
///@todo 1.9: check for (level_["disallow_recall"]))
if(!current_team().persistent()) {
return dummy_units;

View file

@ -25,7 +25,7 @@
#include "../generic_event.hpp"
#include "../config.hpp"
#include "lua/unit_advancements_aspect.hpp"
#include "../unit_ptr.hpp"
//#include "../unit.hpp"
@ -298,7 +298,7 @@ public:
virtual const moves_map& get_possible_moves() const = 0;
virtual const std::vector<unit>& get_recall_list() const = 0;
virtual const std::vector<UnitPtr>& get_recall_list() const = 0;
virtual stage_ptr get_recruitment(ai_context &context) const = 0;
@ -819,7 +819,7 @@ public:
}
virtual const std::vector<unit>& get_recall_list() const
virtual const std::vector<UnitPtr>& get_recall_list() const
{
return target_->get_recall_list();
}
@ -1427,7 +1427,7 @@ public:
virtual const moves_map& get_possible_moves() const;
virtual const std::vector<unit>& get_recall_list() const;
virtual const std::vector<UnitPtr>& get_recall_list() const;
virtual stage_ptr get_recruitment(ai_context &context) const;

View file

@ -32,6 +32,7 @@
#include "../../mouse_handler_base.hpp"
#include "../../resources.hpp"
#include "../../terrain_filter.hpp"
#include "../../unit.hpp"
#include "../../unit_display.hpp"
#include "../../wml_exception.hpp"
@ -655,7 +656,8 @@ public:
: stage_(s)
{
}
std::pair<std::string, double> operator()(const unit &u) {
std::pair<std::string, double> operator()(const UnitPtr u_ptr) {
const unit & u = *u_ptr;
std::pair<std::string,int> p;
p.first = u.id();
const unit_type& u_type = u.type();
@ -761,7 +763,7 @@ bool ai_default_recruitment_stage::analyze_recall_list()
return false;
}
const std::vector<unit> &recalls = current_team().recall_list();
const std::vector<UnitPtr > &recalls = current_team().recall_list();
if (recalls.empty()) {
return false;

View file

@ -28,6 +28,7 @@
#include "../../log.hpp"
#include "../../map.hpp"
#include "../../team.hpp"
#include "../../unit.hpp"
static lg::log_domain log_ai("ai/attack");
#define LOG_AI LOG_STREAM(info, log_ai)
@ -96,7 +97,7 @@ void attack_analysis::analyze(const gamemap& map, unit_map& units,
for (m = movements.begin(); m != movements.end(); ++m) {
// We fix up units map to reflect what this would look like.
unit *up = units.extract(m->first);
UnitPtr up = units.extract(m->first);
up->set_location(m->second);
units.insert(up);
double m_aggression = aggression;

View file

@ -25,6 +25,7 @@
#include "../../map.hpp"
#include "../../resources.hpp"
#include "../../team.hpp"
#include "../../unit.hpp"
#include "../composite/goal.hpp"
#include "../../pathfind/pathfind.hpp"

View file

@ -810,8 +810,8 @@ variant formula_ai::get_value(const std::string& key) const
{
std::vector<variant> tmp;
for(std::vector<unit>::const_iterator i = current_team().recall_list().begin(); i != current_team().recall_list().end(); ++i) {
tmp.push_back( variant( new unit_callable(*i) ) );
for(std::vector<UnitPtr >::const_iterator i = current_team().recall_list().begin(); i != current_team().recall_list().end(); ++i) {
tmp.push_back( variant( new unit_callable(**i) ) );
}
return variant( &tmp );

View file

@ -119,7 +119,7 @@ static bool to_map_location(lua_State *L, int &index, map_location &res)
{
if (lua_isuserdata(L, index))
{
unit const *u = luaW_tounit(L, index);
const UnitConstPtr u = luaW_tounit(L, index);
if (!u) return false;
res = u->get_location();
++index;
@ -142,7 +142,7 @@ static int cfun_ai_get_suitable_keep(lua_State *L)
int index = 1;
ai::readonly_context &context = get_readonly_context(L);
unit const *leader;
UnitConstPtr leader;
if (lua_isuserdata(L, index))
{
leader = luaW_tounit(L, index);

View file

@ -248,15 +248,15 @@ void recruitment::execute() {
// Add recalls.
// Recalls are treated as recruits. While recruiting
// we'll check if we can do a recall instead of a recruitment.
BOOST_FOREACH(const unit& recall, current_team().recall_list()) {
BOOST_FOREACH(const UnitConstPtr & recall, current_team().recall_list()) {
// Check if this leader is allowed to recall this unit.
vconfig filter = vconfig(leader->recall_filter());
if (!recall.matches_filter(filter, map_location::null_location())) {
if (!recall->matches_filter(filter, map_location::null_location())) {
continue;
}
data.recruits.insert(recall.type_id());
data.scores[recall.type_id()] = 0.0;
global_recruits.insert(recall.type_id());
data.recruits.insert(recall->type_id());
data.scores[recall->type_id()] = 0.0;
global_recruits.insert(recall->type_id());
}
// Check if leader is in danger. (If a enemies unit can attack the leader)
@ -470,19 +470,19 @@ const std::string* recruitment::get_appropriate_recall(const std::string& type,
const data& leader_data) const {
const std::string* best_recall_id = NULL;
double best_recall_value = -1;
BOOST_FOREACH(const unit& recall_unit, current_team().recall_list()) {
if (type != recall_unit.type_id()) {
BOOST_FOREACH(const UnitConstPtr & recall_unit, current_team().recall_list()) {
if (type != recall_unit->type_id()) {
continue;
}
// Check if this leader is allowed to recall this unit.
vconfig filter = vconfig(leader_data.leader->recall_filter());
if (!recall_unit.matches_filter(filter, map_location::null_location())) {
LOG_AI_RECRUITMENT << "Refused recall because of filter: " << recall_unit.id() << "\n";
if (!recall_unit->matches_filter(filter, map_location::null_location())) {
LOG_AI_RECRUITMENT << "Refused recall because of filter: " << recall_unit->id() << "\n";
continue;
}
double average_cost_of_advanced_unit = 0;
int counter = 0;
BOOST_FOREACH(const std::string& advancement, recall_unit.advances_to()) {
BOOST_FOREACH(const std::string& advancement, recall_unit->advances_to()) {
const unit_type* advancement_type = unit_types.find(advancement);
if (!advancement_type) {
continue;
@ -494,16 +494,16 @@ const std::string* recruitment::get_appropriate_recall(const std::string& type,
average_cost_of_advanced_unit /= counter;
} else {
// Unit don't have advancements. Use cost of unit itself.
average_cost_of_advanced_unit = recall_unit.cost();
average_cost_of_advanced_unit = recall_unit->cost();
}
double xp_quantity = static_cast<double>(recall_unit.experience()) /
recall_unit.max_experience();
double recall_value = recall_unit.cost() + xp_quantity * average_cost_of_advanced_unit;
double xp_quantity = static_cast<double>(recall_unit->experience()) /
recall_unit->max_experience();
double recall_value = recall_unit->cost() + xp_quantity * average_cost_of_advanced_unit;
if (recall_value < current_team().recall_cost()) {
continue; // Unit is not worth to get recalled.
}
if (recall_value > best_recall_value) {
best_recall_id = &recall_unit.id();
best_recall_id = &recall_unit->id();
best_recall_value = recall_value;
}
}

View file

@ -23,6 +23,7 @@
#include "../util.hpp"
#include "../resources.hpp"
#include "../team.hpp"
#include "../unit.hpp"
#include "../tod_manager.hpp"
static lg::log_domain log_ai_testing("ai/testing");

View file

@ -29,6 +29,7 @@
#include "../../map.hpp"
#include "../../resources.hpp"
#include "../../team.hpp"
#include "../../unit.hpp"
#include "../../pathfind/pathfind.hpp"
#include "../../pathfind/teleport.hpp"

View file

@ -26,6 +26,7 @@
#include "../../map.hpp"
#include "../../resources.hpp"
#include "../../team.hpp"
#include "../../unit.hpp"
#include "../../terrain_filter.hpp"
#include "../../pathfind/pathfind.hpp"

View file

@ -29,6 +29,8 @@
#include "../../map.hpp"
#include "../../resources.hpp"
#include "../../team.hpp"
#include "../../unit.hpp"
#include "../../unit_types.hpp"
#include "../../wml_exception.hpp"
#include "../../pathfind/pathfind.hpp"

View file

@ -18,6 +18,7 @@
#include "formula_callable.hpp"
#include "map.hpp"
#include "team.hpp"
#include "unit.hpp"
#define CALLABLE_WRAPPER_START(klass) \
class klass##_callable : public game_logic::formula_callable { \

View file

@ -18,6 +18,7 @@
#include "config.hpp"
#include "team.hpp"
#include "unit.hpp"
#include "gamestatus.hpp"
#include <boost/foreach.hpp>
#include <cassert>
@ -53,9 +54,9 @@ carryover::carryover(const team& t, const int gold, const bool add)
, recall_list_()
, save_id_(t.save_id())
{
BOOST_FOREACH(const unit& u, t.recall_list()) {
BOOST_FOREACH(const UnitConstPtr & u, t.recall_list()) {
recall_list_.push_back(config());
u.write(recall_list_.back());
u->write(recall_list_.back());
}
}
@ -110,9 +111,9 @@ void carryover::update_carryover(const team& t, const int gold, const bool add){
current_player_ = t.current_player();
name_ = t.name();
previous_recruits_.insert(t.recruits().begin(), t.recruits().end());
BOOST_FOREACH(const unit& u, t.recall_list()) {
BOOST_FOREACH(const UnitConstPtr & u, t.recall_list()) {
recall_list_.push_back(config());
u.write(recall_list_.back());
u->write(recall_list_.back());
}
}

View file

@ -18,6 +18,7 @@
#include "construct_dialog.hpp"
#include "display.hpp"
#include "formula_string_utils.hpp"
#include "gettext.hpp"
#include "sound.hpp"
#include "log.hpp"

View file

@ -85,20 +85,21 @@ namespace
class delete_recall_unit : public gui::dialog_button_action
{
public:
delete_recall_unit(display& disp, gui::filter_textbox& filter, const std::vector<const unit*>& units) : disp_(disp), filter_(filter), units_(units) {}
delete_recall_unit(display& disp, gui::filter_textbox& filter, const std::vector<UnitConstPtr >& units) : disp_(disp), filter_(filter), units_(units) {}
private:
gui::dialog_button_action::RESULT button_pressed(int menu_selection);
display& disp_;
gui::filter_textbox& filter_;
const std::vector<const unit*>& units_;
const std::vector<UnitConstPtr >& units_;
};
gui::dialog_button_action::RESULT delete_recall_unit::button_pressed(int menu_selection)
{
const size_t index = size_t(filter_.get_index(menu_selection));
if(index < units_.size()) {
const unit &u = *(units_[index]);
const UnitConstPtr & u_ptr = units_[index];
const unit & u = *u_ptr;
//If the unit is of level > 1, or is close to advancing,
//we warn the player about it
@ -127,17 +128,17 @@ gui::dialog_button_action::RESULT delete_recall_unit::button_pressed(int menu_se
// Remove the item from filter_textbox memory
filter_.delete_item(menu_selection);
//add dismissal to the undo stack
resources::undo_stack->add_dismissal(u);
resources::undo_stack->add_dismissal(u_ptr);
// Find the unit in the recall list.
std::vector<unit>& recall_list = (*resources::teams)[u.side() -1].recall_list();
std::vector<UnitPtr >& recall_list = (*resources::teams)[u.side() -1].recall_list();
assert(!recall_list.empty());
std::vector<unit>::iterator dismissed_unit =
std::vector<UnitPtr >::iterator dismissed_unit =
find_if_matches_id(recall_list, u.id());
assert(dismissed_unit != recall_list.end());
// Record the dismissal, then delete the unit.
synced_context::run_in_synced_context("disband", replay_helper::get_disband(dismissed_unit->id()));
synced_context::run_in_synced_context("disband", replay_helper::get_disband((*dismissed_unit)->id()));
//recorder.add_disband(dismissed_unit->id());
//recall_list.erase(dismissed_unit);
@ -441,9 +442,9 @@ int recruit_dialog(display& disp, std::vector< const unit_type* >& units, const
#ifdef LOW_MEM
int recall_dialog(display& disp, std::vector< const unit* >& units, int /*side*/, const std::string& title_suffix, const int team_recall_cost)
int recall_dialog(display& disp, std::vector< UnitConstPtr >& units, int /*side*/, const std::string& title_suffix, const int team_recall_cost)
#else
int recall_dialog(display& disp, std::vector< const unit* >& units, int side, const std::string& title_suffix, const int team_recall_cost)
int recall_dialog(display& disp, std::vector< UnitConstPtr >& units, int side, const std::string& title_suffix, const int team_recall_cost)
#endif
{
std::vector<std::string> options, options_to_filter;
@ -462,7 +463,7 @@ int recall_dialog(display& disp, std::vector< const unit* >& units, int side, co
options.push_back(heading.str());
options_to_filter.push_back(options.back());
BOOST_FOREACH(const unit* u, units)
BOOST_FOREACH(const UnitConstPtr & u, units)
{
std::stringstream option, option_to_filter;
std::string name = u->name();
@ -1207,13 +1208,13 @@ void unit_preview_pane::draw_contents()
}
}
units_list_preview_pane::units_list_preview_pane(const unit *u, TYPE type, bool on_left_side) :
units_list_preview_pane::units_list_preview_pane(UnitConstPtr u, TYPE type, bool on_left_side) :
unit_preview_pane(NULL, type, on_left_side),
units_(1, u)
{
}
units_list_preview_pane::units_list_preview_pane(const std::vector<const unit *> &units,
units_list_preview_pane::units_list_preview_pane(const std::vector<UnitConstPtr > &units,
const gui::filter_textbox* filter, TYPE type, bool on_left_side) :
unit_preview_pane(filter, type, on_left_side),
units_(units)
@ -1226,7 +1227,7 @@ units_list_preview_pane::units_list_preview_pane(const std::vector<unit> &units,
units_(units.size())
{
for (unsigned i = 0; i < units.size(); ++i)
units_[i] = &units[i];
units_[i] = UnitConstPtr (new unit(units[i]));
}
size_t units_list_preview_pane::size() const

View file

@ -26,6 +26,7 @@ class terrain_type;
#include "map_location.hpp"
#include "construct_dialog.hpp"
#include "network.hpp"
#include "unit_ptr.hpp"
#include "ai/lua/unit_advancements_aspect.hpp"
namespace dialogs {
@ -59,7 +60,7 @@ std::string load_game_dialog(display& disp, const config& terrain_config, bool*
int recruit_dialog(display& disp, std::vector<const unit_type*>& units, const std::vector<std::string>& items, int side, const std::string& title_suffix);
int recall_dialog(display& disp, std::vector<const unit*>& units, int side, const std::string& title_suffix, const int team_recall_cost);
int recall_dialog(display& disp, std::vector<UnitConstPtr >& units, int side, const std::string& title_suffix, const int team_recall_cost);
/** Show unit-stats in a side-pane to unit-list, recall-list, etc. */
class unit_preview_pane : public gui::preview_pane
@ -110,8 +111,8 @@ private:
class units_list_preview_pane : public dialogs::unit_preview_pane
{
public:
units_list_preview_pane(const unit *u, TYPE type = SHOW_ALL, bool left_side = true);
units_list_preview_pane(const std::vector<const unit *> &units,
units_list_preview_pane(UnitConstPtr u, TYPE type = SHOW_ALL, bool left_side = true);
units_list_preview_pane(const std::vector<UnitConstPtr > &units,
const gui::filter_textbox *filter = NULL,
TYPE type = SHOW_ALL, bool left_side = true);
units_list_preview_pane(const std::vector<unit> &units,
@ -123,7 +124,7 @@ private:
const details get_details() const;
void process_event();
std::vector<const unit *> units_;
std::vector<UnitConstPtr > units_;
};

View file

@ -43,8 +43,10 @@ namespace wb {
class manager;
}
#include "animated.hpp"
#include "display_context.hpp"
#include "font.hpp"
#include "image.hpp" //only needed for enums (!)
#include "key.hpp"
#include "team.hpp"
#include "time_of_day.hpp"

View file

@ -16,6 +16,7 @@
#include "editor_display.hpp"
#include "reports.hpp"
#include "terrain_builder.hpp"
#include "unit_map.hpp"
#include <boost/shared_ptr.hpp>

View file

@ -25,6 +25,7 @@
#include "serialization/binary_or_text.hpp"
#include "serialization/parser.hpp"
#include "team.hpp"
#include "unit.hpp"
#include "wml_exception.hpp"

View file

@ -21,6 +21,7 @@
#include "tooltips.hpp"
#include "overlay.hpp"
#include "filesystem.hpp"
#include "unit_types.hpp"
#include "editor/action/mouse/mouse_action.hpp"

View file

@ -21,6 +21,7 @@
#include "terrain_palettes.hpp"
#include "../../gettext.hpp"
#include "../../formula_string_utils.hpp"
#include <boost/foreach.hpp>

View file

@ -21,6 +21,8 @@
#include "editor_palettes.hpp"
#include "../../unit_types.hpp"
namespace editor {
//std::string get_selected_terrain();

View file

@ -74,12 +74,13 @@ void game_board::set_all_units_user_end_turn() {
}
void game_board::all_survivors_to_recall() {
BOOST_FOREACH (unit & un, units_) {
if (teams_[un.side() - 1].persistent()) {
un.new_turn();
un.new_scenario();
for (unit_map::iterator it = units_.begin(); it != units_.end(); it++) {
UnitPtr un = it.get_shared_ptr();
if (teams_[un->side() - 1].persistent()) {
un->new_turn();
un->new_scenario();
#if 0
teams_[un.side() - 1].recall_list().push_back(un);
teams_[un->side() - 1].recall_list().push_back(un);
#endif
}
}
@ -140,14 +141,14 @@ void game_board::side_change_controller(int side_num, team::CONTROLLER ctrl, con
}
}
bool game_board::try_add_unit_to_recall_list(const map_location& loc, const unit& u)
bool game_board::try_add_unit_to_recall_list(const map_location& loc, const UnitPtr u)
{
if(teams_[u.side()-1].persistent()) {
teams_[u.side()-1].recall_list().push_back(u);
if(teams_[u->side()-1].persistent()) {
teams_[u->side()-1].recall_list().push_back(u);
return true;
} else {
ERR_RG << "unit with id " << u.id() << ": location (" << loc.x << "," << loc.y <<") is not on the map, and player "
<< u.side() << " has no recall list.\n";
ERR_RG << "unit with id " << u->id() << ": location (" << loc.x << "," << loc.y <<") is not on the map, and player "
<< u->side() << " has no recall list.\n";
return false;
}
}
@ -167,7 +168,7 @@ boost::optional<std::string> game_board::replace_map(const gamemap & newmap) {
for (unit_map::iterator itor = units_.begin(); itor != units_.end(); ) {
if (!newmap.on_board(itor->get_location())) {
if (!try_add_unit_to_recall_list(itor->get_location(), *itor)) {
if (!try_add_unit_to_recall_list(itor->get_location(), itor.get_shared_ptr())) {
*ret = std::string("replace_map: Cannot add a unit that would become off-map to the recall list\n");
}
units_.erase(itor++);
@ -256,9 +257,9 @@ void game_board::write_config(config & cfg) const {
}
//recall list
{
BOOST_FOREACH(const unit & j, t->recall_list()) {
BOOST_FOREACH(const UnitConstPtr & j, t->recall_list()) {
config& u = side.add_child("unit");
j.write(u);
j->write(u);
}
}
}
@ -322,7 +323,7 @@ temporary_unit_remover::~temporary_unit_remover()
temporary_unit_mover::temporary_unit_mover(unit_map& m, const map_location& src,
const map_location& dst, int new_moves)
: m_(m), src_(src), dst_(dst), old_moves_(-1),
temp_(src == dst ? NULL : m_.extract(dst))
temp_(src == dst ? UnitPtr() : m_.extract(dst))
{
std::pair<unit_map::iterator, bool> move_result = m_.move(src_, dst_);
@ -337,7 +338,7 @@ temporary_unit_mover::temporary_unit_mover(unit_map& m, const map_location& src,
temporary_unit_mover::temporary_unit_mover(game_board& b, const map_location& src,
const map_location& dst, int new_moves)
: m_(b.units_), src_(src), dst_(dst), old_moves_(-1),
temp_(src == dst ? NULL : m_.extract(dst))
temp_(src == dst ? UnitPtr() : m_.extract(dst))
{
std::pair<unit_map::iterator, bool> move_result = m_.move(src_, dst_);
@ -356,7 +357,7 @@ temporary_unit_mover::temporary_unit_mover(game_board& b, const map_location& sr
temporary_unit_mover::temporary_unit_mover(unit_map& m, const map_location& src,
const map_location& dst)
: m_(m), src_(src), dst_(dst), old_moves_(-1),
temp_(src == dst ? NULL : m_.extract(dst))
temp_(src == dst ? UnitPtr() : m_.extract(dst))
{
m_.move(src_, dst_);
}
@ -364,7 +365,7 @@ temporary_unit_mover::temporary_unit_mover(unit_map& m, const map_location& src,
temporary_unit_mover::temporary_unit_mover(game_board& b, const map_location& src,
const map_location& dst)
: m_(b.units_), src_(src), dst_(dst), old_moves_(-1),
temp_(src == dst ? NULL : m_.extract(dst))
temp_(src == dst ? UnitPtr() : m_.extract(dst))
{
m_.move(src_, dst_);
}

View file

@ -23,6 +23,7 @@
#include <boost/optional.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <vector>
class config;
@ -115,7 +116,7 @@ class game_board : public display_context {
// Manipulator from actionwml
bool try_add_unit_to_recall_list(const map_location& loc, const unit& u);
bool try_add_unit_to_recall_list(const map_location& loc, const UnitPtr u);
boost::optional<std::string> replace_map (const gamemap & r);
void overlay_map (const gamemap & o, const config & cfg, map_location loc, bool border);
@ -153,7 +154,7 @@ struct temporary_unit_placer
private:
unit_map& m_;
const map_location loc_;
unit *temp_;
UnitPtr temp_;
};
// Begin Temporary Unit Move Structs
@ -174,7 +175,7 @@ struct temporary_unit_remover
private:
unit_map& m_;
const map_location loc_;
unit *temp_;
UnitPtr temp_;
};
@ -200,7 +201,7 @@ private:
const map_location src_;
const map_location dst_;
int old_moves_;
unit *temp_;
UnitPtr temp_;
};

View file

@ -28,6 +28,7 @@ class game_board;
#include "chat_events.hpp"
#include "display.hpp"
#include "pathfind/pathfind.hpp"
#include "unit.hpp" // TODO: Refactor so that this is not necessary
#include <deque>

View file

@ -970,10 +970,10 @@ WML_HANDLER_FUNCTION(kill, event_info, cfg)
for(std::vector<team>::iterator pi = resources::teams->begin();
pi!=resources::teams->end(); ++pi)
{
std::vector<unit>& avail_units = pi->recall_list();
for(std::vector<unit>::iterator j = avail_units.begin(); j != avail_units.end();) {
std::vector<UnitPtr>& avail_units = pi->recall_list();
for(std::vector<UnitPtr>::iterator j = avail_units.begin(); j != avail_units.end();) {
scoped_recall_unit auto_store("this_unit", pi->save_id(), j - avail_units.begin());
if (j->matches_filter(cfg, map_location())) {
if ((*j)->matches_filter(cfg, map_location())) {
j = avail_units.erase(j);
} else {
++j;
@ -1574,16 +1574,16 @@ WML_HANDLER_FUNCTION(recall, /*event_info*/, cfg)
continue;
}
std::vector<unit>& avail = (*resources::teams)[index].recall_list();
std::vector<UnitPtr>& avail = (*resources::teams)[index].recall_list();
std::vector<unit_map::unit_iterator> leaders = resources::units->find_leaders(index + 1);
for(std::vector<unit>::iterator u = avail.begin(); u != avail.end(); ++u) {
for(std::vector<UnitPtr>::iterator u = avail.begin(); u != avail.end(); ++u) {
DBG_NG << "checking unit against filter...\n";
scoped_recall_unit auto_store("this_unit", player_id, u - avail.begin());
if (u->matches_filter(unit_filter, map_location())) {
DBG_NG << u->id() << " matched the filter...\n";
const unit to_recruit(*u);
const unit* pass_check = &to_recruit;
if ((*u)->matches_filter(unit_filter, map_location())) {
DBG_NG << (*u)->id() << " matched the filter...\n";
const UnitPtr to_recruit = *u;
const unit* pass_check = to_recruit.get();
if(!cfg["check_passability"].to_bool(true)) pass_check = NULL;
const map_location cfg_loc = cfg_to_loc(cfg);
@ -1592,7 +1592,7 @@ WML_HANDLER_FUNCTION(recall, /*event_info*/, cfg)
DBG_NG << "...considering " + leader->id() + " as the recalling leader...\n";
map_location loc = cfg_loc;
if ( (leader_filter.null() || leader->matches_filter(leader_filter)) &&
u->matches_filter(vconfig(leader->recall_filter()), map_location()) ) {
(*u)->matches_filter(vconfig(leader->recall_filter()), map_location()) ) {
DBG_NG << "...matched the leader filter and is able to recall the unit.\n";
if(!resources::gameboard->map().on_board(loc))
loc = leader->get_location();
@ -1601,7 +1601,7 @@ WML_HANDLER_FUNCTION(recall, /*event_info*/, cfg)
if(resources::gameboard->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
actions::place_recruit(to_recruit, loc, leader->get_location(), 0, 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;
@ -1617,7 +1617,7 @@ 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();
actions::place_recruit(to_recruit, loc, null_location, 0, true, cfg["show"].to_bool(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;
}
@ -1795,10 +1795,10 @@ WML_HANDLER_FUNCTION(role, /*event_info*/, cfg)
}
// Iterate over the player's recall list to find a match
for(size_t i=0; i < pi->recall_list().size(); ++i) {
unit& u = pi->recall_list()[i];
UnitPtr & u = pi->recall_list()[i];
scoped_recall_unit auto_store("this_unit", player_id, i);
if (u.matches_filter(filter, map_location())) {
u.set_role(cfg["role"]);
if (u->matches_filter(filter, map_location())) {
u->set_role(cfg["role"]);
found=true;
break;
}
@ -2513,16 +2513,16 @@ WML_HANDLER_FUNCTION(unstore_unit, /*event_info*/, cfg)
try {
config tmp_cfg(var);
const unit u(tmp_cfg, false);
const UnitPtr u = UnitPtr( new unit(tmp_cfg, false));
preferences::encountered_units().insert(u.type_id());
preferences::encountered_units().insert(u->type_id());
map_location loc = cfg_to_loc(
(cfg.has_attribute("x") && cfg.has_attribute("y")) ? cfg : vconfig(var));
const bool advance = cfg["advance"].to_bool(true);
if(resources::gameboard->map().on_board(loc)) {
if (cfg["find_vacant"].to_bool()) {
const unit* pass_check = NULL;
if (cfg["check_passability"].to_bool(true)) pass_check = &u;
if (cfg["check_passability"].to_bool(true)) pass_check = u.get();
loc = pathfind::find_vacant_tile(
loc,
pathfind::VACANT_ANY,
@ -2530,7 +2530,7 @@ WML_HANDLER_FUNCTION(unstore_unit, /*event_info*/, cfg)
}
resources::units->erase(loc);
resources::units->add(loc, u);
resources::units->add(loc, *u);
std::string text = cfg["text"];
play_controller *controller = resources::controller;
@ -2547,19 +2547,19 @@ WML_HANDLER_FUNCTION(unstore_unit, /*event_info*/, cfg)
&& (loop_limit > 0) )
{
loop_limit--;
int total_opt = unit_helper::number_of_possible_advances(u);
bool use_dialog = side == u.side() &&
int total_opt = unit_helper::number_of_possible_advances(*u);
bool use_dialog = side == u->side() &&
(*resources::teams)[side - 1].is_human();
config selected = mp_sync::get_user_choice("choose",
unstore_unit_advance_choice(total_opt, loc, use_dialog));
dialogs::animate_unit_advancement(loc, selected["value"], cfg["fire_event"].to_bool(false), cfg["animate"].to_bool(true));
}
} else {
if(advance && u.advances()) {
if(advance && u->advances()) {
WRN_NG << "Cannot advance units when unstoring to the recall list." << std::endl;
}
team& t = (*resources::teams)[u.side()-1];
team& t = (*resources::teams)[u->side()-1];
if(t.persistent()) {
@ -2570,12 +2570,12 @@ WML_HANDLER_FUNCTION(unstore_unit, /*event_info*/, cfg)
// replaced by the wrong unit.
if(t.recall_list().size() > 1) {
std::vector<size_t> desciptions;
for(std::vector<unit>::const_iterator citor =
for(std::vector<UnitPtr>::const_iterator citor =
t.recall_list().begin();
citor != t.recall_list().end(); ++citor) {
const size_t desciption =
citor->underlying_id();
(*citor)->underlying_id();
if(std::find(desciptions.begin(), desciptions.end(),
desciption) != desciptions.end()) {
@ -2593,29 +2593,29 @@ WML_HANDLER_FUNCTION(unstore_unit, /*event_info*/, cfg)
* @todo it would be better to change recall_list() from
* a vector to a map and use the underlying_id as key.
*/
const size_t key = u.underlying_id();
for(std::vector<unit>::iterator itor =
const size_t key = u->underlying_id();
for(std::vector<UnitPtr>::iterator itor =
t.recall_list().begin();
itor != t.recall_list().end(); ++itor) {
LOG_NG << "Replaced unit '"
<< key << "' on the recall list\n";
if(itor->underlying_id() == key) {
if((*itor)->underlying_id() == key) {
t.recall_list().erase(itor);
break;
}
}
t.recall_list().push_back(u);
} else {
ERR_NG << "Cannot unstore unit: recall list is empty for player " << u.side()
ERR_NG << "Cannot unstore unit: recall list is empty for player " << u->side()
<< " and the map location is invalid.\n";
}
}
// If we unstore a leader make sure the team gets a leader if not the loading
// in MP might abort since a side without a leader has a recall list.
if(u.can_recruit()) {
(*resources::teams)[u.side() - 1].have_leader();
if(u->can_recruit()) {
(*resources::teams)[u->side() - 1].have_leader();
}
} catch (game::game_error &e) {

View file

@ -89,13 +89,13 @@ namespace { // Support functions
if(counts == default_counts && match_count) {
break;
}
const std::vector<unit>& avail_units = team->recall_list();
for(std::vector<unit>::const_iterator unit = avail_units.begin(); unit!=avail_units.end(); ++unit) {
const std::vector<UnitPtr>& avail_units = team->recall_list();
for(std::vector<UnitPtr>::const_iterator unit = avail_units.begin(); unit!=avail_units.end(); ++unit) {
if(counts == default_counts && match_count) {
break;
}
scoped_recall_unit auto_store("this_unit", team->save_id(), unit - avail_units.begin());
if ( unit->matches_filter(*u) ) {
if ( (*unit)->matches_filter(*u) ) {
++match_count;
}
}

View file

@ -1061,8 +1061,8 @@ void encounter_start_units(const unit_map& units){
static void encounter_recallable_units(const std::vector<team>& teams){
BOOST_FOREACH(const team& t, teams) {
BOOST_FOREACH(const unit& u, t.recall_list()) {
encountered_units_set.insert(u.type_id());
BOOST_FOREACH(const UnitConstPtr & u, t.recall_list()) {
encountered_units_set.insert(u->type_id());
}
}
}

View file

@ -253,8 +253,7 @@ protected:
//seen before
config u_tmp = u;
u_tmp["side"] = str_cast(side_);
unit new_unit(u_tmp, true);
t_->recall_list().push_back(new_unit);
t_->recall_list().push_back(UnitPtr(new unit(u_tmp,true)));
} else {
//not seen before
unit_configs_.push_back(&u);

View file

@ -34,6 +34,8 @@
#include "../../gamestatus.hpp"
#include "../../resources.hpp"
#include "../../team.hpp"
#include "../../unit.hpp"
#include "../../unit_map.hpp"
#include "../../ai/manager.hpp"
#include <vector>
@ -414,19 +416,19 @@ public:
}
if(selected == 3) {
const std::vector<unit> recall_list
const std::vector<UnitPtr> recall_list
= resources::teams
? resources::teams->at(side_ - 1).recall_list()
: std::vector<unit>();
: std::vector<UnitPtr>();
std::stringstream s;
FOREACH(const AUTO & u, recall_list)
{
s << "id=\"" << u.id() << "\" (" << u.type_id() << ")\nL"
<< u.level() << "; " << u.experience() << "/"
<< u.max_experience() << " xp; " << u.hitpoints() << "/"
<< u.max_hitpoints() << " hp\n";
FOREACH(const AUTO & str, u.get_traits_list())
s << "id=\"" << u->id() << "\" (" << u->type_id() << ")\nL"
<< u->level() << "; " << u->experience() << "/"
<< u->max_experience() << " xp; " << u->hitpoints() << "/"
<< u->max_hitpoints() << " hp\n";
FOREACH(const AUTO & str, u->get_traits_list())
{
s << "\t" << str << std::endl;
}
@ -437,16 +439,16 @@ public:
}
if(selected == 4) {
const std::vector<unit> recall_list
const std::vector<UnitPtr> recall_list
= resources::teams
? resources::teams->at(side_ - 1).recall_list()
: std::vector<unit>();
: std::vector<UnitPtr>();
config c;
FOREACH(const AUTO & u, recall_list)
{
config c_unit;
u.write(c_unit);
u->write(c_unit);
c.add_child("unit", c_unit);
}
model_.set_inspect_window_text(config_to_string(c));

View file

@ -26,6 +26,8 @@
//#include "gettext.hpp"
#include "marked-up_text.hpp"
#include "resources.hpp"
#include "unit.hpp"
//
//#include <boost/foreach.hpp>

View file

@ -667,7 +667,7 @@ void menu_handler::recall(int side_num, const map_location &last_hex)
return;
}
std::vector<const unit*> recall_list_team;
std::vector<UnitConstPtr > recall_list_team;
{ wb::future_map future; // ensures recall list has planned recalls removed
recall_list_team = actions::get_recalls(side_num, last_hex);
}
@ -676,7 +676,7 @@ void menu_handler::recall(int side_num, const map_location &last_hex)
DBG_WB <<"menu_handler::recall: Contents of wb-modified recall list:\n";
BOOST_FOREACH(const unit* unit, recall_list_team)
BOOST_FOREACH(const UnitConstPtr & unit, recall_list_team)
{
DBG_WB << unit->name() << " [" << unit->id() <<"]\n";
}

View file

@ -1033,8 +1033,8 @@ int mouse_handler::show_attack_dialog(const map_location& attacker_loc, const ma
}
}
if (items.empty()) {
dialogs::units_list_preview_pane attacker_preview(&*attacker, dialogs::unit_preview_pane::SHOW_BASIC, true);
dialogs::units_list_preview_pane defender_preview(&*defender, dialogs::unit_preview_pane::SHOW_BASIC, false);
dialogs::units_list_preview_pane attacker_preview(attacker.get_shared_ptr(), dialogs::unit_preview_pane::SHOW_BASIC, true);
dialogs::units_list_preview_pane defender_preview(defender.get_shared_ptr(), dialogs::unit_preview_pane::SHOW_BASIC, false);
std::vector<gui::preview_pane*> preview_panes;
preview_panes.push_back(&attacker_preview);
preview_panes.push_back(&defender_preview);
@ -1051,8 +1051,8 @@ int mouse_handler::show_attack_dialog(const map_location& attacker_loc, const ma
std::vector<gui::dialog_button_info> buttons;
buttons.push_back(gui::dialog_button_info(&ap_displayer, _("Damage Calculations")));
dialogs::units_list_preview_pane attacker_preview(&*attacker, dialogs::unit_preview_pane::SHOW_BASIC, true);
dialogs::units_list_preview_pane defender_preview(&*defender, dialogs::unit_preview_pane::SHOW_BASIC, false);
dialogs::units_list_preview_pane attacker_preview(attacker.get_shared_ptr(), dialogs::unit_preview_pane::SHOW_BASIC, true);
dialogs::units_list_preview_pane defender_preview(defender.get_shared_ptr(), dialogs::unit_preview_pane::SHOW_BASIC, false);
std::vector<gui::preview_pane*> preview_panes;
preview_panes.push_back(&attacker_preview);
preview_panes.push_back(&defender_preview);

View file

@ -513,8 +513,8 @@ static int impl_unit_collect(lua_State *L)
*/
static int impl_unit_equality(lua_State* L)
{
unit* left = luaW_checkunit(L, 1);
unit* right = luaW_checkunit(L, 2);
UnitPtr left = luaW_checkunit(L, 1);
UnitPtr right = luaW_checkunit(L, 2);
const bool equal = left->underlying_id() == right->underlying_id();
lua_pushboolean(L, equal);
return 1;
@ -530,7 +530,7 @@ static int impl_unit_get(lua_State *L)
{
lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, 1));
char const *m = luaL_checkstring(L, 2);
unit const *pu = lu->get();
const UnitConstPtr pu = lu->get();
if (strcmp(m, "valid") == 0)
{
@ -613,7 +613,7 @@ static int impl_unit_set(lua_State *L)
{
lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, 1));
char const *m = luaL_checkstring(L, 2);
unit *pu = lu->get();
UnitPtr pu = lu->get();
if (!pu) return luaL_argerror(L, 1, "unknown unit");
unit &u = *pu;
@ -653,7 +653,7 @@ static int impl_unit_status_get(lua_State *L)
if (!lua_istable(L, 1))
return luaL_typerror(L, 1, "unit status");
lua_rawgeti(L, 1, 1);
unit const *u = luaW_tounit(L, -1);
const UnitConstPtr u = luaW_tounit(L, -1);
if (!u) return luaL_argerror(L, 1, "unknown unit");
char const *m = luaL_checkstring(L, 2);
lua_pushboolean(L, u->get_state(m));
@ -671,7 +671,7 @@ static int impl_unit_status_set(lua_State *L)
if (!lua_istable(L, 1))
return luaL_typerror(L, 1, "unit status");
lua_rawgeti(L, 1, 1);
unit *u = luaW_tounit(L, -1);
UnitPtr u = luaW_tounit(L, -1);
if (!u) return luaL_argerror(L, 1, "unknown unit");
char const *m = luaL_checkstring(L, 2);
u->set_state(m, luaW_toboolean(L, 3));
@ -689,7 +689,7 @@ static int impl_unit_variables_get(lua_State *L)
if (!lua_istable(L, 1))
return luaL_typerror(L, 1, "unit variables");
lua_rawgeti(L, 1, 1);
unit const *u = luaW_tounit(L, -1);
const UnitConstPtr u = luaW_tounit(L, -1);
if (!u) return luaL_argerror(L, 1, "unknown unit");
char const *m = luaL_checkstring(L, 2);
return_cfgref_attrib("__cfg", u->variables());
@ -708,7 +708,7 @@ static int impl_unit_variables_set(lua_State *L)
if (!lua_istable(L, 1))
return luaL_typerror(L, 1, "unit variables");
lua_rawgeti(L, 1, 1);
unit *u = luaW_tounit(L, -1);
UnitPtr u = luaW_tounit(L, -1);
if (!u) return luaL_argerror(L, 1, "unknown unit");
char const *m = luaL_checkstring(L, 2);
if (strcmp(m, "__cfg") == 0) {
@ -838,7 +838,7 @@ static int intf_match_unit(lua_State *L)
return luaL_typerror(L, 1, "unit");
lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, 1));
unit *u = lu->get();
UnitPtr u = lu->get();
if (!u) return luaL_argerror(L, 1, "unit not found");
vconfig filter = luaW_checkvconfig(L, 2, true);
@ -850,8 +850,9 @@ static int intf_match_unit(lua_State *L)
if (int side = lu->on_recall_list()) {
team &t = (*resources::teams)[side - 1];
std::vector<UnitPtr>::iterator it = find_if_matches_id(t.recall_list(), u->id());
scoped_recall_unit auto_store("this_unit",
t.save_id(), u - &t.recall_list()[0]);
t.save_id(), it - t.recall_list().begin());
lua_pushboolean(L, u->matches_filter(filter, map_location()));
return 1;
}
@ -880,15 +881,16 @@ static int intf_get_recall_units(lua_State *L)
int i = 1, s = 1;
BOOST_FOREACH(team &t, *resources::teams)
{
BOOST_FOREACH(unit &u, t.recall_list())
BOOST_FOREACH(UnitPtr & u, t.recall_list())
{
if (!filter.null()) {
std::vector<UnitPtr>::iterator it = find_if_matches_id(t.recall_list(), u->id());
scoped_recall_unit auto_store("this_unit",
t.save_id(), &u - &t.recall_list()[0]);
if (!u.matches_filter(filter, map_location()))
t.save_id(), it - t.recall_list().begin());
if (!u->matches_filter(filter, map_location()))
continue;
}
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(s, u.underlying_id());
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(s, u->underlying_id());
lua_pushvalue(L, 1);
lua_setmetatable(L, 3);
lua_rawseti(L, 2, i);
@ -1749,7 +1751,7 @@ static int intf_find_path(lua_State *L)
int arg = 1;
map_location src, dst;
unit_map &units = *resources::units;
const unit *u = NULL;
UnitConstPtr u = UnitConstPtr();
if (lua_isuserdata(L, arg))
{
@ -1763,7 +1765,7 @@ static int intf_find_path(lua_State *L)
++arg;
src.y = luaL_checkinteger(L, arg) - 1;
unit_map::const_unit_iterator ui = units.find(src);
if (ui.valid()) u = &*ui;
if (ui.valid()) u = ui.get_shared_ptr();
++arg;
}
@ -1859,7 +1861,7 @@ static int intf_find_path(lua_State *L)
static int intf_find_reach(lua_State *L)
{
int arg = 1;
const unit *u = NULL;
UnitConstPtr u = UnitConstPtr();
if (lua_isuserdata(L, arg))
{
@ -1875,7 +1877,7 @@ static int intf_find_reach(lua_State *L)
unit_map::const_unit_iterator ui = resources::units->find(src);
if (!ui.valid())
return luaL_argerror(L, 1, "unit not found");
u = &*ui;
u = ui.get_shared_ptr();
++arg;
}
@ -1944,7 +1946,7 @@ static int intf_find_reach(lua_State *L)
static int intf_find_cost_map(lua_State *L)
{
int arg = 1;
const unit *u = luaW_tounit(L, arg, true);
UnitConstPtr u = luaW_tounit(L, arg, true);
vconfig filter = vconfig::unconstructed_vconfig();
luaW_tovconfig(L, arg, filter);
@ -1955,7 +1957,7 @@ static int intf_find_cost_map(lua_State *L)
if (u) // 1. arg - unit
{
real_units.push_back(u);
real_units.push_back(u.get());
}
else if (!filter.null()) // 1. arg - filter
{
@ -2147,7 +2149,7 @@ static int intf_put_unit(lua_State *L)
int unit_arg = 1;
lua_unit *lu = NULL;
unit *u = NULL;
UnitPtr u = UnitPtr();
map_location loc;
if (lua_isnumber(L, 1)) {
unit_arg = 3;
@ -2180,7 +2182,7 @@ static int intf_put_unit(lua_State *L)
if (!resources::gameboard->map().on_board(loc))
return luaL_argerror(L, 1, "invalid location");
}
u = new unit(cfg, true);
u = UnitPtr (new unit(cfg, true));
}
resources::screen->invalidate(loc);
@ -2206,7 +2208,7 @@ static int intf_put_unit(lua_State *L)
static int intf_put_recall_unit(lua_State *L)
{
lua_unit *lu = NULL;
unit *u = NULL;
UnitPtr u = UnitPtr();
int side = lua_tointeger(L, 2);
if (unsigned(side) > resources::teams->size()) side = 0;
@ -2220,25 +2222,25 @@ static int intf_put_recall_unit(lua_State *L)
else
{
config cfg = luaW_checkconfig(L, 1);
u = new unit(cfg, true);
u = UnitPtr(new unit(cfg, true));
}
if (!side) side = u->side();
team &t = (*resources::teams)[side - 1];
if (!t.persistent())
return luaL_argerror(L, 2, "nonpersistent side");
std::vector<unit> &rl = t.recall_list();
std::vector<UnitPtr> &rl = t.recall_list();
// Avoid duplicates in the recall list.
size_t uid = u->underlying_id();
std::vector<unit>::iterator i = rl.begin();
std::vector<UnitPtr>::iterator i = rl.begin();
while (i != rl.end()) {
if (i->underlying_id() == u->underlying_id()) {
if ((*i)->underlying_id() == u->underlying_id()) {
i = rl.erase(i);
} else ++i;
}
rl.push_back(*u);
rl.push_back(u);
if (lu) {
if (lu->on_map())
resources::units->erase(u->get_location());
@ -2258,7 +2260,7 @@ static int intf_extract_unit(lua_State *L)
if (!luaW_hasmetatable(L, 1, getunitKey))
return luaL_typerror(L, 1, "unit");
lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, 1));
unit *u = lu->get();
UnitPtr u = lu->get();
if (!u) return luaL_argerror(L, 1, "unit not found");
if (lu->on_map()) {
@ -2267,9 +2269,10 @@ static int intf_extract_unit(lua_State *L)
u->clear_haloes();
} else if (int side = lu->on_recall_list()) {
team &t = (*resources::teams)[side - 1];
unit *v = new unit(*u);
std::vector<unit> &rl = t.recall_list();
rl.erase(rl.begin() + (u - &rl[0]));
UnitPtr v = UnitPtr(new unit(*u));
std::vector<UnitPtr> &rl = t.recall_list();
std::vector<UnitPtr>::iterator it = find_if_matches_id(t.recall_list(), u->id());
rl.erase(rl.begin() + (it - rl.begin()));
u = v;
} else {
return 0;
@ -2290,22 +2293,18 @@ static int intf_find_vacant_tile(lua_State *L)
{
int x = luaL_checkint(L, 1) - 1, y = luaL_checkint(L, 2) - 1;
const unit *u = NULL;
bool fake_unit = false;
UnitPtr u = UnitPtr();
if (!lua_isnoneornil(L, 3)) {
if (luaW_hasmetatable(L, 3, getunitKey)) {
u = static_cast<lua_unit *>(lua_touserdata(L, 3))->get();
} else {
config cfg = luaW_checkconfig(L, 3);
u = new unit(cfg, false);
fake_unit = true;
u.reset(new unit(cfg, false));
}
}
map_location res = find_vacant_tile(map_location(x, y),
pathfind::VACANT_ANY, u);
if (fake_unit) delete u;
pathfind::VACANT_ANY, u.get());
if (!res.valid()) return 0;
lua_pushinteger(L, res.x + 1);
@ -2338,7 +2337,7 @@ static int intf_float_label(lua_State *L)
static int intf_create_unit(lua_State *L)
{
config cfg = luaW_checkconfig(L, 1);
unit *u = new unit(cfg, true);
UnitPtr u = UnitPtr(new unit(cfg, true));
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(u);
lua_pushlightuserdata(L
, getunitKey);
@ -2354,8 +2353,8 @@ static int intf_create_unit(lua_State *L)
*/
static int intf_copy_unit(lua_State *L)
{
unit const *u = luaW_checkunit(L, 1);
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(new unit(*u));
UnitPtr u = luaW_checkunit(L, 1);
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(UnitPtr(new unit(*u)));
lua_pushlightuserdata(L
, getunitKey);
lua_rawget(L, LUA_REGISTRYINDEX);
@ -2373,7 +2372,7 @@ static int intf_copy_unit(lua_State *L)
*/
static int intf_unit_resistance(lua_State *L)
{
unit const *u = luaW_checkunit(L, 1);
const UnitConstPtr u = luaW_checkunit(L, 1);
char const *m = luaL_checkstring(L, 2);
bool a = luaW_toboolean(L, 3);
@ -2395,7 +2394,7 @@ static int intf_unit_resistance(lua_State *L)
*/
static int intf_unit_movement_cost(lua_State *L)
{
unit const *u = luaW_checkunit(L, 1);
const UnitConstPtr u = luaW_checkunit(L, 1);
char const *m = luaL_checkstring(L, 2);
t_translation::t_terrain t = t_translation::read_terrain_code(m);
lua_pushinteger(L, u->movement_cost(t));
@ -2410,7 +2409,7 @@ static int intf_unit_movement_cost(lua_State *L)
*/
static int intf_unit_defense(lua_State *L)
{
unit const *u = luaW_checkunit(L, 1);
const UnitConstPtr u = luaW_checkunit(L, 1);
char const *m = luaL_checkstring(L, 2);
t_translation::t_terrain t = t_translation::read_terrain_code(m);
lua_pushinteger(L, u->defense_modifier(t));
@ -2425,7 +2424,7 @@ static int intf_unit_defense(lua_State *L)
*/
static int intf_unit_ability(lua_State *L)
{
unit const *u = luaW_checkunit(L, 1);
const UnitConstPtr u = luaW_checkunit(L, 1);
char const *m = luaL_checkstring(L, 2);
lua_pushboolean(L, u->get_ability_bool(m));
return 1;
@ -2438,7 +2437,7 @@ static int intf_unit_ability(lua_State *L)
*/
static int intf_transform_unit(lua_State *L)
{
unit *u = luaW_checkunit(L, 1);
UnitPtr u = luaW_checkunit(L, 1);
char const *m = luaL_checkstring(L, 2);
const unit_type *utp = unit_types.find(m);
if (!utp) return luaL_argerror(L, 2, "unknown unit type");
@ -2533,7 +2532,7 @@ static int intf_simulate_combat(lua_State *L)
{
int arg_num = 1, att_w = -1, def_w = -1;
unit const *att = luaW_checkunit(L, arg_num);
UnitConstPtr att = luaW_checkunit(L, arg_num);
++arg_num;
if (lua_isnumber(L, arg_num)) {
att_w = lua_tointeger(L, arg_num) - 1;
@ -2542,7 +2541,7 @@ static int intf_simulate_combat(lua_State *L)
++arg_num;
}
unit const *def = luaW_checkunit(L, arg_num, true);
UnitConstPtr def = luaW_checkunit(L, arg_num, true);
++arg_num;
if (lua_isnumber(L, arg_num)) {
def_w = lua_tointeger(L, arg_num) - 1;
@ -2552,7 +2551,7 @@ static int intf_simulate_combat(lua_State *L)
}
battle_context context(*resources::units, att->get_location(),
def->get_location(), att_w, def_w, 0.0, NULL, att);
def->get_location(), att_w, def_w, 0.0, NULL, att.get());
luaW_pushsimdata(L, context.get_attacker_combatant());
luaW_pushsimdata(L, context.get_defender_combatant());
@ -3298,7 +3297,7 @@ static int intf_get_traits(lua_State* L)
*/
static int intf_add_modification(lua_State *L)
{
unit *u = luaW_checkunit(L, 1);
UnitPtr u = luaW_checkunit(L, 1);
char const *m = luaL_checkstring(L, 2);
std::string sm = m;
if (sm != "advance" && sm != "object" && sm != "trait")

View file

@ -386,21 +386,20 @@ bool luaW_getglobal(lua_State *L, ...)
lua_unit::~lua_unit()
{
delete ptr;
}
unit *lua_unit::get()
UnitPtr lua_unit::get()
{
if (ptr) return ptr;
if (side) {
BOOST_FOREACH(unit &u, (*resources::teams)[side - 1].recall_list()) {
if (u.underlying_id() == uid) return &u;
BOOST_FOREACH(UnitPtr &u, (*resources::teams)[side - 1].recall_list()) {
if (u->underlying_id() == uid) return u;
}
return NULL;
return UnitPtr();
}
unit_map::unit_iterator ui = resources::units->find(uid);
if (!ui.valid()) return NULL;
return &*ui;
if (!ui.valid()) return UnitPtr();
return ui.get_shared_ptr(); //&*ui would not be legal, must get new shared_ptr by copy ctor because the unit_map itself is holding a boost shared pointer.
}
// Having this function here not only simplifies other code, it allows us to move
@ -414,24 +413,24 @@ bool lua_unit::put_map(const map_location &loc)
resources::units->erase(loc);
std::pair<unit_map::unit_iterator, bool> res = resources::units->insert(ptr);
if (res.second) {
ptr = NULL;
ptr.reset();
uid = res.first->underlying_id();
} else {
ERR_LUA << "Could not move unit " << ptr->underlying_id() << " onto map location " << loc << '\n';
return false;
}
} else if (side) { // recall list
std::vector<unit> &recall_list = (*resources::teams)[side - 1].recall_list();
std::vector<unit>::iterator it = recall_list.begin();
std::vector<UnitPtr> &recall_list = (*resources::teams)[side - 1].recall_list();
std::vector<UnitPtr>::iterator it = recall_list.begin();
for(; it != recall_list.end(); ++it) {
if (it->underlying_id() == uid) {
if ((*it)->underlying_id() == uid) {
break;
}
}
if (it != recall_list.end()) {
side = 0;
// uid may be changed by unit_map on insertion
uid = resources::units->replace(loc, *it).first->underlying_id();
uid = resources::units->replace(loc, **it).first->underlying_id();
recall_list.erase(it);
} else {
ERR_LUA << "Could not find unit " << uid << " on recall list of side " << side << '\n';
@ -454,17 +453,17 @@ bool lua_unit::put_map(const map_location &loc)
return true;
}
unit *luaW_tounit(lua_State *L, int index, bool only_on_map)
UnitPtr luaW_tounit(lua_State *L, int index, bool only_on_map)
{
if (!luaW_hasmetatable(L, index, getunitKey)) return NULL;
if (!luaW_hasmetatable(L, index, getunitKey)) return UnitPtr();
lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, index));
if (only_on_map && !lu->on_map()) return NULL;
if (only_on_map && !lu->on_map()) return UnitPtr();
return lu->get();
}
unit *luaW_checkunit(lua_State *L, int index, bool only_on_map)
UnitPtr luaW_checkunit(lua_State *L, int index, bool only_on_map)
{
unit *u = luaW_tounit(L, index, only_on_map);
UnitPtr u = luaW_tounit(L, index, only_on_map);
if (!u) luaL_typerror(L, index, "unit");
return u;
}

View file

@ -19,16 +19,16 @@
#include <string>
#include "config.hpp" // forward declaration of the nested type config::attribute_value is not possible
#include "lua_types.hpp" // the luatype typedef
#include "unit_ptr.hpp"
struct lua_State;
class t_string;
class vconfig;
class unit;
/**
* Converts a Lua value to a unit pointer.
*/
unit *luaW_tounit(lua_State *L, int index, bool only_on_map = false);
UnitPtr luaW_tounit(lua_State *L, int index, bool only_on_map = false);
/**
* Displays a message in the chat window.
@ -123,7 +123,7 @@ bool luaW_getglobal(lua_State *L, ...);
/**
* Converts a Lua value to a unit pointer.
*/
unit *luaW_checkunit(lua_State *L, int index, bool only_on_map = false);
UnitPtr luaW_checkunit(lua_State *L, int index, bool only_on_map = false);
bool luaW_toboolean(lua_State *L, int n);
@ -137,18 +137,18 @@ struct map_location;
class lua_unit
{
size_t uid;
unit *ptr;
UnitPtr ptr;
int side;
lua_unit(lua_unit const &);
public:
lua_unit(size_t u): uid(u), ptr(NULL), side(0) {}
lua_unit(unit *u): uid(0), ptr(u), side(0) {}
lua_unit(int s, size_t u): uid(u), ptr(NULL), side(s) {}
lua_unit(size_t u): uid(u), ptr(), side(0) {}
lua_unit(UnitPtr u): uid(0), ptr(u), side(0) {}
lua_unit(int s, size_t u): uid(u), ptr(), side(s) {}
~lua_unit();
bool on_map() const { return !ptr && side == 0; }
int on_recall_list() const { return side; }
unit *get();
UnitPtr get();
// Clobbers loc
bool put_map(const map_location &loc);

View file

@ -24,6 +24,7 @@
#include "team.hpp"
#include "serialization/string_utils.hpp"
#include "network.hpp"
#include "unit.hpp"
#include <boost/foreach.hpp>
@ -137,10 +138,11 @@ bool side_filter::match_internal(const team &t) const
}
}
if(!found && unit_filter["search_recall_list"].to_bool(false)) {
const std::vector<unit>& recall_list = t.recall_list();
BOOST_FOREACH(const unit& u, recall_list) {
scoped_recall_unit this_unit("this_unit", t.save_id(), &u - &recall_list[0]);
if(u.matches_filter(unit_filter, u.get_location(), flat_)) {
const std::vector<UnitPtr>& recall_list = t.recall_list();
BOOST_FOREACH(const UnitConstPtr & u, recall_list) {
std::vector<UnitPtr>::const_iterator it = find_if_matches_id(recall_list, u->id());
scoped_recall_unit this_unit("this_unit", t.save_id(), it - recall_list.begin());
if(u->matches_filter(unit_filter, u->get_location(), flat_)) {
found = true;
break;
}

View file

@ -222,7 +222,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(disband, child, /*use_undo*/, /*show*/, error_ha
team &current_team = (*resources::teams)[current_team_num - 1];
const std::string& unit_id = child["value"];
std::vector<unit>::iterator disband_unit =
std::vector<UnitPtr>::iterator disband_unit =
find_if_matches_id(current_team.recall_list(), unit_id);
if(disband_unit != current_team.recall_list().end()) {

View file

@ -17,8 +17,13 @@
#include "color_range.hpp"
#include "game_config.hpp"
#include "make_enum.hpp"
#include "map_location.hpp"
#include "savegame_config.hpp"
#include "unit.hpp"
#include "SDL.h" //Apparently needed b/c of SDL_Color
#include "unit_ptr.hpp"
#include "util.hpp"
#include <boost/shared_ptr.hpp>
class gamemap;
@ -180,8 +185,8 @@ public:
{ countdown_time_ = amount; }
int action_bonus_count() const { return action_bonus_count_; }
void set_action_bonus_count(const int count) { action_bonus_count_ = count; }
std::vector<unit>& recall_list() {return recall_list_;}
const std::vector<unit>& recall_list() const {return recall_list_;}
std::vector<UnitPtr >& recall_list() {return recall_list_;}
const std::vector<UnitPtr >& recall_list() const {return recall_list_;}
void set_current_player(const std::string& player)
{ info_.current_player = player; }
@ -344,7 +349,7 @@ private:
mutable int countdown_time_;
int action_bonus_count_;
std::vector<unit> recall_list_;
std::vector<UnitPtr > recall_list_;
std::string last_recruit_;
bool calculate_enemies(size_t index) const;

View file

@ -25,6 +25,7 @@
#include "team.hpp"
#include "terrain_filter.hpp"
#include "tod_manager.hpp"
#include "unit.hpp"
#include "variable.hpp"
#include <boost/foreach.hpp>

View file

@ -151,7 +151,7 @@ BOOST_AUTO_TEST_CASE( track_real_unit_by_underlying_id ) {
BOOST_CHECK(ui->underlying_id() == orc1_side0_real.underlying_id());
}
unit* extracted_unit = unit_map.extract(hex);
UnitPtr extracted_unit = unit_map.extract(hex);
{
unit_map::unit_iterator ui = unit_map.find(underlying_id);
@ -159,7 +159,7 @@ BOOST_AUTO_TEST_CASE( track_real_unit_by_underlying_id ) {
}
unit_map.insert(extracted_unit);
extracted_unit = NULL;
extracted_unit.reset();
{
unit_map::unit_iterator ui = unit_map.find(underlying_id);
@ -198,7 +198,7 @@ BOOST_AUTO_TEST_CASE( track_fake_unit_by_underlying_id ) {
BOOST_CHECK(ui->underlying_id() == orc1_side0_fake.underlying_id());
}
unit* extracted_unit = unit_map.extract(hex);
UnitPtr extracted_unit = unit_map.extract(hex);
{
unit_map::unit_iterator ui = unit_map.find(underlying_id);
@ -206,7 +206,7 @@ BOOST_AUTO_TEST_CASE( track_fake_unit_by_underlying_id ) {
}
unit_map.insert(extracted_unit);
extracted_unit = NULL;
extracted_unit.reset();
{
unit_map::unit_iterator ui = unit_map.find(underlying_id);
@ -240,7 +240,7 @@ BOOST_AUTO_TEST_CASE( track_real_unit_by_iterator ) {
BOOST_CHECK(unit_iterator.valid());
unit* extracted_unit = unit_map.extract(hex);
UnitPtr extracted_unit = unit_map.extract(hex);
BOOST_CHECK_MESSAGE(unit_iterator.valid() == false, "Iterator should be invalid after extraction.");
@ -277,7 +277,7 @@ BOOST_AUTO_TEST_CASE( track_fake_unit_by_iterator ) {
BOOST_CHECK(unit_iterator.valid());
unit* extracted_unit = unit_map.extract(hex);
UnitPtr extracted_unit = unit_map.extract(hex);
BOOST_CHECK_MESSAGE(unit_iterator.valid() == false, "Iterator should be invalid after extraction.");

View file

@ -37,7 +37,7 @@ struct dummy_action: action{
void remove_temp_modifier(unit_map&){}
void draw_hex(const map_location&){}
map_location get_numbering_hex() const { return map_location(); }
unit* get_unit() const { return 0; }
UnitPtr get_unit() const { return UnitPtr(); }
fake_unit_ptr get_fake_unit(){ return fake_unit_ptr(); }
error check_validity() const { return OK; }
};

View file

@ -71,6 +71,22 @@ namespace {
const std::string leader_crown_path = "misc/leader-crown.png";
}
/**
* Intrusive Pointer interface
*
**/
void intrusive_ptr_add_ref(const unit * u)
{
++(u->ref_count_);
}
void intrusive_ptr_release(const unit * u)
{
if (--(u->ref_count_) == 0)
delete u;
}
/**
* Converts a string ID to a unit_type.
* Throws a game_error exception if the string does not correspond to a type.
@ -2902,40 +2918,45 @@ bool unit::matches_id(const std::string& unit_id) const
return id_ == unit_id;
}
bool find_if_matches_helper(const UnitPtr & ptr, const std::string & unit_id)
{
return ptr->matches_id(unit_id);
}
/**
* Used to find units in vectors by their ID. (Convenience wrapper)
* @returns what std::find_if() returns.
*/
std::vector<unit>::iterator find_if_matches_id(
std::vector<unit> &unit_list, // Not const so we can get a non-const iterator to return.
std::vector<UnitPtr >::iterator find_if_matches_id(
std::vector<UnitPtr > &unit_list, // Not const so we can get a non-const iterator to return.
const std::string &unit_id)
{
return std::find_if(unit_list.begin(), unit_list.end(),
boost::bind(&unit::matches_id, _1, unit_id));
boost::bind(&find_if_matches_helper, _1, unit_id));
}
/**
* Used to find units in vectors by their ID. (Convenience wrapper; const version)
* @returns what std::find_if() returns.
*/
std::vector<unit>::const_iterator find_if_matches_id(
const std::vector<unit> &unit_list,
std::vector<UnitPtr >::const_iterator find_if_matches_id(
const std::vector<UnitPtr > &unit_list,
const std::string &unit_id)
{
return std::find_if(unit_list.begin(), unit_list.end(),
boost::bind(&unit::matches_id, _1, unit_id));
boost::bind(&find_if_matches_helper, _1, unit_id));
}
/**
* Used to erase units from vectors by their ID. (Convenience wrapper)
* @returns what std::vector<>::erase() returns.
*/
std::vector<unit>::iterator erase_if_matches_id(
std::vector<unit> &unit_list,
std::vector<UnitPtr >::iterator erase_if_matches_id(
std::vector<UnitPtr > &unit_list,
const std::string &unit_id)
{
return unit_list.erase(std::remove_if(unit_list.begin(), unit_list.end(),
boost::bind(&unit::matches_id, _1, unit_id)),
boost::bind(&find_if_matches_helper, _1, unit_id)),
unit_list.end());
}

View file

@ -23,6 +23,7 @@
#include "unit_animation.hpp"
#include "unit_types.hpp"
#include "unit_map.hpp"
#include "unit_ptr.hpp"
class display;
class gamemap;
@ -391,7 +392,12 @@ public:
const std::string& effect_image_mods() const;
std::string image_mods() const;
long ref_count() const { return ref_count_; }
friend void intrusive_ptr_add_ref(const unit *);
friend void intrusive_ptr_release(const unit *);
private:
mutable long ref_count_; //used by intrusive_ptr
void advance_to(const config &old_cfg, const unit_type &t,
bool use_traits);
@ -534,16 +540,16 @@ private:
};
/// Used to find units in vectors by their ID. (Convenience wrapper)
std::vector<unit>::iterator find_if_matches_id(
std::vector<unit> &unit_list,
std::vector<UnitPtr >::iterator find_if_matches_id(
std::vector<UnitPtr > &unit_list,
const std::string &unit_id);
/// Used to find units in vectors by their ID. (Convenience wrapper)
std::vector<unit>::const_iterator find_if_matches_id(
const std::vector<unit> &unit_list,
std::vector<UnitPtr >::const_iterator find_if_matches_id(
const std::vector<UnitPtr > &unit_list,
const std::string &unit_id);
/// Used to erase units from vectors by their ID. (Convenience wrapper)
std::vector<unit>::iterator erase_if_matches_id(
std::vector<unit> &unit_list,
std::vector<UnitPtr >::iterator erase_if_matches_id(
std::vector<UnitPtr > &unit_list,
const std::string &unit_id);
/** Returns the number of units of the side @a side_num. */

View file

@ -65,16 +65,16 @@ unit_map::~unit_map() {
unit_map::t_umap::iterator unit_map::begin_core() const {
self_check();
t_umap::iterator i = umap_.begin();
while (i != umap_.end() && (i->second.unit == NULL)) { ++i; }
while (i != umap_.end() && (!i->second.unit)) { ++i; }
return i;
}
std::pair<unit_map::unit_iterator, bool> unit_map::add(const map_location &l, const unit &u) {
self_check();
unit *p = new unit(u);
UnitPtr p = UnitPtr (new unit(u)); //TODO: should this instead take a shared pointer to a unit, rather than make a copy?
p->set_location(l);
std::pair<unit_map::unit_iterator, bool> res( insert(p) );
if(res.second == false) { delete p; }
if(res.second == false) { p.reset(); }
return res;
}
@ -91,8 +91,8 @@ std::pair<unit_map::unit_iterator, bool> unit_map::move(const map_location &src,
if(src == dst){ return std::make_pair(make_unit_iterator(uit), true);}
//Fail if there is no unit to move
unit *p = uit->second.unit;
if(p == NULL){ return std::make_pair(make_unit_iterator(uit), false);}
UnitPtr p = uit->second.unit;
if(!p){ return std::make_pair(make_unit_iterator(uit), false);}
p->set_location(dst);
@ -125,7 +125,7 @@ The one oddity is that to facilitate non-invalidating iterators the list
sometimes has NULL pointers which should be used when they correspond
to uids previously used.
*/
std::pair<unit_map::unit_iterator, bool> unit_map::insert(unit *p) {
std::pair<unit_map::unit_iterator, bool> unit_map::insert(UnitPtr p) {
self_check();
assert(p);
@ -139,7 +139,7 @@ std::pair<unit_map::unit_iterator, bool> unit_map::insert(unit *p) {
}
unit_pod upod;
upod.unit = p;
upod.unit = p ;
DBG_NG << "Adding unit " << p->underlying_id() << " - " << p->id()
<< " to location: (" << loc << ")\n";
@ -148,12 +148,12 @@ std::pair<unit_map::unit_iterator, bool> unit_map::insert(unit *p) {
if (! uinsert.second) {
//If the pod is empty reinsert the unit in the same list element
if ( uinsert.first->second.unit == NULL) {
if (!uinsert.first->second.unit) {
unit_pod &opod = uinsert.first->second;
opod.unit = p;
opod.unit = p ;
assert(opod.ref_count != 0);
} else {
unit *q = uinsert.first->second.unit;
UnitPtr q = uinsert.first->second.unit;
ERR_NG << "Trying to add " << p->name()
<< " - " << p->id() << " - " << p->underlying_id()
<< " (" << loc << ") over " << q->name()
@ -191,7 +191,7 @@ std::pair<unit_map::unit_iterator, bool> unit_map::insert(unit *p) {
umap_.erase(uinsert.first);
} else {
//undo a reinsertion
uinsert.first->second.unit = NULL;
uinsert.first->second.unit.reset();
}
DBG_NG << "Trying to add " << p->name()
<< " - " << p->id() << " at location ("<<loc <<"); Occupied by "
@ -238,7 +238,7 @@ void unit_map::clear(bool force) {
for (t_umap::iterator i = umap_.begin(); i != umap_.end(); ++i) {
if (is_valid(i)) {
DBG_NG << "Delete unit " << i->second.unit->underlying_id() << "\n";
delete i->second.unit;
i->second.unit.reset();
}
}
@ -246,14 +246,14 @@ void unit_map::clear(bool force) {
umap_.clear();
}
unit *unit_map::extract(const map_location &loc) {
UnitPtr unit_map::extract(const map_location &loc) {
self_check();
t_lmap::iterator i = lmap_.find(loc);
if (i == lmap_.end()) { return NULL; }
if (i == lmap_.end()) { return UnitPtr(); }
t_umap::iterator uit(i->second);
unit *u = uit->second.unit;
UnitPtr u = uit->second.unit;
size_t uid( u->underlying_id() );
DBG_NG << "Extract unit " << uid << " - " << u->id()
@ -264,7 +264,7 @@ unit *unit_map::extract(const map_location &loc) {
umap_.erase(uit);
} else {
//Soft extraction keeps the old lit item if any iterators reference it
uit->second.unit = NULL;
uit->second.unit.reset();
}
lmap_.erase(i);
@ -276,16 +276,16 @@ unit *unit_map::extract(const map_location &loc) {
size_t unit_map::erase(const map_location &loc) {
self_check();
unit *u = extract(loc);
UnitPtr u = extract(loc);
if (!u) return 0;
delete u;
u.reset();
return 1;
}
unit_map::unit_iterator unit_map::find(size_t id) {
self_check();
t_umap::iterator i(umap_.find(id));
if((i != umap_.end()) && i->second.unit==NULL){ i = umap_.end() ;}
if((i != umap_.end()) && !i->second.unit){ i = umap_.end() ;}
return make_unit_iterator<t_umap::iterator>( i );
}
@ -343,14 +343,14 @@ bool unit_map::self_check() const {
good=false;
ERR_NG << "unit_map pod ref_count <0 is " << uit->second.ref_count<< std::endl;
}
if(uit->second.unit != NULL){
if(uit->second.unit){
uit->second.unit->id(); //crash if bad pointer
}
if(uit->first <= 0){
good=false;
ERR_NG << "unit_map umap uid <=0 is " << uit->first << std::endl;
}
if(uit->second.unit == NULL && uit->second.ref_count == 0 ){
if(!uit->second.unit && uit->second.ref_count == 0 ){
good=false;
ERR_NG << "unit_map umap unit==NULL when refcount == 0" << std::endl;
}
@ -381,7 +381,7 @@ bool unit_map::has_unit(const unit * const u) const
assert(u);
BOOST_FOREACH(const t_umap::value_type& item, umap_) {
if(item.second.unit == u) {
if(item.second.unit.get() == u) {
return true;
}
}

View file

@ -20,6 +20,7 @@
#include "utils/reference_counter.hpp"
#include "map_location.hpp"
#include "unit_ptr.hpp"
#include <cassert>
#include <list>
@ -28,8 +29,6 @@
//#define DEBUG_UNIT_MAP
class unit;
/**
* Container associating units to locations.
* An indirection location -> underlying_id -> unit ensures that iterators
@ -94,12 +93,12 @@ class unit_map {
struct unit_pod {
unit_pod()
: unit(NULL)
: unit()
, ref_count()
{
}
class unit * unit;
UnitPtr unit;
mutable n_ref_counter::t_ref_counter<signed int> ref_count;
};
@ -132,7 +131,7 @@ public:
typedef std::forward_iterator_tag iterator_category;
typedef int difference_type;
typedef typename iter_types::value_type value_type;
typedef value_type* pointer;
typedef boost::intrusive_ptr<value_type> pointer;
typedef value_type& reference;
typedef typename iter_types::container_type container_type;
typedef typename iter_types::iterator_type iterator_type;
@ -178,6 +177,10 @@ public:
assert(valid());
tank_->self_check();
return i_->second.unit; }
pointer get_shared_ptr() const { // This is exactly the same as operator-> but it's slightly more readable, and can replace &*iter syntax easily.
assert(valid());
tank_->self_check();
return i_->second.unit; }
reference operator*() const {
tank_->self_check();
assert(valid());
@ -189,7 +192,7 @@ public:
iterator_type new_i(i_);
do{
++new_i;
}while ((new_i != the_map().end()) && (new_i->second.unit == NULL)) ;
}while ((new_i != the_map().end()) && (!new_i->second.unit)) ;
dec();
i_ = new_i;
inc();
@ -210,7 +213,7 @@ public:
dec();
do {
--i_ ;
}while(i_ != begin && (i_->second.unit == NULL));
}while(i_ != begin && (!i_->second.unit));
inc();
valid_exit();
@ -225,7 +228,7 @@ public:
bool valid() const {
if(valid_for_dereference()) {
return i_->second.unit != NULL;
return i_->second.unit;
}
return false;
}
@ -254,7 +257,7 @@ public:
void dec() {
if( valid_ref_count() ){
assert(i_->second.ref_count != 0);
if( (--(i_->second.ref_count) == 0) && (i_->second.unit == NULL) ){
if( (--(i_->second.ref_count) == 0) && (!i_->second.unit) ){
iterator_type old = i_++;
tank_->umap_.erase(old);
}
@ -334,7 +337,7 @@ public:
* will be generated.
* @note The map takes ownership of the pointed object, only if it succeeds.
*/
std::pair<unit_iterator, bool> insert(unit *p);
std::pair<unit_iterator, bool> insert(UnitPtr p);
/**
* Moves a unit from location @a src to location @a dst.
@ -371,7 +374,7 @@ public:
* The unit is no longer owned by the map.
* It can be reinserted later, if needed.
*/
unit *extract(const map_location &loc);
UnitPtr extract(const map_location &loc);
///Checks invariants. For debugging purposes only. Doesn't do anything in non-debug mode.
bool self_check() const

32
src/unit_ptr.hpp Normal file
View file

@ -0,0 +1,32 @@
/*
Copyright (C) 2014 by Chris Beck <render787@gmail.com>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
// The purpose of this header is to forward declare the UnitPtr, if it
// is an intrusive pointer then this requires some boilerplate taken
// care of here.
#ifndef UNIT_PTR_H_INCLUDED
#define UNIT_PTR_H_INCLUDED
#include <boost/intrusive_ptr.hpp>
class unit;
void intrusive_ptr_add_ref(const unit *);
void intrusive_ptr_release(const unit *);
typedef boost::intrusive_ptr<unit> UnitPtr;
typedef boost::intrusive_ptr<const unit> UnitConstPtr;
#endif

View file

@ -428,7 +428,7 @@ void scoped_recall_unit::activate()
if(team_it != teams.end()) {
if(team_it->recall_list().size() > recall_index_) {
config &tmp_cfg = store();
team_it->recall_list()[recall_index_].write(tmp_cfg);
team_it->recall_list()[recall_index_]->write(tmp_cfg);
tmp_cfg["x"] = "recall";
tmp_cfg["y"] = "recall";
LOG_NG << "auto-storing $" << name() << " for player: " << player_

View file

@ -116,7 +116,7 @@ action::~action()
size_t action::get_unit_id() const
{
unit *ret = get_unit();
UnitPtr ret = get_unit();
return ret ? ret->underlying_id() : 0;
}

View file

@ -66,7 +66,7 @@ public:
virtual map_location get_numbering_hex() const = 0;
/** Return the unit targeted by this action. Null if unit doesn't exist. */
virtual unit* get_unit() const = 0;
virtual UnitPtr get_unit() const = 0;
/**
* Returns the id of the unit targeted by this action.

View file

@ -48,8 +48,8 @@ highlighter::highlighter(unit_map& unit_map, side_actions_ptr side_actions)
: unit_map_(unit_map)
, mouseover_hex_()
, exclusive_display_hexes_()
, owner_unit_(NULL)
, selection_candidate_(NULL)
, owner_unit_()
, selection_candidate_()
, selected_action_()
, main_highlight_()
, secondary_highlights_()
@ -79,10 +79,10 @@ void highlighter::set_mouseover_hex(const map_location& hex)
//if we're right over a unit, just highlight all of this unit's actions
unit_map::iterator it = unit_map_.find(hex);
if(it != unit_map_.end()) {
selection_candidate_ = &(*it);
selection_candidate_ = it.get_shared_ptr();
if(resources::teams->at(it->side()-1).get_side_actions()->unit_has_actions(*it)) {
owner_unit_ = &(*it);
owner_unit_ = it.get_shared_ptr();
}
//commented code below is to also select the first action of this unit as
@ -121,7 +121,7 @@ void highlighter::clear()
{
unhighlight();
main_highlight_.reset();
owner_unit_ = NULL;
owner_unit_.reset();
secondary_highlights_.clear();
selected_action_.reset();
}
@ -255,7 +255,7 @@ action_ptr highlighter::get_bump_target()
return selected_action_.lock();
}
unit* highlighter::get_selection_target()
UnitPtr highlighter::get_selection_target()
{
if(owner_unit_) {
return owner_unit_;

View file

@ -50,7 +50,7 @@ public:
action_ptr get_execute_target();
action_ptr get_delete_target();
action_ptr get_bump_target();
unit* get_selection_target();
UnitPtr get_selection_target();
/// @return the action that currently receives the highlight focus
weak_action_ptr get_main_highlight() { return main_highlight_; }
@ -79,8 +79,8 @@ private:
map_location mouseover_hex_;
std::set<map_location> exclusive_display_hexes_;
unit* owner_unit_;
unit* selection_candidate_;
UnitPtr owner_unit_;
UnitPtr selection_candidate_;
weak_action_ptr selected_action_;
weak_action_ptr main_highlight_;

View file

@ -326,8 +326,8 @@ void manager::post_delete_action(action_ptr action)
side_actions_ptr side_actions = resources::teams->at(action->team_index()).get_side_actions();
unit *actor = action->get_unit();
if(actor != NULL) { // The unit might have died following the execution of an attack
UnitPtr actor = action->get_unit();
if(actor) { // The unit might have died following the execution of an attack
side_actions::iterator action_it = side_actions->find_last_action_of(*actor);
if(action_it != side_actions->end()) {
move_ptr move = boost::dynamic_pointer_cast<class move>(*action_it);

View file

@ -117,12 +117,12 @@ void mapbuilder::process(side_actions &sa, side_actions::iterator action_it)
{
action_ptr action = *action_it;
bool acted=false;
unit* unit = action->get_unit();
UnitPtr unit = action->get_unit();
if(!unit) {
return;
}
if(acted_this_turn_.find(unit) == acted_this_turn_.end()) {
if(acted_this_turn_.find(unit.get()) == acted_this_turn_.end()) {
//reset MP
unit->set_movement(unit->total_movement());
acted=true;
@ -134,9 +134,9 @@ void mapbuilder::process(side_actions &sa, side_actions::iterator action_it)
if(erval != action::OK) {
// We do not delete obstructed moves, nor invalid actions caused by obstructed moves.
if(has_invalid_actions_.find(unit) == has_invalid_actions_.end()) {
if(has_invalid_actions_.find(unit.get()) == has_invalid_actions_.end()) {
if(erval == action::TOO_FAR || (erval == action::LOCATION_OCCUPIED && boost::dynamic_pointer_cast<move>(action))) {
has_invalid_actions_.insert(unit);
has_invalid_actions_.insert(unit.get());
invalid_actions_.push_back(action_it);
} else {
sa.remove_action(action_it, false);
@ -149,10 +149,10 @@ void mapbuilder::process(side_actions &sa, side_actions::iterator action_it)
}
// We do not keep invalid actions replaced by a valid one.
std::set<class unit const*>::iterator invalid_it = has_invalid_actions_.find(unit);
std::set<class unit const*>::iterator invalid_it = has_invalid_actions_.find(unit.get());
if(invalid_it != has_invalid_actions_.end()) {
for(std::list<side_actions::iterator>::iterator it = invalid_actions_.begin(); it != invalid_actions_.end();) {
if((**it)->get_unit() == unit) {
if((**it)->get_unit().get() == unit.get()) {
sa.remove_action(*it, false);
it = invalid_actions_.erase(it);
} else {
@ -163,7 +163,7 @@ void mapbuilder::process(side_actions &sa, side_actions::iterator action_it)
}
if(acted) {
acted_this_turn_.insert(unit);
acted_this_turn_.insert(unit.get());
}
action->apply_temp_modifier(unit_map_);
@ -181,8 +181,8 @@ void mapbuilder::post_visit_team(size_t turn)
move_ptr move = boost::dynamic_pointer_cast<class move>(action);
if(move) {
move->set_turn_number(0);
if(move->get_route().steps.size() > 1 && seen.count(move->get_unit()) == 0) {
seen.insert(move->get_unit());
if(move->get_route().steps.size() > 1 && seen.count(move->get_unit().get()) == 0) {
seen.insert(move->get_unit().get());
move->set_turn_number(turn + 1);
}
}

View file

@ -275,13 +275,13 @@ void move::execute(bool& success, bool& complete)
}
}
unit* move::get_unit() const
UnitPtr move::get_unit() const
{
unit_map::iterator itor = resources::units->find(unit_underlying_id_);
if (itor.valid())
return &*itor;
return itor.get_shared_ptr();
else
return NULL;
return UnitPtr();
}
map_location move::get_source_hex() const

View file

@ -52,7 +52,7 @@ public:
virtual error check_validity() const;
/** Return the unit targeted by this action. Null if unit doesn't exist. */
virtual unit* get_unit() const;
virtual UnitPtr get_unit() const;
/** @return pointer to the fake unit used only for visuals */
virtual fake_unit_ptr get_fake_unit() { return fake_unit_; }

View file

@ -71,11 +71,11 @@ recall::recall(config const& cfg, bool hidden)
{
// Construct and validate temp_unit_
size_t underlying_id = cfg["temp_unit_"];
BOOST_FOREACH(unit const& recall_unit, resources::teams->at(team_index()).recall_list())
BOOST_FOREACH(const UnitConstPtr & recall_unit, resources::teams->at(team_index()).recall_list())
{
if(recall_unit.underlying_id()==underlying_id)
if(recall_unit->underlying_id()==underlying_id)
{
temp_unit_.reset(new unit(recall_unit));
temp_unit_.reset(new unit(*recall_unit)); //TODO: is it necessary to make a copy?
break;
}
}
@ -144,21 +144,21 @@ void recall::apply_temp_modifier(unit_map& unit_map)
<< "] at position " << temp_unit_->get_location() << ".\n";
//temporarily remove unit from recall list
std::vector<unit>& recalls = resources::teams->at(team_index()).recall_list();
std::vector<unit>::iterator it = find_if_matches_id(recalls, temp_unit_->id());
std::vector<UnitPtr>& recalls = resources::teams->at(team_index()).recall_list();
std::vector<UnitPtr>::iterator it = find_if_matches_id(recalls, temp_unit_->id());
assert(it != recalls.end());
//Add cost to money spent on recruits.
int cost = resources::teams->at(team_index()).recall_cost();
if (it->recall_cost() > -1) {
cost = it->recall_cost();
if ((*it)->recall_cost() > -1) {
cost = (*it)->recall_cost();
}
recalls.erase(it);
// Temporarily insert unit into unit_map
//unit map takes ownership of temp_unit
unit_map.insert(temp_unit_.release());
unit_map.insert(temp_unit_);
resources::teams->at(team_index()).get_side_actions()->change_gold_spent_by(cost);
// Update gold in top bar
@ -167,11 +167,11 @@ void recall::apply_temp_modifier(unit_map& unit_map)
void recall::remove_temp_modifier(unit_map& unit_map)
{
temp_unit_.reset(unit_map.extract(recall_hex_));
temp_unit_ = unit_map.extract(recall_hex_);
assert(temp_unit_.get());
//Put unit back into recall list
resources::teams->at(team_index()).recall_list().push_back(*temp_unit_);
resources::teams->at(team_index()).recall_list().push_back(temp_unit_);
}
void recall::draw_hex(map_location const& hex)
@ -209,7 +209,7 @@ action::error recall::check_validity() const
return LOCATION_OCCUPIED;
}
//Check that unit to recall is still in side's recall list
const std::vector<unit>& recalls = (*resources::teams)[team_index()].recall_list();
const std::vector<UnitPtr>& recalls = (*resources::teams)[team_index()].recall_list();
if( find_if_matches_id(recalls, temp_unit_->id()) == recalls.end() ) {
return UNIT_UNAVAILABLE;
}

View file

@ -61,7 +61,7 @@ public:
virtual map_location get_numbering_hex() const { return recall_hex_; }
/** @return pointer to a copy of the recall unit. */
virtual unit* get_unit() const { return temp_unit_.get(); }
virtual UnitPtr get_unit() const { return temp_unit_; }
/** @return pointer to the fake unit used only for visuals */
virtual fake_unit_ptr get_fake_unit() { return fake_unit_; }
@ -81,7 +81,7 @@ private:
virtual void do_hide();
virtual void do_show();
std::auto_ptr<unit> temp_unit_;
UnitPtr temp_unit_;
map_location recall_hex_;
fake_unit_ptr fake_unit_;
};

View file

@ -129,7 +129,7 @@ void recruit::apply_temp_modifier(unit_map& unit_map)
// Temporarily insert unit into unit_map
// unit map takes ownership of temp_unit
unit_map.insert(temp_unit_.release());
unit_map.insert(temp_unit_);
// Update gold in the top bar
resources::screen->invalidate_game_status();
@ -138,7 +138,7 @@ void recruit::apply_temp_modifier(unit_map& unit_map)
void recruit::remove_temp_modifier(unit_map& unit_map)
{
//Unit map gives back ownership of temp_unit_
temp_unit_.reset(unit_map.extract(recruit_hex_));
temp_unit_ = unit_map.extract(recruit_hex_);
assert(temp_unit_.get());
}
@ -164,14 +164,14 @@ void recruit::redraw()
}
std::auto_ptr<unit> recruit::create_corresponding_unit()
UnitPtr recruit::create_corresponding_unit()
{
unit_type const* type = unit_types.find(unit_name_);
assert(type);
int side_num = team_index() + 1;
//real_unit = false needed to avoid generating random traits and causing OOS
bool real_unit = false;
std::auto_ptr<unit> result(new unit(*type, side_num, real_unit));
UnitPtr result(new unit(*type, side_num, real_unit));
result->set_movement(0, true);
result->set_attacks(0);
return result; //ownership gets transferred to returned auto_ptr copy

View file

@ -65,7 +65,7 @@ public:
virtual map_location get_numbering_hex() const { return recruit_hex_; }
/** @return pointer to a fake unit representing the one that will eventually be recruited. */
virtual unit* get_unit() const { return temp_unit_.get(); }
virtual UnitPtr get_unit() const { return temp_unit_; }
/** @return pointer to the fake unit used only for visuals */
virtual fake_unit_ptr get_fake_unit() { return fake_unit_; }
@ -82,7 +82,7 @@ protected:
std::string unit_name_;
map_location recruit_hex_;
//Temp unit to insert in the future unit map when needed
std::auto_ptr<unit> temp_unit_;
UnitPtr temp_unit_;
fake_unit_ptr fake_unit_;
int cost_;
@ -92,7 +92,7 @@ private:
virtual void do_hide();
virtual void do_show();
std::auto_ptr<unit> create_corresponding_unit();
UnitPtr create_corresponding_unit();
};
std::ostream& operator<<(std::ostream& s, recruit_ptr recruit);

View file

@ -453,9 +453,9 @@ namespace
move_ptr second_;
void check_recruit_recall(const map_location &loc) {
unit const* leader = second_->get_unit();
const UnitConstPtr leader = second_->get_unit();
if(leader->can_recruit() && can_recruit_on(*leader, loc)) {
if(unit const* backup_leader = find_backup_leader(*leader)) {
if(const UnitConstPtr backup_leader = find_backup_leader(*leader)) {
side_actions::iterator it = sa_.find_first_action_of(*backup_leader);
if(!(it == sa_.end() || position_ < it)) {
return; //backup leader but he moves before us, refuse bump
@ -487,9 +487,9 @@ side_actions::iterator side_actions::bump_earlier(side_actions::iterator positio
side_actions::iterator previous = position - 1;
//Verify we're not moving an action out-of-order compared to other action of the same unit
unit const* previous_ptr = (*previous)->get_unit();
unit const* current_ptr = (*position)->get_unit();
if(previous_ptr && current_ptr && previous_ptr == current_ptr) {
const UnitConstPtr previous_ptr = (*previous)->get_unit();
const UnitConstPtr current_ptr = (*position)->get_unit();
if(previous_ptr && current_ptr && previous_ptr.get() == current_ptr.get()) {
return end();
}
@ -859,16 +859,16 @@ side_actions::net_cmd side_actions::make_net_cmd_refresh() const
void side_actions::raw_turn_shift()
{
//find units who still have plans for turn 0 (i.e. were too lazy to finish their jobs)
std::set<unit const*> lazy_units;
std::set<UnitConstPtr> lazy_units;
BOOST_FOREACH(action_ptr const& act, iter_turn(0)) {
unit const* u = act->get_unit();
UnitConstPtr u = act->get_unit();
if(u) {
lazy_units.insert(u);
}
}
//push their plans back one turn
std::set<unit const*>::iterator lazy_end = lazy_units.end();
std::set<UnitConstPtr>::iterator lazy_end = lazy_units.end();
iterator itor = end();
while(itor != begin()) {
--itor;

View file

@ -96,13 +96,13 @@ suppose_dead::~suppose_dead()
resources::screen->invalidate(loc_);
}
unit* suppose_dead::get_unit() const
UnitPtr suppose_dead::get_unit() const
{
unit_map::iterator itor = resources::units->find(unit_underlying_id_);
if (itor.valid())
return &*itor;
return itor.get_shared_ptr();
else
return NULL;
return UnitPtr();
}
void suppose_dead::accept(visitor& v)
@ -116,12 +116,12 @@ void suppose_dead::execute(bool& success, bool& complete)
void suppose_dead::apply_temp_modifier(unit_map& unit_map)
{
// Remove the unit
unit const* removed_unit = unit_map.extract(loc_);
const UnitConstPtr removed_unit = unit_map.extract(loc_);
DBG_WB << "Suppose dead: Temporarily removing unit " << removed_unit->name() << " [" << removed_unit->id()
<< "] from (" << loc_ << ")\n";
// Just check to make sure we removed the unit we expected to remove
assert(get_unit() == removed_unit);
assert(get_unit().get() == removed_unit.get());
}
void suppose_dead::remove_temp_modifier(unit_map& unit_map)

View file

@ -35,7 +35,7 @@ public:
virtual ~suppose_dead();
/** Return the unit targeted by this action. Null if unit doesn't exist. */
virtual unit* get_unit() const;
virtual UnitPtr get_unit() const;
/** @return null pointer */
virtual fake_unit_ptr get_fake_unit() { return fake_unit_ptr(); }
/** Return the location at which this action was planned. */

View file

@ -61,19 +61,19 @@ side_actions_ptr current_side_actions()
return side_actions;
}
unit const* find_backup_leader(unit const& leader)
UnitConstPtr find_backup_leader(const unit & leader)
{
assert(leader.can_recruit());
assert(resources::gameboard->map().is_keep(leader.get_location()));
BOOST_FOREACH(unit const& unit, *resources::units)
for (unit_map::const_iterator unit = resources::units->begin(); unit != resources::units->end(); unit++)
{
if (unit.can_recruit() && unit.id() != leader.id())
if (unit->can_recruit() && unit->id() != leader.id())
{
if ( can_recruit_on(unit, leader.get_location()) )
return &unit;
if ( can_recruit_on(*unit, leader.get_location()) )
return unit.get_shared_ptr();
}
}
return NULL;
return UnitConstPtr();
}
unit* find_recruiter(size_t team_index, map_location const& hex)

View file

@ -47,7 +47,7 @@ side_actions_ptr current_side_actions();
* For a given leader on a keep, find another leader on another keep in the same castle.
* @retval NULL if no such leader has been found
*/
unit const* find_backup_leader(unit const& leader);
UnitConstPtr find_backup_leader(unit const& leader);
/**
* @return a leader from the specified team who can recruit on the specified hex