Basic move validation is in place when executing/removing/etc.

Right now an invalid path is simply replaced by a new path is
possible; the player might not appreciate and would probably prefer
getting a visual warning and redefining it manually.
This commit is contained in:
Gabriel Morin 2010-06-30 07:52:18 +00:00
parent 6050f0d617
commit 35e45bf5ad
6 changed files with 107 additions and 3 deletions

View file

@ -84,7 +84,15 @@ public:
virtual void set_last_action(bool last_action) = 0;
//TODO: rename this if it ends up only refreshing the future and last action display
virtual void update_display() = 0;
/**
* Indicates to an action whether its status is invalid, and whether it should change its
* display (and avoid any change to the game state) accordingly
*/
virtual void set_valid(bool valid) = 0;
virtual bool is_valid() = 0;
};
} // end namespace wb

View file

@ -187,4 +187,20 @@ void move::update_display()
}
}
void move::set_valid(bool valid)
{
const std::string ARROW_STYLE_VALID = "";
const std::string ARROW_STYLE_INVALID = "invalid";
valid_ = valid;
if (valid_)
{
arrow_->set_style(ARROW_STYLE_VALID);
}
else
{
arrow_->set_style(ARROW_STYLE_INVALID);
}
}
} // end namespace wb

View file

@ -37,6 +37,7 @@ namespace wb {
*/
class move : public action, public boost::enable_shared_from_this<move>
{
friend class validate_visitor;
public: //constants
static const double ALPHA_HIGHLIGHT;
static const double ALPHA_NORMAL;
@ -69,6 +70,9 @@ public:
virtual void set_last_action(bool last_action) {last_action_ = last_action; update_display(); }
virtual void update_display();
virtual void set_valid(bool valid);
virtual bool is_valid() { return valid_; }
private:
unit & unit_;
map_location orig_hex_;
@ -79,6 +83,8 @@ private:
bool future_display_;
bool last_action_;
bool valid_;
};
} // end namespace wb

View file

@ -19,8 +19,10 @@
#include "side_actions.hpp"
#include "action.hpp"
#include "move.hpp"
#include "validate_visitor.hpp"
#include "foreach.hpp"
#include "resources.hpp"
#include <set>
namespace wb
@ -51,7 +53,7 @@ void side_actions::execute_next()
update_last_action_display();
}
//TODO: Validate remaining actions here
validate_actions();
}
}
@ -63,7 +65,7 @@ void side_actions::execute(action_ptr action)
{
remove_action(action);
}
//TODO: Validate remaining actions here
validate_actions();
}
void side_actions::insert_move(unit& subject, const map_location& source_hex, const map_location& target_hex, size_t index, boost::shared_ptr<arrow> arrow,
@ -72,6 +74,7 @@ void side_actions::insert_move(unit& subject, const map_location& source_hex, co
action_ptr action(new move(subject, source_hex, target_hex, arrow, fake_unit));
assert(index < end());
actions_.insert(actions_.begin() + index, action);
validate_actions();
update_last_action_display();
}
@ -103,6 +106,7 @@ void side_actions::remove_action(size_t index)
if (position < actions_.end())
{
actions_.erase(position);
validate_actions();
update_last_action_display();
}
}
@ -118,6 +122,7 @@ void side_actions::remove_action(action_ptr action)
if (*position == action)
{
actions_.erase(position);
validate_actions();
update_last_action_display();
break;
}
@ -153,6 +158,15 @@ void side_actions::update_last_action_display()
}
}
void side_actions::validate_actions()
{
validate_visitor validator(*resources::units);
foreach(action_ptr action, actions_)
{
action->accept(validator);
}
}
/*
* Utility function to move actions around the queue.
* Positive increment = move toward back of the queue and later execution.
@ -187,6 +201,7 @@ void side_actions::move_in_queue(size_t index, int increment)
//be careful, previous iterators have just been invalidated by erase()
action_set::iterator destination = after + increment;
actions_.insert(destination, action);
validate_actions();
}

View file

@ -116,6 +116,8 @@ public:
*/
void update_last_action_display();
void validate_actions();
private:
/**

View file

@ -17,6 +17,13 @@
*/
#include "validate_visitor.hpp"
#include "arrow.hpp"
#include "move.hpp"
#include "pathfind/pathfind.hpp"
#include "play_controller.hpp"
#include "resources.hpp"
#include "team.hpp"
namespace wb
{
@ -30,9 +37,59 @@ validate_visitor::~validate_visitor()
{
}
//FIXME: move this some place it can be accessible from the whole whiteboard
static team& get_current_team()
{
int current_side = resources::controller->current_side();
team& current_team = (*resources::teams)[current_side - 1];
return current_team;
}
void validate_visitor::visit_move(boost::shared_ptr<move> move)
{
mapbuilder_visitor::visit_move(move);
bool valid = true;
if (!(move->orig_hex_.valid() && move->dest_hex_.valid()))
valid = false;
if (valid && resources::units->find(move->orig_hex_) == resources::units->end())
valid = false;
pathfind::plain_route route;
if (valid)
{
pathfind::shortest_path_calculator path_calc(move->unit_, get_current_team(), *resources::units,
*resources::teams, *resources::game_map);
route = pathfind::a_star_search(move->orig_hex_,
move->dest_hex_, 10000, &path_calc, resources::game_map->w(), resources::game_map->h());
if (route.move_cost >= path_calc.getNoPathValue())
{
valid = false;
}
}
if (valid)
{
if (!std::equal(route.steps.begin(), route.steps.end(), move->arrow_->get_path().begin()))
{
//new valid path differs from the previous one, replace
move->arrow_->set_path(route.steps);
//TODO: Since this might lengthen the path, we probably need a special conflict state
// to warn the player that the initial path is no longer possible.
}
// Now call the superclass to apply the result of this move to the unit map,
// so that further pathfinding takes it into account.
mapbuilder_visitor::visit_move(move);
}
else //path invalid
{
// Don't apply the move's results to the unit map
// Mark the move as invalid
move->set_valid(false);
}
}