gave ability for terrain to have multiple aliases
This commit is contained in:
parent
a05c618c27
commit
d08630afe7
21 changed files with 238 additions and 142 deletions
|
@ -12,7 +12,6 @@ char="~"
|
|||
image=ocean
|
||||
name=deep water
|
||||
char=s
|
||||
blue=150
|
||||
submerge=0.5
|
||||
unit_height_adjust=-3
|
||||
[/terrain]
|
||||
|
@ -22,7 +21,6 @@ image=coast
|
|||
name=shallow water
|
||||
adjacent_image=coast
|
||||
char=c
|
||||
blue=250
|
||||
submerge=0.4
|
||||
unit_height_adjust=-4
|
||||
[/terrain]
|
||||
|
@ -41,10 +39,12 @@ image=flag-coast-neutral
|
|||
adjacent_image=coast
|
||||
name=mermen village
|
||||
char=Z
|
||||
aliasof=t
|
||||
aliasof=c
|
||||
no_overlay=true
|
||||
submerge=0.4
|
||||
unit_height_adjust=-4
|
||||
heals=true
|
||||
gives_income=true
|
||||
[/terrain]
|
||||
|
||||
[terrain]
|
||||
|
@ -52,9 +52,7 @@ image=pier
|
|||
name=pier
|
||||
adjacent_image=coast
|
||||
char=p
|
||||
red=104
|
||||
green=63
|
||||
aliasof=g
|
||||
aliasof=gc
|
||||
#make this only overlay deep water, not shallow water
|
||||
no_overlay=true
|
||||
[/terrain]
|
||||
|
@ -72,45 +70,39 @@ image=flag-swampwater-neutral
|
|||
adjacent_image=swampwater
|
||||
name=swamp village
|
||||
char=Y
|
||||
aliasof=t
|
||||
aliasof=tw
|
||||
no_overlay=true
|
||||
submerge=0.4
|
||||
unit_height_adjust=-3
|
||||
heals=true
|
||||
gives_income=true
|
||||
[/terrain]
|
||||
|
||||
[terrain]
|
||||
image=bridge-n-s
|
||||
name=bridge
|
||||
char=|
|
||||
green=150
|
||||
red=150
|
||||
aliasof=g
|
||||
aliasof=gc
|
||||
[/terrain]
|
||||
|
||||
[terrain]
|
||||
image=bridge-ne-sw
|
||||
name=bridgediag1
|
||||
char=/
|
||||
green=150
|
||||
red=150
|
||||
aliasof=g
|
||||
aliasof=gc
|
||||
[/terrain]
|
||||
|
||||
[terrain]
|
||||
image=bridge-se-nw
|
||||
name=bridgediag2
|
||||
char=\
|
||||
green=150
|
||||
red=150
|
||||
aliasof=g
|
||||
aliasof=gc
|
||||
[/terrain]
|
||||
|
||||
[terrain]
|
||||
image=desert,desert,desert,desert,desert,desert,desert-plant
|
||||
name=sand
|
||||
char=d
|
||||
red=200
|
||||
green=200
|
||||
light=true
|
||||
[/terrain]
|
||||
|
||||
|
@ -119,9 +111,6 @@ light=true
|
|||
image=road
|
||||
name=road
|
||||
char=R
|
||||
red=140
|
||||
green=140
|
||||
blue=140
|
||||
aliasof=g
|
||||
[/terrain]
|
||||
|
||||
|
@ -129,8 +118,6 @@ aliasof=g
|
|||
image=dirt
|
||||
name=dirt
|
||||
char=r
|
||||
red=104
|
||||
green=63
|
||||
aliasof=g
|
||||
[/terrain]
|
||||
|
||||
|
@ -140,19 +127,17 @@ aliasof=g
|
|||
image=grassland,grassland,grassland,grassland,grassland,grassland,grassland,grassland,grassland,grassland,grassland,grassland,grassland,grassland,grassland,grassland,grassland,grassland,grassland,grassland,grassland,grassland,grassland-flowers,grassland-flowers,grassland-rocks
|
||||
name=grassland
|
||||
char=g
|
||||
green=200
|
||||
[/terrain]
|
||||
|
||||
[terrain]
|
||||
image=flag-neutral
|
||||
name=village
|
||||
char=t
|
||||
red=200
|
||||
green=200
|
||||
blue=200
|
||||
|
||||
#make this not overlay nearby grassland (but will overlay other lower terrain)
|
||||
no_overlay=true
|
||||
heals=true
|
||||
gives_income=true
|
||||
[/terrain]
|
||||
|
||||
[terrain]
|
||||
|
@ -163,15 +148,14 @@ aliasof=t
|
|||
no_overlay=true
|
||||
adjacent_image=grassland
|
||||
light=true
|
||||
heals=true
|
||||
gives_income=true
|
||||
[/terrain]
|
||||
|
||||
[terrain]
|
||||
image=snow,snow,snow2
|
||||
name=tundra
|
||||
char=S
|
||||
red=255
|
||||
green=255
|
||||
blue=255
|
||||
light=true
|
||||
[/terrain]
|
||||
|
||||
|
@ -180,17 +164,17 @@ image=flag-snow-neutral
|
|||
adjacent_image=snow
|
||||
name=snow village
|
||||
char=V
|
||||
aliasof=t
|
||||
aliasof=tS
|
||||
no_overlay=true
|
||||
light=true
|
||||
heals=true
|
||||
gives_income=true
|
||||
[/terrain]
|
||||
|
||||
[terrain]
|
||||
image=hills
|
||||
name=hills
|
||||
char=h
|
||||
red=100
|
||||
green=170
|
||||
[/terrain]
|
||||
|
||||
[terrain]
|
||||
|
@ -204,15 +188,12 @@ aliasof=h
|
|||
image=mountains
|
||||
name=mountains
|
||||
char=m
|
||||
red=150
|
||||
green=150
|
||||
[/terrain]
|
||||
|
||||
[terrain]
|
||||
image=forest
|
||||
name=forest
|
||||
char=f
|
||||
green=100
|
||||
[/terrain]
|
||||
|
||||
[terrain]
|
||||
|
@ -226,9 +207,6 @@ char=F
|
|||
image=cavewall
|
||||
name=cavewall
|
||||
char=W
|
||||
red=50
|
||||
green=50
|
||||
blue=20
|
||||
light=true
|
||||
[/terrain]
|
||||
|
||||
|
@ -236,27 +214,25 @@ light=true
|
|||
image=cave
|
||||
name=cave
|
||||
char=u
|
||||
red=120
|
||||
green=120
|
||||
[/terrain]
|
||||
|
||||
[terrain]
|
||||
image=flag-cave-neutral
|
||||
name=underground village
|
||||
char=D
|
||||
aliasof=t
|
||||
aliasof=tu
|
||||
no_overlay=true
|
||||
adjacent_image=cave
|
||||
heals=true
|
||||
gives_income=true
|
||||
[/terrain]
|
||||
|
||||
[terrain]
|
||||
image=castle
|
||||
name=castle
|
||||
char=C
|
||||
red=100
|
||||
green=100
|
||||
blue=100
|
||||
unit_height_adjust=3
|
||||
recruit_onto=true
|
||||
[/terrain]
|
||||
|
||||
[terrain]
|
||||
|
|
|
@ -39,7 +39,7 @@ struct castle_cost_calculator
|
|||
|
||||
double cost(const gamemap::location& loc, double cost_so_far) const
|
||||
{
|
||||
if(!map_.on_board(loc) || map_[loc.x][loc.y] != gamemap::CASTLE)
|
||||
if(!map_.is_castle(loc))
|
||||
return 10000;
|
||||
|
||||
return 1;
|
||||
|
@ -86,7 +86,7 @@ std::string recruit_unit(const gamemap& map, int side,
|
|||
if(u == units.end())
|
||||
return string_table["no_leader_to_recruit"];
|
||||
|
||||
if(map.get_terrain(u->first) != gamemap::KEEP) {
|
||||
if(map.is_keep(u->first)) {
|
||||
std::cerr << "Leader not on start: leader is on " << (u->first.x+1) << "," << (u->first.y+1) << "\n";
|
||||
return string_table["leader_not_on_start"];
|
||||
}
|
||||
|
@ -95,13 +95,13 @@ std::string recruit_unit(const gamemap& map, int side,
|
|||
const paths::route& rt = a_star_search(u->first,recruit_location,
|
||||
100.0,castle_cost_calculator(map));
|
||||
if(rt.steps.empty() || units.find(recruit_location) != units.end() ||
|
||||
map[recruit_location.x][recruit_location.y] != gamemap::CASTLE)
|
||||
!map.is_castle(recruit_location))
|
||||
recruit_location = gamemap::location();
|
||||
}
|
||||
|
||||
if(!map.on_board(recruit_location)) {
|
||||
recruit_location = find_vacant_tile(map,units,u->first,
|
||||
need_castle ? gamemap::CASTLE : 0);
|
||||
need_castle ? VACANT_CASTLE : VACANT_ANY);
|
||||
}
|
||||
|
||||
if(!map.on_board(recruit_location)) {
|
||||
|
@ -625,7 +625,7 @@ void attack(display& gui, const gamemap& map,
|
|||
|
||||
//plague units make clones of themselves on the target hex
|
||||
//units on villages that die cannot be plagued
|
||||
if(stats.attacker_plague && map.underlying_terrain(map[loc.x][loc.y]) != gamemap::TOWER) {
|
||||
if(stats.attacker_plague && !map.is_village(loc)) {
|
||||
a = units.find(attacker_loc);
|
||||
if(a != units.end()) {
|
||||
units.insert(std::pair<gamemap::location,unit>(loc,a->second));
|
||||
|
@ -757,7 +757,7 @@ void attack(display& gui, const gamemap& map,
|
|||
|
||||
//plague units make clones of themselves on the target hex.
|
||||
//units on villages that die cannot be plagued
|
||||
if(stats.defender_plague && map.underlying_terrain(map[loc.x][loc.y]) != gamemap::TOWER) {
|
||||
if(stats.defender_plague && !map.is_village(loc)) {
|
||||
d = units.find(defender_loc);
|
||||
if(d != units.end()) {
|
||||
units.insert(std::pair<gamemap::location,unit>(
|
||||
|
@ -953,8 +953,7 @@ void calculate_healing(display& disp, const gamemap& map,
|
|||
//it has regeneration, and it is wounded
|
||||
if(i->second.side() == side) {
|
||||
if(i->second.hitpoints() < i->second.max_hitpoints()){
|
||||
if((map.underlying_terrain(map[i->first.x][i->first.y]) == gamemap::TOWER ||
|
||||
i->second.type().regenerates())) {
|
||||
if(map.gives_healing(i->first) || i->second.type().regenerates()) {
|
||||
amount_healed = game_config::cure_amount;
|
||||
}
|
||||
}
|
||||
|
@ -1474,7 +1473,7 @@ size_t move_unit(display* disp, const game_data& gamedata,
|
|||
//if we use fog or shroud, see if we have sighted an enemy unit, in
|
||||
//which case we should stop immediately.
|
||||
if(teams[team_num].uses_shroud() || teams[team_num].uses_fog()) {
|
||||
if(units.count(*step) == 0 && map.underlying_terrain(map.get_terrain(*step)) != gamemap::TOWER) {
|
||||
if(units.count(*step) == 0 && !map.is_village(*step)) {
|
||||
units.insert(std::pair<gamemap::location,unit>(*step,ui->second));
|
||||
|
||||
bool res;
|
||||
|
@ -1547,7 +1546,7 @@ size_t move_unit(display* disp, const game_data& gamedata,
|
|||
}
|
||||
|
||||
int orig_tower_owner = -1;
|
||||
if(map.underlying_terrain(map[steps.back().x][steps.back().y]) == gamemap::TOWER) {
|
||||
if(map.is_village(steps.back())) {
|
||||
orig_tower_owner = tower_owner(steps.back(),teams);
|
||||
|
||||
if(orig_tower_owner != team_num) {
|
||||
|
|
13
src/ai.cpp
13
src/ai.cpp
|
@ -225,8 +225,9 @@ gamemap::location ai_interface::move_unit(location from, location to, std::map<l
|
|||
|
||||
current_unit.set_movement(0);
|
||||
info_.units.insert(std::pair<location,unit>(to,current_unit));
|
||||
if(info_.map.underlying_terrain(info_.map[to.x][to.y]) == gamemap::TOWER)
|
||||
if(info_.map.is_village(to)) {
|
||||
get_tower(to,info_.teams,info_.team_num-1,info_.units);
|
||||
}
|
||||
|
||||
info_.disp.draw_tile(to.x,to.y);
|
||||
info_.disp.draw();
|
||||
|
@ -292,7 +293,7 @@ void ai_interface::calculate_possible_moves(std::map<location,paths>& res, move_
|
|||
bool friend_owns = false;
|
||||
|
||||
//don't take friendly villages
|
||||
if(!enemy && info_.map.underlying_terrain(info_.map[dst.x][dst.y]) == gamemap::TOWER) {
|
||||
if(!enemy && info_.map.is_village(dst)) {
|
||||
for(size_t n = 0; n != info_.teams.size(); ++n) {
|
||||
if(info_.teams[n].owns_tower(dst)) {
|
||||
if(n+1 != info_.team_num && current_team().is_enemy(n+1) == false) {
|
||||
|
@ -509,8 +510,9 @@ bool ai::get_villages(std::map<gamemap::location,paths>& possible_moves, const m
|
|||
{
|
||||
//try to acquire towers
|
||||
for(move_map::const_iterator i = dstsrc.begin(); i != dstsrc.end(); ++i) {
|
||||
if(map_.underlying_terrain(map_[i->first.x][i->first.y]) != gamemap::TOWER)
|
||||
if(map_.is_village(i->first)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool want_tower = true, owned = false;
|
||||
for(size_t j = 0; j != teams_.size(); ++j) {
|
||||
|
@ -571,8 +573,7 @@ bool ai::get_healing(std::map<gamemap::location,paths>& possible_moves, const mo
|
|||
Itor best_loc = it.second;
|
||||
while(it.first != it.second) {
|
||||
const location& dst = it.first->second;
|
||||
if(map_.underlying_terrain(map_[dst.x][dst.y]) == gamemap::TOWER &&
|
||||
units_.find(dst) == units_.end()) {
|
||||
if(map_.is_village(dst) && units_.find(dst) == units_.end()) {
|
||||
const double vuln = power_projection(it.first->first,
|
||||
enemy_srcdst,enemy_dstsrc);
|
||||
std::cerr << "found village with vulnerability: " << vuln << "\n";
|
||||
|
@ -665,7 +666,7 @@ bool ai::retreat_units(std::map<gamemap::location,paths>& possible_moves, const
|
|||
}
|
||||
|
||||
//give a bonus for getting to a village.
|
||||
const int modified_defense = defense - (map_.underlying_terrain(map_.get_terrain(hex)) == gamemap::TOWER ? 10 : 0);
|
||||
const int modified_defense = defense - (map_.is_village(hex) ? 10 : 0);
|
||||
|
||||
if(modified_defense < best_defensive_rating) {
|
||||
best_defensive_rating = modified_defense;
|
||||
|
|
|
@ -218,8 +218,7 @@ private:
|
|||
calculate_possible_moves(possible_moves,srcdst,dstsrc,false);
|
||||
|
||||
for(move_map::const_iterator i = dstsrc.begin(); i != dstsrc.end(); ++i) {
|
||||
if(get_info().map.underlying_terrain(get_info().map.get_terrain(i->first)) == gamemap::TOWER &&
|
||||
current_team().owns_tower(i->first) == false) {
|
||||
if(get_info().map.is_village(i->first) && current_team().owns_tower(i->first) == false) {
|
||||
move_unit(i->second,i->first,possible_moves);
|
||||
get_villages();
|
||||
return;
|
||||
|
|
|
@ -289,7 +289,7 @@ void ai::attack_analysis::analyze(const gamemap& map,
|
|||
unit_map::const_iterator att = units.find(movements[i].first);
|
||||
double cost = att->second.type().cost();
|
||||
|
||||
const bool on_village = map.underlying_terrain(map[movements[i].second.x][movements[i].second.y]) == gamemap::TOWER;
|
||||
const bool on_village = map.is_village(movements[i].second);
|
||||
|
||||
//up to double the value of a unit based on experience
|
||||
cost += (double(att->second.experience())/
|
||||
|
@ -379,7 +379,7 @@ void ai::attack_analysis::analyze(const gamemap& map,
|
|||
defhp = defend_it->second.hitpoints();
|
||||
} else if(defhp == 0) {
|
||||
chance_to_kill += 1.0;
|
||||
} else if(map.underlying_terrain(map[defend_it->first.x][defend_it->first.y]) == gamemap::TOWER) {
|
||||
} else if(map.is_village(defend_it->first)) {
|
||||
defhp += game_config::heal_amount;
|
||||
if(defhp > target_hp)
|
||||
defhp = target_hp;
|
||||
|
@ -525,7 +525,7 @@ double ai::power_projection(const gamemap::location& loc, const move_map& srcdst
|
|||
most_damage = damage;
|
||||
}
|
||||
|
||||
const bool village = map_.underlying_terrain(terrain) == gamemap::TOWER;
|
||||
const bool village = map_.is_village(terrain);
|
||||
const double village_bonus = (use_terrain && village) ? 2.0 : 1.0;
|
||||
|
||||
const double defense = use_terrain ? double(100 - un.defense_modifier(map_,terrain))/100.0 : 0.5;
|
||||
|
|
|
@ -40,12 +40,14 @@ struct move_cost_calculator
|
|||
typedef std::multimap<gamemap::location,gamemap::location>::const_iterator Itor;
|
||||
std::pair<Itor,Itor> range = dstsrc_.equal_range(loc);
|
||||
while(range.first != range.second) {
|
||||
if(range.first->second == loc_)
|
||||
if(range.first->second == loc_) {
|
||||
return 0.01;
|
||||
}
|
||||
|
||||
++range.first;
|
||||
}
|
||||
|
||||
const gamemap::TERRAIN terrain = map_.underlying_terrain(map_[loc.x][loc.y]);
|
||||
const gamemap::TERRAIN terrain = map_[loc.x][loc.y];
|
||||
|
||||
const double modifier = 1.0;//move_type_.defense_modifier(map_,terrain);
|
||||
const double move_cost = move_type_.movement_cost(map_,terrain);
|
||||
|
|
|
@ -1711,7 +1711,7 @@ SDL_Surface* display::getTerrain(gamemap::TERRAIN terrain,image::TYPE image_type
|
|||
|
||||
SDL_Surface* display::getFlag(gamemap::TERRAIN terrain, int x, int y)
|
||||
{
|
||||
const bool village = (map_.underlying_terrain(terrain) == gamemap::TOWER);
|
||||
const bool village = map_.is_village(terrain);
|
||||
if(!village)
|
||||
return NULL;
|
||||
|
||||
|
|
|
@ -283,7 +283,7 @@ bool event_handler::handle_event_command(const queued_event& event_info, const s
|
|||
if(u != units->end()) {
|
||||
const gamemap::location dst(cfg);
|
||||
if(game_map->on_board(dst)) {
|
||||
const gamemap::location vacant_dst = find_vacant_tile(*game_map,*units,dst,(*game_map)[dst.x][dst.y]);
|
||||
const gamemap::location vacant_dst = find_vacant_tile(*game_map,*units,dst);
|
||||
if(game_map->on_board(vacant_dst)) {
|
||||
//note that inserting into a map does NOT invalidate iterators
|
||||
//into the map, so this sequence is fine.
|
||||
|
|
78
src/map.cpp
78
src/map.cpp
|
@ -35,36 +35,80 @@ const std::string& gamemap::terrain_name(gamemap::TERRAIN terrain) const
|
|||
return i->second.name();
|
||||
}
|
||||
|
||||
const std::string& gamemap::underlying_terrain_name(gamemap::TERRAIN terrain) const
|
||||
std::vector<std::string> gamemap::underlying_terrain_name(gamemap::TERRAIN terrain) const
|
||||
{
|
||||
static const std::string default_val;
|
||||
const std::map<TERRAIN,terrain_type>::const_iterator i =
|
||||
letterToTerrain_.find(terrain);
|
||||
if(i == letterToTerrain_.end()) {
|
||||
return default_val;
|
||||
return std::vector<std::string>();
|
||||
} else {
|
||||
if(i->second.is_alias()) {
|
||||
//we could call underlying_terrain_name, but that could allow
|
||||
//infinite recursion with bad data files, so we call terrain_name
|
||||
//to be safe
|
||||
return terrain_name(i->second.type());
|
||||
std::vector<std::string> res;
|
||||
|
||||
const std::string& type = i->second.type();
|
||||
for(std::string::const_iterator j = type.begin(); j != type.end(); ++j) {
|
||||
res.push_back(terrain_name(*j));
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
return i->second.name();
|
||||
return std::vector<std::string>(1,i->second.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gamemap::TERRAIN gamemap::underlying_terrain(TERRAIN terrain) const
|
||||
const std::string& gamemap::underlying_terrain(TERRAIN terrain) const
|
||||
{
|
||||
const std::map<TERRAIN,terrain_type>::const_iterator i =
|
||||
letterToTerrain_.find(terrain);
|
||||
const std::map<TERRAIN,terrain_type>::const_iterator i = letterToTerrain_.find(terrain);
|
||||
if(i == letterToTerrain_.end()) {
|
||||
return terrain;
|
||||
static std::string res;
|
||||
res.resize(1);
|
||||
res[0] = terrain;
|
||||
return res;
|
||||
} else {
|
||||
return i->second.type();
|
||||
}
|
||||
}
|
||||
|
||||
bool gamemap::is_village(gamemap::TERRAIN terrain) const
|
||||
{
|
||||
return get_terrain_info(terrain).is_village();
|
||||
}
|
||||
|
||||
bool gamemap::gives_healing(gamemap::TERRAIN terrain) const
|
||||
{
|
||||
return get_terrain_info(terrain).gives_healing();
|
||||
}
|
||||
|
||||
bool gamemap::is_castle(gamemap::TERRAIN terrain) const
|
||||
{
|
||||
return get_terrain_info(terrain).is_castle();
|
||||
}
|
||||
|
||||
bool gamemap::is_keep(gamemap::TERRAIN terrain) const
|
||||
{
|
||||
return get_terrain_info(terrain).is_keep();
|
||||
}
|
||||
|
||||
bool gamemap::is_village(const gamemap::location& loc) const
|
||||
{
|
||||
return on_board(loc) && is_village(get_terrain(loc));
|
||||
}
|
||||
|
||||
bool gamemap::gives_healing(const gamemap::location& loc) const
|
||||
{
|
||||
return is_village(loc);
|
||||
}
|
||||
|
||||
bool gamemap::is_castle(const gamemap::location& loc) const
|
||||
{
|
||||
return on_board(loc) && is_castle(get_terrain(loc));
|
||||
}
|
||||
|
||||
bool gamemap::is_keep(const gamemap::location& loc) const
|
||||
{
|
||||
return on_board(loc) && is_keep(get_terrain(loc));
|
||||
}
|
||||
|
||||
gamemap::location::location(const config& cfg) : x(-1), y(-1)
|
||||
{
|
||||
const std::string& xstr = cfg["x"];
|
||||
|
@ -144,7 +188,7 @@ gamemap::gamemap(const config& cfg, const std::string& data) : tiles_(1)
|
|||
}
|
||||
}
|
||||
|
||||
if(underlying_terrain(c) == TOWER) {
|
||||
if(is_village(c)) {
|
||||
towers_.push_back(location(int(x),int(y)));
|
||||
}
|
||||
|
||||
|
@ -230,7 +274,7 @@ gamemap::TERRAIN gamemap::get_terrain(const gamemap::location& loc) const
|
|||
TERRAIN used_terrain = 0;
|
||||
int terrain_count = 0;
|
||||
for(int i = 0; i != nitems; ++i) {
|
||||
if(items[i] != used_terrain && underlying_terrain(items[i]) != TOWER) {
|
||||
if(items[i] != used_terrain && !is_village(items[i])) {
|
||||
const int c = std::count(items+i+1,items+nitems,items[i]) + 1;
|
||||
if(c > terrain_count) {
|
||||
used_terrain = items[i];
|
||||
|
@ -297,11 +341,7 @@ const std::vector<gamemap::TERRAIN>& gamemap::get_terrain_precedence() const
|
|||
|
||||
bool gamemap::is_built(const location &loc) const
|
||||
{
|
||||
gamemap::TERRAIN terrain = get_terrain(loc);
|
||||
if((terrain == gamemap::CASTLE) || (terrain == gamemap::KEEP))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
return is_castle(loc);
|
||||
}
|
||||
|
||||
void gamemap::set_terrain(const gamemap::location& loc, gamemap::TERRAIN ter)
|
||||
|
|
14
src/map.hpp
14
src/map.hpp
|
@ -40,8 +40,8 @@ public:
|
|||
//is simply an alias, the underlying terrain name is the name of the
|
||||
//terrain that it's aliased to
|
||||
const std::string& terrain_name(TERRAIN terrain) const;
|
||||
const std::string& underlying_terrain_name(TERRAIN terrain) const;
|
||||
TERRAIN underlying_terrain(TERRAIN terrain) const;
|
||||
std::vector<std::string> underlying_terrain_name(TERRAIN terrain) const;
|
||||
const std::string& underlying_terrain(TERRAIN terrain) const;
|
||||
|
||||
//exception thrown if the map file is not in the correct format.
|
||||
struct incorrect_format_exception {
|
||||
|
@ -74,6 +74,16 @@ public:
|
|||
static location null_location;
|
||||
};
|
||||
|
||||
bool is_village(TERRAIN terrain) const;
|
||||
bool gives_healing(TERRAIN terrain) const;
|
||||
bool is_castle(TERRAIN terrain) const;
|
||||
bool is_keep(TERRAIN terrain) const;
|
||||
|
||||
bool is_village(const location& loc) const;
|
||||
bool gives_healing(const location& loc) const;
|
||||
bool is_castle(const location& loc) const;
|
||||
bool is_keep(const location& loc) const;
|
||||
|
||||
//loads a map, with the given terrain configuration.
|
||||
//data should be a series of lines, with each character representing
|
||||
//one hex on the map. Starting locations are represented by numbers,
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace {
|
|||
gamemap::location find_vacant(const gamemap& map,
|
||||
const std::map<gamemap::location,unit>& units,
|
||||
const gamemap::location& loc, int depth,
|
||||
gamemap::TERRAIN terrain,
|
||||
VACANT_TILE_TYPE vacancy,
|
||||
std::set<gamemap::location>& touched)
|
||||
{
|
||||
if(touched.count(loc))
|
||||
|
@ -31,8 +31,8 @@ gamemap::location find_vacant(const gamemap& map,
|
|||
touched.insert(loc);
|
||||
|
||||
if(map.on_board(loc) && units.find(loc) == units.end() &&
|
||||
map.underlying_terrain(map[loc.x][loc.y]) != gamemap::TOWER &&
|
||||
(terrain == 0 || terrain == map[loc.x][loc.y])) {
|
||||
map.is_village(loc) == false &&
|
||||
(vacancy == VACANT_ANY || map.is_castle(loc))) {
|
||||
return loc;
|
||||
} else if(depth == 0) {
|
||||
return gamemap::location();
|
||||
|
@ -40,12 +40,11 @@ gamemap::location find_vacant(const gamemap& map,
|
|||
gamemap::location adj[6];
|
||||
get_adjacent_tiles(loc,adj);
|
||||
for(int i = 0; i != 6; ++i) {
|
||||
if(!map.on_board(adj[i]) ||
|
||||
terrain != 0 && terrain != map[adj[i].x][adj[i].y])
|
||||
if(!map.on_board(adj[i]) || vacancy == VACANT_CASTLE && !map.is_castle(adj[i]))
|
||||
continue;
|
||||
|
||||
const gamemap::location res =
|
||||
find_vacant(map,units,adj[i],depth-1,terrain,touched);
|
||||
find_vacant(map,units,adj[i],depth-1,vacancy,touched);
|
||||
|
||||
if(map.on_board(res))
|
||||
return res;
|
||||
|
@ -60,11 +59,11 @@ gamemap::location find_vacant(const gamemap& map,
|
|||
gamemap::location find_vacant_tile(const gamemap& map,
|
||||
const std::map<gamemap::location,unit>& units,
|
||||
const gamemap::location& loc,
|
||||
gamemap::TERRAIN terrain)
|
||||
VACANT_TILE_TYPE vacancy)
|
||||
{
|
||||
for(int i = 1; i != 50; ++i) {
|
||||
std::set<gamemap::location> touch;
|
||||
const gamemap::location res = find_vacant(map,units,loc,i,terrain,touch);
|
||||
const gamemap::location res = find_vacant(map,units,loc,i,vacancy,touch);
|
||||
if(map.on_board(res))
|
||||
return res;
|
||||
}
|
||||
|
@ -159,7 +158,7 @@ void find_routes(const gamemap& map, const gamestatus& status,
|
|||
|
||||
//check for teleporting units -- we must be on a vacant (or occupied by this unit)
|
||||
//tower, that is controlled by our team to be able to teleport.
|
||||
if(allow_teleport && map.underlying_terrain(map[loc.x][loc.y]) == gamemap::TOWER &&
|
||||
if(allow_teleport && map.is_village(loc) &&
|
||||
current_team.owns_tower(loc) && (starting_pos || units.count(loc) == 0)) {
|
||||
const std::vector<gamemap::location>& towers = map.towers();
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ bool tiles_adjacent(const gamemap::location& a, const gamemap::location& b);
|
|||
//number of hexes that have to be traversed to get from one hex to the other)
|
||||
size_t distance_between(const gamemap::location& a, const gamemap::location& b);
|
||||
|
||||
enum VACANT_TILE_TYPE { VACANT_CASTLE, VACANT_ANY };
|
||||
|
||||
//function which will find a location on the board that is as near to loc as
|
||||
//possible, but which is unoccupied by any units. If terrain is not 0, then
|
||||
//the location found must be of the given terrain type, and must have a path
|
||||
|
@ -48,7 +50,7 @@ size_t distance_between(const gamemap::location& a, const gamemap::location& b);
|
|||
gamemap::location find_vacant_tile(const gamemap& map,
|
||||
const std::map<gamemap::location,unit>& un,
|
||||
const gamemap::location& loc,
|
||||
gamemap::TERRAIN terrain=0);
|
||||
VACANT_TILE_TYPE vacancy=VACANT_ANY);
|
||||
|
||||
//function which determines if a given location is an enemy zone of control
|
||||
bool enemy_zoc(const gamemap& map,const gamestatus& status,
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace {
|
|||
const gamemap::location pos(i,j);
|
||||
if(map.on_board(pos)) {
|
||||
++positions;
|
||||
if(std::count(terrain_liked.begin(),terrain_liked.end(),map.underlying_terrain(map[i][j]))) {
|
||||
if(std::count(terrain_liked.begin(),terrain_liked.end(),map[i][j])) {
|
||||
++liked;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -835,9 +835,7 @@ bool turn_info::in_context_menu(hotkey::HOTKEY_COMMAND command) const
|
|||
case hotkey::HOTKEY_RECALL: {
|
||||
// last_hex_ is set by turn_info::mouse_motion
|
||||
// Enable recruit/recall on castle/keep tiles
|
||||
if(!map_.on_board(last_hex_)) return false;
|
||||
char terrain = map_.underlying_terrain(map_[last_hex_.x][last_hex_.y]);
|
||||
return terrain == gamemap::CASTLE || terrain == gamemap::KEEP;
|
||||
return map_.is_castle(last_hex_);
|
||||
}
|
||||
default:
|
||||
return true;
|
||||
|
@ -1129,7 +1127,7 @@ void turn_info::undo()
|
|||
return;
|
||||
}
|
||||
|
||||
if(map_.underlying_terrain(map_[route.front().x][route.front().y]) == gamemap::TOWER) {
|
||||
if(map_.is_village(route.front())) {
|
||||
get_tower(route.front(),teams_,action.original_village_owner,units_);
|
||||
}
|
||||
|
||||
|
@ -1212,7 +1210,7 @@ void turn_info::redo()
|
|||
un.set_movement(starting_moves);
|
||||
units_.insert(std::pair<gamemap::location,unit>(route.back(),un));
|
||||
|
||||
if(map_.underlying_terrain(map_[route.back().x][route.back().y]) == gamemap::TOWER) {
|
||||
if(map_.is_village(route.back())) {
|
||||
get_tower(route.back(),teams_,un.side()-1,units_);
|
||||
}
|
||||
|
||||
|
|
|
@ -699,7 +699,7 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
|
|||
|
||||
current_unit.set_movement(rt->second.move_left);
|
||||
u = units.insert(std::pair<gamemap::location,unit>(dst,current_unit)).first;
|
||||
if(map.underlying_terrain(map[dst.x][dst.y]) == gamemap::TOWER) {
|
||||
if(map.is_village(dst)) {
|
||||
const int orig_owner = tower_owner(dst,teams) + 1;
|
||||
if(orig_owner != team_num) {
|
||||
u->second.set_movement(0);
|
||||
|
|
|
@ -253,12 +253,21 @@ report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
|||
|
||||
const gamemap::TERRAIN terrain = map.get_terrain(mouseover);
|
||||
const std::string& name = map.terrain_name(terrain);
|
||||
const std::string& underlying_name = map.underlying_terrain_name(terrain);
|
||||
const std::vector<std::string>& underlying_names = map.underlying_terrain_name(terrain);
|
||||
|
||||
str << translate_string(name);
|
||||
|
||||
if(underlying_name != name) {
|
||||
str << " (" << translate_string(underlying_name) << ")";
|
||||
if(underlying_names.size() != 1 || underlying_names.front() != name) {
|
||||
str << " (";
|
||||
|
||||
for(std::vector<std::string>::const_iterator i = underlying_names.begin(); i != underlying_names.end(); ++i) {
|
||||
str << translate_string(*i);
|
||||
if(i+1 != underlying_names.end()) {
|
||||
str << ",";
|
||||
}
|
||||
}
|
||||
|
||||
str << ")";
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -17,8 +17,9 @@
|
|||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
terrain_type::terrain_type() : images_(1,"void"), type_(' '), letter_(' '),
|
||||
height_adjust_(0), submerge_(0.0), equal_precedence_(false)
|
||||
terrain_type::terrain_type() : images_(1,"void"), type_(" "), letter_(' '),
|
||||
height_adjust_(0), submerge_(0.0), equal_precedence_(false),
|
||||
heals_(false), village_(false), castle_(false), keep_(false)
|
||||
{}
|
||||
|
||||
terrain_type::terrain_type(const config& cfg)
|
||||
|
@ -30,14 +31,20 @@ terrain_type::terrain_type(const config& cfg)
|
|||
|
||||
name_ = cfg["name"];
|
||||
const std::string& letter = cfg["char"];
|
||||
assert(!letter.empty());
|
||||
letter_ = letter[0];
|
||||
|
||||
if(letter == "") {
|
||||
letter_ = 0;
|
||||
} else {
|
||||
letter_ = letter[0];
|
||||
}
|
||||
|
||||
const std::string& alias = cfg["aliasof"];
|
||||
if(alias.empty())
|
||||
type_ = letter_;
|
||||
else
|
||||
type_ = alias[0];
|
||||
if(alias.empty()) {
|
||||
type_.resize(1);
|
||||
type_[0] = letter_;
|
||||
} else {
|
||||
type_ = alias;
|
||||
}
|
||||
|
||||
colour_.read(cfg);
|
||||
|
||||
|
@ -46,6 +53,11 @@ terrain_type::terrain_type(const config& cfg)
|
|||
|
||||
equal_precedence_ = cfg["no_overlay"] == "true";
|
||||
is_light_ = cfg["light"] == "true";
|
||||
|
||||
heals_ = cfg["heals"] == "true";
|
||||
village_ = cfg["gives_income"] == "true";
|
||||
castle_ = cfg["recruit_onto"] == "true";
|
||||
keep_ = cfg["recruit_from"] == "true";
|
||||
}
|
||||
|
||||
const std::string& terrain_type::image(int x, int y) const
|
||||
|
@ -76,7 +88,7 @@ char terrain_type::letter() const
|
|||
return letter_;
|
||||
}
|
||||
|
||||
char terrain_type::type() const
|
||||
const std::string& terrain_type::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
@ -93,7 +105,7 @@ bool terrain_type::is_light() const
|
|||
|
||||
bool terrain_type::is_alias() const
|
||||
{
|
||||
return type_ != letter_;
|
||||
return type_.size() != 1 || type_[0] != letter_;
|
||||
}
|
||||
|
||||
int terrain_type::unit_height_adjust() const
|
||||
|
@ -111,6 +123,26 @@ bool terrain_type::equal_precedence() const
|
|||
return equal_precedence_;
|
||||
}
|
||||
|
||||
bool terrain_type::gives_healing() const
|
||||
{
|
||||
return heals_;
|
||||
}
|
||||
|
||||
bool terrain_type::is_village() const
|
||||
{
|
||||
return village_;
|
||||
}
|
||||
|
||||
bool terrain_type::is_castle() const
|
||||
{
|
||||
return castle_;
|
||||
}
|
||||
|
||||
bool terrain_type::is_keep() const
|
||||
{
|
||||
return keep_;
|
||||
}
|
||||
|
||||
void create_terrain_maps(const std::vector<config*>& cfgs,
|
||||
std::vector<char>& terrain_precedence,
|
||||
std::map<char,terrain_type>& letter_to_terrain,
|
||||
|
|
|
@ -28,8 +28,12 @@ public:
|
|||
const std::string& default_image() const;
|
||||
const std::string& adjacent_image() const;
|
||||
const std::string& name() const;
|
||||
|
||||
//the character representing this terrain
|
||||
char letter() const;
|
||||
char type() const;
|
||||
|
||||
//the underlying type of the terrain
|
||||
const std::string& type() const;
|
||||
|
||||
pixel_data get_rgb() const;
|
||||
|
||||
|
@ -42,16 +46,21 @@ public:
|
|||
//whether the terrain's overlay precedence is equal (rather than higher
|
||||
//than) the preceeding terrain
|
||||
bool equal_precedence() const;
|
||||
|
||||
bool gives_healing() const;
|
||||
bool is_village() const;
|
||||
bool is_castle() const;
|
||||
bool is_keep() const;
|
||||
private:
|
||||
std::vector<std::string> images_;
|
||||
std::string adjacent_image_;
|
||||
std::string name_;
|
||||
|
||||
//the 'letter' is the letter that represents this
|
||||
//terrain type. The 'type' is the letter of the
|
||||
//terrain type which this is equivalent to, which
|
||||
//may be the same as 'letter'
|
||||
char type_, letter_;
|
||||
//terrain type. The 'type' is a list of the 'underlying types'
|
||||
//of the terrain. This may simply be the same as the letter.
|
||||
char letter_;
|
||||
std::string type_;
|
||||
|
||||
pixel_data colour_;
|
||||
|
||||
|
@ -61,6 +70,8 @@ private:
|
|||
|
||||
bool equal_precedence_;
|
||||
bool is_light_;
|
||||
|
||||
bool heals_, village_, castle_, keep_;
|
||||
};
|
||||
|
||||
void create_terrain_maps(const std::vector<config*>& cfgs,
|
||||
|
|
|
@ -356,14 +356,14 @@ void unit::heal_all()
|
|||
hitpoints_ = max_hitpoints();
|
||||
}
|
||||
|
||||
bool unit::invisible(gamemap::TERRAIN terrain, int lawful_bonus,
|
||||
bool unit::invisible(const std::string& terrain, int lawful_bonus,
|
||||
const gamemap::location loc,
|
||||
const unit_map& units,const std::vector<team>& teams) const
|
||||
{
|
||||
bool is_inv = false;
|
||||
|
||||
static const std::string forest_invisible("ambush");
|
||||
if((terrain == gamemap::FOREST) && has_flag(forest_invisible)) {
|
||||
if(std::count(terrain.begin(),terrain.end(),gamemap::FOREST) && has_flag(forest_invisible)) {
|
||||
is_inv = true;
|
||||
}
|
||||
static const std::string night_invisible("nightstalk");
|
||||
|
@ -671,9 +671,11 @@ int unit::movement_cost(const gamemap& map, gamemap::TERRAIN terrain) const
|
|||
{
|
||||
//don't allow level 0 units to take villages - removed until AI
|
||||
//is smart enough to deal with this.
|
||||
// if(type_->level() == 0 && terrain == gamemap::TOWER)
|
||||
// if(type_->level() == 0 && map.is_village(terrain))
|
||||
// return 100;
|
||||
|
||||
|
||||
|
||||
const int res = type_->movement_type().movement_cost(map,terrain);
|
||||
|
||||
static const std::string slowed_string("slowed");
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
void heal(int amount);
|
||||
void heal_all();
|
||||
|
||||
bool invisible(gamemap::TERRAIN terrain, int lawful_bonus,
|
||||
bool invisible(const std::string& terrain, int lawful_bonus,
|
||||
const gamemap::location loc,
|
||||
const unit_map& units,const std::vector<team>& teams) const;
|
||||
bool poisoned() const;
|
||||
|
|
|
@ -269,16 +269,24 @@ int unit_movement_type::movement_cost(const gamemap& map,
|
|||
int res = -1;
|
||||
|
||||
if(movement_costs != NULL) {
|
||||
const std::string& name = map.underlying_terrain_name(terrain);
|
||||
const std::string& val = (*movement_costs)[name];
|
||||
const std::vector<std::string> names = map.underlying_terrain_name(terrain);
|
||||
for(std::vector<std::string>::const_iterator i = names.begin(); i != names.end(); ++i) {
|
||||
const std::string& val = (*movement_costs)[*i];
|
||||
|
||||
if(val != "") {
|
||||
res = atoi(val.c_str());
|
||||
if(val != "") {
|
||||
const int value = atoi(val.c_str());
|
||||
if(res == -1 || value < res) {
|
||||
res = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(res == -1 && parent_ != NULL) {
|
||||
res = parent_->movement_cost(map,terrain);
|
||||
if(parent_ != NULL) {
|
||||
const int value = parent_->movement_cost(map,terrain);
|
||||
if(res == -1 || value < res) {
|
||||
res = value;
|
||||
}
|
||||
}
|
||||
|
||||
if(res <= 0)
|
||||
|
@ -303,16 +311,24 @@ int unit_movement_type::defense_modifier(const gamemap& map,
|
|||
const config* const defense = cfg_.child("defense");
|
||||
|
||||
if(defense != NULL) {
|
||||
const std::string& name = map.underlying_terrain_name(terrain);
|
||||
const std::string& val = (*defense)[name];
|
||||
const std::vector<std::string> names = map.underlying_terrain_name(terrain);
|
||||
for(std::vector<std::string>::const_iterator i = names.begin(); i != names.end(); ++i) {
|
||||
const std::string& val = (*defense)[*i];
|
||||
|
||||
if(val != "") {
|
||||
res = atoi(val.c_str());
|
||||
if(val != "") {
|
||||
const int value = atoi(val.c_str());
|
||||
if(res == -1 || value < res) {
|
||||
res = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(res == -1 && parent_ != NULL) {
|
||||
res = parent_->defense_modifier(map,terrain);
|
||||
if(parent_ != NULL) {
|
||||
const int value = parent_->defense_modifier(map,terrain);
|
||||
if(res == -1 || value < res) {
|
||||
res = value;
|
||||
}
|
||||
}
|
||||
|
||||
if(res < 0)
|
||||
|
|
Loading…
Add table
Reference in a new issue