~ubuntu-branches/ubuntu/saucy/lordsawar/saucy

« back to all changes in this revision

Viewing changes to src/GameMap.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Barry deFreese, Barry deFreese
  • Date: 2008-12-20 13:52:12 UTC
  • mfrom: (1.1.6 upstream) (5.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20081220135212-noeb2w3y98ebo7o9
Tags: 0.1.4-1
[ Barry deFreese ]
* New upstream release.
* Move 0.0.8-2.1 changelog entry to correct point in changelog.
* Make lordsawar-data suggest lordsawar.
* Update my e-mail address.
* Add build-depends on intltool, uuid-dev, and libboost-dev.
* Don't install locales since there are no translations currently.
* Add simple man page for new lordsawar-pbm binary.
* Drop gcc4.3 patches as they have been fixed upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
// Copyright (C) 2003, 2005, 2006 Andrea Paternesi
4
4
// Copyright (C) 2006, 2007, 2008 Ben Asselstine
5
5
// Copyright (C) 2007 Ole Laursen
 
6
// Copyright (C) 2008 Janek Kozicki
6
7
//
7
8
//  This program is free software; you can redistribute it and/or modify
8
9
//  it under the terms of the GNU General Public License as published by
40
41
#include "tilesetlist.h"
41
42
#include "shieldsetlist.h"
42
43
#include "citysetlist.h"
 
44
#include "GraphicsCache.h"
 
45
#include "MapBackpack.h"
43
46
 
 
47
std::string GameMap::d_tag = "map";
 
48
std::string GameMap::d_itemstack_tag = "itemstack";
44
49
using namespace std;
45
50
 
46
51
//#include <iostream>
103
108
 
104
109
}
105
110
 
 
111
void GameMap::processStyles(std::string styles, int chars_per_style)
 
112
{
 
113
  int c = chars_per_style;
 
114
    int offset = 0;
 
115
    for (int j = 0; j < s_height; j++)
 
116
    {
 
117
        // remove newline and carriage return lines
 
118
        char test = styles[j*s_width*c + offset];
 
119
        while (test == '\n' || test == '\r')
 
120
        {
 
121
            offset++;
 
122
            test = styles[j*s_width*c + offset];
 
123
        }
 
124
 
 
125
        for (int i = 0; i < s_width; i++)
 
126
        {
 
127
            char hexstr[15];
 
128
            //due to the circumstances, styles is a long stream of
 
129
            //hex digit pairs, so read it character for character
 
130
            hexstr[0] = '0';
 
131
            hexstr[1] = 'x';
 
132
            memcpy (&hexstr[2], &styles[j*s_width*c + (i * c) + offset], c);
 
133
            hexstr[2 + c + 1 - 1] = '\0';
 
134
 
 
135
            unsigned long int val = 0;
 
136
            char *end = NULL;
 
137
            val = strtoul (hexstr, &end, 16);
 
138
            Uint32 id = (Uint32) val;
 
139
            TileStyle *style = d_tileSet->getTileStyle(id);
 
140
            if (!style)
 
141
              style = d_tileSet->getTileStyle(0);
 
142
            d_map[j*s_width + i]->setTileStyle(style);
 
143
        }
 
144
    }
 
145
}
 
146
    
 
147
int GameMap::determineCharsPerStyle(std::string styles)
 
148
{
 
149
  return styles.length() / (s_width * s_height);
 
150
}
 
151
 
106
152
GameMap::GameMap(XML_Helper* helper)
107
153
{
108
154
    std::string types;
150
196
        }
151
197
    }
152
198
 
153
 
    offset = 0;
154
 
    for (int j = 0; j < s_height; j++)
155
 
    {
156
 
        // remove newline and carriage return lines
157
 
        char test = styles[j*s_width*2 + offset];
158
 
        while (test == '\n' || test == '\r')
159
 
        {
160
 
            offset++;
161
 
            test = styles[j*s_width*2 + offset];
162
 
        }
163
 
 
164
 
        for (int i = 0; i < s_width; i++)
165
 
        {
166
 
            char hexstr[5];
167
 
            //due to the circumstances, styles is a long stream of
168
 
            //hex digit pairs, so read it character for character
169
 
            hexstr[0] = '0';
170
 
            hexstr[1] = 'x';
171
 
            hexstr[2] = styles[j*s_width*2 + (i * 2) + offset];  
172
 
            hexstr[3] = styles[j*s_width*2 + (i * 2) + offset + 1];
173
 
            hexstr[4] = '\0';
174
 
 
175
 
            unsigned long int val = 0;
176
 
            char *end = NULL;
177
 
            val = strtoul (hexstr, &end, 16);
178
 
            Uint32 id = (Uint32) val;
179
 
            TileStyle *style = d_tileSet->getTileStyle(id);
180
 
            d_map[j*s_width + i]->setTileStyle(style);
181
 
        }
182
 
    }
 
