1 // Copyright (C) 2003 Michael Bartl
2 // Copyright (C) 2003, 2004, 2005, 2006 Ulf Lorenz
3 // Copyright (C) 2003, 2005, 2006 Andrea Paternesi
4 // Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2014, 2015, 2017,
5 // 2020 Ben Asselstine
6 // Copyright (C) 2007 Ole Laursen
7 // Copyright (C) 2008 Janek Kozicki
8 //
9 //  This program is free software; you can redistribute it and/or modify
10 //  it under the terms of the GNU General Public License as published by
11 //  the Free Software Foundation; either version 3 of the License, or
12 //  (at your option) any later version.
13 //
14 //  This program is distributed in the hope that it will be useful,
15 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 //  GNU Library General Public License for more details.
18 //
19 //  You should have received a copy of the GNU General Public License
20 //  along with this program; if not, write to the Free Software
21 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 //  02110-1301, USA.
23 
24 #include <sstream>
25 #include <iostream>
26 #include <string>
27 #include <iomanip>
28 #include <assert.h>
29 #include <sigc++/functors/mem_fun.h>
30 #include <string.h>
31 #include <math.h>
32 
33 #include "ucompose.hpp"
34 #include "army.h"
35 #include "GameMap.h"
36 #include "citylist.h"
37 #include "bridgelist.h"
38 #include "bridge.h"
39 #include "portlist.h"
40 #include "port.h"
41 #include "roadlist.h"
42 #include "road.h"
43 #include "stonelist.h"
44 #include "stone.h"
45 #include "city.h"
46 #include "ruin.h"
47 #include "temple.h"
48 #include "playerlist.h"
49 #include "stacklist.h"
50 #include "ruinlist.h"
51 #include "templelist.h"
52 #include "signpostlist.h"
53 #include "xmlhelper.h"
54 #include "MapGenerator.h"
55 #include "tilesetlist.h"
56 #include "shieldsetlist.h"
57 #include "citysetlist.h"
58 #include "MapBackpack.h"
59 #include "stacktile.h"
60 #include "armyprodbase.h"
61 #include "stack.h"
62 #include "armyset.h"
63 #include "armysetlist.h"
64 #include "CreateScenario.h"
65 #include "SightMap.h"
66 #include "reward.h"
67 #include "rewardlist.h"
68 #include "keeper.h"
69 
70 Glib::ustring GameMap::d_tag = "map";
71 Glib::ustring GameMap::d_itemstack_tag = "itemstack";
72 
73 //#define debug(x) {std::cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<std::endl<<flush;}
74 #define debug(x)
75 
76 GameMap* GameMap::s_instance = 0;
77 
78 int GameMap::s_width = 112;
79 int GameMap::s_height = 156;
80 Tileset* GameMap::s_tileset = 0;
81 Cityset* GameMap::s_cityset = 0;
82 Shieldset* GameMap::s_shieldset = 0;
83 
84 
getInstance(Glib::ustring TilesetName,Glib::ustring ShieldsetName,Glib::ustring CitysetName)85 GameMap* GameMap::getInstance(Glib::ustring TilesetName,
86 			      Glib::ustring ShieldsetName,
87 			      Glib::ustring CitysetName)
88 {
89     if (s_instance == 0)
90     {
91         s_instance = new GameMap(TilesetName, ShieldsetName, CitysetName);
92 
93     }
94     return s_instance;
95 }
96 
getInstance(XML_Helper * helper)97 GameMap* GameMap::getInstance(XML_Helper* helper)
98 {
99     if (s_instance)
100         deleteInstance();
101 
102     s_instance = new GameMap(helper);
103 
104     return s_instance;
105 }
106 
deleteInstance()107 void GameMap::deleteInstance()
108 {
109     if (s_instance)
110         delete s_instance;
111     s_instance = 0;
112 }
113 
GameMap(Glib::ustring TilesetName,Glib::ustring ShieldsetName,Glib::ustring CitysetName)114 GameMap::GameMap(Glib::ustring TilesetName, Glib::ustring ShieldsetName,
115 		 Glib::ustring CitysetName)
116 {
117   s_tileset = 0;
118   s_cityset = 0;
119   s_shieldset = 0;
120   if (TilesetName != "")
121     d_tileset = TilesetName;
122   if (ShieldsetName != "")
123     d_shieldset = ShieldsetName;
124   if (CitysetName != "")
125     d_cityset = CitysetName;
126 
127   Vector<int>::setMaximumWidth(s_width);
128   d_map = new Maptile[s_width*s_height];
129   for (int j = 0; j < s_height; j++)
130     for (int i = 0; i < s_width; i++)
131       d_map[j*s_width + i].setPos(Vector<int>(i, j));
132 }
133 
offmap(int x,int y)134 bool GameMap::offmap(int x, int y)
135 {
136   if (y<0||y>=GameMap::s_height||x<0||x>=GameMap::s_width)
137     return true;
138   return false;
139 }
140 
processStyles(Glib::ustring s,int chars_per_style)141 void GameMap::processStyles(Glib::ustring s, int chars_per_style)
142 {
143   std::string styles = s.raw();
144   Tileset *tileset = GameMap::getTileset();
145   int c = chars_per_style;
146     int offset = 0;
147     for (int j = 0; j < s_height; j++)
148     {
149         // remove newline and carriage return lines
150         char test = styles[j*s_width*c + offset];
151         while (test == '\n' || test == '\r')
152         {
153             offset++;
154             test = styles[j*s_width*c + offset];
155         }
156 
157         for (int i = 0; i < s_width; i++)
158         {
159 	    char hexstr[15];
160             //due to the circumstances, styles is a long stream of
161             //hex digit pairs, so read it character for character
162 	    hexstr[0] = '0';
163 	    hexstr[1] = 'x';
164 	    memcpy (&hexstr[2], &styles[j*s_width*c + (i * c) + offset], c);
165 	    hexstr[2 + c + 1 - 1] = '\0';
166 
167 	    unsigned long int val = 0;
168 	    char *end = NULL;
169 	    val = strtoul (hexstr, &end, 16);
170 	    guint32 id = (guint32) val;
171 	    TileStyle *style = tileset->getTileStyle(id);
172 	    if (!style)
173 	      style = tileset->getTileStyle(0);
174 	    d_map[j*s_width + i].setTileStyle(style);
175         }
176     }
177 }
178 
determineCharsPerStyle(Glib::ustring styles)179 int GameMap::determineCharsPerStyle(Glib::ustring styles)
180 {
181   return styles.length() / (s_width * s_height);
182 }
183 
GameMap(XML_Helper * helper)184 GameMap::GameMap(XML_Helper* helper)
185 {
186     s_tileset = 0;
187     s_cityset = 0;
188     s_shieldset = 0;
189     Glib::ustring types;
190     Glib::ustring styles;
191     Glib::ustring t_dir;
192     Glib::ustring s_dir;
193     Glib::ustring c_dir;
194 
195     helper->getData(s_width, "width");
196     helper->getData(s_height, "height");
197     helper->getData(t_dir,"tileset");
198     helper->getData(s_dir,"shieldset");
199     helper->getData(c_dir,"cityset");
200     helper->getData(types, "types");
201     helper->getData(styles, "styles");
202 
203     d_tileset = t_dir;
204     d_shieldset = s_dir;
205     d_cityset = c_dir;
206 
207     Tileset *tileset = Tilesetlist::getInstance()->get(d_tileset);
208     s_tileset = tileset;
209     Cityset *cityset = Citysetlist::getInstance()->get(d_cityset);
210     s_cityset = cityset;
211     Shieldset *shieldset = Shieldsetlist::getInstance()->get(d_shieldset);
212     s_shieldset = shieldset;
213     Vector<int>::setMaximumWidth(s_width);
214     //create the map
215     d_map = new Maptile[s_width*s_height];
216 
217     int row = 0, col = 0;
218     for (const char *letter = types.c_str(); *letter; letter++)
219       {
220         if (*letter == '\n' || *letter == '\r')
221           continue;
222         d_map[row*s_width + col].setPos(Vector<int>(col, row));
223         guint32 type = *letter - '0';
224         d_map[row*s_width + col].setIndex(GameMap::getTileset()->lookupIndexByType (type == 0 ? Tile::Type (type) : Tile::Type (pow(2,type-1))));
225         col++;
226         if (col >= s_width)
227           {
228             col = 0;
229             row++;
230           }
231       }
232 
233     int chars_per_style = determineCharsPerStyle(styles);
234     processStyles(styles, chars_per_style);
235 
236     //add some callbacks for item loading
237     helper->registerTag(MapBackpack::d_tag, sigc::mem_fun(this, &GameMap::loadItems));
238 }
239 
~GameMap()240 GameMap::~GameMap()
241 {
242     delete[] d_map;
243 }
244 
fill(MapGenerator * generator)245 bool GameMap::fill(MapGenerator* generator)
246 //basically, this does the same as the former random function, but you don't
247 //need to go the whole way via dumping the map in a file etc.
248 {
249     int width = 0;
250     int height = 0;
251     const Tile::Type* terrain = generator->getMap(width, height);
252     Tileset *tileset = GameMap::getTileset();
253 
254     //the sizes should definitely match, else we have a problem here
255     if (width != s_width || height != s_height)
256       {
257         std::cerr << String::ucompose(_("Error!  Map Generator and Game Map tile sizes differ.  %1 != %2 || %3 != %4.  Exiting."), width, s_width, height, s_height) << std::endl;
258         exit(-1);
259       }
260 
261     // create tiles; there is a hack here: The map generator outputs tile types,
262     // but we supply the index of the tile types in the tileset to Maptile. Was
263     // the easiest version when rewriting this.
264     for (int j = 0; j < height; j++)
265         for (int i = 0; i < width; i++)
266         {
267             int index = tileset->getIndex(terrain[j*width + i]);
268 	    if (index != -1)
269 	      d_map[j*s_width + i].setIndex ((guint32)index);
270         }
271 
272     applyTileStyles(0, 0, height, width, true);
273     return true;
274 }
275 
fill(guint32 type)276 bool GameMap::fill(guint32 type)
277 {
278   for (int i = 0; i < s_width; i++)
279     for (int j = 0; j < s_height; j++)
280       d_map[j*s_width + i].setIndex(GameMap::getTileset()->lookupIndexByType (Tile::Type(type)));
281 
282   applyTileStyles(0, 0, s_height, s_width, false);
283   return true;
284 }
285 
save(XML_Helper * helper) const286 bool GameMap::save(XML_Helper* helper) const
287 {
288     Tileset *tileset = GameMap::getTileset();
289     bool retval = true;
290 
291     std::stringstream types;
292 
293     types <<std::endl;
294     for (int i = 0; i < s_height; i++)
295     {
296         for (int j = 0; j < s_width; j++)
297           {
298             guint32 tile_type = getTile(j, i)->getType();
299             if (tile_type != 0)
300               tile_type = log2(tile_type)+1;
301             types << (guint32) tile_type;
302           }
303         types <<std::endl;
304     }
305 
306     std::stringstream styles;
307     styles <<std::endl;
308 
309     int largest_style_id = tileset->getLargestTileStyleId();
310     guint32 num_digits = TileStyle::calculateHexDigits(largest_style_id);
311     for (int i = 0; i < s_height; i++)
312     {
313         for (int j = 0; j < s_width; j++)
314 	  {
315 	    Glib::ustring hexstr;
316 	    TileStyle *style = getTile(j, i)->getTileStyle();
317 	    assert (style != NULL);
318             hexstr = TileStyle::idToString(style->getId(), num_digits);
319 	    styles << hexstr;
320 	  }
321         styles <<std::endl;
322     }
323 
324 
325     retval &= helper->openTag(GameMap::d_tag);
326     retval &= helper->saveData("width", s_width);
327     retval &= helper->saveData("height", s_height);
328     retval &= helper->saveData("tileset", d_tileset);
329     retval &= helper->saveData("shieldset", d_shieldset);
330     retval &= helper->saveData("cityset", d_cityset);
331     retval &= helper->saveData("types", types.str());
332     retval &= helper->saveData("styles", styles.str());
333 
334     // last, save all items lying around somewhere
335     for (int i = 0; i < s_width; i++)
336       for (int j = 0; j < s_height; j++)
337 	if (!getTile(i,j)->getBackpack()->empty())
338 	  retval &= getTile(i,j)->getBackpack()->save(helper);
339 
340     retval &= helper->closeTag();
341     return retval;
342 }
343 
loadItems(Glib::ustring tag,XML_Helper * helper)344 bool GameMap::loadItems(Glib::ustring tag, XML_Helper* helper)
345 {
346     if (tag == MapBackpack::d_tag)
347       {
348         MapBackpack* backpack = new MapBackpack(helper);
349         Vector<int> pos = backpack->getPos();
350         getTile(pos)->setBackpack(backpack);
351       }
352 
353     return true;
354 }
355 
setTileIndex(int x,int y,guint32 new_index)356 void GameMap::setTileIndex(int x, int y, guint32 new_index)
357 {
358     d_map[y*s_width + x].setIndex (new_index);
359     applyTileStyle (y, x);
360 }
361 
addArmy(Vector<int> pos,Army * a)362 Stack* GameMap::addArmy(Vector<int> pos, Army *a)
363 {
364   City *c = getCity(pos);
365   if (c)
366     {
367       if (c->isBurnt() || c->getOwner() != a->getOwner())
368         return addArmyAtPos(pos, a);
369       else
370         return addArmy(c, a);
371     }
372   Temple *t = getTemple(pos);
373   if (t)
374     return addArmy(t, a);
375   Ruin *r = getRuin(pos);
376   if (r)
377     return addArmy(r, a);
378   return addArmyAtPos(pos, a);
379 }
380 
addArmyAtPos(Vector<int> pos,Army * a)381 Stack* GameMap::addArmyAtPos(Vector<int> pos, Army *a)
382 {
383   Stack *s = NULL;
384   bool added_army = false;
385   guint32 i, j;
386   guint32 d;
387   guint32 max;
388   int x, y;
389   if (s_height > s_width)
390     max = s_height;
391   else
392     max = s_width;
393   max--;
394 
395   if (getBuilding(pos) == Maptile::NONE)
396     {
397       Location l(pos, 1);
398       s = l.addArmy(a);
399       if (s)
400         return s;
401     }
402 
403   // we couldn't add the army to the square(s) identified by location,
404   // so the idea is to go around in ever widening boxes until we find a
405   // suitable tile.
406 
407   bool land = true;
408   if (getTile(pos.x, pos.y)->getType() == Tile::WATER)
409     land = false;
410 
411   //d is the distance from Pos where our box starts
412   for (d = 1; d < max; d++)
413     {
414       guint32 imax = (d * 2) + 1;
415       guint32 jmax = (d * 2) + 1;
416       for (i = 0; i < imax; i++)
417         {
418           for (j = 0; j < jmax; j++)
419             {
420               if ((i == 0 || i == imax - 1) &&
421                   (j == 0 || j == jmax - 1))
422                 {
423                   x = pos.x + (i - d);
424                   y = pos.y + (j - d);
425 		  if (offmap(x, y))
426 		    continue;
427                   //is there somebody else's city here?
428                   City *c = getCity(Vector<int>(x, y));
429                   if (c && c->getOwner() != a->getOwner())
430                     {
431                       if (c->isBurnt() == false)
432                         continue;
433                     }
434                   //is this an unsuitable tile?
435                   if (land && getTile(x, y)->getType() == Tile::WATER)
436                     continue;
437                   if (!land && getTile(x, y)->getType() != Tile::WATER)
438                     continue;
439                   if (land && getTile(x, y)->getType() == Tile::MOUNTAIN &&
440 		      (a->getStat(Army::MOVE_BONUS) & Tile::MOUNTAIN) == 0)
441                     continue;
442 		  //do we already have a nifty stack here?
443 		  s = getFriendlyStack(Vector<int>(x,y));
444                   if (s)
445                     {
446 		      if (canAddArmy(Vector<int>(x,y)) == false)
447 			continue;
448                       //is our stack too full?
449 		      s->add(a);
450                     }
451                   else
452                     {
453                       Vector<int> p(x, y);
454 		      //hmm. no nifty stacks here.  anybody else's?
455 		      s = getEnemyStack(p);
456 		      if (s)
457 			continue;
458 		      //okay, no stacks here at all.  make one.
459                       s = new Stack(a->getOwner(), p);
460 		      s->add(a);
461                       a->getOwner()->addStack(s);
462                     }
463                   added_army = true;
464                   break;
465                 }
466             }
467           if (added_army)
468             break;
469         }
470       if (added_army)
471         break;
472     }
473 
474   if (added_army)
475     {
476       s->setDefending(false);
477       s->setParked(false);
478       return s;
479     }
480   else
481     return NULL;
482 }
483 
addArmy(Location * l,Army * a)484 Stack* GameMap::addArmy(Location *l, Army *a)
485 {
486   Stack *s;
487   s = l->addArmy(a);
488   if (s)
489     return s;
490   return addArmyAtPos(l->getPos(), a);
491 }
492 
isDock(Vector<int> pos)493 bool GameMap::isDock(Vector<int> pos)
494 {
495   if (getBuilding(pos) == Maptile::CITY)
496     return true;
497   if (getBuilding(pos) == Maptile::PORT)
498     return true;
499   if (getBuilding(pos) == Maptile::BRIDGE)
500     return true;
501   return false;
502 }
503 
isBlockedAvenue(int x,int y,int destx,int desty)504 bool GameMap::isBlockedAvenue(int x, int y, int destx, int desty)
505 {
506   if (offmap(destx, desty))
507     return true;
508   //if (Citylist::getInstance()->empty())
509       //return false;
510   int diffx = destx - x;
511   int diffy = desty - y;
512   if (diffx >= -1 && diffx <= 1 && diffy >= -1 && diffy <= 1)
513     {
514       //assert (Citylist::getInstance()->size());
515       bool from_dock = isDock(Vector<int>(x,y));
516       bool to_dock = isDock(Vector<int>(destx,desty));
517       Maptile *from = getTile(x, y);
518       Maptile *to = getTile(destx, desty);
519       if (from == to)
520         return false;
521       //am i on land, going towards water that has a port on it?
522       //if (from->getType() != Tile::WATER &&
523           //to->getType() == Tile::WATER &&
524           //to_dock)
525         //return false;
526       //am i on water going towards land from a port?
527       //if (from->getType() == Tile::WATER &&
528           //to->getType() != Tile::WATER &&
529           //from_dock)
530         //return false;
531 
532       //am i on water going towards land that isn't a city,
533       //and i'm not coming from a port
534       if (from->getType() == Tile::WATER && to->getType() != Tile::WATER &&
535           !to_dock && !from_dock)
536         return true;
537 
538       //am i on land, going towards water from a tile that isn't a
539       //city, or a port and i'm not going to a port?
540       if (from->getType() != Tile::WATER && to->getType() == Tile::WATER &&
541           !from_dock && !to_dock)
542         return true;
543 
544       //is the tile i'm going to a mountain that doesn't have a road?
545       if (to->getType() == Tile::MOUNTAIN &&
546           getRoad(Vector<int>(destx, desty)) == NULL)
547         return true;
548 
549       //am i on a mountain without a road?
550       if (from->getType() == Tile::MOUNTAIN &&
551 	  getRoad(Vector<int>(x, y)) == NULL)
552         return true;
553     }
554  return false;
555 }
556 
calculateBlockedAvenue(int i,int j)557 void GameMap::calculateBlockedAvenue(int i, int j)
558 {
559   int diffx = 0, diffy = 0;
560   int destx = 0, desty = 0;
561   Maptile *maptile = getTile(i, j);
562   for (int k = 0; k < 8; k++)
563     {
564       switch (k)
565 	{
566 	case 0: diffx = -1;  diffy = -1; break;
567 	case 1: diffx = -1; diffy = 0; break;
568 	case 2: diffx = -1; diffy = 1; break;
569 	case 3: diffx = 0; diffy = 1; break;
570 	case 4: diffx = 0; diffy = -1; break;
571 	case 5: diffx = 1; diffy = -1; break;
572 	case 6: diffx = 1; diffy = 0; break;
573 	case 7: diffx = 1; diffy = 1; break;
574 	}
575       destx = i + diffx;
576       desty = j + diffy;
577       if (offmap (destx, desty))
578 	{
579 	  maptile->d_blocked[k] = true;
580 	  continue;
581 	}
582       maptile->d_blocked[k] = isBlockedAvenue(i, j, destx, desty);
583     }
584 }
calculateBlockedAvenues()585 void GameMap::calculateBlockedAvenues()
586 {
587   for (int i = 0; i < s_width; i++)
588     for (int j = 0; j < s_height; j++)
589       calculateBlockedAvenue(i, j);
590 }
591 
findPlantedStandard(Player * p)592 Vector<int> GameMap::findPlantedStandard(Player *p)
593 {
594     bool found = false;
595     Vector<int> pos;
596     pos.x = -1;
597     pos.y = -1;
598     for (int x = 0; x < getWidth(); x++)
599       {
600         for (int y = 0; y < getHeight(); y++)
601           {
602 	    MapBackpack *backpack = getTile(x, y)->getBackpack();
603 	    found = backpack->getPlantedItem(p) != NULL;
604 	    if (found)
605 	      {
606 		pos.x = x;
607 		pos.y = y;
608 		break;
609 	      }
610           }
611       }
612   return pos;
613 }
614 
getBackpacks() const615 std::list<MapBackpack*> GameMap::getBackpacks() const
616 {
617   std::list<MapBackpack*> bags;
618   for (int x = 0; x < getWidth(); x++)
619     {
620       for (int y = 0; y < getHeight(); y++)
621         {
622           MapBackpack *backpack = getTile(x, y)->getBackpack();
623           if (backpack->size() > 0)
624             bags.push_back(backpack);
625         }
626     }
627   return bags;
628 }
629 
630 
calculatePreferredStyle(int i,int j)631 TileStyle *GameMap::calculatePreferredStyle(int i, int j)
632 {
633   Tileset *tileset = GameMap::getTileset();
634   Maptile *mtile = getTile(j, i);
635   int box[3][3];
636   for (int k = -1; k <= +1; k++)
637     for (int l = -1; l <= +1; l++)
638       {
639 	box[k+1][l+1] = 1;
640 	if (offmap(j+l, i+k))
641 	  continue;
642 	box[k+1][l+1] =
643           are_those_tiles_similar(getTile(j+l, i+k)->getType(),
644                                   mtile->getType(), false);
645       }
646   if (box[0][0] && box[0][1] && box[0][2] &&
647       box[1][0] && box[1][1] && box[1][2] &&
648       box[2][0] && box[2][1] && box[2][2])
649     return tileset->getRandomTileStyle(mtile->getIndex(),
650 				       TileStyle::INNERMIDDLECENTER);
651   else if (box[0][0] && box[0][1] && !box[0][2] &&
652 	   box[1][0] && box[1][1] && box[1][2] &&
653 	   !box[2][0] && box[2][1] && box[2][2])
654     return tileset->getRandomTileStyle(mtile->getIndex(),
655 				       TileStyle::TOPLEFTTOBOTTOMRIGHTDIAGONAL);
656   else if (!box[0][0] && box[0][1] && box[0][2] &&
657 	   box[1][0] && box[1][1] && box[1][2] &&
658 	   box[2][0] && box[2][1] && !box[2][2])
659     return tileset->getRandomTileStyle(mtile->getIndex(),
660 				       TileStyle::BOTTOMLEFTTOTOPRIGHTDIAGONAL);
661   else if (/*box[0][0] &&*/ !box[0][1] && /*box[0][2] &&*/
662 	   !box[1][0] && box[1][1] && box[1][2] &&
663 	   /*!box[2][0] &&*/ box[2][1] && box[2][2])
664     return tileset->getRandomTileStyle(mtile->getIndex(),
665 				       TileStyle::OUTERTOPLEFT);
666   else if (/*box[0][0] &&*/ !box[0][1] && /*box[0][2] &&*/
667 	   box[1][0] && box[1][1] && !box[1][2] &&
668 	   box[2][0] && box[2][1] /*&& !box[2][2] */)
669     return tileset->getRandomTileStyle(mtile->getIndex(),
670 				       TileStyle::OUTERTOPRIGHT);
671   else if (/*box[0][0] &&*/ box[0][1] && box[0][2] &&
672 	   !box[1][0] && box[1][1] && box[1][2] &&
673 	   /*box[2][0] &&*/ !box[2][1] /*&& box[2][2]*/)
674     return tileset->getRandomTileStyle(mtile->getIndex(),
675 				       TileStyle::OUTERBOTTOMLEFT);
676   else if (box[0][0] && box[0][1] && /*!box[0][2] &&*/
677 	   box[1][0] && box[1][1] && !box[1][2] &&
678 	   /*box[2][0] &&*/ !box[2][1] /*&& box[2][2]*/)
679     return tileset->getRandomTileStyle(mtile->getIndex(),
680 				       TileStyle::OUTERBOTTOMRIGHT);
681   else if (/*box[0][0] &&*/ box[0][1] && /*box[0][2] && */
682 	   !box[1][0] && box[1][1] && box[1][2] &&
683 	   /*box[2][0] &&*/ box[2][1] /*&& box[2][2]*/)
684     return tileset->getRandomTileStyle(mtile->getIndex(),
685 				       TileStyle::OUTERMIDDLELEFT);
686   else if (/*box[0][0] &&*/ box[0][1] && /*box[0][2] && */
687 	   box[1][0] && box[1][1] && !box[1][2] &&
688 	   /*box[2][0] &&*/ box[2][1] /*&& box[2][2] */)
689     return tileset->getRandomTileStyle(mtile->getIndex(),
690 				       TileStyle::OUTERMIDDLERIGHT);
691   else if (box[0][0] && box[0][1] && /*box[0][2] && */
692 	   box[1][0] && box[1][1] && box[1][2] &&
693 	   box[2][0] && box[2][1] && !box[2][2])
694     return tileset->getRandomTileStyle(mtile->getIndex(),
695 				       TileStyle::INNERTOPLEFT);
696   else if (/*box[0][0] &&*/ box[0][1] && box[0][2] &&
697 	   box[1][0] && box[1][1] && box[1][2] &&
698 	   !box[2][0] && box[2][1] && box[2][2])
699     return tileset->getRandomTileStyle(mtile->getIndex(),
700 				       TileStyle::INNERTOPRIGHT);
701   else if (box[0][0] && box[0][1] && !box[0][2] &&
702 	   box[1][0] && box[1][1] && box[1][2] &&
703 	   box[2][0] && box[2][1] /*&& box[2][2]*/)
704     return tileset->getRandomTileStyle(mtile->getIndex(),
705 				       TileStyle::INNERBOTTOMLEFT);
706   else if (!box[0][0] && box[0][1] && box[0][2] &&
707 	   box[1][0] && box[1][1] && box[1][2] &&
708 	   /*box[2][0] &&*/ box[2][1] && box[2][2])
709     return tileset->getRandomTileStyle(mtile->getIndex(),
710 				       TileStyle::INNERBOTTOMRIGHT);
711   else if (/*!box[0][0] &&*/ !box[0][1] && /*!box[0][2] &&*/
712 	   box[1][0] && box[1][1] && box[1][2] &&
713 	   /*!box[2][0] &&*/ box[2][1] /*&& box[2][2]*/)
714     return tileset->getRandomTileStyle(mtile->getIndex(),
715 				       TileStyle::OUTERTOPCENTER);
716   else if (/*box[0][0] &&*/ box[0][1] && /*box[0][2] &&*/
717 	   box[1][0] && box[1][1] && box[1][2] &&
718 	   /*!box[2][0] &&*/ !box[2][1] /*&& !box[2][2]*/)
719     return tileset->getRandomTileStyle(mtile->getIndex(),
720 				       TileStyle::OUTERBOTTOMCENTER);
721   return NULL;
722 }
723 
close_circles(int minx,int miny,int maxx,int maxy)724 void GameMap::close_circles (int minx, int miny, int maxx, int maxy)
725 {
726   Tileset *tileset = GameMap::getTileset();
727   for (int i = minx; i < maxx; i++)
728     {
729       for (int j = miny; j < maxy; j++)
730 	{
731 	  if (offmap(j, i))
732 	    continue;
733 	  Maptile *tile = getTile(j, i);
734 	  TileStyle *tilestyle = tile->getTileStyle();
735 	  if (j + 1 < s_width)
736 	    {
737 	      Maptile *nexttile = getTile(j + 1, i);
738 	      TileStyle *nextstyle = nexttile->getTileStyle();
739 	      if (tilestyle->getType() == TileStyle::OUTERTOPCENTER &&
740 		  nextstyle->getType() == TileStyle::OUTERBOTTOMCENTER)
741 		{
742 		  TileStyle *style;
743 		  style = tileset->getRandomTileStyle(tile->getIndex(),
744 						      TileStyle::OUTERTOPRIGHT);
745 		  tile->setTileStyle(style);
746 		  style = tileset->getRandomTileStyle(nexttile->getIndex(),
747 						      TileStyle::OUTERBOTTOMLEFT);
748 		  nexttile->setTileStyle(style);
749 		}
750 	      if (tilestyle->getType() == TileStyle::OUTERBOTTOMCENTER &&
751 		  nextstyle->getType() == TileStyle::OUTERTOPCENTER)
752 		{
753 		  TileStyle *style;
754 		  style = tileset->getRandomTileStyle(tile->getIndex(),
755 						      TileStyle::OUTERBOTTOMRIGHT);
756 		  tile->setTileStyle(style);
757 		  style = tileset->getRandomTileStyle(nexttile->getIndex(),
758 						      TileStyle::OUTERTOPLEFT);
759 		  nexttile->setTileStyle(style);
760 		}
761 	      }
762 	  if (i + 1 < s_height)
763 	    {
764 	      Maptile *nexttile = getTile(j, i + 1);
765 	      TileStyle *nextstyle = nexttile->getTileStyle();
766 	      if (tilestyle->getType() == TileStyle::OUTERMIDDLERIGHT&&
767 		  nextstyle->getType() == TileStyle::OUTERMIDDLELEFT)
768 		{
769 		  TileStyle *style;
770 		  style = tileset->getRandomTileStyle(tile->getIndex(),
771 						      TileStyle::OUTERBOTTOMRIGHT);
772 		  tile->setTileStyle(style);
773 		  style = tileset->getRandomTileStyle(nexttile->getIndex(),
774 						      TileStyle::OUTERTOPLEFT);
775 		  nexttile->setTileStyle(style);
776 		}
777 	      if (tilestyle->getType() == TileStyle::OUTERMIDDLELEFT&&
778 		  nextstyle->getType() == TileStyle::OUTERMIDDLERIGHT)
779 		{
780 		  TileStyle *style;
781 		  style = tileset->getRandomTileStyle(tile->getIndex(),
782 						      TileStyle::OUTERBOTTOMLEFT);
783 		  tile->setTileStyle(style);
784 		  style = tileset->getRandomTileStyle(nexttile->getIndex(),
785 						      TileStyle::OUTERTOPRIGHT);
786 		  nexttile->setTileStyle(style);
787 		}
788 	      }
789 	}
790     }
791 }
792 
are_those_tiles_similar(Tile::Type outer_tile,Tile::Type inner_tile,bool checking_loneliness)793 bool GameMap::are_those_tiles_similar(Tile::Type outer_tile,Tile::Type inner_tile, bool checking_loneliness)
794 {
795     if(checking_loneliness || inner_tile == Tile::HILLS)
796     {
797         if( (outer_tile == Tile::MOUNTAIN && inner_tile == Tile::HILLS) ||
798             (inner_tile == Tile::MOUNTAIN && outer_tile == Tile::HILLS))
799             // Mountains and hills are similar, MapGenerator::surroundMountains()
800             // makes sure that mountains are surrounded by hills. So a hill tile
801             // with only a mountain neighbour is not a lone tile
802             //
803             // There never should be a lone mountain in grass (not surrounded by hills).
804             // Mountain surrounded by hills is perfectly correct.
805             return true;
806         return outer_tile == inner_tile;
807     }
808     else
809     { // to pick correct tile picture for a mountain we treat hills as a tile
810       // different than mountain.
811         return outer_tile == inner_tile;
812     }
813 }
814 
tile_is_connected_to_other_like_tiles(Tile::Type tile,int i,int j)815 int GameMap::tile_is_connected_to_other_like_tiles (Tile::Type tile, int i, int j)
816 {
817   int box[3][3];
818   memset (box, 0, sizeof (box));
819   for (int k = -1; k <= +1; k++)
820     for (int l = -1; l <= +1; l++)
821       {
822 	if (offmap(j+l,i+k))
823 	  continue;
824 	box[k+1][l+1] = are_those_tiles_similar(getTile(j+l, i+k)->getType(),
825                                                 tile, true);
826       }
827   if (box[0][0] && box[0][1] && box[1][0] && box[1][1])
828     return 1;
829   if (box[0][1] && box[0][2] && box[1][1] && box[1][2])
830     return 1;
831   if (box[1][0] && box[1][1] && box[2][0] && box[2][1])
832     return 1;
833   if (box[1][1] && box[1][2] && box[2][1] && box[2][2])
834     return 1;
835   return 0;
836 }
837 
demote_lone_tile(int minx,int miny,int maxx,int maxy,Tile::Type intype,Tile::Type outtype)838 void GameMap::demote_lone_tile(int minx, int miny, int maxx, int maxy,
839 			       Tile::Type intype, Tile::Type outtype)
840 {
841   Tileset *tileset = GameMap::getTileset();
842   int i;
843   int j;
844   for (i = minx; i < maxx; i++)
845     for (j = miny; j < maxy; j++)
846       {
847 	if (offmap(j, i))
848 	  continue;
849 	Tile::Type tile = getTile(j, i)->getType();
850 	if (tile == intype)
851 	  {
852 	    //if we're not connected in a square of
853 	    //same types, then we're a lone tile.
854             if (getTile(j,i)->getBuilding())
855               continue;
856 	    if (tile_is_connected_to_other_like_tiles(tile, i, j) == 0)
857 	      {
858 		//okay, this is a lone tile.
859 		//downgrade it
860 		int idx = tileset->getIndex(outtype);
861 		if (idx != -1)
862 		  setTileIndex(j, i, (guint32)idx);
863 	      }
864 	  }
865       }
866 }
867 
applyTileStyles(LwRectangle r,bool smooth_terrain)868 void GameMap::applyTileStyles (LwRectangle r, bool smooth_terrain)
869 {
870   applyTileStyles (r.y, r.x, r.y + r.h, r.x + r.w, smooth_terrain);
871 }
872 
applyTileStyles(int minx,int miny,int maxx,int maxy,bool smooth_terrain)873 void GameMap::applyTileStyles (int minx, int miny, int maxx, int maxy,
874 			       bool smooth_terrain)
875 {
876 
877   if (smooth_terrain)
878     {
879       demote_lone_tile(minx, miny, maxx, maxy, Tile::FOREST, Tile::GRASS);
880       demote_lone_tile(minx, miny, maxx, maxy, Tile::MOUNTAIN, Tile::HILLS);
881       demote_lone_tile(minx, miny, maxx, maxy, Tile::HILLS, Tile::GRASS);
882       demote_lone_tile(minx, miny, maxx, maxy, Tile::WATER, Tile::SWAMP);
883       surroundMountains(minx, miny, maxx, maxy);
884     }
885 
886   for (int i = minx; i < maxx; i++)
887     {
888       for (int j = miny; j < maxy; j++)
889 	{
890 	  if (offmap(j, i))
891 	    continue;
892 	  applyTileStyle(i, j);
893 	}
894     }
895   close_circles(minx, miny, maxx, maxy);
896 }
897 
getItems()898 std::vector<Vector<int> > GameMap::getItems()
899 {
900   std::vector<Vector<int> > items;
901   for (int j = 0; j < s_height; j++)
902     for (int i = 0; i < s_width; i++)
903       {
904         if (d_map[j*s_width + i].getBackpack()->empty() == false)
905           items.push_back(Vector<int>(i, j));
906 
907       }
908   return items;
909 }
910 
911 
surroundMountains(int minx,int miny,int maxx,int maxy)912 void GameMap::surroundMountains(int minx, int miny, int maxx, int maxy)
913 {
914   Tileset *tileset = GameMap::getTileset();
915   for(int j = miny; j < maxy; j++)
916     for(int i = minx; i < maxx; i++)
917       {
918 	if (offmap(j, i))
919 	  continue;
920 	if(getTile(j, i)->getType() == Tile::MOUNTAIN)
921 	  for(int J = -1; J <= +1; ++J)
922 	    for(int I = -1; I <= +1; ++I)
923 	      if((!(offmap(j+J,i+I))) &&
924 		 (getTile((j+J),(i+I))->getType() != Tile::MOUNTAIN))
925 		{
926 		  int idx = tileset->getIndex(Tile::HILLS);
927 		  if(getTile((j+J), (i+I))->getType() != Tile::WATER)
928 		    {
929 		      if (idx != -1)
930                         {
931                           Maptile::Building b = getTile(j+J, i+I)->getBuilding();
932                           setTileIndex(j+J, i+I, (guint32)idx);
933                           if (b)
934                             setBuilding(Vector<int>(j+J,i+I), b);
935                         }
936 		    }
937 		  else
938 		    {
939 		    // water has priority here, there was some work done to conenct bodies of water
940 		    // so don't break those connections.
941 		      setTileIndex(j, i, (guint32)idx);
942 		    }
943 		}
944       }
945 }
946 
applyTileStyle(int i,int j)947 void GameMap::applyTileStyle (int i, int j)
948 {
949   Maptile *mtile = getTile(j, i);
950   Tileset *tileset = GameMap::getTileset();
951 
952   TileStyle *style = calculatePreferredStyle(i, j);
953   if (!style)
954     style = tileset->getRandomTileStyle(mtile->getIndex(),
955 					TileStyle::LONE);
956   if (!style)
957     style = tileset->getRandomTileStyle(mtile->getIndex(),
958 					TileStyle::INNERMIDDLECENTER);
959   if (!style)
960     printf ("applying null tile style at %d,%d for tile of kind %d\n", i, j,
961 	    mtile->getType());
962   mtile->setTileStyle(style);
963 }
964 
findNearestObjectInDir(Vector<int> pos,Vector<int> dir)965 Vector<int> GameMap::findNearestObjectInDir(Vector<int> pos, Vector<int> dir)
966 {
967   std::vector<Vector<int> > objects;
968   Road *road = Roadlist::getInstance()->getNearestObjectInDir(pos, dir);
969   if (road)
970     objects.push_back(road->getPos());
971   City *city = Citylist::getInstance()->getNearestObjectInDir(pos, dir);
972   if (city)
973     objects.push_back(city->getPos());
974   Temple *temple = Templelist::getInstance()->getNearestObjectInDir(pos, dir);
975   if (temple)
976     objects.push_back(temple->getPos());
977   Ruin *ruin = Ruinlist::getInstance()->getNearestObjectInDir(pos, dir);
978   if (ruin && ruin->isHidden() == false)
979     objects.push_back(ruin->getPos());
980   if (objects.size() == 0)
981     return Vector<int>(-1,-1);
982 
983   int min_distance = -1;
984   Vector<int> closest = Vector<int>(-1,-1);
985   for (unsigned int i = 0; i < objects.size(); i++)
986     {
987       int distance = dist(pos, objects[i]);
988       if (min_distance == -1 || distance < min_distance)
989 	{
990 	  min_distance = distance;
991 	  closest = objects[i];
992 	}
993     }
994   return closest;
995 }
996 
findNearestObjectToTheNorth(Vector<int> pos)997 Vector<int> GameMap::findNearestObjectToTheNorth(Vector<int> pos)
998 {
999   Vector<int> dir = Vector<int>(0, -1);
1000   return findNearestObjectInDir(pos, dir);
1001 }
1002 
findNearestObjectToTheSouth(Vector<int> pos)1003 Vector<int> GameMap::findNearestObjectToTheSouth(Vector<int> pos)
1004 {
1005   Vector<int> dir = Vector<int>(0, 1);
1006   return findNearestObjectInDir(pos, dir);
1007 }
1008 
findNearestObjectToTheEast(Vector<int> pos)1009 Vector<int> GameMap::findNearestObjectToTheEast(Vector<int> pos)
1010 {
1011   Vector<int> dir = Vector<int>(1, 0);
1012   return findNearestObjectInDir(pos, dir);
1013 }
1014 
findNearestObjectToTheWest(Vector<int> pos)1015 Vector<int> GameMap::findNearestObjectToTheWest(Vector<int> pos)
1016 {
1017   Vector<int> dir = Vector<int>(-1, 0);
1018   return findNearestObjectInDir(pos, dir);
1019 }
1020 
getCity(Vector<int> pos)1021 City* GameMap::getCity(Vector<int> pos)
1022 {
1023   if (getInstance()->getBuilding(pos) != Maptile::CITY)
1024     return NULL;
1025   return Citylist::getInstance()->getObjectAt(pos);
1026 }
1027 
getEnemyCity(Vector<int> pos)1028 City* GameMap::getEnemyCity(Vector<int> pos)
1029 {
1030   if (getInstance()->getBuilding(pos) != Maptile::CITY)
1031     return NULL;
1032   City *c = Citylist::getInstance()->getObjectAt(pos);
1033   if (c && c->getOwner() != Playerlist::getActiveplayer())
1034     return c;
1035   return NULL;
1036 }
1037 
getRuin(Vector<int> pos)1038 Ruin* GameMap::getRuin(Vector<int> pos)
1039 {
1040   if (getInstance()->getBuilding(pos) != Maptile::RUIN)
1041     return NULL;
1042   return Ruinlist::getInstance()->getObjectAt(pos);
1043 }
1044 
getStone(Vector<int> pos)1045 Stone* GameMap::getStone(Vector<int> pos)
1046 {
1047   if (getInstance()->getBuilding(pos) != Maptile::STONE &&
1048       getInstance()->getBuilding(pos) != Maptile::ROAD)
1049     return NULL;
1050   return Stonelist::getInstance()->getObjectAt(pos);
1051 }
1052 
getTemple(Vector<int> pos)1053 Temple* GameMap::getTemple(Vector<int> pos)
1054 {
1055   if (getInstance()->getBuilding(pos) != Maptile::TEMPLE)
1056     return NULL;
1057   return Templelist::getInstance()->getObjectAt(pos);
1058 }
1059 
getPort(Vector<int> pos)1060 Port* GameMap::getPort(Vector<int> pos)
1061 {
1062   if (getInstance()->getBuilding(pos) != Maptile::PORT)
1063     return NULL;
1064   return Portlist::getInstance()->getObjectAt(pos);
1065 }
1066 
getRoad(Vector<int> pos)1067 Road* GameMap::getRoad(Vector<int> pos)
1068 {
1069   if (getInstance()->getBuilding(pos) != Maptile::ROAD)
1070     return NULL;
1071   return Roadlist::getInstance()->getObjectAt(pos);
1072 }
1073 
getBridge(Vector<int> pos)1074 Bridge* GameMap::getBridge(Vector<int> pos)
1075 {
1076   if (getInstance()->getBuilding(pos) != Maptile::BRIDGE)
1077     return NULL;
1078   return Bridgelist::getInstance()->getObjectAt(pos);
1079 }
1080 
getSignpost(Vector<int> pos)1081 Signpost* GameMap::getSignpost(Vector<int> pos)
1082 {
1083   if (getInstance()->getBuilding(pos) != Maptile::SIGNPOST)
1084     return NULL;
1085   return Signpostlist::getInstance()->getObjectAt(pos);
1086 }
1087 
getFriendlyStack(Vector<int> pos)1088 Stack* GameMap::getFriendlyStack(Vector<int> pos)
1089 {
1090   return getStacks(pos)->getFriendlyStack(Playerlist::getActiveplayer());
1091 }
1092 
getFriendlyStacks(Vector<int> pos,Player * player)1093 std::vector<Stack*> GameMap::getFriendlyStacks(Vector<int> pos, Player *player)
1094 {
1095   if (player == NULL)
1096     player = Playerlist::getActiveplayer();
1097   return getStacks(pos)->getFriendlyStacks(player);
1098 }
1099 
getEnemyStack(Vector<int> pos)1100 Stack* GameMap::getEnemyStack(Vector<int> pos)
1101 {
1102   return getStacks(pos)->getEnemyStack(Playerlist::getActiveplayer());
1103 }
1104 
getEnemyStacks(std::list<Vector<int>> positions)1105 std::vector<Stack*> GameMap::getEnemyStacks(std::list<Vector<int> > positions)
1106 {
1107   std::vector<Stack*> enemy_stacks;
1108   std::list<Vector<int> >::iterator it = positions.begin();
1109   for (; it != positions.end(); it++)
1110     {
1111       Stack *enemy = getEnemyStack(*it);
1112       if (enemy)
1113 	enemy_stacks.push_back(enemy);
1114     }
1115   return enemy_stacks;
1116 }
1117 
getEnemyStacks(Vector<int> pos,Player * player)1118 std::vector<Stack*> GameMap::getEnemyStacks(Vector<int> pos, Player *player)
1119 {
1120   if (!getStacks(pos))
1121     {
1122       std::vector<Stack*> empty;
1123       return empty;
1124     }
1125 
1126   if (player == NULL)
1127     player = Playerlist::getActiveplayer();
1128   return getStacks(pos)->getEnemyStacks(player);
1129 }
1130 
1131 
compareStackStrength(Stack * lhs,Stack * rhs)1132 bool GameMap::compareStackStrength(Stack *lhs, Stack *rhs)
1133 {
1134   Army *lhero = lhs->getStrongestHero();
1135   Army *rhero = rhs->getStrongestHero();
1136   if (lhero && rhero)
1137     return
1138       lhero->getStat(Army::STRENGTH) > rhero->getStat(Army::STRENGTH);
1139   else if (!lhero && rhero)
1140     return false;
1141   else if (lhero && !rhero)
1142     return true;
1143 
1144   Army *larmy = lhs->getStrongestArmy();
1145   Army *rarmy = rhs->getStrongestArmy();
1146   return larmy->getStat(Army::STRENGTH) > rarmy->getStat(Army::STRENGTH);
1147 }
1148 
getStrongestStack(Vector<int> pos)1149 Stack* GameMap::getStrongestStack(Vector<int> pos)
1150 {
1151   StackTile *s = getStacks(pos);
1152   std::vector<Stack*> stacks = s->getStacks();
1153   if (stacks.empty())
1154     return NULL;
1155   std::sort (stacks.begin(), stacks.end(), compareStackStrength);
1156   return stacks.front();
1157 }
1158 
getStack(Vector<int> pos)1159 Stack* GameMap::getStack(Vector<int> pos)
1160 {
1161   if (getStacks(pos))
1162     return getStacks(pos)->getStack();
1163   else
1164     return NULL;
1165 }
1166 
getStacks(Vector<int> pos)1167 StackTile* GameMap::getStacks(Vector<int> pos)
1168 {
1169   if (getInstance()->getTile(pos))
1170     return getInstance()->getTile(pos)->getStacks();
1171   else
1172     return NULL;
1173 }
1174 
groupStacks(Vector<int> pos)1175 Stack *GameMap::groupStacks(Vector<int> pos)
1176 {
1177   return getInstance()->groupStacks(pos, Playerlist::getActiveplayer());
1178 }
1179 
groupStacks(Vector<int> pos,Player * player)1180 Stack *GameMap::groupStacks(Vector<int> pos, Player *player)
1181 {
1182   if (getStacks(pos))
1183     return getStacks(pos)->group(player);
1184   else
1185     return NULL;
1186 }
1187 
groupStacks(Stack * stack)1188 void GameMap::groupStacks(Stack *stack)
1189 {
1190   if (getStacks(stack->getPos()))
1191     return getStacks(stack->getPos())->group(Playerlist::getActiveplayer(), stack);
1192 }
1193 
clearStackPositions()1194 void GameMap::clearStackPositions()
1195 {
1196   for (auto i :*Playerlist::getInstance())
1197     {
1198       Stacklist *sl = i->getStacklist();
1199       for (Stacklist::iterator s = sl->begin(); s != sl->end(); s++)
1200         {
1201           StackTile *st = getStacks((*s)->getPos());
1202           st->clear();
1203         }
1204     }
1205 }
updateStackPositions()1206 void GameMap::updateStackPositions()
1207 {
1208   for (auto i: *Playerlist::getInstance())
1209     {
1210       Stacklist *sl = i->getStacklist();
1211       for (Stacklist::iterator s = sl->begin(); s != sl->end(); s++)
1212         getStacks((*s)->getPos())->add(*s);
1213     }
1214 }
1215 
canJoin(const Stack * src,Vector<int> dest)1216 bool GameMap::canJoin(const Stack *src, Vector<int> dest)
1217 {
1218   return getStacks(dest)->canAdd(src);
1219 }
canJoin(const Stack * src,Stack * dest)1220 bool GameMap::canJoin(const Stack *src, Stack *dest)
1221 {
1222   return canJoin (src, dest->getPos());
1223 }
1224 
canAddArmy(Vector<int> dest)1225 bool GameMap::canAddArmy(Vector<int> dest)
1226 {
1227   if (countArmyUnits(dest) < MAX_ARMIES_ON_A_SINGLE_TILE)
1228     return true;
1229   return false;
1230 }
canAddArmies(Vector<int> dest,guint32 stackSize)1231 bool GameMap::canAddArmies(Vector<int> dest, guint32 stackSize)
1232 {
1233   if (countArmyUnits(dest) + stackSize <= MAX_ARMIES_ON_A_SINGLE_TILE)
1234     return true;
1235   return false;
1236 }
1237 
switchTileset(Tileset * tileset)1238 void GameMap::switchTileset(Tileset *tileset)
1239 {
1240   d_tileset = tileset->getBaseName();
1241   s_tileset = Tilesetlist::getInstance()->get(d_tileset);
1242   for (int i = 0; i < s_width; i++)
1243     for (int j = 0; j < s_height; j++)
1244       {
1245         //there is also the problem of the index being kept in the maptile.
1246         //perhaps we need to get a new index, right? e.g. when we switch
1247         //the tileset for another one in the editor.
1248         //because "Grass" won't always be in the 0th spot in the tileset.
1249         d_map[j*s_width + i].setIndex(d_map[j*s_width + i].getIndex());
1250       }
1251   applyTileStyles (0, 0, s_width, s_height,  false);
1252 }
1253 
reloadTileset()1254 void GameMap::reloadTileset()
1255 {
1256   Tileset *tileset = GameMap::getTileset();
1257   if (tileset)
1258     Tilesetlist::getInstance()->reload(tileset->getId());
1259 }
1260 
reloadShieldset()1261 void GameMap::reloadShieldset()
1262 {
1263   Shieldset *shieldset = GameMap::getShieldset();
1264   if (shieldset)
1265     {
1266       Shieldsetlist::getInstance()->reload(shieldset->getId());
1267       Playerlist::getInstance()->setNewColours(shieldset);
1268     }
1269 }
1270 
switchShieldset(Shieldset * shieldset)1271 void GameMap::switchShieldset(Shieldset *shieldset)
1272 {
1273   Playerlist::getInstance()->setNewColours(shieldset);
1274   d_shieldset = shieldset->getBaseName();
1275   s_shieldset = Shieldsetlist::getInstance()->get(d_shieldset);
1276 }
1277 
findNearestAreaForBuilding(Maptile::Building building_type,Vector<int> pos,guint32 width)1278 Vector<int> GameMap::findNearestAreaForBuilding(Maptile::Building building_type, Vector<int> pos, guint32 width)
1279 {
1280   std::list<Vector<int> > points = getNearbyPoints(pos, -1);
1281   std::list<Vector<int> >::iterator it = points.begin();
1282   for (;it != points.end(); it++)
1283     {
1284       if (canPutBuilding (building_type, width, *it, true))
1285         return *it;
1286     }
1287   return Vector<int>(-1,-1);
1288 }
1289 
switchCityset(Cityset * cityset)1290 void GameMap::switchCityset(Cityset *cityset)
1291 {
1292   setCityset(cityset->getBaseName());
1293 
1294   if (Templelist::getInstance()->size())
1295     {
1296       guint32 tiles =
1297         GameMap::getInstance()->countBuildings(Maptile::TEMPLE) /
1298         Templelist::getInstance()->size();
1299       double old_tile_width = sqrt ((double)tiles);
1300       if (old_tile_width != cityset->getTempleTileWidth())
1301         Templelist::getInstance()->resizeLocations
1302           (Maptile::TEMPLE, cityset->getTempleTileWidth(), old_tile_width,
1303            (void (*)(Location*, Maptile::Building, guint32)) changeFootprintToSmallerCityset,
1304            (void (*)(Location*, Maptile::Building, guint32)) relocateLocation);
1305     }
1306 
1307   if (Ruinlist::getInstance()->size())
1308     {
1309       guint32 tiles = GameMap::getInstance()->countBuildings(Maptile::RUIN) /
1310         Ruinlist::getInstance()->size();
1311       double old_tile_width = sqrt ((double)tiles);
1312       if (old_tile_width != cityset->getRuinTileWidth())
1313         Ruinlist::getInstance()->resizeLocations
1314           (Maptile::RUIN, cityset->getRuinTileWidth(), old_tile_width,
1315            (void (*)(Location*, Maptile::Building, guint32)) changeFootprintToSmallerCityset,
1316            (void (*)(Location*, Maptile::Building, guint32)) relocateLocation);
1317     }
1318   if (Citylist::getInstance()->size())
1319     {
1320       guint32 tiles = GameMap::getInstance()->countBuildings(Maptile::CITY) /
1321         Citylist::getInstance()->size();
1322       double old_tile_width = sqrt ((double)tiles);
1323       if (old_tile_width != cityset->getCityTileWidth())
1324         Citylist::getInstance()->resizeLocations
1325           (Maptile::CITY, cityset->getCityTileWidth(), old_tile_width,
1326            (void (*)(Location*, Maptile::Building, guint32)) changeFootprintToSmallerCityset,
1327            (void (*)(Location*, Maptile::Building, guint32)) relocateLocation);
1328     }
1329 }
1330 
countBuildings(Maptile::Building building_type)1331 guint32 GameMap::countBuildings(Maptile::Building building_type)
1332 {
1333   guint32 count = 0;
1334   for (int x = 0; x < getWidth(); x++)
1335     {
1336       for (int y = 0; y < getHeight(); y++)
1337         {
1338           Vector<int> pos = Vector<int>(x, y);
1339           if (getBuilding(pos) == building_type)
1340             count++;
1341         }
1342     }
1343   return count;
1344 }
1345 
reloadCityset()1346 void GameMap::reloadCityset()
1347 {
1348   Cityset *cityset = GameMap::getCityset();
1349   if (cityset)
1350     {
1351       Citysetlist::getInstance()->reload(cityset->getId());
1352       switchCityset(cityset);  //is this still needed?
1353     }
1354 }
1355 
switchArmysets(Armyset * armyset)1356 void GameMap::switchArmysets(Armyset *armyset)
1357 {
1358   //change the keepers in ruins
1359   for (auto i: *Ruinlist::getInstance())
1360     {
1361       Keeper *k = i->getOccupant();
1362       if (k == NULL)
1363 	continue;
1364       Stack *s = k->getStack ();
1365       if (s == NULL)
1366         continue;
1367       s->removeArmiesWithoutArmyType(armyset->getId());
1368       for (Stack::iterator j = s->begin(); j != s->end(); j++)
1369 	Armyset::switchArmysetForRuinKeeper(*j, armyset);
1370       k->rename();
1371     }
1372   for (auto i: *Playerlist::getInstance())
1373     {
1374       //change the armyprodbases in cities.
1375       for (auto c: *Citylist::getInstance())
1376 	{
1377           c->removeArmyProdBasesWithoutAType(armyset->getId());
1378 	  for (unsigned int k = 0; k < c->getSize(); k++)
1379 	    {
1380 	      ArmyProdBase *prodbase = (*c)[k]->getArmyProdBase();
1381 	      if (prodbase)
1382 		Armyset::switchArmyset(prodbase, armyset);
1383 	    }
1384 	}
1385 
1386       //change the armies in the stacklist
1387       Stacklist *sl = i->getStacklist();
1388       for (Stacklist::iterator j = sl->begin(); j != sl->end(); j++)
1389 	{
1390 	  Stack *s = (*j);
1391           s->removeArmiesWithoutArmyType(armyset->getId());
1392           if (s->size() == 0)
1393             {
1394               GameMap::getInstance()->getStacks(s->getPos())->leaving(s);
1395               j=sl->flErase(j);//this doesn't remove the stack from the map of id->stack pointer in stacklist. XXX XXX XXX
1396               if (sl->size() > 0)
1397                 j--;
1398               continue;
1399             }
1400           for (Stack::iterator k = s->begin(); k != s->end(); k++)
1401             Armyset::switchArmyset(*k,armyset);
1402 	}
1403 
1404       //finally, change the player's armyset.
1405       i->setArmyset(armyset->getId());
1406       //where else are armyset ids hanging around?
1407     }
1408 }
1409 
reloadArmyset(Armyset * armyset)1410 void GameMap::reloadArmyset(Armyset *armyset)
1411 {
1412   Armysetlist::getInstance()->reload(armyset->getId());
1413 }
1414 
canDropBag(Vector<int> pos)1415 bool GameMap::canDropBag (Vector<int> pos)
1416 {
1417   if (getTile(pos)->getType() == Tile::WATER)
1418     return false;
1419   return true;
1420 }
1421 
canPutBuilding(Maptile::Building bldg,guint32 size,Vector<int> to,bool making_islands)1422 bool GameMap::canPutBuilding(Maptile::Building bldg, guint32 size, Vector<int> to, bool making_islands)
1423 {
1424   bool can_move = true;
1425   //gotta have a building to move
1426   if (bldg == Maptile::NONE)
1427     return false;
1428   //there can't be another building in the way.
1429   bool found = false;
1430   for (unsigned int i = 0; i < size; i++)
1431     for (unsigned int j = 0; j < size; j++)
1432       {
1433 	Vector<int> pos = to + Vector<int>(i,j);
1434 	if (offmap(pos.x, pos.y))
1435 	  return false;
1436 	if (getBuilding(pos) != Maptile::NONE)
1437 	  found = true;
1438       }
1439   if (found)
1440     return false;
1441   //ok different objects have different rules wrt the kinds of tiles they
1442   //can be on.
1443   switch (bldg)
1444     {
1445       case Maptile::CITY:
1446 	//gotta be on grass.
1447 	  {
1448 	    if (making_islands)
1449 	      return true;
1450 	    for (unsigned int i = 0; i < size; i++)
1451 	      for (unsigned int j = 0; j < size; j++)
1452 		{
1453 		  Vector<int> pos = to + Vector<int>(i, j);
1454 		  if (getTerrainType(pos) != Tile::GRASS)
1455 		    return false;
1456 		}
1457 	  }
1458 	break;
1459       case Maptile::RUIN:
1460       case Maptile::TEMPLE:
1461       case Maptile::SIGNPOST:
1462 	  {
1463 	    if (making_islands)
1464 	      return true;
1465 	    for (unsigned int i = 0; i < size; i++)
1466 	      for (unsigned int j = 0; j < size; j++)
1467 		{
1468 		  Vector<int> pos = to + Vector<int>(i, j);
1469 		  if (getTerrainType(pos) == Tile::WATER)
1470 		    return false;
1471 		}
1472 	  }
1473 	break;
1474       case Maptile::ROAD:
1475 	//can't be in the water
1476 	if (getTerrainType(to) == Tile::WATER)
1477 	  return false;
1478 	break;
1479       case Maptile::PORT:
1480 	if (getTerrainType(to) == Tile::WATER &&
1481 	    getTile(to)->getTileStyle()->getType() !=
1482 	    TileStyle::INNERMIDDLECENTER)
1483 	  return can_move;
1484 	else
1485 	  return false;
1486 	break;
1487       case Maptile::BRIDGE:
1488 	if (getTerrainType(to) == Tile::WATER &&
1489 	    (getTile(to)->getTileStyle()->getType() ==
1490 	     TileStyle::OUTERTOPCENTER ||
1491 	    getTile(to)->getTileStyle()->getType() ==
1492 	    TileStyle::OUTERBOTTOMCENTER ||
1493 	    getTile(to)->getTileStyle()->getType() ==
1494 	    TileStyle::OUTERMIDDLELEFT ||
1495 	    getTile(to)->getTileStyle()->getType() ==
1496 	    TileStyle::OUTERMIDDLERIGHT ))
1497 	  return can_move;
1498 	else
1499 	  return false;
1500 	break;
1501       case Maptile::STONE:
1502 	if (getTerrainType(to) == Tile::GRASS &&
1503             (getBuilding(to) == Maptile::ROAD ||
1504              getBuilding(to) == Maptile::NONE))
1505 	  return true;
1506         else
1507           return false;
1508         break;
1509       case Maptile::NONE: break;
1510     }
1511   return can_move;
1512 }
1513 
moveBuilding(Vector<int> from,Vector<int> to,guint32 new_width)1514 bool GameMap::moveBuilding(Vector<int> from, Vector<int> to, guint32 new_width)
1515 {
1516   //move a game object located at FROM, and move it to TO.
1517   //watch out for overlaps.
1518   //return true if we moved something.
1519   bool moved = true;
1520 
1521   guint32 size = getBuildingSize(from);
1522   if (size == 0)
1523     return false;
1524 
1525   if (canPutBuilding(getBuilding(from), size, to) == false)
1526     {
1527       if (getLocation(from)->contains(to) == false &&
1528 	  LocationBox(to, size).contains(from) == false)
1529 	return false;
1530     }
1531 
1532   switch (getBuilding(from))
1533     {
1534     case Maptile::NONE:
1535       break;
1536     case Maptile::SIGNPOST:
1537 	{
1538 	  Signpost *old_signpost = getSignpost(getSignpost(from)->getPos());
1539 	  Signpost *new_signpost = new Signpost(*old_signpost, to);
1540 	  removeSignpost(old_signpost->getPos());
1541           if (new_width)
1542             new_signpost->setSize(new_width);
1543 	  putSignpost(new_signpost);
1544 	  break;
1545 	}
1546     case Maptile::PORT:
1547 	{
1548 	  Port *old_port = getPort(getPort(from)->getPos());
1549 	  Port *new_port = new Port(*old_port, to);
1550 	  removePort(old_port->getPos());
1551           if (new_width)
1552             new_port->setSize(new_width);
1553 	  putPort(new_port);
1554 	  break;
1555 	}
1556     case Maptile::BRIDGE:
1557 	{
1558 	  Bridge *old_bridge = getBridge(getBridge(from)->getPos());
1559 	  Bridge *new_bridge = new Bridge(*old_bridge, to);
1560 	  removeBridge(old_bridge->getPos());
1561           if (new_width)
1562             new_bridge->setSize(new_width);
1563 	  putBridge(new_bridge);
1564 	  break;
1565 	}
1566     case Maptile::ROAD:
1567 	{
1568           bool had_stone = getStone(from) != NULL;
1569 	  Road *old_road = getRoad(getRoad(from)->getPos());
1570 	  Road *new_road = new Road(*old_road, to);
1571 	  removeRoad(old_road->getPos());
1572           if (new_width)
1573             new_road->setSize(new_width);
1574 	  putRoad(new_road);
1575           if (had_stone)
1576             {
1577               Stone::Type type =
1578                 Stone::Type(Stone::getRandomType
1579                             (Road::Type(new_road->getType())));
1580               Stone *s = new Stone (to, type);
1581               putStone(s);
1582             }
1583 	  break;
1584 	}
1585     case Maptile::RUIN:
1586 	{
1587 	  Ruin* old_ruin = getRuin(getRuin(from)->getPos());
1588 	  Ruin *new_ruin = new Ruin(*old_ruin, to);
1589 	  removeRuin(old_ruin->getPos());
1590           if (new_width)
1591             new_ruin->setSize(new_width);
1592 	  putRuin(new_ruin);
1593 	  break;
1594 	}
1595     case Maptile::TEMPLE:
1596 	{
1597 	  Temple* old_temple = getTemple(getTemple(from)->getPos());
1598 	  Temple* new_temple = new Temple(*old_temple, to);
1599 	  removeTemple(old_temple->getPos());
1600           if (new_width)
1601             new_temple->setSize(new_width);
1602 	  putTemple(new_temple);
1603 	  break;
1604 	}
1605     case Maptile::CITY:
1606 	{
1607 	  City* old_city = getCity(getCity(from)->getPos());
1608 	  City* new_city = new City(*old_city, to);
1609 	  removeCity(old_city->getPos());
1610           if (new_width)
1611             new_city->setSize(new_width);
1612 	  putCity(new_city, true);
1613 	  break;
1614 	}
1615     case Maptile::STONE:
1616 	{
1617 	  Stone* old_stone = getStone(getStone(from)->getPos());
1618 	  Stone* new_stone = new Stone(*old_stone, to);
1619 	  removeStone(old_stone->getPos());
1620           if (new_width)
1621             new_stone->setSize(new_width);
1622 	  putStone(new_stone);
1623 	  break;
1624 	}
1625     }
1626   return moved;
1627 }
1628 
setBuilding(Vector<int> tile,Maptile::Building building)1629 void GameMap::setBuilding(Vector<int> tile, Maptile::Building building)
1630 {
1631   if (getTile(tile))
1632     getTile(tile)->setBuilding(building);
1633 }
1634 
getBuildingSize(Vector<int> tile)1635 guint32 GameMap::getBuildingSize(Vector<int> tile)
1636 {
1637   if (getTile(tile) == NULL)
1638     return 0;
1639   switch (getTile(tile)->getBuilding())
1640     {
1641     case Maptile::CITY: return getCity(tile)->getSize(); break;
1642     case Maptile::RUIN: return getRuin(tile)->getSize(); break;
1643     case Maptile::TEMPLE: return getTemple(tile)->getSize(); break;
1644     case Maptile::ROAD: return getRoad(tile)->getSize(); break;
1645     case Maptile::BRIDGE: return getBridge(tile)->getSize(); break;
1646     case Maptile::SIGNPOST: return getSignpost(tile)->getSize(); break;
1647     case Maptile::PORT: return getPort(tile)->getSize(); break;
1648     case Maptile::STONE: return getStone(tile)->getSize(); break;
1649     case Maptile::NONE: break;
1650     }
1651 
1652   return 0;
1653 }
1654 
canPutStack(guint32 size,Player * p,Vector<int> to)1655 bool GameMap::canPutStack(guint32 size, Player *p, Vector<int> to)
1656 {
1657   StackTile *stile = GameMap::getInstance()->getStacks(to);
1658   if (!stile)
1659     return true;
1660   if (stile->canAdd(size, p) == true)
1661     return true;
1662   return false;
1663 
1664 }
1665 
moveStack(Stack * stack,Vector<int> to)1666 bool GameMap::moveStack(Stack *stack, Vector<int> to)
1667 {
1668   bool moved = true;
1669   if (stack->getPos() == to)
1670     return true;
1671   if (canPutStack(stack->size(), stack->getOwner(), to) == false)
1672     return false;
1673 
1674 
1675   getStacks(stack->getPos())->leaving(stack);
1676   stack->setPos(to);
1677   City *c = GameMap::getCity(to);
1678   if (c != NULL && stack->getOwner() != c->getOwner())
1679     stack = Stacklist::changeOwnership(stack, c->getOwner());
1680   getStacks(stack->getPos())->arriving(stack);
1681   updateShips(stack->getPos());
1682   updateTowers(stack->getPos());
1683 
1684   return moved;
1685 }
1686 
getBackpack(Vector<int> pos)1687 MapBackpack *GameMap::getBackpack(Vector<int> pos)
1688 {
1689   if (getInstance()->getTile(pos))
1690     return getInstance()->getTile(pos)->getBackpack();
1691   else
1692     return NULL;
1693 }
1694 
moveBackpack(MapBackpack * bag,Vector<int> to)1695 void GameMap::moveBackpack(MapBackpack *bag, Vector<int> to)
1696 {
1697   getBackpack(to)->add(bag);
1698   bag->clear();
1699 }
1700 
removeRuin(Vector<int> pos)1701 bool GameMap::removeRuin(Vector<int> pos)
1702 {
1703   Ruin *r = GameMap::getRuin(pos);
1704   if (r)
1705     {
1706       removeBuilding(r);
1707       Ruinlist::getInstance()->subtract(r);
1708       return true;
1709     }
1710   return false;
1711 }
1712 
containsWater(LwRectangle rect)1713 bool GameMap::containsWater(LwRectangle rect)
1714 {
1715   for (int y = rect.y; y < rect.y + rect.h; y++)
1716     for (int x = rect.x; x < rect.x + rect.w; x++)
1717       if (getTile(x, y)->getType() == Tile::WATER)
1718         return true;
1719   return false;
1720 }
1721 
containsForest(LwRectangle rect)1722 bool GameMap::containsForest(LwRectangle rect)
1723 {
1724   for (int y = rect.y; y < rect.y + rect.h; y++)
1725     for (int x = rect.x; x < rect.x + rect.w; x++)
1726       if (getTile(x, y)->getType() == Tile::FOREST)
1727         return true;
1728   return false;
1729 }
1730 
putRuin(Ruin * r)1731 bool GameMap::putRuin(Ruin *r)
1732 {
1733   Ruinlist::getInstance()->add(r);
1734   if (containsWater(r->getArea()) ||
1735       containsForest (r->getArea ()))
1736     putTerrain(r->getArea(), Tile::GRASS);
1737   putBuilding(r, Maptile::RUIN);
1738   return true;
1739 }
1740 
removeLocation(Vector<int> pos)1741 bool GameMap::removeLocation (Vector<int> pos)
1742 {
1743   switch (getBuilding(pos))
1744     {
1745     case Maptile::CITY: return removeCity(pos);
1746     case Maptile::RUIN: return removeRuin(pos);
1747     case Maptile::TEMPLE: return removeTemple(pos);
1748     case Maptile::ROAD: return removeRoad(pos);
1749     case Maptile::BRIDGE: return removeBridge(pos);
1750     case Maptile::SIGNPOST: return removeSignpost(pos);
1751     case Maptile::PORT: return removePort(pos);
1752     case Maptile::STONE: return removeStone(pos);
1753     case Maptile::NONE: break;
1754     }
1755   return false;
1756 }
1757 
1758 
removeStone(Vector<int> pos)1759 bool GameMap::removeStone(Vector<int> pos)
1760 {
1761   Stone *s = GameMap::getStone(pos);
1762   if (s)
1763     {
1764       if (getBuilding(s->getPos()) == Maptile::STONE)
1765         setBuilding(s->getPos(), Maptile::NONE);
1766 
1767       Stonelist::getInstance()->subtract(s);
1768       return true;
1769     }
1770   return false;
1771 }
1772 
putStone(Stone * s)1773 bool GameMap::putStone(Stone *s)
1774 {
1775   Stonelist::getInstance()->add(s);
1776   if (containsWater(s->getArea()) ||
1777       containsForest (s->getArea ()))
1778     putTerrain(s->getArea(), Tile::GRASS);
1779   if (getBuilding(s->getPos()) != Maptile::ROAD)
1780     setBuilding(s->getPos(), Maptile::STONE);
1781   return true;
1782 }
1783 
removeTemple(Vector<int> pos)1784 bool GameMap::removeTemple(Vector<int> pos)
1785 {
1786   Temple *t = GameMap::getTemple(pos);
1787   if (t)
1788     {
1789       removeBuilding(t);
1790       Templelist::getInstance()->subtract(t);
1791       return true;
1792     }
1793   return false;
1794 }
1795 
putTemple(Temple * t)1796 bool GameMap::putTemple(Temple *t)
1797 {
1798   Templelist::getInstance()->add(t);
1799   if (containsWater(t->getArea()) ||
1800       containsForest (t->getArea ()))
1801     putTerrain(t->getArea(), Tile::GRASS);
1802   putBuilding(t, Maptile::TEMPLE);
1803   return true;
1804 }
1805 
removePort(Vector<int> pos)1806 bool GameMap::removePort(Vector<int> pos)
1807 {
1808   Port *p = GameMap::getPort(pos);
1809   if (p)
1810     {
1811       removeBuilding(p);
1812       Portlist::getInstance()->subtract(p);
1813       return true;
1814     }
1815   return false;
1816 }
1817 
putPort(Port * p)1818 bool GameMap::putPort(Port *p)
1819 {
1820   Portlist::getInstance()->add(p);
1821   putBuilding(p, Maptile::PORT);
1822   //is there a stack here?
1823   if (GameMap::getStack(p->getPos()) != NULL)
1824     {
1825       updateShips(p->getPos());
1826       updateTowers (p->getPos ());
1827     }
1828   return true;
1829 }
1830 
removeSignpost(Vector<int> pos)1831 bool GameMap::removeSignpost(Vector<int> pos)
1832 {
1833   Signpost *s = GameMap::getSignpost(pos);
1834   if (s)
1835     {
1836       removeBuilding(s);
1837       Signpostlist::getInstance()->subtract(s);
1838       return true;
1839     }
1840   return false;
1841 }
1842 
putSignpost(Signpost * s)1843 bool GameMap::putSignpost(Signpost *s)
1844 {
1845   Signpostlist::getInstance()->add(s);
1846   if (containsWater(s->getArea()) ||
1847       containsForest (s->getArea ()))
1848     putTerrain(s->getArea(), Tile::GRASS);
1849   putBuilding(s, Maptile::SIGNPOST);
1850   return true;
1851 }
1852 
removeRoad(Vector<int> pos)1853 bool GameMap::removeRoad(Vector<int> pos)
1854 {
1855   Road *r = GameMap::getRoad(pos);
1856   if (r)
1857     {
1858       removeBuilding(r);
1859       Roadlist::getInstance()->subtract(r);
1860       Stone *s = Stonelist::getInstance()->getObjectAt(pos);
1861       if (s)
1862         Stonelist::getInstance()->subtract(s);
1863       return true;
1864     }
1865   return false;
1866 }
1867 
putNewRoad(Vector<int> tile)1868 bool GameMap::putNewRoad(Vector<int> tile)
1869 {
1870   Road *r = new Road(tile);
1871   if (r)
1872     return putRoad(r);
1873   else
1874     return false;
1875 }
1876 
putRoad(Road * r,bool smooth)1877 bool GameMap::putRoad(Road *r, bool smooth)
1878 {
1879   if (containsWater(r->getArea()))
1880     putTerrain(r->getArea(), Tile::GRASS);
1881   Roadlist::getInstance()->add(r);
1882   setBuilding(r->getPos(), Maptile::ROAD);
1883 
1884   if (smooth == false)
1885     return true;
1886   // now reconfigure all roads in the surroundings
1887   Vector<int> tile = r->getPos();
1888   for (int x = tile.x - 1; x <= tile.x + 1; ++x)
1889     for (int y = tile.y - 1; y <= tile.y + 1; ++y)
1890       {
1891         if (offmap(x,y))
1892           continue;
1893 
1894 	Vector<int> pos(x, y);
1895 	if (Roadlist::getInstance()->getObjectAt(pos))
1896 	  {
1897             r = Roadlist::getInstance()->getObjectAt(pos);
1898 	    int newtype = CreateScenario::calculateRoadType(pos);
1899 	    r->setType(newtype);
1900 	  }
1901       }
1902   return true;
1903 }
1904 
removeBridge(Vector<int> pos)1905 bool GameMap::removeBridge(Vector<int> pos)
1906 {
1907   Bridge *b = GameMap::getBridge(pos);
1908   if (b)
1909     {
1910       removeBuilding(b);
1911       Bridgelist::getInstance()->subtract(b);
1912       updateShips(pos);
1913       updateTowers(pos);
1914       return true;
1915     }
1916   return false;
1917 }
1918 
putBridge(Bridge * b)1919 bool GameMap::putBridge(Bridge *b)
1920 {
1921   Bridgelist::getInstance()->add(b);
1922   setBuilding(b->getPos(), Maptile::BRIDGE);
1923   if (GameMap::getStack(b->getPos()) != NULL)
1924     {
1925       updateShips(b->getPos());
1926       updateTowers (b->getPos ());
1927     }
1928   return true;
1929 }
1930 
putTerrain(LwRectangle r,Tile::Type type,int tile_style_id,bool always_alter_tilestyles)1931 LwRectangle GameMap::putTerrain(LwRectangle r, Tile::Type type, int tile_style_id, bool always_alter_tilestyles)
1932 {
1933   bool replaced = false;
1934   Tileset *tileset = GameMap::getTileset();
1935   int index = tileset->getIndex(type);
1936   if (index == -1)
1937     return r;
1938   for (int x = r.x; x < r.x + r.w; ++x)
1939     for (int y = r.y; y < r.y + r.h; ++y)
1940       {
1941 	if (offmap(x,y))
1942 	  continue;
1943 
1944 	Maptile* t = getTile(Vector<int>(x, y));
1945         if (t->hasLandBuilding() && type == Tile::WATER)
1946           continue;
1947         if (t->hasWaterBuilding() && type != Tile::WATER)
1948           continue;
1949 	if (t->getType() != type)
1950           {
1951             //it's always grass under cities.
1952             if (t->getBuilding() == Maptile::CITY)
1953               t->setIndex(tileset->getIndex(Tile::GRASS));
1954             else if (type == Tile::FOREST &&
1955                      t->getBuilding() != Maptile::ROAD &&
1956                      t->getBuilding() != Maptile::NONE)
1957               t->setIndex(tileset->getIndex(Tile::GRASS));
1958             else
1959               t->setIndex(index);
1960             updateShips(Vector<int>(x,y));
1961             updateTowers(Vector<int>(x,y));
1962             replaced = true;
1963           }
1964       }
1965   if (replaced)
1966     {
1967       for (int x = r.x - 2; x < r.x + r.w + 2; ++x)
1968         for (int y = r.y - 2; y < r.y + r.h + 2; ++y)
1969           {
1970             if (offmap(x,y))
1971               continue;
1972             calculateBlockedAvenue(x, y);
1973           }
1974     }
1975   if (tile_style_id == -1)
1976     {
1977       if (replaced || always_alter_tilestyles)
1978         {
1979           guint32 border = 1;
1980           r.pos -= Vector<int>(border, border);
1981           r.dim += Vector<int>(border * 2, border * 2);
1982           applyTileStyles(r, true);
1983         }
1984     }
1985   else
1986     {
1987       for (int x = r.x; x < r.x + r.w; ++x)
1988         for (int y = r.y; y < r.y + r.h; ++y)
1989           {
1990             if (offmap(x,y))
1991               continue;
1992 	    TileStyle *style = tileset->getTileStyle(tile_style_id);
1993 	    getTile(x, y)->setTileStyle(style);
1994           }
1995     }
1996 
1997   return r;
1998 }
1999 
clearBuilding(Vector<int> pos,guint32 width)2000 void GameMap::clearBuilding(Vector<int> pos, guint32 width)
2001 {
2002   for (unsigned int x = pos.x; x < pos.x + width; ++x)
2003     for (unsigned int y = pos.y; y < pos.y + width; ++y)
2004       {
2005         if (offmap(x,y))
2006           continue;
2007 	Maptile* t = getTile(Vector<int>(x, y));
2008 	t->setBuilding(Maptile::NONE);
2009       }
2010 }
2011 
putBuilding(LocationBox * b,Maptile::Building building)2012 void GameMap::putBuilding(LocationBox *b, Maptile::Building building)
2013 {
2014   LwRectangle r = b->getArea();
2015   for (int x = r.x; x < r.x + r.w; ++x)
2016     for (int y = r.y; y < r.y + r.h; ++y)
2017       {
2018 	Maptile* t = getTile(Vector<int>(x, y));
2019 	t->setBuilding(building);
2020         if (building == Maptile::CITY || building == Maptile::PORT ||
2021             building == Maptile::BRIDGE)
2022           GameMap::getInstance()->calculateBlockedAvenue(x, y);
2023       }
2024 }
2025 
removeBuilding(LocationBox * b)2026 void GameMap::removeBuilding(LocationBox *b)
2027 {
2028   LwRectangle r = b->getArea();
2029   for (int x = r.x; x < r.x + r.w; ++x)
2030     for (int y = r.y; y < r.y + r.h; ++y)
2031       {
2032 	Maptile* t = getTile(Vector<int>(x, y));
2033 	t->setBuilding(Maptile::NONE);
2034       }
2035 }
2036 
removeCity(Vector<int> pos)2037 bool GameMap::removeCity(Vector<int> pos)
2038 {
2039   City *c = GameMap::getCity(pos);
2040   if (c)
2041     {
2042       removeBuilding(c);
2043       Citylist::getInstance()->subtract(c);
2044       return true;
2045     }
2046   return false;
2047 }
2048 
putNewCity(Vector<int> tile)2049 bool GameMap::putNewCity(Vector<int> tile)
2050 {
2051   Cityset *cs = GameMap::getCityset();
2052   // check if we can place the city
2053   bool city_placeable =
2054     canPutBuilding (Maptile::CITY, cs->getCityTileWidth(), tile);
2055 
2056   if (!city_placeable)
2057     return false;
2058 
2059   City *c = new City(tile, cs->getCityTileWidth());
2060   return putCity(c);
2061 }
2062 
putNewRuin(Vector<int> tile)2063 bool GameMap::putNewRuin(Vector<int> tile)
2064 {
2065   Cityset *cs = GameMap::getCityset();
2066   // check if we can place the city
2067   bool ruin_placeable =
2068     canPutBuilding (Maptile::RUIN, cs->getRuinTileWidth(), tile);
2069 
2070   if (!ruin_placeable)
2071     return false;
2072 
2073   Ruin *r = new Ruin(tile, cs->getRuinTileWidth());
2074   return putRuin(r);
2075 }
2076 
putNewStone(Vector<int> tile)2077 bool GameMap::putNewStone(Vector<int> tile)
2078 {
2079   // check if we can place the stone
2080   bool stone_placeable =
2081     canPutBuilding (Maptile::STONE, 1, tile);
2082 
2083   if (!stone_placeable)
2084     return false;
2085 
2086   Stone *t = new Stone(tile, 1);
2087   return putStone(t);
2088 }
2089 
putNewTemple(Vector<int> tile)2090 bool GameMap::putNewTemple(Vector<int> tile)
2091 {
2092   Cityset *cs = GameMap::getCityset();
2093   // check if we can place the city
2094   bool temple_placeable =
2095     canPutBuilding (Maptile::TEMPLE, cs->getTempleTileWidth(), tile);
2096 
2097   if (!temple_placeable)
2098     return false;
2099 
2100   Temple *t = new Temple(tile, cs->getTempleTileWidth());
2101   return putTemple(t);
2102 }
2103 
putCity(City * c,bool keep_owner)2104 bool GameMap::putCity(City *c, bool keep_owner)
2105 {
2106   Player *active = Playerlist::getActiveplayer();
2107 
2108   // create the city
2109   if (keep_owner == false)
2110     c->setOwner(active);
2111   else
2112     active = c->getOwner();
2113   Citylist::getInstance()->add(c);
2114 
2115   putTerrain(c->getArea(), Tile::GRASS);
2116   // notify the maptiles that a city has been placed here
2117   putBuilding(c, Maptile::CITY);
2118 
2119   //change allegiance of stacks under this city
2120   for (unsigned int x = 0; x < c->getSize(); x++)
2121     {
2122       for (unsigned int y = 0; y < c->getSize(); y++)
2123 	{
2124 	  Stack *s = getStack(c->getPos() + Vector<int>(x,y));
2125 	  if (s)
2126 	    {
2127 	      if (c->getOwner() == active && s->getFortified() == true)
2128 		s->setFortified(false);
2129 	      if (s->getOwner() != c->getOwner())
2130 		Stacklist::changeOwnership(s, c->getOwner());
2131 	    }
2132 	}
2133     }
2134   return true;
2135 }
2136 
2137 //the ground changed, and now we need all stacks on a tile to react.
updateShips(Vector<int> pos)2138 void GameMap::updateShips(Vector<int> pos)
2139 {
2140   std::vector<Stack*> stks = getStacks(pos)->getStacks();
2141   for (std::vector<Stack *>::iterator it = stks.begin(); it != stks.end(); it++)
2142     {
2143       for (Stack::iterator sit = (*it)->begin(); sit != (*it)->end(); sit++)
2144 	{
2145 	  if (((*sit)->getStat(Army::MOVE_BONUS) & Tile::WATER) == 0 &&
2146 	      getTerrainType(pos) == Tile::WATER)
2147 	    {
2148 	      if (getBridge(pos) || getPort(pos))
2149 		(*sit)->setInShip(false);
2150 	      else
2151 		(*sit)->setInShip(true);
2152 	    }
2153 	  else
2154 	    (*sit)->setInShip(false);
2155 
2156 	}
2157     }
2158 }
2159 
updateTowers(Vector<int> pos)2160 void GameMap::updateTowers (Vector<int> pos)
2161 {
2162   std::vector<Stack*> stks = getStacks(pos)->getStacks();
2163   for (std::vector<Stack *>::iterator it = stks.begin(); it != stks.end(); it++)
2164     {
2165       for (Stack::iterator sit = (*it)->begin(); sit != (*it)->end(); sit++)
2166 	{
2167           if (((*sit)->getFortified ()) && !can_defend(*it))
2168             (*sit)->setFortified (false);
2169 	}
2170     }
2171 }
2172 
getLocation(Vector<int> tile)2173 Location *GameMap::getLocation(Vector<int> tile)
2174 {
2175   switch (getBuilding(tile))
2176     {
2177     case Maptile::CITY: return getCity(tile);
2178     case Maptile::RUIN: return getRuin(tile);
2179     case Maptile::TEMPLE: return getTemple(tile);
2180     case Maptile::ROAD: return getRoad(tile);
2181     case Maptile::BRIDGE: return getBridge(tile);
2182     case Maptile::SIGNPOST: return getSignpost(tile);
2183     case Maptile::PORT: return getPort(tile);
2184     case Maptile::STONE: return getStone(tile);
2185     case Maptile::NONE: break;
2186     }
2187   return NULL;
2188 }
2189 
putStack(Stack * s)2190 bool GameMap::putStack(Stack *s)
2191 {
2192   Playerlist::getActiveplayer()->addStack(s);
2193   getStacks(s->getPos())->add(s);
2194   updateShips(s->getPos());
2195   updateTowers (s->getPos());
2196   return true;
2197 }
2198 
removeStack(Stack * s)2199 void GameMap::removeStack(Stack *s)
2200 {
2201   getStacks(s->getPos())->leaving(s);
2202   s->getOwner()->deleteStack(s);
2203 }
2204 
countArmyUnits(Vector<int> pos)2205 guint32 GameMap::countArmyUnits(Vector<int> pos)
2206 {
2207   if (getStacks(pos))
2208     return getStacks(pos)->countNumberOfArmies(Playerlist::getActiveplayer());
2209   return 0;
2210 }
2211 
getNearbyFriendlyStacks(Vector<int> pos,int dist)2212 std::vector<Stack*> GameMap::getNearbyFriendlyStacks(Vector<int> pos, int dist)
2213 {
2214   return getNearbyStacks(pos, dist, true);
2215 }
2216 
getNearbyEnemyStacks(Vector<int> pos,int dist)2217 std::vector<Stack*> GameMap::getNearbyEnemyStacks(Vector<int> pos, int dist)
2218 {
2219   return getNearbyStacks(pos, dist, false);
2220 }
2221 
getNearbyStacks(Vector<int> pos,int dist,bool friendly)2222 std::vector<Stack*> GameMap::getNearbyStacks(Vector<int> pos, int dist, bool friendly)
2223 {
2224   std::list<Vector<int> > points = getNearbyPoints(pos, dist);
2225   std::vector<Stack*> stks;
2226   std::vector<Stack *> stacks;
2227   for (std::list<Vector<int> >::iterator it = points.begin();
2228        it != points.end(); it++)
2229     {
2230       if (friendly)
2231         stks = GameMap::getFriendlyStacks(*it);
2232       else
2233         stks = GameMap::getEnemyStacks(*it);
2234       stacks.insert(std::end(stacks), std::begin(stks), std::end(stks));
2235     }
2236 
2237   return stacks;
2238 }
2239 
getNearbyPoints(Vector<int> pos,int dist)2240 std::list<Vector<int> > GameMap::getNearbyPoints(Vector<int> pos, int dist)
2241 {
2242   std::list<Vector<int> > points;
2243   guint32 i, j;
2244   guint32 d;
2245   guint32 max = dist;
2246   int x, y;
2247 
2248   points.push_back(pos);
2249 
2250   if (dist == -1)
2251     {
2252       if (getWidth() > getHeight())
2253         max = getWidth();
2254       else
2255         max = getHeight();
2256     }
2257   //d is the distance from Pos where our box starts
2258   //instead of a regular loop around a box of dist large, we're going to add
2259   //the nearer stacks first.
2260   for (d = 1; d <= max; d++)
2261     {
2262       for (i = 0; i < (d * 2) + 1; i++)
2263         {
2264           for (j = 0; j < (d * 2) + 1; j++)
2265             {
2266               if ((i == 0 || i == (d * 2)) ||
2267                   (j == 0 || j == (d * 2)))
2268                 {
2269                   x = pos.x + (i - d);
2270                   y = pos.y + (j - d);
2271 		  if (offmap(x, y))
2272 		    continue;
2273                   points.push_back(Vector<int>(x,y));
2274                 }
2275             }
2276         }
2277     }
2278 
2279   return points;
2280 }
2281 
checkCityAccessibility()2282 bool GameMap::checkCityAccessibility()
2283 {
2284   //check to see if all cities are accessible
2285   //check if all cities are accessible
2286   if (Citylist::getInstance()->size() <= 1)
2287     return true;
2288   Vector<int> pos = GameMap::getCenterOfMap();
2289   City *center = Citylist::getInstance()->getNearestCity(pos);
2290   Stack s(NULL, center->getPos());
2291   ArmyProto *basearmy = ArmyProto::createScout();
2292   Army *a = Army::createNonUniqueArmy(*basearmy);
2293   delete basearmy;
2294   s.push_back(a);
2295   PathCalculator pc(&s, true, 10, 10);
2296 
2297   for (auto it: *Citylist::getInstance())
2298     {
2299       if (center == it)
2300 	continue;
2301 
2302       int mp = pc.calculate(it->getPos());
2303       if (mp <= 0)
2304 	{
2305 	  printf("we made a map that has an inaccessible city (%d)\n", mp);
2306 	  printf("can't get from %s to %s\n", it->getName().c_str(), center->getName().c_str());
2307 	  return false;
2308 	}
2309     }
2310   return true;
2311 }
2312 
getCenterOfMap()2313 Vector<int> GameMap::getCenterOfMap()
2314 {
2315   return Vector<int>(GameMap::s_width/2, GameMap::s_height/2);
2316 }
2317 
calculateTilesPerOverviewMapTile(int width,int height)2318 int GameMap::calculateTilesPerOverviewMapTile(int width, int height)
2319 {
2320   if (width <= (int)MAP_SIZE_NORMAL_WIDTH &&
2321       height <= (int)MAP_SIZE_NORMAL_HEIGHT)
2322     return 1;
2323   //i want the map to fit into say, 300 pixels wide.
2324   //so we make sure the map fits into 100 pixels and then
2325   //multiply it later on with pixels per tile in overviewmap
2326   int w = width / 100;
2327   if (w <= 1)
2328     return 2;
2329   return w;
2330 }
2331 
calculateTilesPerOverviewMapTile()2332 int GameMap::calculateTilesPerOverviewMapTile()
2333 {
2334   return calculateTilesPerOverviewMapTile(GameMap::getWidth(), GameMap::getHeight());
2335 }
2336 
changeFootprintToSmallerCityset(Location * location,Maptile::Building building_type,guint32 old_tile_width)2337 void GameMap::changeFootprintToSmallerCityset(Location *location, Maptile::Building building_type, guint32 old_tile_width)
2338 {
2339   GameMap::getInstance()->clearBuilding(location->getPos(), (guint32)old_tile_width);
2340 
2341   GameMap::getInstance()->putBuilding (location, building_type);
2342 }
2343 
relocateLocation(Location * location,Maptile::Building building_type,guint32 tile_width)2344 void GameMap::relocateLocation(Location *location, Maptile::Building building_type, guint32 tile_width)
2345 {
2346   //look for a suitable place for this building
2347   //remove our buildingness so it can find where we are now.
2348   GameMap::getInstance()->removeBuilding(location);
2349   Vector<int> dest =
2350     GameMap::getInstance()->findNearestAreaForBuilding(building_type, location->getPos(), tile_width);
2351   GameMap::getInstance()->putBuilding (location, building_type);
2352   if (dest == Vector<int>(-1, -1))
2353     GameMap::getInstance()->removeLocation (location->getPos());
2354   else
2355     GameMap::getInstance()->moveBuilding (location->getPos(), dest, tile_width);
2356 }
2357 
getTileSize() const2358 guint32 GameMap::getTileSize() const
2359 {
2360   Tileset *ts = GameMap::getTileset();
2361   return ts->getTileSize();
2362 }
2363 
getUnscaledTileSize() const2364 guint32 GameMap::getUnscaledTileSize() const
2365 {
2366   Tileset *ts = GameMap::getTileset();
2367   return ts->getUnscaledTileSize();
2368 }
2369 
getTilesetId() const2370 guint32 GameMap::getTilesetId() const
2371 {
2372   if (GameMap::getTileset())
2373     return GameMap::getTileset()->getId();
2374   else
2375     return 0;
2376 }
2377 
getCitysetId() const2378 guint32 GameMap::getCitysetId() const
2379 {
2380   if (GameMap::getCityset())
2381     return GameMap::getCityset()->getId();
2382   else
2383     return 0;
2384 }
2385 
getShieldsetId() const2386 guint32 GameMap::getShieldsetId() const
2387 {
2388   return Shieldsetlist::getInstance()->getSetId(d_shieldset);
2389 }
2390 
getTilesetBaseName() const2391 Glib::ustring GameMap::getTilesetBaseName() const
2392 {
2393   return d_tileset;
2394 }
2395 
getCitysetBaseName() const2396 Glib::ustring GameMap::getCitysetBaseName() const
2397 {
2398   return d_cityset;
2399 }
2400 
getShieldsetBaseName() const2401 Glib::ustring GameMap::getShieldsetBaseName() const
2402 {
2403   return d_shieldset;
2404 }
2405 
eraseTiles(LwRectangle r)2406 bool GameMap::eraseTiles(LwRectangle r)
2407 {
2408   bool erased = false;
2409   for (int x = r.x; x < r.x + r.w; ++x)
2410     for (int y = r.y; y < r.y + r.h; ++y)
2411       {
2412 	if (offmap(x,y))
2413 	  continue;
2414         erased |= eraseTile(Vector<int>(x,y));
2415       }
2416   return erased;
2417 }
2418 
eraseTile(Vector<int> tile)2419 bool GameMap::eraseTile(Vector<int> tile)
2420 {
2421   bool erased = false;
2422   // first stack, it's above everything else
2423   while  (getStack(tile) != NULL)
2424     {
2425       Stack *s = getStack(tile);
2426       removeStack(s);
2427       erased = true;
2428     }
2429 
2430   // ... or a temple ...
2431   erased |= removeTemple(tile);
2432 
2433   // ... or a port ...
2434   erased |= removePort(tile);
2435 
2436   // ... or a ruin ...
2437   if (getRuin(tile) != NULL)
2438     {
2439       for (auto i: *Rewardlist::getInstance())
2440         {
2441           if (i->getType() == Reward::RUIN)
2442             {
2443               Reward_Ruin *rr = static_cast<Reward_Ruin*>(i);
2444               if (rr->getRuin()->getPos() == tile)
2445                 Rewardlist::getInstance()->remove(i);
2446             }
2447         }
2448     }
2449   erased |= removeRuin(tile);
2450 
2451   // ... or a road ...
2452   erased |= removeRoad(tile);
2453 
2454   // ... or a bridge...
2455   erased |= removeBridge(tile);
2456 
2457   // ... or a signpost ...
2458   erased |= removeSignpost(tile);
2459 
2460   // ... or a city
2461   erased |= removeCity(tile);
2462 
2463   // ... or a bag
2464   if (getTile(tile)->getBackpack()->size() > 0)
2465     {
2466       getTile(tile)->getBackpack()->removeAllFromBackpack();
2467       erased = true;
2468     }
2469 
2470   // ... or a stone
2471   erased |= removeStone(tile);
2472   return erased;
2473 }
2474 
getTileset()2475 Tileset* GameMap::getTileset()
2476 {
2477   if (s_tileset == 0)
2478     s_tileset = Tilesetlist::getInstance()->get(GameMap::getInstance()->getTilesetBaseName());
2479 
2480   return s_tileset;
2481 }
2482 
getCityset()2483 Cityset* GameMap::getCityset()
2484 {
2485   if (s_cityset == 0)
2486     s_cityset = Citysetlist::getInstance()->get(GameMap::getInstance()->getCitysetBaseName());
2487 
2488   return s_cityset;
2489 }
2490 
getShieldset()2491 Shieldset* GameMap::getShieldset()
2492 {
2493   if (s_shieldset == 0)
2494     s_shieldset = Shieldsetlist::getInstance()->get(GameMap::getInstance()->getShieldsetId());
2495 
2496   return s_shieldset;
2497 }
2498 
setTileset(Glib::ustring tileset)2499 void GameMap::setTileset(Glib::ustring tileset)
2500 {
2501   d_tileset = tileset;
2502   s_tileset = Tilesetlist::getInstance()->get(tileset);
2503 }
2504 
setCityset(Glib::ustring cityset)2505 void GameMap::setCityset(Glib::ustring cityset)
2506 {
2507   d_cityset = cityset;
2508   s_cityset = Citysetlist::getInstance()->get(cityset);
2509 }
2510 
setShieldset(Glib::ustring shieldset)2511 void GameMap::setShieldset(Glib::ustring shieldset)
2512 {
2513   d_shieldset = shieldset;
2514   s_shieldset = Shieldsetlist::getInstance()->get(shieldset);
2515 }
2516 
can_search(Stack * stack)2517 bool GameMap::can_search(Stack *stack)
2518 {
2519   /*
2520    * a note about searching.
2521    * ruins can be searched by stacks that have a hero, and when the
2522    * hero has moves left.  also the ruin must be unexplored.
2523    * temples can be searched by any stack, when the stack has
2524    * movement left.
2525    */
2526   if (!stack)
2527     return false;
2528   if (stack->getMoves() < 1)
2529     return false;
2530   bool temple_searchable = false;
2531   Temple *temple = GameMap::getTemple(stack->getPos());
2532   if (temple)
2533     temple_searchable = true;
2534   bool ruin_searchable = true;
2535   Ruin *ruin = GameMap::getRuin(stack->getPos());
2536   if (!ruin)
2537     ruin_searchable = false;
2538   else
2539     {
2540       if (ruin->isSearched() == true)
2541         ruin_searchable = false;
2542       if (ruin->isHidden() == true &&
2543           ruin->getOwner() != Playerlist::getActiveplayer())
2544         ruin_searchable = false;
2545       if (stack->hasHero() == false)
2546         ruin_searchable = false;
2547     }
2548   if (ruin_searchable || temple_searchable)
2549     return true;
2550   return false;
2551 }
2552 
can_plant_flag(Stack * stack)2553 bool GameMap::can_plant_flag(Stack *stack)
2554 {
2555   Player *player = Playerlist::getActiveplayer();
2556   if (stack->hasHero())
2557     {
2558       //does the hero have the player's standard?
2559       for (Stack::iterator it = stack->begin(); it != stack->end(); it++)
2560         {
2561           if ((*it)->isHero())
2562             {
2563               Hero *hero = dynamic_cast<Hero*>((*it));
2564               if (hero->getBackpack()->getPlantableItem(player))
2565                 {
2566                   //can't plant on city/ruin/temple/signpost
2567                   City *city = getCity(stack->getPos());
2568                   Temple *temple = getTemple(stack);
2569                   Ruin *ruin = getRuin(stack);
2570                   Signpost *sign = getSignpost(stack);
2571                   if (!city && !temple && !ruin && !sign)
2572                     {
2573                       MapBackpack *backpack;
2574                       Vector<int> pos = stack->getPos();
2575                       backpack = getInstance()->getTile(pos)->getBackpack();
2576                       bool standard_already_planted =
2577                         backpack->getFirstPlantedItem() != NULL;
2578                       //are there any other standards here?
2579                       if (standard_already_planted == false)
2580                         return true;
2581                     }
2582                 }
2583             }
2584         }
2585     }
2586   return false;
2587 }
2588 
burnBridge(Vector<int> pos)2589 bool GameMap::burnBridge(Vector<int> pos)
2590 {
2591   bool burned = false;
2592   Bridge *bridge = GameMap::getBridge(pos);
2593   if (bridge)
2594     {
2595       Bridge *other = Bridgelist::getInstance()->getOtherSide(bridge);
2596       Vector<int> src = bridge->getPos();
2597       GameMap::getInstance()->removeBridge(src);
2598       Vector<int> dest = Vector<int>(-1, -1);
2599       std::vector<Stack*> stacks;
2600       if (other)
2601         {
2602           dest = other->getPos();
2603           GameMap::getInstance()->removeBridge(dest);
2604           std::vector<Stack*> s = GameMap::getStacks(src)->getStacks();
2605           stacks.insert(std::end(stacks), std::begin(s), std::end(s));
2606         }
2607       std::vector<Stack*> s =
2608         GameMap::getFriendlyStacks(src, Playerlist::getActiveplayer());
2609       stacks.insert(std::end(stacks), std::begin(s), std::end(s));
2610       for (std::vector<Stack*>::iterator i = stacks.begin();
2611            i != stacks.end(); i++)
2612         {
2613           (*i)->setDefending(false);
2614           (*i)->setParked(false);
2615           (*i)->clearPath();
2616           (*i)->drainMovement();
2617         }
2618       std::list<Vector<int> > r =
2619         Bridgelist::getInstance()->getRoadEntryPoints(bridge);
2620       for (std::list<Vector<int> >::iterator i = r.begin(); i != r.end(); i++)
2621         {
2622           Road *rd = GameMap::getInstance()->getRoad(*i);
2623           if (rd)
2624             rd->setType(Roadlist::getInstance()->calculateType(rd->getPos()));
2625         }
2626       burned = true;
2627     }
2628   return burned;
2629 }
2630 
friendlyCitiesPresent()2631 bool GameMap::friendlyCitiesPresent()
2632 {
2633   return Citylist::getInstance()->countCities(Playerlist::getActiveplayer());
2634 }
2635 
enemyCitiesPresent()2636 bool GameMap::enemyCitiesPresent()
2637 {
2638   for (auto i: *Playerlist::getInstance())
2639     {
2640       if (i == Playerlist::getInstance()->getNeutral())
2641         continue;
2642       if (i == Playerlist::getActiveplayer())
2643         continue;
2644       if (i->isDead())
2645         continue;
2646       if (Citylist::getInstance()->countCities(i) > 0)
2647         return true;
2648     }
2649   return false;
2650 }
2651 
neutralCitiesPresent()2652 bool GameMap::neutralCitiesPresent()
2653 {
2654   return Citylist::getInstance()->countCities
2655     (Playerlist::getInstance()->getNeutral());
2656 }
2657 
addArmies(const ArmyProto * a,guint32 num_allies,Vector<int> pos)2658 void GameMap::addArmies(const ArmyProto *a, guint32 num_allies, Vector<int> pos)
2659 {
2660   for (unsigned int i = 0; i < num_allies; i++)
2661     {
2662       Army *army = new Army(*a, Playerlist::getActiveplayer());
2663       if (army)
2664         addArmy(pos, army);
2665     }
2666 }
2667 
2668 //we can't defend on cities, ruins, temples, ports, or water.
can_defend(Stack * stack)2669 bool GameMap::can_defend(Stack *stack)
2670 {
2671   Tile::Type type = getInstance()->getTile(stack->getPos())->getType();
2672   Maptile::Building building = getInstance()->getBuilding(stack->getPos());
2673   if (type == Tile::WATER && building == Maptile::NONE)
2674     return false;
2675   if (building == Maptile::CITY || building == Maptile::RUIN ||
2676       building == Maptile::TEMPLE || building == Maptile::PORT)
2677     return false;
2678   return true;
2679 }
2680 
checkBuildingTerrain(Maptile::Building b,bool land)2681 bool GameMap::checkBuildingTerrain(Maptile::Building b, bool land)
2682 {
2683   bool found = false;
2684   for (int i = 0; i < s_width; i++)
2685     {
2686       for (int j = 0; j < s_height; j++)
2687         {
2688           Vector<int> tile = Vector<int>(i, j);
2689           if (GameMap::getInstance()->getBuilding(tile) == b)
2690             {
2691               if (land)
2692                 {
2693                   if (GameMap::getInstance()->getTerrainType(tile) != Tile::WATER)
2694                     found = true;
2695                 }
2696               else
2697                 {
2698                   if (GameMap::getInstance()->getTerrainType(tile) == Tile::WATER)
2699                     found = true;
2700                 }
2701               if (found)
2702                 break;
2703             }
2704         }
2705     }
2706 
2707   return found;
2708 }
2709 
getCity(Movable * m)2710 City* GameMap::getCity(Movable *m)
2711 {
2712   return getCity(m->getPos());
2713 }
2714 
getRuin(Movable * m)2715 Ruin* GameMap::getRuin(Movable *m)
2716 {
2717   return getRuin(m->getPos());
2718 }
2719 
getTemple(Movable * m)2720 Temple* GameMap::getTemple(Movable *m)
2721 {
2722   return getTemple(m->getPos());
2723 }
2724 
getSignpost(Movable * m)2725 Signpost* GameMap::getSignpost(Movable *m)
2726 {
2727   return getSignpost(m->getPos());
2728 }
2729 
countBags()2730 guint32 GameMap::countBags ()
2731 {
2732   guint32 count = 0;
2733   for (int i = 0; i < s_width; i++)
2734     for (int j = 0; j < s_height; j++)
2735       {
2736         MapBackpack *bag = getBackpack (Vector<int>(i, j));
2737         if (bag && bag->empty () == false)
2738           count++;
2739       }
2740   return count;
2741 }
2742