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