199
    int chars_per_style = determineCharsPerStyle(styles);
 
200
    processStyles(styles, chars_per_style);
183
201
 
184
202
    //add some callbacks for item loading
185
 
    helper->registerTag("itemstack", sigc::mem_fun(this, &GameMap::loadItems));
186
 
    helper->registerTag("item", sigc::mem_fun(this, &GameMap::loadItems));
 
203
    helper->registerTag(GameMap::d_itemstack_tag, 
 
204
                        sigc::mem_fun(this, &GameMap::loadItems));
 
205
    helper->registerTag(Item::d_tag, sigc::mem_fun(this, &GameMap::loadItems));
187
206
}
188
207
 
189
208
 
215
234
    //the sizes should definitely match, else we have a problem here
216
235
    if (width != s_width || height != s_height)
217
236
    {
218
 
        std::cerr <<_("Error in GameMap::fillMap: sizes don't match!! Exiting.\n");
 
237
        std::cerr << "Error in GameMap::fillMap: sizes don't match!! Exiting.\n";
219
238
        exit(-1);
220
239
    }
221
240
 
261
280
 
262
281
    std::stringstream styles;
263
282
    styles <<endl;
 
283
            
 
284
    int largest_style_id = d_tileSet->getLargestTileStyleId();
264
285
    for (int i = 0; i < s_height; i++)
265
286
    {
266
287
        for (int j = 0; j < s_width; j++)
267
288
          {
268
289
            char *hexstr = NULL;
 
290
            int byteswritten = -1;
269
291
            TileStyle *style = getTile(j, i)->getTileStyle();
270
 
            asprintf (&hexstr, "%02x", style->getId());
271
 
            styles << hexstr;
272
 
            free (hexstr);
 
292
            if (largest_style_id < 256)
 
293
              byteswritten = asprintf (&hexstr, "%02x", style->getId());
 
294
            else if (largest_style_id < 4096)
 
295
              byteswritten = asprintf (&hexstr, "%03x", style->getId());
 
296
            else if (largest_style_id < 65536)
 
297
              byteswritten = asprintf (&hexstr, "%04x", style->getId());
 
298
            if (hexstr && byteswritten > -1)
 
299
              {
 
300
                styles << hexstr;
 
301
                free (hexstr);
 
302
              }
273
303
          }
274
304
        styles <<endl;
275
305
    }
276
306
 
277
307
 
278
 
    retval &= helper->openTag("map");
 
308
    retval &= helper->openTag(GameMap::d_tag);
279
309
    retval &= helper->saveData("width", s_width);
280
310
    retval &= helper->saveData("height", s_height);
281
311
    retval &= helper->saveData("tileset", d_tileSet->getSubDir());
286
316
 
287
317
    // last, save all items lying around somewhere
288
318
    for (int i = 0; i < s_width; i++)
289
 
        for (int j = 0; j < s_height; j++)
290
 
            if (!getTile(i,j)->getItems().empty())
291
 
            {
292
 
                retval &= helper->openTag("itemstack");
293
 
                retval &= helper->saveData("x", i);
294
 
                retval &= helper->saveData("y", j);
295
 
                
296
 
                std::list<Item*> items = getTile(i,j)->getItems();
297
 
                
298
 
                std::list<Item*>::const_iterator it;
299
 
                for (it = items.begin(); it != items.end(); it++)
300
 
                    (*it)->save(helper);
301
 
 
302
 
                retval &= helper->closeTag();
303
 
            }
 
319
      for (int j = 0; j < s_height; j++)
 
320
        if (!getTile(i,j)->getBackpack()->empty())
 
321
          retval &= getTile(i,j)->getBackpack()->save(helper);
304
322
     
305
323
    retval &= helper->closeTag();
306
324
    return retval;
311
329
    static int x = 0;
312
330
    static int y = 0;
313
331
    
314
 
    if (tag == "itemstack")
 
332
    if (tag == GameMap::d_itemstack_tag)
