whiteboard/side_actions.hpp

Go to the documentation of this file.
00001 /* $Id: side_actions.hpp 53003 2012-02-14 18:09:47Z mordante $ */
00002 /*
00003  Copyright (C) 2010 - 2012 by Gabriel Morin <gabrielmorin (at) gmail (dot) com>
00004  Part of the Battle for Wesnoth Project http://www.wesnoth.org
00005 
00006  This program is free software; you can redistribute it and/or modify
00007  it under the terms of the GNU General Public License as published by
00008  the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010  This program is distributed in the hope that it will be useful,
00011  but WITHOUT ANY WARRANTY.
00012 
00013  See the COPYING file for more details.
00014  */
00015 
00016 /**
00017  * @file
00018  */
00019 
00020 #ifndef WB_SIDE_ACTIONS_HPP_
00021 #define WB_SIDE_ACTIONS_HPP_
00022 
00023 #include "typedefs.hpp"
00024 
00025 namespace wb
00026 {
00027 
00028 class move;
00029 
00030 /**
00031  * This internal whiteboard class holds the planned action queues for a team, and offers many
00032  * utility methods to create and manipulate them. It maintains an internal data structure
00033  * but mostly hides it by providing its own iterators, begin() and end() methods, etc.
00034  */
00035 class side_actions: public boost::enable_shared_from_this<side_actions>
00036 {
00037     /**
00038      * Class invariant:
00039      *   actions_.empty() || !actions_.back().empty();
00040      */
00041 
00042     typedef std::deque<action_queue> contents_t;
00043 
00044 public:
00045     class iterator;
00046     class const_iterator;
00047     friend class iterator;
00048     friend class const_iterator;
00049     typedef std::reverse_iterator<iterator> reverse_iterator;
00050     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00051 
00052     side_actions();
00053     virtual ~side_actions();
00054 
00055     ///Must be called only once, right after the team that owns this side_actions is added to the teams vector
00056     void set_team_index(size_t team_index);
00057 
00058     ///Returns the team index this action queue belongs to
00059     size_t team_index() { assert(team_index_defined_); return team_index_; }
00060 
00061     /// Get the underlying action container
00062     contents_t const& actions() const { return actions_; }
00063 
00064     struct numbers_t;
00065     /** Gets called when display is drawing a hex to determine which numbers to draw on it */
00066     void get_numbers(const map_location& hex, numbers_t& result);
00067 
00068     /**
00069      * Executes the first action in the queue, and then deletes it.
00070      * @return true - if the action was completed successfully
00071      */
00072     bool execute_next();
00073 
00074     /**
00075      * Executes the specified action, if it exists in the queue.
00076      * If the action is not finished, it's moved at the end of the queue.
00077      * @return true - if the action was completed successfully
00078      */
00079     bool execute(iterator position);
00080 
00081     /**
00082      * Returns the iterator for the first (executed earlier) action within the actions queue.
00083      */
00084     iterator begin();
00085     /// reverse version of the above
00086     reverse_iterator rbegin();
00087     /// const versions of the above
00088     const_iterator begin() const;
00089     const_reverse_iterator rbegin() const;
00090 
00091     /**
00092      * Returns the iterator for the position *after* the last executed action within the actions queue.
00093      */
00094     iterator end();
00095     /// reverse version of the above
00096     reverse_iterator rend();
00097     /// const versions of the above
00098     const_iterator end() const;
00099     const_reverse_iterator rend() const;
00100 
00101     /**
00102      * Indicates whether the action queue is empty.
00103      * Since it's a queue of queues (one per turn), it can be empty of actions,
00104      * while still containing empty queues.
00105      * @todo devise a cleanup system to prevent the possibility of empty queues.
00106      */
00107     bool empty() const { return actions_.empty(); }
00108 
00109     /**
00110      * Returns the number of actions in the action queue.
00111      */
00112     size_t size() const;
00113 
00114     ///Returns the number of turns that have plans.
00115     size_t num_turns() const {return actions_.size();}
00116 
00117     ///Returns an iterator to a specific turn queue.
00118     iterator turn_begin(size_t turn_num);
00119     iterator turn_end(size_t turn_num);
00120     reverse_iterator turn_rbegin(size_t turn_num);
00121     reverse_iterator turn_rend(size_t turn_num);
00122 
00123     typedef std::pair<iterator,iterator> range_t;
00124     typedef std::pair<reverse_iterator,reverse_iterator> rrange_t;
00125     ///Returns an iterator range corresponding to the requested turn.
00126     range_t iter_turn(size_t turn_num);
00127     rrange_t riter_turn(size_t turn_num);
00128 
00129     /** @return the number of actions planned for turn turn_num */
00130     size_t turn_size(size_t turn_num) const {
00131         if (num_turns() >= turn_num)
00132             return actions_[turn_num].size();
00133         else
00134             return 0;
00135     }
00136 
00137     /**
00138      * Empties the action queue.
00139      */
00140     void clear() { safe_clear(); }
00141 
00142     /** Sets whether or not the contents should be drawn on the screen. */
00143     void hide();
00144     void show();
00145     bool hidden() const {return hidden_;}
00146 
00147     /**
00148      * Queues a move to be executed last
00149      * @return The queued move's position
00150      */
00151     iterator queue_move(size_t turn_num, unit& mover, const pathfind::marked_route& route,
00152             arrow_ptr arrow, fake_unit_ptr fake_unit);
00153 
00154     /**
00155      * Queues an attack or attack-move to be executed last
00156      * @return The queued attack's position
00157      */
00158     iterator queue_attack(size_t turn_num, unit& mover, const map_location& target_hex, int weapon_choice, const pathfind::marked_route& route,
00159             arrow_ptr arrow, fake_unit_ptr fake_unit);
00160 
00161     /**
00162      * Queues a recruit to be executed last
00163      * @return The queued recruit's position
00164      */
00165     iterator queue_recruit(size_t turn_num, const std::string& unit_name, const map_location& recruit_hex);
00166 
00167     /**
00168      * Queues a recall to be executed last
00169      * @return The queued recall's position
00170      */
00171     iterator queue_recall(size_t turn_num, const unit& unit, const map_location& recall_hex);
00172 
00173     /**
00174      * Queues a suppose_dead to be executed last
00175      * @return The queued suppose_dead's position (an iterator to it)
00176      */
00177     iterator queue_suppose_dead(size_t turn_num, unit& curr_unit, map_location const& loc);
00178 
00179     /**
00180      * Inserts an action at the specified position. The begin() and end() functions might prove useful here.
00181      * @return The inserted action's position.
00182      */
00183     iterator insert_action(iterator position, action_ptr action);
00184 
00185     /**
00186      * Queues an action to be executed last
00187      * @return The queued action's position
00188      */
00189     iterator queue_action(size_t turn_num, action_ptr action);
00190 
00191     /**
00192      * Moves an action earlier in the execution order (i.e. at the front of the queue),
00193      * by one position.
00194      * @return The action's new position.
00195      */
00196     iterator bump_earlier(iterator position);
00197 
00198     /**
00199      * Moves an action later in the execution order (i.e. at the back of the queue),
00200      * by one position.
00201      * @return The action's new position.
00202      */
00203     iterator bump_later(iterator position);
00204 
00205     /**
00206      * Deletes the action at the specified position.
00207      * @return The position of the element after the one deleted, or end() if the queue is empty.
00208      */
00209     iterator remove_action(iterator position, bool validate_after_delete = true);
00210 
00211     /**
00212      * @param action The action whose position you're looking for
00213      * @return The action's position within the queue, or end() if action wasn't found.
00214      */
00215     iterator get_position_of(action_ptr action);
00216 
00217     /**
00218      * Finds the first action that belongs to this unit, starting the search at the specified position.
00219      * @return The position, or end() if not found.
00220      */
00221     iterator find_first_action_of(unit const* unit, iterator start_position);
00222     ///Variant of this method that always start searching at the beginning of the queue
00223     iterator find_first_action_of(unit const* unit);
00224 
00225     /**
00226      * Finds the last action that belongs to this unit, starting the search backwards from the specified position.
00227      * @return The position, or end() if not found.
00228      */
00229     iterator find_last_action_of(unit const* unit, iterator start_position);
00230     ///Variant of the previous method that always start searching at the end of the queue
00231     iterator find_last_action_of(unit const* unit);
00232 
00233     bool unit_has_actions(unit const* unit);
00234     size_t count_actions_of(unit const* unit);
00235 
00236     ///Removes all invalid actions "attached" to the unit
00237     void remove_invalid_of(unit const*);
00238 
00239     ///Determines the appropriate turn number for the next action planned for this unit
00240     size_t get_turn_num_of(unit const&) const;
00241 
00242     ///Validates all planned actions in the queue
00243     void validate_actions();
00244 
00245     ///Used to track gold spending by recruits/recalls when building the future unit map
00246     int get_gold_spent() const { return gold_spent_; }
00247     ///Used to track gold spending by recruits/recalls when building the future unit map
00248     void change_gold_spent_by(int difference);
00249     ///Set gold spent back to zero
00250     void reset_gold_spent();
00251 
00252     void raw_turn_shift();
00253     void synced_turn_shift();
00254 
00255     /**
00256      * Network code. A net_cmd object (a config in disguise) represents a modification
00257      * to a side_actions object. execute_net_cmd() translates one of these into
00258      * a real modification of *this. The make_net_cmd_***() family of functions is
00259      * convenient for building specific types of net_cmds.
00260      */
00261     typedef config net_cmd;
00262     void execute_net_cmd(net_cmd const&);
00263     net_cmd make_net_cmd_insert(size_t turn_num, size_t pos, action_const_ptr) const;
00264     net_cmd make_net_cmd_insert(const_iterator const& pos, action_const_ptr) const;
00265     net_cmd make_net_cmd_replace(const_iterator const& pos, action_const_ptr) const; //< an optimized remove+insert
00266     net_cmd make_net_cmd_remove(const_iterator const& pos) const;
00267     net_cmd make_net_cmd_bump_later(const_iterator const& pos) const;
00268     net_cmd make_net_cmd_clear() const;
00269     net_cmd make_net_cmd_refresh() const;
00270 
00271 private:
00272     bool validate_iterator(iterator position);
00273     void update_size();
00274     iterator raw_erase(iterator itor);
00275     iterator raw_insert(iterator itor, action_ptr to_insert);
00276     iterator raw_enqueue(size_t turn_num, action_ptr to_insert);
00277     iterator safe_insert(size_t turn_num, size_t pos, action_ptr to_insert);
00278     iterator synced_erase(iterator itor);
00279     iterator synced_insert(iterator itor, action_ptr to_insert);
00280     iterator synced_enqueue(size_t turn_num, action_ptr to_insert);
00281     iterator safe_erase(iterator const& itor);
00282     void safe_clear() { contents_t temp = actions_; return actions_.clear(); }
00283 
00284     static iterator null;
00285 
00286     contents_t actions_;
00287     size_t team_index_;
00288     bool team_index_defined_;
00289 
00290     /// Used to store gold "spent" in planned recruits/recalls when the future unit map is applied
00291     int gold_spent_;
00292 
00293     bool hidden_;
00294 };
00295 
00296 /** Dumps side_actions on a stream, for debug purposes. */
00297 std::ostream &operator<<(std::ostream &s, wb::side_actions const& side_actions);
00298 
00299 class side_actions::iterator
00300     : public std::iterator<std::bidirectional_iterator_tag, action_ptr>
00301 {
00302     friend class side_actions;
00303     typedef action_queue::iterator base_t;
00304     typedef iterator this_t;
00305 
00306 public:
00307     iterator()
00308             : base_()
00309             , turn_num_()
00310             , contents_()
00311         {}
00312     explicit iterator(side_actions::reverse_iterator const& that)
00313             : base_(that.base().base_)
00314             , turn_num_(that.base().turn_num_)
00315             , contents_(that.base().contents_)
00316         {}
00317 
00318     /**
00319      * Copy constructor.
00320      *
00321      * If the contents_ is NULL the iterator is singular. Copying singular
00322      * iterators is UB, so avoid it.
00323      */
00324     iterator(const iterator& that)
00325             : base_(that.contents_ ? that.base_ : base_t())
00326             , turn_num_(that.contents_ ? that.turn_num_ : 0)
00327             , contents_(that.contents_)
00328     {
00329     }
00330 
00331     action_ptr& operator*() const {return *base_;}
00332     action_ptr* operator->() const {return base_.operator->();}
00333     this_t& operator++()
00334     {
00335         ++base_;
00336         init();
00337         return *this;
00338     }
00339     this_t& operator--()
00340     {
00341         assert(contents_);
00342         while(base_ == (*contents_)[turn_num_].begin())
00343             base_ = (*contents_)[--turn_num_].end();
00344         --base_;
00345         return *this;
00346     }
00347     this_t operator+(int x) const
00348     {
00349         this_t result = *this;
00350         if(x >= 0)
00351             for(int i=0; i<x; ++i)
00352                 ++result;
00353         else
00354             for(int i=0; i>x; --i)
00355                 --result;
00356         return result;
00357     }
00358     this_t operator-(int x) const {return operator+(-x);}
00359     size_t operator-(this_t x) const
00360     {
00361         int result = 0;
00362         for(; x!=*this; ++x)
00363             ++result;
00364         return result;
00365     }
00366     bool operator<(this_t const& that) const
00367     {
00368         assert(contents_ == that.contents_);
00369         if(contents_==NULL)
00370             return false;
00371         return turn_num_<that.turn_num_ || (turn_num_==that.turn_num_ && base_<that.base_);
00372     }
00373     bool operator==(this_t const& that) const
00374     {
00375         assert(contents_ == that.contents_);
00376         if(contents_==NULL)
00377             return true;
00378         return turn_num_==that.turn_num_ && base_==that.base_;
00379     }
00380     bool operator!=(this_t const& that) const {return !(*this==that);}
00381 
00382 private:
00383     iterator(base_t const& base, size_t turn_num, side_actions& sa)
00384             : base_(base), turn_num_(turn_num), contents_(&sa.actions_)
00385         {init();}
00386 
00387     iterator(base_t const& base, size_t turn_num, side_actions::contents_t* contents)
00388             // If contents == NULL base is a singualar iterator
00389             : base_(contents ? base : base_t())
00390             , turn_num_(turn_num)
00391             , contents_(contents)
00392         {}
00393 
00394     void init()
00395     {
00396         assert(contents_);
00397         while(base_ == (*contents_)[turn_num_].end() //terminates thanks to invariant
00398                 && turn_num_+1 < contents_->size())
00399             base_ = (*contents_)[++turn_num_].begin();
00400     }
00401 
00402     base_t base_;
00403     size_t turn_num_;
00404     contents_t* contents_;
00405 };
00406 class side_actions::const_iterator
00407     : public std::iterator<std::bidirectional_iterator_tag, action_ptr const>
00408 {
00409     friend class side_actions;
00410     typedef side_actions::iterator base_t;
00411     typedef side_actions::const_iterator this_t;
00412 
00413 public:
00414     const_iterator()
00415             : std::iterator<std::bidirectional_iterator_tag, action_ptr const>()
00416             , base_()
00417         {}
00418     //conversion from non-const to const
00419     /*implicit*/ const_iterator(base_t const& base)
00420             : std::iterator<std::bidirectional_iterator_tag, action_ptr const>()
00421             , base_(base)
00422         {}
00423 
00424     action_ptr const& operator*() const {return *base_;}
00425     action_ptr const* operator->() const {return base_.operator->();}
00426     this_t& operator++() {++base_;   return *this;}
00427     this_t& operator--() {--base_;   return *this;}
00428     this_t operator+(int x) const {return base_ + x;}
00429     this_t operator-(int x) const {return base_ - x;}
00430     size_t operator-(this_t const& that) const {return base_-that.base_;}
00431     bool operator==(this_t const& that) const {return base_ == that.base_;}
00432     bool operator!=(this_t const& that) const {return base_ != that.base_;}
00433     bool operator<(this_t const& that) const {return base_ < that.base_;}
00434 
00435 private:
00436     base_t base_;
00437 };
00438 
00439 struct side_actions::numbers_t
00440 {
00441     std::vector<int> numbers_to_draw;
00442     std::vector<size_t> team_numbers;
00443     int main_number;
00444     std::set<size_t> secondary_numbers;
00445 
00446     numbers_t()
00447             : numbers_to_draw()
00448             , team_numbers()
00449             , main_number(-1)
00450             , secondary_numbers()
00451         {}
00452 };
00453 
00454 } //end namespace wb
00455 
00456 #endif /* WB_SIDE_ACTIONS_HPP_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:15 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs