more powerful [filter_location],

now accepts radius=, [not], and [filter] to match units at the location
This commit is contained in:
Patrick Parker 2007-04-04 04:54:27 +00:00
parent 01b434e647
commit 7a5765f12b
6 changed files with 55 additions and 9 deletions

View File

@ -84,6 +84,8 @@ Version 1.3.1+svn:
which the attack engine didn't expect (bug #8814)
* new key for [time], sound=, to specify a list of sounds that can play
when ToD changes
* more powerful [filter_location], now accepts radius=, [not], and
[filter] to match units at the location
* user interface:
* new sounds for user interface events
* added the option to show warnings about deprecated WML usage

View File

@ -18,7 +18,7 @@
#include "gamestatus.hpp"
#include "log.hpp"
#include "map.hpp"
#include "pathutils.hpp"
#include "pathfind.hpp"
#include "util.hpp"
#include "variable.hpp"
#include "wassert.hpp"
@ -567,7 +567,37 @@ bool gamemap::location::matches_range(const std::string& xloc, const std::string
return true;
}
bool gamemap::terrain_matches_filter(const gamemap::location& loc, const config& cfg,
bool gamemap::terrain_matches_filter(const gamemap::location& loc, const vconfig& cfg,
const gamestatus& game_status, const unit_map& units, const bool flat_tod,
const size_t max_loop) const
{
//handle radius
const size_t radius = minimum<size_t>(max_loop,
lexical_cast_default<size_t>(cfg["radius"]));
std::set<gamemap::location> hexes;
std::vector<gamemap::location> loc_vec(1, loc);
get_tiles_radius(*this, loc_vec, radius, hexes);
size_t loop_count = 0;
bool matches = false;
std::set<gamemap::location>::const_iterator i;
for(i = hexes.begin(); i != hexes.end() && loop_count <= max_loop && !matches; ++i) {
matches = terrain_matches_internal(*i, cfg, game_status, units, flat_tod);
++loop_count;
}
if(!matches) return false;
//handle [not]
const vconfig::child_list& nots = cfg.get_children("not");
for(vconfig::child_list::const_iterator j = nots.begin(); j != nots.end(); ++j) {
if(terrain_matches_filter(loc, *j, game_status, units, flat_tod, max_loop)) {
return false;
}
}
return true;
}
bool gamemap::terrain_matches_internal(const gamemap::location& loc, const vconfig& cfg,
const gamestatus& game_status, const unit_map& units, const bool flat_tod) const
{
/* *
@ -626,6 +656,14 @@ bool gamemap::terrain_matches_filter(const gamemap::location& loc, const config&
}
}
//Allow filtering on unit
if(cfg.has_child("filter")) {
const config& unit_filter = cfg.child("filter").get_config();
const unit_map::const_iterator u = units.find(loc);
if (u == units.end() || !u->second.matches_filter(unit_filter, loc, flat_tod))
return false;
}
const std::string& tod_type = cfg["time_of_day"];
const std::string& tod_id = cfg["time_of_day_id"];
static config const dummy_cfg;

View File

@ -27,6 +27,8 @@ class unit_map;
#include <string>
#include <vector>
#define MAX_MAP_AREA 65536
//class which encapsulates the map of the game. Although the game is hexagonal,
//the map is stored as a grid. Each type of terrain is represented by a letter.
class gamemap
@ -178,8 +180,9 @@ public:
const terrain_type& get_terrain_info(const location &loc) const
{ return get_terrain_info(get_terrain(loc)); }
//
bool terrain_matches_filter(const location& loc, const config& cfg,
const gamestatus& game_status, const unit_map& units, const bool flat_tod=false) const;
bool terrain_matches_filter(const location& loc, const vconfig& cfg,
const gamestatus& game_status, const unit_map& units,
const bool flat_tod=false, const size_t max_loop=MAX_MAP_AREA) const;
//gets the list of terrains
const t_translation::t_list& get_terrain_list() const
@ -207,6 +210,8 @@ protected:
location startingPositions_[STARTING_POSITIONS];
private:
bool terrain_matches_internal(const location& loc, const vconfig& cfg,
const gamestatus& game_status, const unit_map& units, const bool flat_tod=false) const;
int num_starting_positions() const
{ return sizeof(startingPositions_)/sizeof(*startingPositions_); }

View File

@ -796,7 +796,7 @@ void play_controller::expand_wml_commands(std::vector<std::string>& items)
if ((show_if.empty()
|| game_events::conditional_passed(&units_, &show_if))
&& (location_filter.empty()
|| map_.terrain_matches_filter(hex, vconfig(&location_filter).get_parsed_config(), status_, units_)))
|| map_.terrain_matches_filter(hex, &location_filter, status_, units_)))
{
wml_commands_.push_back(itor->second);
std::string newitem = itor->second->description;

View File

@ -777,7 +777,7 @@ bool unit::internal_matches_filter(const config& orig_cfg,const gamemap::locatio
wassert(map_ != NULL);
wassert(gamestatus_ != NULL);
wassert(units_ != NULL);
bool res = map_->terrain_matches_filter(loc,*filter_location,*gamestatus_,*units_,use_flat_tod);
bool res = map_->terrain_matches_filter(loc,filter_location,*gamestatus_,*units_,use_flat_tod);
if(res == false) {
return false;
}

View File

@ -14,9 +14,10 @@
#include "unit.hpp"
#include "unit_abilities.hpp"
#include "wassert.hpp"
#include "log.hpp"
#include "pathutils.hpp"
#include "variable.hpp"
#include "wassert.hpp"
#include <deque>
@ -322,7 +323,7 @@ bool unit::ability_active(const std::string& ability,const config& cfg,const gam
if(index != gamemap::location::NDIRECTIONS) {
wassert(map_ != NULL);
wassert(gamestatus_ != NULL);
if(!map_->terrain_matches_filter(adjacent[index],**i,*gamestatus_,*units_,ability=="illuminates")) {
if(!map_->terrain_matches_filter(adjacent[index],*i,*gamestatus_,*units_,ability=="illuminates",0)) {
return false;
}
}
@ -749,7 +750,7 @@ bool attack_type::special_active(const config& cfg,bool self,bool report) const
if(index != gamemap::location::NDIRECTIONS) {
wassert(map_ != NULL);
wassert(game_status_ != NULL);
if(!map_->terrain_matches_filter(adjacent[index],**i,*game_status_,*unitmap_)) {
if(!map_->terrain_matches_filter(adjacent[index],*i,*game_status_,*unitmap_,false,0)) {
return false;
}
}