315
333
    {
316
334
        helper->getData(x, "x");
317
335
        helper->getData(y, "y");
318
336
    }
319
337
 
320
 
    if (tag == "item")
 
338
    if (tag == Item::d_tag)
321
339
    {
322
340
        Item* item = new Item(helper);
323
 
        getTile(x, y)->addItem(item);
 
341
        getTile(x, y)->getBackpack()->addToBackpack(item);
324
342
    }
325
343
 
326
344
    return true;
330
348
{
331
349
    delete d_map[y*s_width + x];
332
350
    d_map[y*s_width + x] = tile;
 
351
    applyTileStyle (y, x);
333
352
}
334
353
 
335
354
Maptile* GameMap::getTile(int x, int y) const
413
432
                    continue;
414
433
                  if (!land && getTile(x, y)->getType() != Tile::WATER)
415
434
                    continue;
 
435
                  if (land && getTile(x, y)->getType() == Tile::VOID)
 
436
                    continue;
416
437
                  if (land && getTile(x, y)->getType() == Tile::MOUNTAIN &&
417
 
                      (a->getStat(Army::MOVE_BONUS) & Tile::MOUNTAIN) == 
418
 
                      Tile::MOUNTAIN)
 
438
                      (a->getStat(Army::MOVE_BONUS) & Tile::MOUNTAIN) == 0)
419
439
                    continue;
420
440
                  //is there somebody else's stack here?
421
441
                  s = Stacklist::getObjectAt(x, y);
447
467
    }
448
468
 
449
469
  if (added_army)
450
 
    return s;
 
470
    {
 
471
      s->setDefending(false);
 
472
      s->setParked(false);
 
473
      if (s->countGroupedArmies() == 0)
 
474
        s->ungroup();
 
475
      return s;
 
476
    }
451
477
  else
452
478
    return NULL;
453
479
}
525
551
      if (from->getMaptileType() == Tile::MOUNTAIN &&
526
552
          Roadlist::getInstance()->getObjectAt(x, y) == NULL)
527
553
        return true;
 
554
 
 
555
      if (from->getMaptileType() == Tile::VOID)
 
556
        return true;
 
557
      if (to->getMaptileType() == Tile::VOID)
 
558
        return true;
528
559
    }
529
560
 return false;
530
561
}
579
610
      {
580
611
        for (int y = 0; y < getHeight(); y++)
581
612
          {
582
 
            std::list<Item*> items = getTile(x, y)->getItems();
583
 
            for (std::list<Item*>::iterator it = items.begin(); 
584
 
                 it != items.end(); it++)
585
 
              {
586
 
                if ((*it)->isPlantable() && (*it)->getPlantableOwner() == p &&
587
 
                    (*it)->getPlanted() == true)
588
 
                  {
589
 
                    pos.x = x;
590
 
                    pos.y = y;
591
 
                    found = true;
592
 
                    break;
593
 
                  }
594
 
              }
595
 
            if (found)
596
 
              break;
 
613
            MapBackpack *backpack = getTile(x, y)->getBackpack();
 
614
            found = backpack->getPlantedItem(p) != NULL;
 
615
            if (found)
 
616
              {
 
617
                pos.x = x;
 
618
                pos.y = y;
 
619
                break;
 
620
              }
597
621
          }
598
622
      }
599
623
  return pos;
612
636
          continue;
613
637
        if ((j+l) >= s_width || (j+l) < 0)
614
638
          continue;
615
 
        box[k+1][l+1] = (getTile(j+l, i+k)->getType() == mtile->getType());
 
639
        box[k+1][l+1] = are_those_tiles_similar(getTile(j+l, i+k)->getMaptileType(), mtile->getMaptileType(), false);
616
640
      }
617
641
  if (box[0][0] && box[0][1] && box[0][2] &&
618
642
      box[1][0] && box[1][1] && box[1][2] &&
763
787
    }
764
788
}
765
789
 
 
790
bool GameMap::are_those_tiles_similar(Tile::Type outer_tile,Tile::Type inner_tile, bool checking_loneliness)
 
