Reimplemented a lot of iteration code using the new visitor_base template.

Removed visitor.cpp because all the code is in visitor.hpp now.
This commit is contained in:
Tommy Schmitz 2011-08-02 10:17:48 +00:00
parent 85ef242fe3
commit b2be7c7cab
12 changed files with 104 additions and 146 deletions

View file

@ -7008,34 +7008,6 @@
RelativePath="..\..\src\whiteboard\validate_visitor.hpp"
>
</File>
<File
RelativePath="..\..\src\whiteboard\visitor.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)\Whiteboard\"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)\Whiteboard\"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug (fast)|Win32"
>
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)\Whiteboard\"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\whiteboard\visitor.hpp"
>

View file

@ -577,7 +577,6 @@ set(wesnoth-main_SRC
whiteboard/suppose_dead.cpp
whiteboard/utility.cpp
whiteboard/validate_visitor.cpp
whiteboard/visitor.cpp
widgets/combo.cpp
widgets/combo_drag.cpp
widgets/drop_target.cpp

View file

@ -437,7 +437,6 @@ wesnoth_sources = Split("""
whiteboard/suppose_dead.cpp
whiteboard/utility.cpp
whiteboard/validate_visitor.cpp
whiteboard/visitor.cpp
widgets/combo.cpp
widgets/combo_drag.cpp
widgets/drop_target.cpp

View file

@ -378,25 +378,20 @@ void highlight_visitor::find_main_highlight()
// viewing side assignments after victory
//assert(side_actions_->team_index() == resources::screen->viewing_team());
//Iterate backwards over all actions from all teams until the main highlight is found
size_t current_team = resources::controller->current_side() - 1;
size_t num_teams = resources::teams->size();
for(size_t iteration = 0; iteration < num_teams; ++iteration)
//Find the main highlight -- see visit(), below.
visitor_base<highlight_visitor>::reverse_visit_all();
}
//Used only by find_main_highlight()
bool highlight_visitor::visit(size_t, team&, side_actions&, side_actions::iterator itor)
{
(*itor)->accept(*this);
if (action_ptr main = main_highlight_.lock())
{
size_t team_index = (current_team+num_teams-1-iteration) % num_teams;
side_actions& sa = *resources::teams->at(team_index).get_side_actions();
side_actions::reverse_iterator rend = sa.rend();
side_actions::reverse_iterator action = sa.rbegin();
for (; action != rend; ++action )
{
(*action)->accept(*this);
if (action_ptr main = main_highlight_.lock())
{
owner_unit_ = main->get_unit();
return;
}
}
owner_unit_ = main->get_unit();
return false;
}
return true;
}
void highlight_visitor::find_secondary_highlights()
@ -404,7 +399,7 @@ void highlight_visitor::find_secondary_highlights()
assert(owner_unit_);
assert(secondary_highlights_.empty());
mode_ = FIND_SECONDARY_HIGHLIGHTS;
visit_all_actions();
visitor::visit_all(); //< Standard visitation procedure.
}
} // end namespace wb

View file

@ -37,8 +37,12 @@ namespace wb
* Visitor that handles highlighting planned actions as you hover over them,
* and determine the right target for contextual execution.
*/
class highlight_visitor: public wb::visitor
class highlight_visitor
: private visitor
, private visitor_base<highlight_visitor>
{
friend class visitor_base<highlight_visitor>;
public:
highlight_visitor(const unit_map& unit_map, side_actions_ptr side_actions);
virtual ~highlight_visitor();
@ -67,6 +71,11 @@ private:
virtual void visit_recall(recall_ptr recall);
virtual void visit_suppose_dead(suppose_dead_ptr sup_d);
//"Inherited" from visitor_base
bool visit(size_t team_index, team&, side_actions&, side_actions::iterator);
using visitor::pre_visit_team;
using visitor::post_visit_team;
void unhighlight();
void find_main_highlight();

View file

@ -343,6 +343,35 @@ static void draw_numbers(map_location const& hex, side_actions::numbers_t number
}
}
namespace
{
//Only used by manager::draw_hex()
struct draw_visitor
: private visitor_base<draw_visitor>
{
friend class visitor_base<draw_visitor>;
public:
draw_visitor(map_location const& hex, side_actions::numbers_t& numbers)
: hex_(hex)
, numbers_(numbers)
{}
void operator()() {visit_all();}
private:
//"Inherited" from visitor_base
bool visit(size_t team_index, team&, side_actions&, side_actions::iterator itor)
{ (*itor)->draw_hex(hex_); return true; }
//using default pre_visit_team()
bool post_visit_team(size_t team_index, team&, side_actions& sa)
{ sa.get_numbers(hex_,numbers_); return true; }
map_location const& hex_;
side_actions::numbers_t& numbers_;
};
}
void manager::draw_hex(const map_location& hex)
{
if (!wait_for_side_init_)
@ -350,17 +379,7 @@ void manager::draw_hex(const map_location& hex)
//Info about the action numbers to be displayed on screen.
side_actions::numbers_t numbers;
//Draw graphics from every team's actions, beginning with the current_team.
size_t current_team = resources::controller->current_side() - 1;
size_t num_teams = resources::teams->size();
for(size_t iteration = 0; iteration < num_teams; ++iteration)
{
size_t team_index = (current_team+iteration) % num_teams;
side_actions& sa = *resources::teams->at(team_index).get_side_actions();
foreach(action_ptr act, sa)
act->draw_hex(hex);
sa.get_numbers(hex,numbers);
}
draw_visitor(hex,numbers)();
draw_numbers(hex,numbers); //< helper fcn
}

View file

@ -63,31 +63,18 @@ void mapbuilder_visitor::reset_moves()
void mapbuilder_visitor::build_map()
{
mode_ = BUILD_PLANNED_MAP;
size_t current_team = resources::controller->current_side() - 1;
//Temporarily reset all units' moves to full EXCEPT for the ones on current_team.
reset_moves();
//Apply modifiers from every team's action_queue, ...
size_t viewing_team = viewer_team();
size_t num_teams = resources::teams->size();
for(size_t iteration = 0; iteration < num_teams; ++iteration)
{
//... beginning with the current_team, ...
size_t team_index = (current_team+iteration) % num_teams;
mode_ = BUILD_PLANNED_MAP;
visit_all(); //< Inherited from visitor_base
}
foreach(action_ptr act, *resources::teams->at(team_index).get_side_actions())
{
if(act->is_valid())
act->accept(*this);
}
//... and ending with the viewer_team.
if(team_index == viewing_team)
break;
}
bool mapbuilder_visitor::visit(size_t, team&, side_actions&, side_actions::iterator itor)
{
if((*itor)->is_valid())
(*itor)->accept(*this);
return true;
}
void mapbuilder_visitor::visit_move(move_ptr move)

View file

@ -22,9 +22,9 @@
#include <boost/ptr_container/ptr_vector.hpp>
#include "visitor.hpp"
#include "action.hpp"
#include "utility.hpp"
#include "visitor.hpp"
struct unit_movement_resetter;
@ -35,8 +35,11 @@ namespace wb
* Visitor that collects and applies unit_map modifications from the actions it visits
* and reverts all changes on destruction.
*/
class mapbuilder_visitor: public visitor
class mapbuilder_visitor
: protected visitor
, private visitor_base<mapbuilder_visitor>
{
friend class visitor_base<mapbuilder_visitor>;
public:
mapbuilder_visitor(unit_map& unit_map);
@ -56,11 +59,19 @@ protected:
virtual void visit_recall(recall_ptr recall);
virtual void visit_suppose_dead(suppose_dead_ptr sup_d);
//"Inherited" from visitor_base
bool visit(size_t team_index, team&, side_actions&, side_actions::iterator);
using visitor::pre_visit_team;
bool post_visit_team(size_t team_index, team&, side_actions&)
{return team_index != viewer_team();} //< Stop after visiting viewer_team
//Helper fcn: Temporarily resets all units' moves to max EXCEPT for
//the ones controlled by the player whose turn it is currently.
void reset_moves();
private:
void visit_all() {visitor_base<mapbuilder_visitor>::visit_all();}
void restore_normal_map();
unit_map& unit_map_;

View file

@ -56,22 +56,10 @@ bool validate_visitor::validate_actions()
//Temporarily reset all units' moves to full EXCEPT for the ones on viewer_side().
reset_moves(); //< protected fcn inherited from mapbuilder_visitor
//Apply modifiers from every team's action_queue, beginning with the current_team.
size_t current_team = resources::controller->current_side() - 1;
size_t num_teams = resources::teams->size();
for(size_t iteration = 0; iteration < num_teams; ++iteration)
{
size_t team_index = (current_team+iteration) % num_teams;
side_actions& actions = *resources::teams->at(team_index).get_side_actions();
arg_itor_ = actions.begin(); //< Parameter for the visit_***() fcns
side_actions::iterator end = actions.end();
for(; arg_itor_!=end; ++arg_itor_)
(*arg_itor_)->accept(*this);
}
visit_all();
//FIXME: by reverse iterating this can be done in a more efficiant way
// by using the iterator returned by remove_action it could even be done in the loop above
// by using the iterator returned by remove_action it could even be done in visit_all above
if (!actions_to_erase_.empty())
{
int side_actions_size_before = viewer_actions_.actions().size();

View file

@ -34,8 +34,12 @@ namespace wb
* * actions are evaluated for validity along the way.
* * Some invalid actions are deleted.
*/
class validate_visitor: private mapbuilder_visitor
class validate_visitor
: private mapbuilder_visitor
, private visitor_base<validate_visitor>
{
friend class visitor_base<validate_visitor>;
public:
explicit validate_visitor(unit_map& unit_map);
virtual ~validate_visitor();
@ -55,6 +59,13 @@ private:
VALIDITY evaluate_move_validity(move_ptr);
bool no_previous_invalids(side_actions::iterator const&);
//"Inherited" from visitor_base
bool visit(size_t team_index, team& t, side_actions& sa, side_actions::iterator itor)
{ arg_itor_=itor; return visitor::visit(team_index,t,sa,itor); }
using mapbuilder_visitor::pre_visit_team;
using visitor_base<validate_visitor>::post_visit_team;
using visitor_base<validate_visitor>::visit_all;
side_actions& viewer_actions_;
std::set<action_ptr> actions_to_erase_;

View file

@ -1,45 +0,0 @@
/* $Id$ */
/*
Copyright (C) 2010 - 2011 by Gabriel Morin <gabrielmorin (at) gmail (dot) 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.
*/
/**
* @file
*/
#include "visitor.hpp"
#include "action.hpp"
#include "foreach.hpp"
#include "side_actions.hpp"
#include "play_controller.hpp"
#include "resources.hpp"
#include "team.hpp"
namespace wb
{
void visitor::visit_all_actions()
{
size_t current_team = resources::controller->current_side() - 1;
size_t num_teams = resources::teams->size();
for(size_t iteration = 0; iteration < num_teams; ++iteration)
{
size_t team_index = (current_team+iteration) % num_teams;
foreach(action_ptr act, *resources::teams->at(team_index).get_side_actions())
act->accept(*this);
}
}
}//end namespace wb

View file

@ -42,6 +42,7 @@ namespace wb
* Derived classes should declare visitor_base<Derived> as a friend, or
* else make the overridden functions public.
* I recommend making the inheritance private or protected.
* See class visitor for an example.
*/
template<typename Derived>
class visitor_base
@ -108,19 +109,31 @@ private:
* Abstract base class for all the visitors (cf GoF Visitor Design Pattern)
* the whiteboard uses.
*/
class visitor : private boost::noncopyable
class visitor
: private boost::noncopyable
, private visitor_base<visitor>
{
friend class visitor_base<visitor>;
friend class move;
friend class attack;
friend class recruit;
friend class recall;
friend class suppose_dead;
public:
using visitor_base<visitor>::visit_all;
using visitor_base<visitor>::reverse_visit_all;
protected:
visitor() {}
virtual ~visitor() {} //Not intended for polymorphic deletion
void visit_all_actions(); //< weird utility function for derived classes
//"Inherited" from visitor_base
bool visit(size_t, team&, side_actions&, side_actions::iterator itor)
{ (*itor)->accept(*this); return true; }
using visitor_base<visitor>::pre_visit_team;
using visitor_base<visitor>::post_visit_team;
virtual void visit_move(move_ptr move) = 0;
virtual void visit_attack(attack_ptr attack) = 0;