now [store_unit] and [kill] understand x,y=recall,recall

still some bugs with the Tutorial... needs research
This commit is contained in:
Patrick Parker 2008-08-17 07:26:26 +00:00
parent 4293de829e
commit e20c3cbd6c
4 changed files with 58 additions and 44 deletions

View File

@ -1102,7 +1102,14 @@ These dummies only attack if you are a single tile away. With care, you should b
[event]
name=advance
first_time_only=no
{VARIABLE_OP unit.variables.previous_xp add $unit.max_experience}
[store_unit]
x,y=$x1,$y1
variable=Unit
[/store_unit]
{VARIABLE_OP Unit.variables.previous_xp add $Unit.max_experience}
[unstore_unit]
variable=Unit
advance=false
[/unstore_unit]
[/event]
[/tutorial]

View File

@ -461,9 +461,7 @@ One Elvish Shaman")}
[store_unit]
variable=recall
[filter]
[not]
x,y=1-99,1-99
[/not]
x,y=recall,recall
[/filter]
[/store_unit]

View File

@ -2022,7 +2022,7 @@ namespace {
bool too_many_recursions_;
public:
recursion_preventer(gamemap::location& loc) :
recursion_preventer(gamemap::location& loc) :
loc_(loc),
too_many_recursions_(false)
{
@ -2096,7 +2096,11 @@ namespace {
// If the filter doesn't contain positional information,
// then it may match units on all recall lists.
if(cfg["x"].empty() && cfg["y"].empty()) {
t_string const& cfg_x = cfg["x"];
t_string const& cfg_y = cfg["y"];
if((cfg_x.empty() || cfg_x == "recall")
&& (cfg_y.empty() || cfg_y == "recall"))
{
std::map<std::string, player_info>& players=state_of_game->players;
for(std::map<std::string, player_info>::iterator pi = players.begin();
@ -2226,7 +2230,11 @@ namespace {
}
}
if(filter["x"].empty() && filter["y"].empty()) {
t_string const& filter_x = filter["x"];
t_string const& filter_y = filter["y"];
if((filter_x.empty() || filter_x == "recall")
&& (filter_y.empty() || filter_y == "recall"))
{
std::map<std::string, player_info>& players = state_of_game->players;
for(std::map<std::string, player_info>::iterator pi = players.begin();
@ -2308,6 +2316,7 @@ namespace {
// The code in dialogs::advance_unit tests whether the unit can advance
dialogs::advance_unit(*game_map, *units, loc, *screen, !sel, true);
//! @todo FIXME: triggers advance events without preventing infinite loop
}
} else {

View File

@ -12,7 +12,7 @@
See the COPYING file for more details.
*/
//! @file map.cpp
//! @file map.cpp
//! Routines related to game-maps, terrain, locations, directions. etc.
#include "global.hpp"
@ -184,12 +184,12 @@ gamemap::location::location(const config& cfg, const variable_set *variables) :
xs = utils::interpolate_variables_into_string( xs, *variables);
ys = utils::interpolate_variables_into_string( ys, *variables);
}
// The co-ordinates in config files will be 1-based,
// The co-ordinates in config files will be 1-based,
// while we want them as 0-based.
if(xs.empty() == false)
if(xs.empty() == false && xs != "recall")
x = atoi(xs.c_str()) - 1;
if(ys.empty() == false)
if(ys.empty() == false && ys != "recall")
y = atoi(ys.c_str()) - 1;
}
@ -321,22 +321,22 @@ gamemap::location::DIRECTION gamemap::location::get_opposite_dir(gamemap::locati
}
//! gamemap constructor
//!
//!
//! @param cfg the game config
//! @param data the mapdata to load
gamemap::gamemap(const config& cfg, const std::string& data):
tiles_(1),
tiles_(1),
terrainList_(),
tcodeToTerrain_(),
villages_(),
borderCache_(),
terrainFrequencyCache_(),
w_(-1),
w_(-1),
h_(-1),
total_width_(0),
total_height_(0),
border_size_(NO_BORDER),
usage_(IS_MAP)
usage_(IS_MAP)
{
DBG_G << "loading map: '" << data << "'\n";
const config::child_list& terrains = cfg.get_children("terrain");
@ -349,7 +349,7 @@ gamemap::~gamemap()
{
}
//! Reads a map
//! Reads a map
//!
//! @param data the mapdata to load
void gamemap::read(const std::string& data)
@ -357,7 +357,7 @@ void gamemap::read(const std::string& data)
// Initial stuff
tiles_.clear();
villages_.clear();
std::fill(startingPositions_, startingPositions_ +
std::fill(startingPositions_, startingPositions_ +
sizeof(startingPositions_) / sizeof(*startingPositions_), location());
std::map<int, t_translation::coordinate> starting_positions;
@ -370,18 +370,18 @@ void gamemap::read(const std::string& data)
// Test whether there is a header section
size_t header_offset = data.find("\n\n");
if(header_offset == std::string::npos) {
// For some reason Windows will fail to load a file with \r\n
// lineending properly no problems on Linux with those files.
// This workaround fixes the problem the copy later will copy
// For some reason Windows will fail to load a file with \r\n
// lineending properly no problems on Linux with those files.
// This workaround fixes the problem the copy later will copy
// the second \r\n to the map, but that's no problem.
header_offset = data.find("\r\n\r\n");
}
const size_t comma_offset = data.find(",");
// The header shouldn't contain commas, so if the comma is found
// before the header, we hit a \n\n inside or after a map.
// The header shouldn't contain commas, so if the comma is found
// before the header, we hit a \n\n inside or after a map.
// This is no header, so don't parse it as it would be.
VALIDATE(
!(header_offset == std::string::npos || comma_offset < header_offset),
!(header_offset == std::string::npos || comma_offset < header_offset),
_("A map without a header is not supported"));
std::string header_str(std::string(data, 0, header_offset + 1));
@ -397,7 +397,7 @@ void gamemap::read(const std::string& data)
symbols["usage_val"] = usage;
const std::string msg = "'$border_size_key|' should be "
"'$border_size_val|' when '$usage_key| = $usage_val|'";
if(usage == "map") {
usage_ = IS_MAP;
symbols["border_size_val"] = "1";
@ -420,7 +420,7 @@ void gamemap::read(const std::string& data)
tiles_ = t_translation::read_game_map(map, starting_positions);
} catch(t_translation::error& e) {
// We re-throw the error but as map error.
// We re-throw the error but as map error.
// Since all codepaths test for this, it's the least work.
throw incorrect_format_exception(e.message.c_str());
}
@ -431,7 +431,7 @@ void gamemap::read(const std::string& data)
for(; itor != starting_positions.end(); ++itor) {
// Check for valid position,
// Check for valid position,
// the first valid position is 1,
// so the offset 0 in the array is never used.
if(itor->first < 1 || itor->first >= MAX_PLAYERS+1) {
@ -452,8 +452,8 @@ void gamemap::read(const std::string& data)
for(int x = 0; x < total_width_; ++x) {
for(int y = 0; y < total_height_; ++y) {
// Is the terrain valid?
// Is the terrain valid?
if(tcodeToTerrain_.count(tiles_[x][y]) == 0) {
if(!try_merge_terrains(tiles_[x][y])) {
ERR_CF << "Illegal character in map: (" << t_translation::write_terrain_code(tiles_[x][y])
@ -488,7 +488,7 @@ std::string gamemap::write() const
// Let the low level convertor do the conversion
const std::string& data = t_translation::write_game_map(tiles_, starting_positions);
const std::string& header = "border_size=" + lexical_cast<std::string>(border_size_)
const std::string& header = "border_size=" + lexical_cast<std::string>(border_size_)
+ "\nusage=" + (usage_ == IS_MAP ? "map" : "mask");
return header + "\n\n" + data;
}
@ -566,7 +566,7 @@ void gamemap::overlay(const gamemap& m, const config& rules_cfg, const int xpos,
if(!terrain.empty()) {
new_terrain = terrain[0];
}
if(!utils::string_bool(cfg["use_old"])) {
set_terrain(location(x2,y2), new_terrain, mode, utils::string_bool(cfg["replace_if_failed"]));
}
@ -609,14 +609,14 @@ t_translation::t_terrain gamemap::get_terrain(const gamemap::location& loc) cons
items[nitems] = tiles_[adj[n].x][adj[n].y];
++nitems;
} else {
// If the terrain is off map but already in the border cache,
// this will be used to determine the terrain.
// If the terrain is off map but already in the border cache,
// this will be used to determine the terrain.
// This avoids glitches
// * on map with an even width in the top right corner
// * on map with an odd height in the bottom left corner.
// It might also change the result on other map and become random,
// but the border tiles will be determined in the future, so then
// this will no longer be used in the game
// this will no longer be used in the game
// (The editor will use this feature to expand maps in a better way).
std::map<location, t_translation::t_terrain>::const_iterator itor =
borderCache_.find(adj[n]);
@ -632,7 +632,7 @@ t_translation::t_terrain gamemap::get_terrain(const gamemap::location& loc) cons
}
// Count all the terrain types found,
// Count all the terrain types found,
// and see which one is the most common, and use it.
t_translation::t_terrain used_terrain;
int terrain_count = 0;
@ -696,7 +696,7 @@ bool gamemap::on_board_with_border(const location& loc) const
if(tiles_.empty()) {
return false;
} else {
return loc.x >= (0 - border_size_) && loc.x < (w_ + border_size_) &&
return loc.x >= (0 - border_size_) && loc.x < (w_ + border_size_) &&
loc.y >= (0 - border_size_) && loc.y < (h_ + border_size_);
}
}
@ -862,7 +862,7 @@ const std::map<t_translation::t_terrain, size_t>& gamemap::get_weighted_terrain_
for(size_t i = 0; i != size_t(w()); ++i) {
for(size_t j = 0; j != size_t(h()); ++j) {
const size_t distance = distance_between(location(i,j),center);
terrainFrequencyCache_[(*this)[i][j]] += weight_at_edge +
terrainFrequencyCache_[(*this)[i][j]] += weight_at_edge +
(furthest_distance-distance)*additional_weight_at_center;
}
}
@ -873,16 +873,16 @@ const std::map<t_translation::t_terrain, size_t>& gamemap::get_weighted_terrain_
bool gamemap::try_merge_terrains(const t_translation::t_terrain terrain) {
if(tcodeToTerrain_.count(terrain) == 0) {
const std::map<t_translation::t_terrain, terrain_type>::const_iterator base_iter =
const std::map<t_translation::t_terrain, terrain_type>::const_iterator base_iter =
tcodeToTerrain_.find(t_translation::t_terrain(terrain.base, t_translation::NO_LAYER));
const std::map<t_translation::t_terrain, terrain_type>::const_iterator overlay_iter =
const std::map<t_translation::t_terrain, terrain_type>::const_iterator overlay_iter =
tcodeToTerrain_.find(t_translation::t_terrain(t_translation::NO_LAYER, terrain.overlay));
if(base_iter == tcodeToTerrain_.end() || overlay_iter == tcodeToTerrain_.end()) {
return false;
}
terrain_type new_terrain(base_iter->second, overlay_iter->second);
terrain_type new_terrain(base_iter->second, overlay_iter->second);
terrainList_.push_back(new_terrain.number());
tcodeToTerrain_.insert(std::pair<t_translation::t_terrain, terrain_type>(
new_terrain.number(), new_terrain));
@ -912,7 +912,7 @@ t_translation::t_terrain gamemap::merge_terrains(const t_translation::t_terrain
result = new_t;
}
}
// if merging of overlay and base failed, and replace_if_failed is set,
// replace the terrain with the complete new terrain (if given)
// or with (default base)^(new overlay)
@ -922,7 +922,7 @@ t_translation::t_terrain gamemap::merge_terrains(const t_translation::t_terrain
if (try_merge_terrains(new_t)) {
result = new_t;
}
}
}
else if (get_terrain_info(new_t).default_base() != t_translation::NONE_TERRAIN) {
result = get_terrain_info(new_t).terrain_with_default_base();
}