791
{
 
792
    if(checking_loneliness || inner_tile == Tile::HILLS)
 
793
    {
 
794
        if( (outer_tile == Tile::MOUNTAIN && inner_tile == Tile::HILLS) ||
 
795
            (inner_tile == Tile::MOUNTAIN && outer_tile == Tile::HILLS))
 
796
            // Mountains and hills are similar, MapGenerator::surroundMountains()
 
797
            // makes sure that mountains are surrounded by hills. So a hill tile
 
798
            // with only a mountain neighbour is not a lone tile
 
799
            //
 
800
            // There never should be a lone mountain in grass (not surrounded by hills).
 
801
            // Mountain surrounded by hills is perfectly correct.
 
802
            return true;
 
803
        return outer_tile == inner_tile;
 
804
    } 
 
805
    else 
 
806
    { // to pick correct tile picture for a mountain we treat hills as a tile
 
807
      // different than mountain.
 
808
        return outer_tile == inner_tile;
 
809
    }
 
810
}
 
811
 
766
812
int GameMap::tile_is_connected_to_other_like_tiles (Tile::Type tile, int i, int j)
767
813
{
768
814
  int box[3][3];
774
820
          continue;
775
821
        if ((j+l) >= s_width || (j+l) < 0)
776
822
          continue;
777
 
        box[k+1][l+1] = (getTile(j+l, i+k)->getMaptileType() == tile);
 
823
        box[k+1][l+1] = are_those_tiles_similar(getTile(j+l, i+k)->getMaptileType(), tile, true);
778
824
      }
779
825
  if (box[0][0] && box[0][1] && box[1][0] && box[1][1])
780
826
    return 1;
822
868
 
823
869
  if (smooth_terrain)
824
870
    {
825
 
      demote_lone_tile(0, 0, s_height, s_width, Tile::FOREST, Tile::GRASS);
826
 
      demote_lone_tile(0, 0, s_height, s_width, Tile::MOUNTAIN, Tile::HILLS);
827
 
      demote_lone_tile(0, 0, s_height, s_width, Tile::HILLS, Tile::GRASS);
828
 
      demote_lone_tile(0, 0, s_height, s_width, Tile::WATER, Tile::SWAMP);
 
871
      demote_lone_tile(minx, miny, maxx, maxy, Tile::FOREST, Tile::GRASS);
 
872
      demote_lone_tile(minx, miny, maxx, maxy, Tile::MOUNTAIN, Tile::HILLS);
 
873
      demote_lone_tile(minx, miny, maxx, maxy, Tile::HILLS, Tile::GRASS);
 
874
      demote_lone_tile(minx, miny, maxx, maxy, Tile::WATER, Tile::SWAMP);
 
875
      surroundMountains(minx, miny, maxx, maxy);
829
876
    }
830
877
 
831
878
  for (int i = minx; i < maxx; i++)
836
883
            continue;
837
884
          if (j < 0 || j >= s_width)
838
885
            continue;
839
 
          Maptile *mtile = getTile(j, i);
840
 
          Tileset *tileset = getTileset();
841
 
          TileStyle *style = calculatePreferredStyle(i, j);
842
 
          if (!style)
843
 
            style = tileset->getRandomTileStyle(mtile->getType(), 
844
 
                                                TileStyle::LONE);
845
 
          if (!style)
846
 
            style = tileset->getRandomTileStyle(mtile->getType(), 
847
 
                                                TileStyle::INNERMIDDLECENTER);
848
 
          mtile->setTileStyle(style);
 
886
          applyTileStyle(i, j);
849
887
        }
850
888
    }
851
889
  close_circles(minx, miny, maxx, maxy);
858
896
    for (int i = 0; i < s_width; i++)
859
897
      {
860
898
        if (d_map[j*s_width + i])
861
 
          if (d_map[j*s_width + i]->getItems().empty() == false)
 
899
          if (d_map[j*s_width + i]->getBackpack()->empty() == false)
862
900
            items.push_back(Vector<int>(i, j));
863
901
 
864
902
      }
865
903
  return items;
866
904
}
 
905
 
 
906
#define offmap(bx,by) (by<0)||(by>=s_height)||(bx<0)||(bx>=s_width)
 
907
void GameMap::surroundMountains(int minx, int miny, int maxx, int maxy)
 
908
{
 
909
  for(int j = miny; j < maxy; j++)
 
910
    for(int i = minx; i < maxx; i++)
 
911
      {
 
912
        if (offmap(j, i))
 
913
          continue;
 
914
        if(getTile(j, i)->getMaptileType() == Tile::MOUNTAIN)
 
915
          for(int J = -1; J <= +1; ++J)
 
916
            for(int I = -1; I <= +1; ++I)
 
917
              if((!(offmap(j+J,i+I))) &&
 
918
                 (getTile((j+J),(i+I))->getMaptileType() != Tile::MOUNTAIN))
 
919
                {
 
920
                  if(getTile((j+J), (i+I))->getMaptileType() != Tile::WATER)
 
921
                    setTile(j+J, i+I, 
 
922
                            new Maptile (d_tileSet, j+J, i+I, 
 
923
                                         d_tileSet->getIndex(Tile::HILLS), NULL));
 
924
                  else 
 
925
                    // water has priority here, there was some work done to conenct bodies of water
 
926
                    // so don't break those connections.
 
927
                    setTile(j, i, 
 
928
                            new Maptile (d_tileSet, j, i, 
 
929
                                         d_tileSet->getIndex(Tile::HILLS), NULL));
 
930
                }
 
931
      }
 
932
}
 
933
 
 
934
void GameMap::applyTileStyle (int i, int j)
 
935
{
 
936
  Maptile *mtile = getTile(j, i);
 
937
  Tileset *tileset = getTileset();
 
938
  TileStyle *style = calculatePreferredStyle(i, j);
 
939
  if (!style)
 
940
    style = tileset->getRandomTileStyle(mtile->getType(), 
 
941
                                        TileStyle::LONE);
 
942
  if (!style)
 
943
    style = tileset->getRandomTileStyle(mtile->getType(), 
 
944
                                        TileStyle::INNERMIDDLECENTER);
 
945
  if (!style)
 
946
    printf ("applying null tile style at %d,%d for tile of kind %d\n", i, j,
 
947
            mtile->getMaptileType());
 
948
  mtile->setTileStyle(style);
 
949
}
 
950
 
 
951
Vector<int> GameMap::findNearestObjectInDir(Vector<int> pos, Vector<int> dir)
 
952
{
 
953
  std::vector<Vector<int> > objects;
 
954
  Road *road = Roadlist::getInstance()->getNearestObjectInDir(pos, dir);
 
955
  if (road)
 
956
    objects.push_back(road->getPos());
 
957
  Bridge *bridge = Bridgelist::getInstance()->getNearestObjectInDir(pos, dir);
 
958
  if (bridge)
 
959
    objects.push_back(bridge->getPos());
 
960
  City *city = Citylist::getInstance()->getNearestObjectInDir(pos, dir);
 
961
  if (city)
 
962
    objects.push_back(city->getPos());
 
963
  Temple *temple = Templelist::getInstance()->getNearestObjectInDir(pos, dir);
 
964
  if (temple)
 
965
    objects.push_back(temple->getPos());
 
966
  Ruin *ruin = Ruinlist::getInstance()->getNearestObjectInDir(pos, dir);
 
967
  if (ruin && ruin->isHidden() == false)
 
968
    objects.push_back(ruin->getPos());
 
969
  if (objects.size() == 0)
 
970
    return Vector<int>(-1,-1);
 
971
 
 
972
  int min_distance = -1;
 
973
  Vector<int> closest = Vector<int>(-1,-1);
 
974
  for (unsigned int i = 0; i < objects.size(); i++)
 
975
    {
 
976
      int distance = dist(pos, objects[i]);
 
977
      if (min_distance == -1 || distance < min_distance)
 
978
        {
 
979
          min_distance = distance;
 
980
          closest = objects[i];
 
981
        }
 
982
    }
 
983
  return closest;
 
984
}
 
985
 
 
986
Vector<int> GameMap::findNearestObjectToTheNorth(Vector<int> pos)
 
987
{
 
988
  Vector<int> dir = Vector<int>(0, -1);
 
989
  return findNearestObjectInDir(pos, dir);
 
990
}
 
991
 
 
992
Vector<int> GameMap::findNearestObjectToTheSouth(Vector<int> pos)
 
993
{
 
994
  Vector<int> dir = Vector<int>(0, 1);
 
995
  return findNearestObjectInDir(pos, dir);
 
996
}
 
997
 
 
998
Vector<int> GameMap::findNearestObjectToTheEast(Vector<int> pos)
 
999
{
 
1000
  Vector<int> dir = Vector<int>(1, 0);
 
1001
  return findNearestObjectInDir(pos, dir);
 
1002
}
 
1003
 
 
1004
Vector<int> GameMap::findNearestObjectToTheWest(Vector<int> pos)
 
1005
{
 
1006
  Vector<int> dir = Vector<int>(-1, 0);
 
1007
  return findNearestObjectInDir(pos, dir);
 
1008
}