HOG2
Map.cpp
Go to the documentation of this file.
1 /*
2  * $Id: map.cpp
3  * hog2
4  *
5  * Created by Nathan Sturtevant on 03/07/07.
6  * Modified by Nathan Sturtevant on 02/29/20.
7  *
8  * This file is part of HOG2. See https://github.com/nathansttt/hog2 for licensing information.
9  *
10  */
11 
12 #include <stack>
13 #include "Map.h"
14 #include "GLUtil.h"
15 #include <cstdlib>
16 #include <cstring>
17 #include "BitMap.h"
18 
19 GLuint wall = -1;
20 
21 using namespace std;
22 
23 static const bool verbose = false;
24 
26 {
27  if (wall == -1)
28  {
29  BitMapPic p("/Users/nathanst/hog2/textures/u.bmp");
30  p.Save("/Users/nathanst/hog2/textures/out.bmp");
31  // Use OpenGL ES to generate a name for the texture.
32  glGenTextures(1, &wall);
33  // Bind the texture name.
34  glBindTexture(GL_TEXTURE_2D, wall);
35  // Set the texture parameters to use a minifying filter and a linear filer (weighted average)
36 
37  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
38  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
39  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
40  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
41 
42 // if (p.BytesReversed())
43  {
44  // Specify a 2D texture image, providing the a pointer to the image data in memory
45  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, p.GetWidth(), p.GetHeight(), 0, GL_BGRA, GL_UNSIGNED_BYTE, p.GetBytes());
46  }
47 // else {
48 // // Specify a 2D texture image, providing the a pointer to the image data in memory
49 // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, p.GetWidth(), p.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, p.GetBytes());
50 // }
51  }
52 }
53 
62 {
63  corners[0] = corners[1] = corners[2] = 0;
64  type = kGround;
65  node = -1;
66 }
67 
76 :tile1(), tile2(), split(kNoSplit)
77 { }
78 
84 Map::Map(long _width, long _height)
85 :width(_width), height(_height)
86 {
87  mapType = kOctile;
88  tileSet = kFall;
89  map_name[0] = 0;
90  sizeMultiplier = 1;
91  land = new Tile *[width];
92  // for (int x = 0; x < 8; x++)
93  // g[x] = 0;
94  for (int x = 0; x < width; x++) land[x] = new Tile [height];
95  drawLand = true;
96  dList = 0;
97  updated = true;
98  revision = 0;
99  // numAbstractions = 1;
100  // pathgraph = 0;
101 }
102 
109 {
110  mapType = m->mapType;
111  tileSet = m->tileSet;
112  strncpy(map_name, m->map_name, 128);
114  width = m->width;
115  height = m->height;
116 
117  land = new Tile *[width];
118  for (int x = 0; x < width; x++) land[x] = new Tile [height];
119 
120  drawLand = m->drawLand;
121  dList = 0;
122  updated = true;
123  revision = m->revision;
124 
125  for (int x = 0; x < width; x++)
126  for (int y = 0; y < height; y++)
127  land[x][y] = m->land[x][y];
128 }
129 
135 Map::Map(const char *filename)
136 {
137  sizeMultiplier = 1;
138  land = 0;
139  Load(filename);
140  tileSet = kFall;
141 }
142 
148 Map::Map(FILE *f)
149 {
150  sizeMultiplier = 1;
151  map_name[0] = 0;
152  land = 0;
153  Load(f);
154  tileSet = kFall;
155 }
156 
162 Map::Map(std::istringstream &/*data*/)
163 {
164  sizeMultiplier = 1;
165  dList = 0;
166  tileSet = kFall;
167 }
168 
170 {
171  for (int x = 0; x < width; x++)
172  delete [] land[x];
173  delete [] land;
174  land = 0;
175 }
176 
177 void Map::Scale(long newWidth, long newHeight)
178 {
179  Tile **newLand;
180  newLand = new Tile *[newWidth];
181  for (int x = 0; x < newWidth; x++)
182  {
183  newLand[x] = new Tile [newHeight];
184  for (int y = 0; y < newHeight; y++)
185  {
186  newLand[x][y] = land[(x*width)/newWidth][(y*height)/newHeight];
187 
188  if (((y*height)/newHeight > 0) && (AdjacentEdges((x*width)/newWidth, (y*height)/newHeight, kTopEdge)))
189  { // make sure top edge is still adjacent
190  newLand[x][y].tile1.corners[0] = newLand[x][y-1].tile1.corners[1];
191  // this won't work with splits...
192  newLand[x][y].tile2.corners[0] = newLand[x][y-1].tile1.corners[2];
193  }
194  if (((x*width)/newWidth > 0) && (AdjacentEdges((x*width)/newWidth, (y*height)/newHeight, kLeftEdge)))
195  { // make sure left edge is still adjacent
196  newLand[x][y].tile1.corners[0] = newLand[x-1][y].tile2.corners[0];
197  // this won't work with splits...
198  newLand[x][y].tile1.corners[1] = newLand[x-1][y].tile1.corners[2];
199  }
200  }
201  }
202  for (int x = 0; x < width; x++) delete [] land[x];
203  delete [] land;
204  land = newLand;
205  width = newWidth;
206  height = newHeight;
207  revision++;
208  updated = true;
209  map_name[0] = 0;
210 }
211 
212 void Map::Trim()
213 {
214  int MinX = width-1, MinY = height-1, MaxX = 0, MaxY = 0;
215  for (int x = 0; x < width; x++)
216  {
217  for (int y = 0; y < height; y++)
218  {
219  if (GetTerrainType(x, y) != kOutOfBounds)
220  {
221  MinX = min(MinX, x);
222  MaxX = max(MaxX, x);
223  MinY = min(MinY, y);
224  MaxY = max(MaxY, y);
225  }
226  }
227  }
228 
229  int newWidth = MaxX-MinX+1;
230  int newHeight = MaxY-MinY+1;
231  Tile **newLand;
232  newLand = new Tile *[newWidth];
233  for (int x = 0; x < newWidth; x++)
234  {
235  newLand[x] = new Tile [newHeight];
236  for (int y = 0; y < newHeight; y++)
237  {
238  newLand[x][y] = land[x+MinX][y+MinY];
239  }
240  }
241  for (int x = 0; x < width; x++) delete [] land[x];
242  delete [] land;
243  land = newLand;
244  width = newWidth;
245  height = newHeight;
246  revision++;
247  updated = true;
248  map_name[0] = 0;
249 }
250 
251 
257 void Map::Load(const char *filename)
258 {
259  if (land)
260  {
261  for (int x = 0; x < width; x++)
262  delete [] land[x];
263  delete [] land;
264  land = 0;
265  }
266  revision++;
267  FILE *f = fopen(filename, "r");
268  if (f)
269  {
270  Load(f);
271  fclose(f);
272  strncpy(map_name, filename, 128);
273  }
274  else {
275  printf("Error! Can't open file %s\n", filename);
276  width = height = 64;
277  land = new Tile *[width];
278  // for (int x = 0; x < 8; x++)
279  // g[x] = 0;
280  for (int x = 0; x < width; x++)
281  land[x] = new Tile [height];
282  drawLand = true;
283  dList = 0;
284  updated = true;
285  map_name[0] = 0;
286  }
287 }
288 
292 void Map::Load(FILE *f)
293 {
294  if (land)
295  {
296  for (int x = 0; x < width; x++)
297  delete [] land[x];
298  delete [] land;
299  land = 0;
300  }
301 
302  char format[32];
303  // ADD ERROR HANDLING HERE
304  int num = fscanf(f, "type %s\nheight %d\nwidth %d\nmap\n", format, &height, &width);
305  // printf("got height %d, width %d\n", height, width);
306  if (num == 3)
307  {
308  if (strcmp(format, "octile") == 0)
309  loadOctile(f, height, width);
310  else if (strcmp(format, "octile-corner") == 0)
312  else if (strcmp(format, "raw") == 0)
313  loadRaw(f, height, width);
314  return;
315  }
316  if (tryLoadRollingStone(f))
317  {
318  return;
319  }
320  if (tryDragonAge(f))
321  {
322  //Trim();
323  return;
324  }
325 
326  {
327  printf("Unknown map type; aborting load!\n");
328  width = height = 64;
329  land = new Tile *[width];
330  // for (int x = 0; x < 8; x++)
331  // g[x] = 0;
332  for (int x = 0; x < width; x++) land[x] = new Tile [height];
333  drawLand = true;
334  dList = 0;
335  updated = true;
336  map_name[0] = 0;
337  }
338 }
339 
340 void Map::loadRaw(FILE *f, int high, int wide)
341 {
342  mapType = kRaw;
343  height = high;
344  width = wide;
345  land = new Tile *[wide];
346  for (int x = 0; x < wide; x++)
347  land[x] = new Tile [high];
348  drawLand = true;
349  dList = 0;
350  updated = true;
351  for (int x = 0; x < wide; x++)
352  {
353  fread(&land[x][0], sizeof(Tile), wide, f);
354  for (int y = 0; y < high; y++)
355  {
356  land[x][y].tile1.node = kNoGraphNode;
357  land[x][y].tile2.node = kNoGraphNode;
358  }
359  }
360 }
361 
362 void Map::loadOctile(FILE *f, int high, int wide)
363 {
364  mapType = kOctile;
365  height = high*sizeMultiplier;
366  width = wide*sizeMultiplier;
367  land = new Tile *[wide*sizeMultiplier];
368  for (int x = 0; x < wide*sizeMultiplier; x++) land[x] = new Tile [high*sizeMultiplier];
369  drawLand = true;
370  dList = 0;
371  updated = true;
372  for (int y = 0; y < high; y++)
373  {
374  for (int x = 0; x < wide; x++)
375  {
376  char what;
377  fscanf(f, "%c", &what);
378  switch (toupper(what))
379  {
380  case '@':
381  case 'O':
382  for (int r = 0; r < sizeMultiplier; r++)
383  for (int s = 0; s < sizeMultiplier; s++)
385  kOutOfBounds); break;
386  case 'S':
387  for (int r = 0; r < sizeMultiplier; r++)
388  for (int s = 0; s < sizeMultiplier; s++)
390  kSwamp); break;
391  case 'W':
392  for (int r = 0; r < sizeMultiplier; r++)
393  for (int s = 0; s < sizeMultiplier; s++)
395  kWater); break;
396  case 'T':
397  for (int r = 0; r < sizeMultiplier; r++)
398  for (int s = 0; s < sizeMultiplier; s++)
400  kTrees); break;
401  case 'G':
402  for (int r = 0; r < sizeMultiplier; r++)
403  for (int s = 0; s < sizeMultiplier; s++)
405  kGrass); break;
406  case 'B':
407  for (int r = 0; r < sizeMultiplier; r++)
408  for (int s = 0; s < sizeMultiplier; s++)
410  kBlight); break;
411  default:
412  for (int r = 0; r < sizeMultiplier; r++)
413  for (int s = 0; s < sizeMultiplier; s++)
415  kGround); break;
416  }
417  for (int r = 0; r < sizeMultiplier; r++)
418  for (int s = 0; s < sizeMultiplier; s++)
419  {
422  }
423  }
424  fscanf(f, "\n");
425  }
426 }
427 
428 void Map::loadOctileCorner(FILE *f, int high, int wide)
429 {
431  width--;
432  height--;
433  land = new Tile *[width];
434  for (int x = 0; x < width; x++) land[x] = new Tile [height];
435  drawLand = true;
436  dList = 0;
437  updated = true;
438  for (int y = 0; y < high; y++)
439  {
440  for (int x = 0; x < wide; x++)
441  {
442  int h;
443  char hc;
444  fscanf(f, "%c", &hc);
445  h = hc-'0'-2;
446  if ((x > 0) && (y < high-1))
447  SetCornerHeight(x-1, y, kTopRight, h);
448  if ((x < wide-1) && (y > 0))
449  SetCornerHeight(x, y-1, kBottomLeft, h);
450  if ((x > 0) && (y > 0))
451  SetCornerHeight(x-1, y-1, kBottomRight, h);
452  if ((x < wide-1) && (y < high-1))
453  SetCornerHeight(x, y, kTopLeft, h);
454  }
455  fscanf(f, "\n");
456  }
457  for (int y = 0; y < high; y++)
458  {
459  for (int x = 0; x < wide; x++)
460  {
461  char what;
462  fscanf(f, "%c", &what);
463  if ((y == high-1) || (x == wide-1))
464  continue;
465  if (!islower(what))
466  SetHeight(x, y, GetCornerHeight(x, y, kTopLeft));
467  switch (toupper(what))
468  {
469  case 'O':
470  SetTerrainType(x, y, kOutOfBounds); break;
471  case 'S':
472  SetTerrainType(x, y, kSwamp); break;
473  case 'W':
474  SetTerrainType(x, y, kWater); break;
475  case 'T':
476  SetTerrainType(x, y, kTrees); break;
477  default:
478  SetTerrainType(x, y, kGround); break;
479  }
480  land[x][y].tile1.node = kNoGraphNode;
481  land[x][y].tile2.node = kNoGraphNode;
482  }
483  fscanf(f, "\n");
484  }
485 }
486 
487 #include <vector>
488 
489 struct header
490 {
491  uint32_t magic;
492  uint32_t version;
493  uint32_t platform;
494  uint32_t filetype;
495  uint32_t fileversion;
496  uint32_t structcount;
497  uint32_t dataoffset;
498 };
499 
501 {
502  uint32_t id;
503  uint32_t fieldCnt;
504  uint32_t fieldOffset;
505  uint32_t structSize;
506 };
507 
508 struct fieldData
509 {
510  uint32_t label;
511  uint32_t fieldType;
512  uint32_t index;
513 };
514 
515 struct fullData
516 {
518  std::vector<fieldData> fields;
519 };
520 
521 bool Map::tryDragonAge(FILE *f)
522 {
523  rewind(f);
524  header h;
525  fread(&h, sizeof(header), 1, f);
526  printf("header: %ld, struct array: %ld, fieldData %ld\n", sizeof(header), sizeof(structArray), sizeof(fieldData));
527  printf("MGC: %c%c%c%c\n", h.magic&0xFF, (h.magic>>8)&0xFF,
528  (h.magic>>16)&0xFF, (h.magic>>24)&0xFF);
529  printf("GFF: %c%c%c%c\n", h.version&0xFF, (h.version>>8)&0xFF,
530  (h.version>>16)&0xFF, (h.version>>24)&0xFF);
531  printf("TGT: %c%c%c%c\n", h.platform&0xFF, (h.platform>>8)&0xFF,
532  (h.platform>>16)&0xFF, (h.platform>>24)&0xFF);
533  printf("TYP: %c%c%c%c\n", h.filetype&0xFF, (h.filetype>>8)&0xFF,
534  (h.filetype>>16)&0xFF, (h.filetype>>24)&0xFF);
535  printf("FVR: %c%c%c%c\n", h.fileversion&0xFF, (h.fileversion>>8)&0xFF,
536  (h.fileversion>>16)&0xFF, (h.fileversion>>24)&0xFF);
537  printf("STRUCT: %d\n", h.structcount);
538  printf("DATA: 0x%X\n", h.dataoffset);
539 
540  if (('G' != ((char)(h.magic&0xFF))) ||
541  ('F' != ((char)(h.magic>>8)&0xFF)) ||
542  ('F' != ((char)(h.magic>>16)&0xFF)) ||
543  (' ' != ((char)(h.magic>>24)&0xFF)))
544  {
545  if ('G' != ((char)(h.magic&0xFF))) printf("bad g\n");
546  if ('F' != ((char)(h.magic>>8)&0xFF)) printf("bad f1\n");
547  if ('F' != ((char)(h.magic>>16)&0xFF)) printf("bad f2\n");
548  if (' ' != ((char)(h.magic>>24)&0xFF)) printf("bad <space>\n");
549  printf("DAO: bad magic\n");
550  return false;
551  }
552  if (('V' != ((char)h.version&0xFF)) ||
553  ('4' != ((char)(h.version>>8)&0xFF)) ||
554  ('.' != ((char)(h.version>>16)&0xFF)) ||
555  ('0' != ((char)(h.version>>24)&0xFF)))
556  {
557  printf("DAO: bad version\n");
558  return false;
559  }
560  if (('P' != ((char)h.platform&0xFF)) ||
561  ('C' != ((char)(h.platform>>8)&0xFF)) ||
562  (' ' != ((char)(h.platform>>16)&0xFF)) ||
563  (' ' != ((char)(h.platform>>24)&0xFF)))
564  {
565  printf("DAO: bad platform\n");
566  return false;
567  }
568  if (('A' != ((char)h.filetype&0xFF)) ||
569  ('R' != ((char)(h.filetype>>8)&0xFF)) ||
570  ('L' != ((char)(h.filetype>>16)&0xFF)) ||
571  (' ' != ((char)(h.filetype>>24)&0xFF)))
572  {
573  printf("DAO: bad file type\n");
574  return false;
575  }
576  if (('V' != ((char)h.fileversion&0xFF)) ||
577  ('4' != ((char)(h.fileversion>>8)&0xFF)) ||
578  ('.' != ((char)(h.fileversion>>16)&0xFF)) ||
579  ('0' != ((char)(h.fileversion>>24)&0xFF)))
580  {
581  printf("DAO: bad file version\n");
582  return false;
583  }
584 
585  std::vector<fullData> fd;
586  fd.resize(h.structcount);
587  //structArray sa
588  for (unsigned int x = 0; x < h.structcount; x++)
589  {
590  fread(&fd[x].sa, sizeof(fd[x].sa), 1, f);
591  // printf("Struct %d of %d\n", x, h.structcount-1);
592  // printf("ID: %c%c%c%c\n", fd[x].sa.id&0xFF, (fd[x].sa.id>>8)&0xFF,
593  // (fd[x].sa.id>>16)&0xFF, (fd[x].sa.id>>24)&0xFF);
594  // printf("%d fields at 0x%X offset size %d\n",
595  // fd[x].sa.fieldCnt, fd[x].sa.fieldOffset, fd[x].sa.structSize);
596  }
597 
598  for (unsigned int x = 0; x < h.structcount; x++)
599  {
600  fd[x].fields.resize(fd[x].sa.fieldCnt);
601  fread(&fd[x].fields[0], sizeof(fieldData), fd[x].sa.fieldCnt, f);
602  }
603  height = width = -1;
604  for (unsigned int x = 0; x < h.structcount; x++)
605  {
606  printf("Struct %d of %d ", x, h.structcount-1);
607  printf("ID: %c%c%c%c\n", fd[x].sa.id&0xFF, (fd[x].sa.id>>8)&0xFF,
608  (fd[x].sa.id>>16)&0xFF, (fd[x].sa.id>>24)&0xFF);
609  for (unsigned int y = 0; y < fd[x].sa.fieldCnt; y++)
610  {
611  printf("Field %d of %d\n", y, fd[x].sa.fieldCnt-1);
612  printf("LABEL: %d\n TYPE: %d", fd[x].fields[y].label, fd[x].fields[y].fieldType);
613  printf("(%s %s %s)\n", fd[x].fields[y].fieldType&0x80?"list":"", fd[x].fields[y].fieldType&0x40?"struct":"", fd[x].fields[y].fieldType&0x20?"reference":"");
614  printf("AT: 0x%X (0x%X)\n", fd[x].fields[y].index, fd[x].fields[y].index+h.dataoffset);
615  fseek(f, fd[x].fields[y].index+h.dataoffset+0x10, SEEK_SET);
616  if (fd[x].fields[y].label == 3127)
617  {
618  char str[8];
619  fread(&str, sizeof(char), 8, f);
620  str[7] = 0;
621  printf("name: %s\n", str);
622  }
623  else if ((fd[x].fields[y].label == 3086) ||
624  (fd[x].fields[y].label == 3087) ||
625  // (fd[x].fields[y].label == 3380) ||
626  // (fd[x].fields[y].label == 3381) ||
627  (fd[x].fields[y].label == 3092))
628  {
629  uint32_t loc;
630  fread(&loc, sizeof(loc), 1, f);
631  // printf("VALUE: %d\n", loc);
632  if (fd[x].fields[y].label == 3086)
633  { width = loc; printf("**Width: %d\n", width); }
634  else if (fd[x].fields[y].label == 3087)
635  { height = loc; printf("**Height: %d\n", height); }
636  else if (fd[x].fields[y].label == 3381)
637  { width = loc; printf("**Width: %d\n", width); }
638  else if (fd[x].fields[y].label == 3380)
639  { height = loc; printf("**Height: %d\n", height); }
640  else if (fd[x].fields[y].label == 3092)
641  {
642  if ((height == -1) || (width == -1))
643  printf("Read data before height/width\n");
644  if ((height == 0) || (width == 0))
645  {
646  printf("No height/width data\n");
647  height = 500;
648  width = 500;
649  }
650  mapType = kOctile;
651  land = new Tile *[width];
652  for (int x = 0; x < width; x++) land[x] = new Tile [height];
653  drawLand = true;
654  dList = 0;
655  updated = true;
656 
657  fseek(f, h.dataoffset+loc, SEEK_SET);
658  fread(&loc, sizeof(loc), 1, f);
659  // printf("DATA SIZE: %d\n", loc);
660  for (unsigned int z = 0; z < loc; z++)
661  {
662  uint8_t next;
663  fread(&next, sizeof(next), 1, f);
664  // printf("%2x ", next);
665  if (next < 0x9)
667  else if (next < 0xa)
669  else
671 
672  }
673  // printf("\n");
674  }
675  }
676  else {
677  if (fd[x].fields[y].fieldType == 5)
678  {
679  uint32_t loc;
680  fread(&loc, sizeof(loc), 1, f);
681  printf("**VALUE: %d\n", loc);
682  }
683  if (fd[x].fields[y].fieldType == 8)
684  {
685  float loc;
686  fread(&loc, sizeof(loc), 1, f);
687  printf("**VALUE: %f\n", loc);
688  }
689  }
690  }
691  }
692  return true;
693 }
694 
695 // check to see if we can load it as a rolling stone puzzle
697 {
698  // preprocess - all chars must be ' ', '\n', '*', '$', '#', '@' or '.'
699  // also calculate map dimensions
700  rewind(f);
701  int nrows = 0;
702  int ncols = 0;
703  while (1) // get columns
704  {
705  int currCol = 1;
706  char nextc = fgetc(f);
707  if (feof(f))
708  break;
709  if (!isLegalStone(nextc))
710  {
711  printf("illegal stone on row %d, (column pos %d)\n", nrows, currCol);
712  return false;
713  }
714  nrows++;
715  while ((nextc = fgetc(f)) != '\n') // get this row
716  {
717  if (feof(f))
718  {
719  break;
720  }
721  if (!isLegalStone(nextc))
722  {
723  printf("illegal stone on row %d, column pos %d\n", nrows, currCol);
724  return false;
725  }
726  currCol++;
727  }
728  ncols = max(currCol, ncols);
729  }
730  mapType = kSokoban;
731  printf("Dimensions (%d, %d)\n", ncols, nrows);
732  width = ncols;
733  height = nrows;
734 
735  rewind(f);
736  int manx=0, many=0;
737  land = new Tile *[width];
738  for (int x = 0; x < width; x++) land[x] = new Tile [width];
739  drawLand = true;
740  dList = 0;
741  updated = true;
742  for (int y = 0; y < height; y++)
743  {
744  bool foundEOL = false;
745  for (int x = 0; x < width; x++)
746  {
747  char what;
748  what = fgetc(f);
749  //fscanf(f, "%c", &what);
750  switch (toupper(what))
751  {
752  case ' ':
753  SetTerrainType(x, y, kOutOfBounds); printf(" "); break;
754  case '#':
755  SetTerrainType(x, y, kWater); printf("#"); break;
756  case '$':
757  SetTerrainType(x, y, kSwamp); printf("$"); break;
758  case '*':
759  SetTerrainType(x, y, kBlight); printf("*"); break;
760  case '@':
761  manx = x; many = y;
762  SetTerrainType(x, y, kGrass); printf("@"); break;
763  case '.':
764  SetTerrainType(x, y, kBlight); printf("."); break;
765  case '\n':
766  foundEOL = true;
767  for (; x < width; x++)
768  {
770  printf("_");
771  land[x][y].tile1.node = kNoGraphNode;
772  land[x][y].tile2.node = kNoGraphNode;
773  }
774  x--;
775  break;
776  }
777  land[x][y].tile1.node = kNoGraphNode;
778  land[x][y].tile2.node = kNoGraphNode;
779  }
780  if (!foundEOL)
781  fgetc(f);
782  printf("\n");
783  }
784  // from man location, paint inside of room
785  paintRoomInside(manx, many);
786  for (int x = 0; x < width; x++)
787  {
788  for (int y = 0; y < height; y++)
789  {
790  land[x][y].tile1.node = kNoGraphNode;
791  if (GetTerrainType(x, y) == kWater)
793  SetHeight(x,y,0);
794  SetSplit(x,y,kNoSplit);
795  }
796  }
797  return true;
798 }
799 
800 void Map::paintRoomInside(int x, int y)
801 {
802  if ((x < 0) || (y < 0) || (x >= width) || (y >= height))
803  return;
804  if (land[x][y].tile1.node != kNoGraphNode)
805  return;
806  if (GetTerrainType(x, y) == kWater)
807  return;
808  if (GetTerrainType(x, y) == kOutOfBounds)
809  SetTerrainType(x, y, kGround);
810  land[x][y].tile1.node = kNoGraphNode+1;
811  paintRoomInside(x+1, y);
812  paintRoomInside(x-1, y);
813  paintRoomInside(x, y+1);
814  paintRoomInside(x, y-1);
815 }
816 
817 bool Map::isLegalStone(char c)
818 {
819  const int numLegals = 7;
820  char legals[numLegals] = {' ', '\n', '$', '#', '@', '.', '*'};
821  for (int x = 0; x < numLegals; x++)
822  if (c == legals[x])
823  return true;
824  printf("Found illegal stone: \'%c\'\n", c);
825  return false;
826 }
827 
831 void Map::Save(std::stringstream &/*data*/) {}
832 
838 void Map::Save(const char *filename)
839 {
840  FILE *f = fopen(filename, "w+");
841  if (f)
842  {
843  Save(f);
844  fclose(f);
845  }
846  else {
847  printf("Error! Couldn't open file to save\n");
848  }
849 }
850 
856 void Map::Save(FILE *f)
857 {
858  switch(mapType)
859  {
860  case kOctile:
861  saveOctile(f);
862  break;
863  case kSokoban:
864  case kOctileCorner:
865  printf("Unable to save to identical map type\n");
866  case kRaw:
867  default:
868  saveRaw(f);
869  break;
870  }
871 }
872 
873 void Map::saveOctile(FILE *f)
874 {
875  if (f)
876  {
877  fprintf(f, "type octile\nheight %d\nwidth %d\nmap\n", height, width);
878  for (int y = 0; y < height; y++)
879  {
880  for (int x = 0; x < width; x++)
881  {
882  switch (GetTerrainType(x, y))
883  {
884  case kGround: fprintf(f, "."); break;
885  case kSwamp: fprintf(f, "S"); break;
886  case kWater: fprintf(f, "W"); break;
887  case kTrees: fprintf(f, "T"); break;
888  default: fprintf(f, "@"); break; // out of bounds
889  }
890  }
891  fprintf(f, "\n");
892  }
893  }
894 }
895 
896 void Map::saveRaw(FILE *f)
897 {
898  if (f)
899  {
900  fprintf(f, "type raw\nheight %d\nwidth %d\nmap\n", height, width);
901  for (int x = 0; x < width; x++)
902  {
903  fwrite(&land[x][0], sizeof(Tile), width, f);
904  }
905  }
906 }
907 
908 
917 void Map::Print(int _scale)
918 {
919  // printf("%c[%d;%dmHeight\n", 27, 4, 30);
920  // printf("%c[%d;%dm", 27, 0, 0);
921  // for (int x = 0; x < 5; x++)
922  // printf("%c[%d;%dm%d\n", 27, 1, 31+x, x);
923  // printf("\n");
924  // clear the screen
925 // printf("%c[H", 27);
926  for (int y = 0; y < height; y+=2*_scale)
927  {
928  for (int x = 0; x < width; x+=_scale)
929  {
930  // if (land[x][y].split == kForwardSplit) {
931  // printf("%c[%d;%dm", 27, 0, 0);
932  // printf("/");
933  // } else if (land[x][y].split == kBackwardSplit) {
934  // printf("%c[%d;%dm", 27, 0, 0);
935  // printf("\\");
936  // } else {
937  // printf("%c[%d;%ldm", 27, 1, 31+land[x][y].tile1.corners[0]); }
938  switch (land[x][y].tile1.type) {
939  case kOutOfBounds:
940  if (y+1 >= height)
941  { printf("^"); break; }
942  switch (land[x][y+1].tile1.type) {
943  case kOutOfBounds: printf("X"); break;
944  case kGround: case kSwamp: printf("^"); break;
945  default: printf("#"); break;
946  }
947  break;
948  // case kUndefined: printf("?"); break;
949  // case kWater: printf("%%"); break;
950  // case kSwamp: printf("@"); break;
951  case kGround:
952  if (y+1 >= height)
953  { printf(" "); break; }
954  switch (land[x][y+1].tile1.type) {
955  case kOutOfBounds: printf("x"); break;
956  case kGround: printf(" "); break;
957  default: printf("#"); break;
958  }
959  break;
960  case kSwamp:
961  if (y+1 >= height)
962  { printf(","); break; }
963  switch (land[x][y+1].tile1.type) {
964  case kOutOfBounds: printf("x"); break;
965  case kGround: printf("."); break;
966  case kSwamp: printf(":"); break;
967  default: printf("#"); break;
968  }
969  break;
970  default:
971  printf("?");
972  break;
973  }
974  }
975  printf("\n");
976  }
977 // printf("%c[%d;%dm", 27, 0, 0);
978  printf("\n");
979 }
980 
981 const char *Map::GetMapName()
982 {
983  if (map_name[0] == 0)
984  return "";
985  return map_name;
986 }
987 
994 Tile &Map::GetTile(long x, long y)
995 {
996  return land[x][y];
997 }
998 
1004 tSplit Map::GetSplit(long x, long y) const
1005 {
1006  return land[x][y].split;
1007 }
1008 
1014 void Map::SetSplit(long x, long y, tSplit split)
1015 {
1016  revision++;
1017  land[x][y].split = split;
1018 }
1019 
1020 
1028 long Map::GetTerrainType(long x, long y, tSplitSide split) const
1029 {
1030  if (land[0] == 0)
1031  printf("land: %p, land[0] = %p\n", land, land[0]);
1032  if ((x < 0) || (x >= width) || (y < 0) || (y >= height)) return kUndefined;
1033  if (split == kRightSide) return land[x][y].tile2.type;
1034  return land[x][y].tile1.type;
1035 }
1036 
1049 void Map::SetTerrainType(int32_t x1, int32_t y1,
1050  int32_t x2, int32_t y2, tTerrain t)
1051 {
1052  updated = true;
1053  //printf("---> (%d, %d) to (%d, %d)\n", x1, y1, x2, y2);
1054  double xdiff = (int)x1-(int)x2;
1055  double ydiff = (int)y1-(int)y2;
1056  double dist = sqrt(xdiff*xdiff + ydiff*ydiff);
1057  SetTerrainType(x1, y1, t);
1058  for (double c = 0; c < dist; c += 0.5)
1059  {
1060  double ratio = c/dist;
1061  double newx = (double)x1-xdiff*ratio;
1062  double newy = (double)y1-ydiff*ratio;
1063  SetTerrainType((uint32_t)newx, (uint32_t)newy, t);
1064  }
1065  SetTerrainType(x2, y2, t);
1066 }
1067 
1068 
1077 long Map::GetTerrainType(long x, long y, tEdge side) const
1078 {
1079  if ((x < 0) || (x >= width) || (y < 0) || (y >= height)) return kUndefined;
1080  if (land[x][y].split == kNoSplit) return land[x][y].tile1.type;
1081  switch (side) {
1082  case kLeftEdge:
1083  return land[x][y].tile1.type;
1084  case kRightEdge:
1085  return land[x][y].tile2.type;
1086  case kTopEdge:
1087  if (land[x][y].split == kForwardSplit)
1088  return land[x][y].tile1.type;
1089  else
1090  return land[x][y].tile2.type;
1091  case kBottomEdge:
1092  if (land[x][y].split == kBackwardSplit)
1093  return land[x][y].tile1.type;
1094  else
1095  return land[x][y].tile2.type;
1096  default:
1097  return kUndefined;
1098  }
1099 }
1100 
1108 void Map::SetTerrainType(long x, long y, tTerrain type, tSplitSide split)
1109 {
1110  if ((x >= width)||(x<0)) return;
1111  if ((y >= height)||(x<0)) return;
1112  revision++;
1113  updated = true;
1114  map_name[0] = 0;
1115  if ((land[x][y].split == kNoSplit) && (split != kWholeTile)) return;
1116  if ((y > GetMapHeight()-1) || (x > GetMapWidth()-1))
1117  return;
1118  switch (split) {
1119 
1120  case kWholeTile:
1121  land[x][y].tile1.type = type;
1122  land[x][y].tile2.type = type;
1123  break;
1124 
1125  case kLeftSide:
1126  land[x][y].tile1.type = type;
1127  break;
1128 
1129  case kRightSide:
1130  land[x][y].tile2.type = type;
1131  break;
1132  }
1133 }
1134 
1144 long Map::GetHeight(long x, long y, tSplitSide split)
1145 {
1146  if ((land[x][y].split != kNoSplit) && (split == kWholeTile)) return kUndefinedHeight;
1147 
1148  switch (split) {
1149 
1150  case kWholeTile:
1151 
1152  case kLeftSide:
1153  if ((land[x][y].tile1.corners[0] == land[x][y].tile1.corners[1]) &&
1154  (land[x][y].tile1.corners[1] == land[x][y].tile1.corners[2]))
1155  return land[x][y].tile1.corners[0];
1156  return kUndefinedHeight;
1157  break;
1158 
1159  case kRightSide:
1160  if ((land[x][y].tile2.corners[0] == land[x][y].tile2.corners[1]) &&
1161  (land[x][y].tile2.corners[1] == land[x][y].tile2.corners[2]))
1162  return land[x][y].tile2.corners[0];
1163  break;
1164  }
1165  return kUndefinedHeight;
1166 }
1167 
1173 void Map::SetHeight(long x, long y, long tHeight, tSplitSide split)
1174 {
1175  revision++;
1176  switch (split) {
1177 
1178  case kWholeTile:
1179  land[x][y].tile1.corners[0] = land[x][y].tile1.corners[1] =
1180  land[x][y].tile1.corners[2] = tHeight;
1181  land[x][y].tile2.corners[0] = tHeight;
1182  land[x][y].tile2.corners[1] = tHeight;
1183  land[x][y].tile2.corners[2] = tHeight;
1184  break;
1185  case kLeftSide:
1186  land[x][y].tile1.corners[0] = land[x][y].tile1.corners[1] =
1187  land[x][y].tile1.corners[2] = tHeight;
1188  break;
1189  case kRightSide:
1190  land[x][y].tile2.corners[0] = land[x][y].tile2.corners[1] =
1191  land[x][y].tile2.corners[2] = tHeight;
1192  break;
1193  }
1194 }
1195 
1204 long Map::GetCornerHeight(long x, long y, tCorner which, tEdge edge) const
1205 {
1206  if (GetSplit(x, y) == kNoSplit)
1207  {
1208  switch (which) {
1209  case kTopLeft: return land[x][y].tile1.corners[0];
1210  case kBottomLeft: return land[x][y].tile1.corners[1];
1211  case kTopRight: return land[x][y].tile2.corners[0];
1212  case kBottomRight: return land[x][y].tile1.corners[2];
1213  default: break;
1214  }
1215  }
1216  else {
1217  if (edge == kLeftEdge)
1218  {
1219  switch (which) {
1220  case kTopLeft: return land[x][y].tile1.corners[0];
1221  case kBottomLeft: return land[x][y].tile1.corners[1];
1222  default: break;
1223  }
1224  }
1225  else if (edge == kRightEdge)
1226  {
1227  switch (which) {
1228  case kTopRight: return land[x][y].tile2.corners[0];
1229  case kBottomRight: return land[x][y].tile2.corners[1];
1230  default: break;
1231  }
1232  }
1233  else if ((edge == kTopEdge) && (GetSplit(x, y) == kForwardSplit))
1234  {
1235  switch (which) {
1236  case kTopLeft: return land[x][y].tile1.corners[0];
1237  case kTopRight: return land[x][y].tile1.corners[2];
1238  default: break;
1239  }
1240  }
1241  else if ((edge == kTopEdge) && (GetSplit(x, y) == kBackwardSplit))
1242  {
1243  switch (which) {
1244  case kTopLeft: return land[x][y].tile2.corners[2];
1245  case kTopRight: return land[x][y].tile2.corners[0];
1246  default: break;
1247  }
1248  }
1249  else if ((edge == kBottomEdge) && (GetSplit(x, y) == kForwardSplit))
1250  {
1251  switch (which) {
1252  case kBottomLeft: return land[x][y].tile2.corners[2];
1253  case kBottomRight: return land[x][y].tile2.corners[1];
1254  default: break;
1255  }
1256  }
1257  else if ((edge == kBottomEdge) && (GetSplit(x, y) == kBackwardSplit))
1258  {
1259  switch (which) {
1260  case kBottomLeft: return land[x][y].tile1.corners[1];
1261  case kBottomRight: return land[x][y].tile1.corners[2];
1262  default: break;
1263  }
1264  }
1265  }
1266  // should never get here...
1267  return kUndefinedHeight;
1268 }
1269 
1278 long Map::GetCornerHeight(long x, long y, tCorner which, tSplitSide split) const
1279 {
1280  if ((land[x][y].split != kNoSplit) && (split == kWholeTile))
1281  return kUndefinedHeight;
1282  if (split == kWholeTile)
1283  {
1284  switch (which) {
1285  case kTopLeft: return land[x][y].tile1.corners[0];
1286  case kBottomLeft: return land[x][y].tile1.corners[1];
1287  case kTopRight: return land[x][y].tile2.corners[0];
1288  case kBottomRight: return land[x][y].tile1.corners[2];
1289  default: break;
1290  }
1291  }
1292  else if (split == kLeftSide)
1293  {
1294  switch (which) {
1295  case kTopLeft: return land[x][y].tile1.corners[0];
1296  case kBottomLeft: return land[x][y].tile1.corners[1];
1297  case kTopRight:
1298  if (land[x][y].split == kForwardSplit)
1299  return land[x][y].tile1.corners[2];
1300  return kUndefinedHeight;
1301  case kBottomRight:
1302  if (land[x][y].split == kBackwardSplit)
1303  return land[x][y].tile1.corners[2];
1304  return kUndefinedHeight;
1305  default: break;
1306  }
1307  }
1308  else if (split == kRightSide)
1309  {
1310  switch (which) {
1311  case kTopRight: return land[x][y].tile2.corners[0];
1312  case kBottomRight: return land[x][y].tile2.corners[1];
1313  case kTopLeft:
1314  if (land[x][y].split == kBackwardSplit)
1315  return land[x][y].tile2.corners[2];
1316  return kUndefinedHeight;
1317  case kBottomLeft:
1318  if (land[x][y].split == kForwardSplit)
1319  return land[x][y].tile2.corners[2];
1320  return kUndefinedHeight;
1321  default: break;
1322  }
1323  }
1324  return kUndefinedHeight;
1325 }
1326 
1335 void Map::SetCornerHeight(long x, long y, tCorner which,
1336  long cHeight, tSplitSide split)
1337 {
1338  if ((land[x][y].split != kNoSplit) && (split == kWholeTile))
1339  return;
1340  revision++;
1341  if (split == kWholeTile)
1342  {
1343  switch (which) {
1344  case kTopLeft: land[x][y].tile1.corners[0] = cHeight; break;
1345  case kBottomLeft: land[x][y].tile1.corners[1] = cHeight; break;
1346  case kTopRight: land[x][y].tile2.corners[0] = cHeight; break;
1347  case kBottomRight: land[x][y].tile1.corners[2] = cHeight;
1348  land[x][y].tile2.corners[1] = cHeight;break;
1349  default: break;
1350  }
1351  }
1352  else if (split == kLeftSide)
1353  {
1354  switch (which) {
1355  case kTopLeft: land[x][y].tile1.corners[0] = cHeight; break;
1356  case kBottomLeft: land[x][y].tile1.corners[1] = cHeight; break;
1357  case kTopRight:
1358  if (land[x][y].split == kForwardSplit)
1359  land[x][y].tile1.corners[2] = cHeight;
1360  break;
1361  case kBottomRight:
1362  if (land[x][y].split == kBackwardSplit)
1363  land[x][y].tile1.corners[2] = cHeight;
1364  break;
1365  default: break;
1366  }
1367  }
1368  else if (split == kRightSide)
1369  {
1370  switch (which) {
1371  case kTopRight: land[x][y].tile2.corners[0] = cHeight; break;
1372  case kBottomRight: land[x][y].tile2.corners[1] = cHeight; break;
1373  case kTopLeft:
1374  if (land[x][y].split == kBackwardSplit)
1375  land[x][y].tile2.corners[2] = cHeight;
1376  break;
1377  case kBottomLeft:
1378  if (land[x][y].split == kForwardSplit)
1379  land[x][y].tile2.corners[2] = cHeight;
1380  break;
1381  default: break;
1382  }
1383  }
1384 }
1385 
1386 
1395 void Map::SmoothSetRectHeight(long x1, long y1, long x2, long y2, long h, tTerrain type)
1396 {
1397  updated = true;
1398  map_name[0] = 0;
1399  if (x1 > x2)
1400  {
1401  SmoothSetRectHeight(x2, y1, x1, y2, h, type);
1402  return;
1403  }
1404  else if (y1 > y2)
1405  {
1406  SmoothSetRectHeight(x1, y2, x2, y1, h, type);
1407  return;
1408  }
1409  printf("Doing smooth rect between (%ld, %ld) and (%ld, %ld) height %ld\n", x1, y1, x2, y2, h);
1410  SetRectHeight(x1, y1, x2, y2, h, type);
1411 
1412  // top side
1413  for (int x = x1; x <= x2; x++)
1414  {
1415  SetTerrainType(x, y1-1, type);
1416  switch(GetSplit(x, y1-1)) {
1417  case kNoSplit:
1418  if (GetCornerHeight(x, y1-1, kTopLeft) != GetCornerHeight(x, y1-1, kTopRight))
1419  { // need to split slanted tile
1420  SetSplit(x, y1-1, kForwardSplit); // split is arbitarary?
1421  //SetCornerHeight(x, y1-1, kBottomLeft, GetCornerHeight(x, y1-1, kBottomLeft, kLeftSide), kRightSide);
1422 
1423  SetCornerHeight(x, y1-1, kBottomLeft, h, kRightSide);
1424  SetCornerHeight(x, y1-1, kBottomRight, h, kRightSide);
1425  SetCornerHeight(x, y1-1, kBottomLeft, h, kLeftSide);
1426  }
1427  else {
1428  SetCornerHeight(x, y1-1, kBottomLeft, h);
1429  SetCornerHeight(x, y1-1, kBottomRight, h);
1430  }
1431  break;
1432  case kForwardSplit:
1433  SetCornerHeight(x, y1-1, kBottomLeft, h, kRightSide);
1434  SetCornerHeight(x, y1-1, kBottomRight, h, kRightSide);
1435  SetCornerHeight(x, y1-1, kBottomLeft, h, kLeftSide);
1436  break;
1437  case kBackwardSplit:
1438  SetCornerHeight(x, y1-1, kBottomLeft, h, kLeftSide);
1439  SetCornerHeight(x, y1-1, kBottomRight, h, kLeftSide);
1440  SetCornerHeight(x, y1-1, kBottomRight, h, kRightSide);
1441  break;
1442  }
1443  }
1444 
1445  // bottom side
1446  for (int x = x1; x <= x2; x++)
1447  {
1448  SetTerrainType(x, y2+1, type);
1449  switch(GetSplit(x, y2+1)) {
1450  case kNoSplit:
1451  if (GetCornerHeight(x, y2+1, kBottomLeft) != GetCornerHeight(x, y2+1, kBottomRight))
1452  { // need to split slanted tile
1453  SetSplit(x, y2+1, kBackwardSplit); // split is arbitarary?
1454  //SetCornerHeight(x, y2+1, kTopLeft, GetCornerHeight(x, y2+1, kTopLeft, kLeftSide), kRightSide);
1455 
1456  SetCornerHeight(x, y2+1, kTopLeft, h, kRightSide);
1457  SetCornerHeight(x, y2+1, kTopRight, h, kRightSide);
1458  SetCornerHeight(x, y2+1, kTopLeft, h, kLeftSide);
1459  }
1460  else {
1461  SetCornerHeight(x, y2+1, kTopLeft, h);
1462  SetCornerHeight(x, y2+1, kTopRight, h);
1463  }
1464  break;
1465  case kBackwardSplit:
1466  SetCornerHeight(x, y2+1, kTopLeft, h, kRightSide);
1467  SetCornerHeight(x, y2+1, kTopRight, h, kRightSide);
1468  SetCornerHeight(x, y2+1, kTopLeft, h, kLeftSide);
1469  break;
1470  case kForwardSplit:
1471  SetCornerHeight(x, y2+1, kTopLeft, h, kLeftSide);
1472  SetCornerHeight(x, y2+1, kTopRight, h, kLeftSide);
1473  SetCornerHeight(x, y2+1, kTopRight, h, kRightSide);
1474  break;
1475  }
1476  }
1477 
1478  // left side
1479  for (int y = y1; y <= y2; y++)
1480  {
1481  SetTerrainType(x1-1, y, type);
1482  switch(GetSplit(x1-1, y)) {
1483  case kNoSplit:
1484  if (GetCornerHeight(x1-1, y, kTopLeft) != GetCornerHeight(x1-1, y, kBottomLeft))
1485  { // need to split slanted tile
1486  SetSplit(x1-1, y, kBackwardSplit); // split is arbitarary?
1489 
1490  SetCornerHeight(x1-1, y, kBottomRight, h, kLeftSide);
1491  SetCornerHeight(x1-1, y, kBottomRight, h, kRightSide);
1492  SetCornerHeight(x1-1, y, kTopRight, h, kRightSide);
1493  }
1494  else {
1495  SetCornerHeight(x1-1, y, kTopRight, h);
1496  SetCornerHeight(x1-1, y, kBottomRight, h);
1497  }
1498  break;
1499  case kBackwardSplit:
1500  SetCornerHeight(x1-1, y, kBottomRight, h, kLeftSide);
1501  SetCornerHeight(x1-1, y, kBottomRight, h, kRightSide);
1502  SetCornerHeight(x1-1, y, kTopRight, h, kRightSide);
1503  //SetCornerHeight(x1-1, y, kTopLeft, GetCornerHeight(x1-1, y, kTopLeft, kLeftSide), kRightSide);
1504  break;
1505  case kForwardSplit:
1506  SetCornerHeight(x1-1, y, kTopRight, h, kLeftSide);
1507  SetCornerHeight(x1-1, y, kBottomRight, h, kRightSide);
1508  SetCornerHeight(x1-1, y, kTopRight, h, kRightSide);
1509  break;
1510  }
1511  }
1512 
1513  // right side
1514  for (int y = y1; y <= y2; y++)
1515  {
1516  SetTerrainType(x2+1, y, type);
1517  switch(GetSplit(x2+1, y)) {
1518  case kNoSplit:
1519  if (GetCornerHeight(x2+1, y, kTopLeft) != GetCornerHeight(x2+1, y, kBottomLeft))
1520  { // need to split slanted tile
1521  SetSplit(x2+1, y, kForwardSplit); // split is arbitarary?
1523 
1524  SetCornerHeight(x2+1, y, kBottomLeft, h, kRightSide);
1525  SetCornerHeight(x2+1, y, kBottomLeft, h, kLeftSide);
1526  SetCornerHeight(x2+1, y, kTopLeft, h, kLeftSide);
1527  }
1528  else {
1529  SetCornerHeight(x2+1, y, kTopLeft, h);
1530  SetCornerHeight(x2+1, y, kBottomLeft, h);
1531  }
1532  break;
1533  case kBackwardSplit:
1534  SetCornerHeight(x2+1, y, kTopLeft, h, kRightSide);
1535  SetCornerHeight(x2+1, y, kBottomLeft, h, kLeftSide);
1536  SetCornerHeight(x2+1, y, kTopLeft, h, kLeftSide);
1537  break;
1538  case kForwardSplit:
1539  SetCornerHeight(x2+1, y, kBottomLeft, h, kRightSide);
1540  SetCornerHeight(x2+1, y, kBottomLeft, h, kLeftSide);
1541  SetCornerHeight(x2+1, y, kTopLeft, h, kLeftSide);
1542  break;
1543  }
1544  }
1545 
1546 
1547  SetSplit(x1-1, y1-1, kForwardSplit);
1548  SetTerrainType(x1-1, y1-1, type, kRightSide);
1549  SetCornerHeight(x1-1, y1-1, kBottomRight, h, kRightSide);
1552 
1553  SetSplit(x2+1, y2+1, kForwardSplit);
1554  SetTerrainType(x2+1, y2+1, type, kLeftSide);
1555  SetCornerHeight(x2+1, y2+1, kTopLeft, h, kLeftSide);
1558 
1559  SetSplit(x1-1, y2+1, kBackwardSplit);
1560  SetTerrainType(x1-1, y2+1, type, kRightSide);
1561  SetCornerHeight(x1-1, y2+1, kTopRight, h, kRightSide);
1564 
1565  SetSplit(x2+1, y1-1, kBackwardSplit);
1566  SetTerrainType(x2+1, y1-1, type, kLeftSide);
1567  SetCornerHeight(x2+1, y1-1, kBottomLeft, h, kLeftSide);
1570 }
1571 
1578 void Map::SetRectHeight(long x1, long y1, long x2, long y2, long h, tTerrain type)
1579 {
1580  updated = true;
1581  map_name[0] = 0;
1582  revision++;
1583  //printf("Doing rect between (%ld, %ld) and (%ld, %ld) height %ld\n", x1, y1, x2, y2, h);
1584  for (int x = x1; x <= x2; x++)
1585  {
1586  for (int y = y1; y <= y2; y++)
1587  {
1588  SetSplit(x, y, kNoSplit);
1589  SetTerrainType(x, y, type);
1590  SetHeight(x, y, h);
1591  }
1592  }
1593 }
1594 
1602 bool Map::AdjacentEdges(long x, long y, tEdge edge) const
1603 {
1604  if ((x < 0) || (y < 0) || (x >= width) || (y >= height))
1605  return false;
1606  switch (edge) {
1607  case kInternalEdge:
1608  {
1609  tSplit split;
1610  if ((split = GetSplit(x, y)) == kNoSplit)
1611  return ((GetTerrainType(x, y, kLeftSide)>>terrainBits) == (GetTerrainType(x, y, kRightSide)>>terrainBits));
1612  else if (split == kForwardSplit)
1613  {
1614  return ((GetCornerHeight(x, y, kTopRight, kLeftSide) == GetCornerHeight(x, y, kTopRight, kRightSide)) &&
1617  }
1618  else if (split == kBackwardSplit)
1619  {
1620  return ((GetCornerHeight(x, y, kTopLeft, kLeftSide) == GetCornerHeight(x, y, kTopLeft, kRightSide)) &&
1623  }
1624  return false;
1625  } break;
1626  case kLeftEdge:
1627  if (x == 0)
1628  return false;
1629  return ((GetCornerHeight(x, y, kTopLeft, kLeftEdge) == GetCornerHeight(x-1, y, kTopRight, kRightEdge)) &&
1632  break;
1633  case kRightEdge:
1634  if (x+1 >= width)
1635  return false;
1636  return ((GetCornerHeight(x, y, kTopRight, kRightEdge) == GetCornerHeight(x+1, y, kTopLeft, kLeftEdge)) &&
1639  break;
1640  case kTopEdge:
1641  if (y == 0)
1642  return false;
1643  return ((GetCornerHeight(x, y, kTopRight, kTopEdge) == GetCornerHeight(x, y-1, kBottomRight, kBottomEdge)) &&
1645  //(CanPass(GetTerrainType(x, y, kTopEdge), GetTerrainType(x, y-1, kBottomEdge))));
1647 
1648  break;
1649  case kBottomEdge:
1650  if (y+1 >= height)
1651  return false;
1652  return ((GetCornerHeight(x, y, kBottomRight, kBottomEdge) == GetCornerHeight(x, y+1, kTopRight, kTopEdge)) &&
1654  //(CanPass(GetTerrainType(x, y, kBottomEdge), GetTerrainType(x, y+1, kTopEdge))));
1656  break;
1657  }
1658  return false;
1659 }
1660 
1661 bool Map::AdjacentCorners(long x, long y, tCorner corner) const
1662 {
1663  if ((x < 0) || (y < 0) || (x >= width) || (y >= height))
1664  return false;
1665  switch (corner)
1666  {
1667  case kNone:
1668  return true;
1669  case kTopLeft:
1670  if (((x >= 1) && (y >= 1) && (AdjacentEdges(x, y, kLeftEdge)) && (AdjacentEdges(x, y, kTopEdge)) &&
1671  (AdjacentEdges(x, y-1, kLeftEdge)) && (AdjacentEdges(x-1, y, kTopEdge))) &&
1672  (((AdjacentEdges(x-1, y, kInternalEdge)) || (GetSplit(x-1, y) == kBackwardSplit)) &&
1673  ((AdjacentEdges(x, y-1, kInternalEdge)) || (GetSplit(x, y-1) == kBackwardSplit)) &&
1674  ((AdjacentEdges(x-1, y-1, kInternalEdge)) || (GetSplit(x-1, y-1) == kForwardSplit)) &&
1675  ((AdjacentEdges(x, y, kInternalEdge)) || (GetSplit(x, y) == kForwardSplit))))
1676  return true;
1677  return false;
1678  case kTopRight:
1679  if (((y >= 1) && (x < GetMapWidth()-1) && (AdjacentEdges(x, y, kRightEdge)) && (AdjacentEdges(x, y, kTopEdge)) &&
1680  (AdjacentEdges(x, y-1, kRightEdge)) && (AdjacentEdges(x+1, y, kTopEdge))) &&
1681  (((AdjacentEdges(x+1, y, kInternalEdge)) || (GetSplit(x+1, y) == kForwardSplit)) &&
1682  ((AdjacentEdges(x, y-1, kInternalEdge)) || (GetSplit(x, y-1) == kForwardSplit)) &&
1683  ((AdjacentEdges(x+1, y-1, kInternalEdge)) || (GetSplit(x+1, y-1) == kBackwardSplit)) &&
1684  ((AdjacentEdges(x, y, kInternalEdge)) || (GetSplit(x, y) == kBackwardSplit))))
1685  return true;
1686  return false;
1687  case kBottomLeft: return AdjacentCorners(x-1, y+1, kTopRight);
1688  case kBottomRight: return AdjacentCorners(x+1, y+1, kTopLeft);
1689  default: return false;
1690  }
1691  return false;
1692 }
1693 
1694 bool Map::CanStep(long x1, long y1, long x2, long y2) const
1695 {
1696  if ((abs(x1-x2) > 1) || (abs(y1-y2) > 1))
1697  return false;
1698  if (mapType == kOctile)
1699  {
1700  if (x1 == x2 || y1 == y2)
1701  return ((GetTerrainType(x1, y1)>>terrainBits) == (GetTerrainType(x2, y2)>>terrainBits));
1702  else
1703  return (((GetTerrainType(x1, y1)>>terrainBits) == (GetTerrainType(x2, y2)>>terrainBits)) &&
1704  ((GetTerrainType(x1, y2)>>terrainBits) == (GetTerrainType(x2, y2)>>terrainBits)) &&
1705  ((GetTerrainType(x2, y1)>>terrainBits) == (GetTerrainType(x2, y2)>>terrainBits)));
1706  }
1707  else {
1708  switch (x1-x2) {
1709  case 0: //return true;
1710  switch (y1-y2) {
1711  case 0: return true;
1712  case 1: return AdjacentEdges(x1, y1, kTopEdge);
1713  case -1: return AdjacentEdges(x1, y1, kBottomEdge);
1714  }
1715  break;
1716  case 1: //return AdjacentEdges(x1, y1, kLeftEdge);
1717  switch (y1-y2) {
1718  case 0: return AdjacentEdges(x1, y1, kLeftEdge);
1719  case 1: return AdjacentCorners(x1, y1, kTopLeft);
1720  case -1: return AdjacentCorners(x1, y1, kBottomLeft);
1721  }
1722  break;
1723  case -1: //return AdjacentEdges(x1, y1, kRightEdge);
1724  switch (y1-y2) {
1725  case 0: return AdjacentEdges(x1, y1, kRightEdge);
1726  case 1: return AdjacentCorners(x1, y1, kTopRight);
1727  case -1: return AdjacentCorners(x1, y1, kBottomRight);
1728  }
1729  break;
1730  }
1731  }
1732  return false;
1733 }
1734 
1738 void Map::SetDrawLand(bool dLand)
1739 {
1740  drawLand = dLand;
1741 }
1742 
1748 {
1749  updated = true; // force the display list to re-draw
1750  tileSet = ts;
1751  if (ts == kBitmap)
1752  InitTextures();
1753 }
1754 
1759 {
1760  return tileSet;
1761 }
1762 
1763 
1764 //void Map::setDrawAbstractions(int abstractions)
1765 //{
1766 // numAbstractions = abstractions&0x7;
1767 //}
1768 
1777 void Map::OpenGLDraw(tDisplay how) const
1778 {
1779  glDisable(GL_LIGHTING);
1780  if (drawLand)
1781  {
1782  if (updated)
1783  {
1784  updated = false;
1785  if (dList)
1786  glDeleteLists(dList, 1);
1787  dList = 0;
1788  }
1789 
1790  if (dList)
1791  {
1792  glCallList(dList);
1793  }
1794  else {
1795  if (verbose)
1796  printf("Drawing land into display list\n");
1797  dList = glGenLists(1);
1798  glNewList(dList, GL_COMPILE_AND_EXECUTE);
1799 
1800  if (tileSet == kFast)
1801  {
1802  drawLandQuickly();
1803  }
1804  else {
1805  for (int y = 0; y < height; y++)
1806  {
1807  for (int x = 0; x < width; x++)
1808  {
1809  DrawTile(&land[x][y], x, y, how);
1810  }
1811  }
1812  }
1813  glEndList();
1814  // printf("Done\n");
1815  }
1816  }
1817 }
1818 
1826 bool Map::GetOpenGLCoord(int _x, int _y, GLdouble &x, GLdouble &y, GLdouble &z, GLdouble &radius) const
1827 {
1828  if (_x >= width) return false;
1829  if (_y >= height) return false;
1830  if ((_x == -1) || (_y == -1))
1831  return false;
1832  double _scale, xOffset, yOffset;
1833  if (height > width)
1834  {
1835  _scale = 2.0/(double)(height);
1836  xOffset = (2.0-GetMapWidth()*_scale)*0.5;
1837  yOffset = 0;
1838  }
1839  else {
1840  _scale = 2.0/(double)(width);
1841  yOffset = (2.0-GetMapHeight()*_scale)*0.5;
1842  xOffset = 0;
1843  }
1844  double epsilon = _scale/2.0;
1845  x = -1+_x*_scale+epsilon+xOffset;
1846  y = -1+_y*_scale+epsilon+yOffset;
1847 // x = (2*_x-width)*_scale+epsilon;
1848 // y = (2*_y-height)*_scale+epsilon;
1849  z = -(double)0.5*(land[_x][_y].tile1.corners[0]+land[_x][_y].tile2.corners[0])*(_scale);//+(double)land[_x][_y].tile1.corners[1]/(2*_scale));
1850  radius = epsilon;
1851  return true;
1852 }
1853 
1861 bool Map::GetOpenGLCoord(float _x, float _y, GLdouble &x, GLdouble &y, GLdouble &z, GLdouble &radius) const
1862 {
1863  if (isnan(_x) || isnan(_y))
1864  {
1865  x = y = z = 0;
1866  radius = 0;
1867  assert(false);
1868  return false;
1869  }
1870  int iX = floor(_x);
1871  int iY = floor(_y);
1872  return GetOpenGLCoord(iX, iY, x, y, z, radius);
1873 // double _scale;
1874 // if (height > width)
1875 // _scale = 1/(double)(height+1);
1876 // else
1877 // _scale = 1/(double)(width+1);
1878 // double epsilon = _scale/2.0;
1879 // x = (2*_x-width)*_scale+epsilon;
1880 // y = (2*_y-height)*_scale+epsilon;
1881 // z = -(double)0.5*(land[iX][iY].tile1.corners[0]+land[iX][iY].tile2.corners[0])*(_scale);//+(double)land[_x][_y].tile1.corners[1]/(2*_scale));
1882 // radius = _scale;
1883 // return true;
1884 }
1885 
1893 {
1894  // double scale;
1895  if (height > width)
1896  return (double)(height)/2.0;
1897  return (double)(width)/2.0;
1898 }
1899 
1900 void Map::GetPointFromCoordinate(point3d loc, int &px, int &py) const
1901 {
1902  double _x, _y;
1903  double _scale, xOffset, yOffset;
1904  if (height > width)
1905  {
1906  _scale = 2.0/(double)(height);
1907  xOffset = (2.0-GetMapWidth()*_scale)*0.5;
1908  yOffset = 0;
1909  }
1910  else {
1911  _scale = 2.0/(double)(width);
1912  yOffset = (2.0-GetMapHeight()*_scale)*0.5;
1913  xOffset = 0;
1914  }
1915  double epsilon = _scale/2.0;
1916 
1917  _x = (loc.x-epsilon+1-xOffset)/_scale;
1918  _y = (loc.y-epsilon+1-yOffset)/_scale;
1919 
1920 // _x = ((loc.x-epsilon)/_scale+(double)width)/2.0;
1921 // _y = ((loc.y-epsilon)/_scale+(double)height)/2.0;
1922  px = (int)(_x+0.5); // round off!
1923  py = (int)(_y+0.5);
1924  /*
1925  px = (int)(((loc.x/2.0)+0.5)*((double)width));
1926  py = (int)(((loc.y/2.0)+0.5)*((double)height));
1927  */
1928  if ((px < 0) || (py < 0) || (px >= width) || (py >= height))
1929  {
1930  px = py = -1;
1931  }
1932 }
1933 
1941 void Map::DrawTile(Tile *t, int x, int y, tDisplay how) const
1942 {
1943  GLdouble xx, yy, zz, rr;
1944  if (GetOpenGLCoord(x,y,xx,yy,zz,rr) == false)
1945  return;
1946 
1947  if (tileSet == kBitmap)
1948  {
1949  glNormal3d(0, 0, -1);
1950  glColor3f(1, 1, 1);
1951 
1952  float l, r, u, b;
1953  switch (t->tile1.type)
1954  {
1955  case kTrees:
1956  l = 0; r = 0.5;
1957  u = 0.0; b = 0.5;
1958  break;
1959  case kGround:
1960  l = 0; r = 0.5;
1961  u = 0.5; b = 1.0;
1962  break;
1963  case kWater:
1964  glColor3f(0.5, 0.5, 0.5);
1965  case kSwamp:
1966  l = 0.5; r = 1.0;
1967  u = 0; b = 0.5;
1968  break;
1969 
1970  default:
1971  l = 0.5; r = 1.0;
1972  u = 0.5; b = 1.0;
1973  }
1974 
1975  glEnable(GL_TEXTURE_2D);
1976  glBindTexture(GL_TEXTURE_2D, wall);
1977  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1978 
1979  glBegin(GL_QUADS);
1980 
1981  glTexCoord2f(l,b);
1982  glVertex3f(xx-rr, yy-rr, /*-2*rr*/-rr*t->tile1.corners[0]);
1983  glTexCoord2f(l,u);
1984  glVertex3f(xx-rr, yy+rr, /*-2*rr*/-rr*t->tile1.corners[1]);
1985  glTexCoord2f(r,u);
1986  glVertex3f(xx+rr, yy+rr, /*-2*rr*/-rr*t->tile1.corners[2]);
1987  glTexCoord2f(r,b);
1988  glVertex3f(xx+rr, yy-rr, /*-2*rr*/-rr*t->tile2.corners[0]);
1989 
1990  glEnd();
1991  glDisable(GL_TEXTURE_2D);
1992  return;
1993  }
1994 
1995  switch (how) {
1996  case kPolygons:
1997  if (t->split == kNoSplit)
1998  glBegin(GL_QUADS);
1999  else
2000  glBegin(GL_TRIANGLES);
2001  break;
2002  case kLines:
2003  glBegin(GL_LINE_LOOP);
2004  break;
2005  case kPoints:
2006  default:
2007  glBegin(GL_POINTS);
2008  break;
2009  }
2010  switch (t->split) {
2011  case kNoSplit:
2012  if (t->tile1.type != kOutOfBounds)
2013  {
2014  if ((tileSet == kWinterTile) ||
2015  (tileSet == kFallTile))
2016  rr *= 0.9; // Leave empty grid lines between
2017 
2019  DoNormal(t->split, &t->tile1, x, y);
2020  glVertex3f(xx-rr, yy-rr, -rr*t->tile1.corners[0]);
2021 
2023  glVertex3f(xx-rr, yy+rr, -rr*t->tile1.corners[1]);
2024 
2026  glVertex3f(xx+rr, yy+rr, -rr*t->tile1.corners[2]);
2027 
2029  glVertex3f(xx+rr, yy-rr, -rr*t->tile2.corners[0]);
2030  }
2031  else {
2032 // if (wall != -1)
2033 // {
2034  glColor3f(0, 0, 0);
2035 // }
2036 // else
2037 // glColor3f(0.3, 0.3, 0.3);
2038  // top
2039 
2040  glNormal3d(0, 0, -1);
2041  glTexCoord2f(0.51,1);
2042  glVertex3f(xx-rr, yy-rr, /*-2*rr*/-rr*t->tile1.corners[0]);
2043  glTexCoord2f(0.51,0.51);
2044  glVertex3f(xx-rr, yy+rr, /*-2*rr*/-rr*t->tile1.corners[1]);
2045  glTexCoord2f(1,0.51);
2046  glVertex3f(xx+rr, yy+rr, /*-2*rr*/-rr*t->tile1.corners[2]);
2047  glTexCoord2f(1,1);
2048  glVertex3f(xx+rr, yy-rr, /*-2*rr*/-rr*t->tile2.corners[0]);
2049 
2050 
2051 // glColor3f(1.0, 0.1, 0.1);
2052 // // side 1
2053 // glVertex3f(xx-rr, yy-rr, -2*rr-rr*t->tile1.corners[0]);
2054 // glVertex3f(xx-rr, yy+rr, -2*rr-rr*t->tile1.corners[1]);
2055 // glVertex3f(xx-rr, yy+rr, -rr*t->tile1.corners[2]);
2056 // glVertex3f(xx-rr, yy-rr, -rr*t->tile2.corners[0]);
2057 //
2058 // glColor3f(1.0, 1.0, 0.1);
2059 // // side 2
2060 // glVertex3f(xx+rr, yy-rr, -rr*t->tile1.corners[0]);
2061 // glVertex3f(xx+rr, yy+rr, -rr*t->tile1.corners[1]);
2062 // glVertex3f(xx+rr, yy+rr, -2*rr-rr*t->tile1.corners[2]);
2063 // glVertex3f(xx+rr, yy-rr, -2*rr-rr*t->tile2.corners[0]);
2064 //
2065 // glColor3f(0.0, 1.0, 0.1);
2066 // // side 3
2067 // glVertex3f(xx-rr, yy-rr, -2*rr-rr*t->tile1.corners[0]);
2068 // glVertex3f(xx-rr, yy-rr, -rr*t->tile1.corners[1]);
2069 // glVertex3f(xx+rr, yy-rr, -rr*t->tile1.corners[2]);
2070 // glVertex3f(xx+rr, yy-rr, -2*rr-rr*t->tile2.corners[0]);
2071 //
2072 // glColor3f(0.0, 0.0, 1.0);
2073 // // side 4
2074 // glVertex3f(xx-rr, yy+rr, -2*rr-rr*t->tile1.corners[0]);
2075 // glVertex3f(xx-rr, yy+rr, -rr*t->tile1.corners[1]);
2076 // glVertex3f(xx+rr, yy+rr, -rr*t->tile1.corners[2]);
2077 // glVertex3f(xx+rr, yy+rr, -2*rr-rr*t->tile2.corners[0]);
2078 
2079  }
2080  break;
2081  case kForwardSplit:
2082  if (t->tile1.type != kOutOfBounds)
2083  {
2084  DoNormal(t->split, &t->tile1, x, y);
2085  DoVertexColor(t->tile1.type, t->tile1.corners[0]);
2086  glVertex3f(xx-rr, yy-rr, -rr*t->tile1.corners[0]);
2087  DoVertexColor(t->tile1.type, t->tile1.corners[1]);
2088  glVertex3f(xx-rr, yy+rr, -rr*t->tile1.corners[1]);
2089  DoVertexColor(t->tile1.type, t->tile1.corners[2]);
2090  glVertex3f(xx+rr, yy-rr, -rr*t->tile1.corners[2]);
2091  }
2092  if (how == kLines)
2093  { glEnd(); glBegin(GL_LINE_LOOP); }
2094  if (t->tile2.type != kOutOfBounds)
2095  {
2096  DoNormal(t->split, &t->tile2, x, y);
2097  DoVertexColor(t->tile2.type, t->tile2.corners[0]);
2098  glVertex3f(xx+rr, yy-rr, -rr*t->tile2.corners[0]);
2099  DoVertexColor(t->tile2.type, t->tile2.corners[1]);
2100  glVertex3f(xx+rr, yy+rr, -rr*t->tile2.corners[1]);
2101  DoVertexColor(t->tile2.type, t->tile2.corners[2]);
2102  glVertex3f(xx-rr, yy+rr, -rr*t->tile2.corners[2]);
2103  }
2104  break;
2105  case kBackwardSplit:
2106  if (t->tile1.type != kOutOfBounds)
2107  {
2108  DoNormal(t->split, &t->tile1, x, y);
2109  DoVertexColor(t->tile1.type, t->tile1.corners[0]);
2110  glVertex3f(xx-rr, yy-rr, -rr*t->tile1.corners[0]);
2111  //glVertex3f((double)x/width-.5, (double)2.0*t->tile1.corners[0]/(height+width), (double)y/height-.5);
2112  DoVertexColor(t->tile1.type, t->tile1.corners[1]);
2113  glVertex3f(xx-rr, yy+rr, -rr*t->tile1.corners[1]);
2114  //glVertex3f((double)x/width-.5, (double)2.0*t->tile1.corners[1]/(height+width), (double)y/height+1.0/height-.5);
2115  DoVertexColor(t->tile1.type, t->tile1.corners[2]);
2116  glVertex3f(xx+rr, yy+rr, -rr*t->tile1.corners[2]);
2117  //glVertex3f((double)x/width+1.0/width-.5, (double)2.0*t->tile1.corners[2]/(height+width), (double)y/height+1.0/height-.5);
2118  }
2119  if (how == kLines)
2120  { glEnd(); glBegin(GL_LINE_LOOP); }
2121 
2122  if (t->tile2.type != kOutOfBounds)
2123  {
2124  DoNormal(t->split, &t->tile2, x, y);
2125  DoVertexColor(t->tile2.type, t->tile2.corners[0]);
2126  glVertex3f(xx+rr, yy-rr, -rr*t->tile2.corners[0]);
2127  //glVertex3f((double)x/width+1.0/width-.5, (double)2.0*t->tile2.corners[0]/(height+width), (double)y/height-.5);
2128  DoVertexColor(t->tile2.type, t->tile2.corners[1]);
2129  glVertex3f(xx+rr, yy+rr, -rr*t->tile2.corners[1]);
2130  //glVertex3f((double)x/width+1.0/width-.5, (double)2.0*t->tile2.corners[1]/(height+width), (double)y/height+1.0/height-.5);
2131  DoVertexColor(t->tile2.type, t->tile2.corners[2]);
2132  glVertex3f(xx-rr, yy-rr, -rr*t->tile2.corners[2]);
2133  //glVertex3f((double)x/width-.5, (double)2.0*t->tile2.corners[2]/(height+width), (double)y/height-.5);
2134  }
2135  break;
2136  }
2137  glEnd();
2138  glDisable(GL_TEXTURE_2D);
2139 }
2140 
2147 void Map::DoVertexColor(tTerrain type, int vHeight, bool darken) const
2148 {
2149  double scaleH = (10.0-vHeight)/10.0;
2150  double red=0, green=0, blue=0, alpha = 1.0;
2151  switch (type)
2152  {
2153  case kOutOfBounds:
2154  red = 0; green = 0.2; blue = 0; alpha = .5; // kOutOfBounds
2155  break;
2156  case kOutOfBounds2:
2157  red = .9; green = .9; blue = .9; alpha = .5; // kOutOfBounds2
2158  break;
2159  case kWater:
2160  red = 0; green = (random()%10)/100.0; blue = scaleH*1-(random()%10)/100.0;
2161  break;
2162  case kGround:
2163  if ((tileSet == kFall) || (tileSet == kFallTile))
2164  {
2165  double r1=0, r2=0, r3=0;
2166  if (tileSet == kFall)
2167  {
2168  r1 = (random()%10-5)/100.0;
2169  r2 = (random()%10-5)/100.0;
2170  r3 = (random()%5)/100.0;
2171  }
2172  red = scaleH*.5+r1;
2173  green = scaleH*.25+r2;
2174  blue = r3; // kGround
2175  }
2176  else {
2177  double r1=0, r2=0, r3=0;
2178  if (tileSet == kWinter)
2179  {
2180  r1 = -(random()%8)/100.0;
2181  r2 = -(random()%8)/100.0;
2182  r3 = -(random()%8)/100.0;
2183  }
2184  red = scaleH*0.9+r1;
2185  green = scaleH*0.9+r2;
2186  blue = scaleH*0.9+r3;
2187  }
2188  break;
2189  case kTrees:
2190  red = (random()%10)/100.0;
2191  green = .45*scaleH-(random()%10)/100.0;
2192  blue = (random()%10)/100.0;
2193  break;
2194  case kSwamp:
2195  red = (scaleH*.5+(random()%10-5)/100.0)*0.9;
2196  green = (scaleH*.25+(random()%10-5)/100.0)*0.9;
2197  blue = (80+random()%10-5)/100.0;
2198  break;
2199  case kGrass:
2200  red = (random()%10)/100.0;
2201  green = scaleH-(random()%10)/100.0;
2202  blue = (random()%10)/100.0;
2203  break;
2204  case kBlight:
2205  red = (50+random()%10-5)/100.0;
2206  green = (50+random()%10-5)/100.0;
2207  blue = (50+random()%10-5)/100.0;
2208  break;
2209  default:
2210  break;
2211  }
2212  if ((darken) && (type != kGround))
2213  glColor4f(.5*red, .5*green, .5*blue, alpha);
2214  else if ((darken) && (type == kGround))
2215  glColor4f(.8*red, .8*green, .8*blue, alpha);
2216  else
2217  glColor4f(red, green, blue, alpha);
2218 }
2219 
2224 void Map::DoNormal(tSplit split, halfTile *t, int /*x*/, int /*y*/) const
2225 {
2226  recVec n,pa,pb;
2227 
2228  pa.x = 0;
2229  pa.y = (double)(t->corners[1]-t->corners[0])/(height+width);
2230  pa.z = 1/height;
2231 
2232  pb.x = 1/width;
2233  switch (split) {
2234  case kNoSplit:
2235  case kBackwardSplit:
2236  pb.z = 1/height;
2237  break;
2238  case kForwardSplit:
2239  pb.z = 0;
2240  break;
2241  }
2242  pb.y = (double)(t->corners[2]-t->corners[0])/(height+width);
2243  pa.normalise();
2244  pb.normalise();
2245 
2246  n.x = pb.y * pa.z - pb.z * pa.y;
2247  n.y = pb.z * pa.x - pb.x * pa.z;
2248  n.z = pb.x * pa.y - pb.y * pa.x;
2249  n.normalise();
2250 
2251  glNormal3f(n.x,n.y,n.z);
2252 }
2253 
2255 {
2256  GLdouble xx, yy, zz, rr;
2257  glBegin(GL_QUADS);
2258  glColor3f(0.5, 0.5, 0.5);
2259  for (int y = 0; y < height; y++)
2260  {
2261  if (GetTerrainType(0, y) == kGround)
2262  {
2263  GetOpenGLCoord(0, y, xx, yy, zz, rr);
2264  glVertex3f(xx-rr, yy-rr, zz);
2265  glVertex3f(xx-rr, yy+rr, zz);
2266  }
2267  for (int x = 1; x < width; x++)
2268  {
2269  if (GetTerrainType(x, y) != GetTerrainType(x-1, y))
2270  {
2271  if (GetTerrainType(x-1, y) == kGround)
2272  {
2273  GetOpenGLCoord(x, y, xx, yy, zz, rr);
2274  glVertex3f(xx-rr, yy+rr, zz);
2275  glVertex3f(xx-rr, yy-rr, zz);
2276  }
2277  if (GetTerrainType(x, y) == kGround)
2278  {
2279  GetOpenGLCoord(x, y, xx, yy, zz, rr);
2280  glVertex3f(xx-rr, yy-rr, zz);
2281  glVertex3f(xx-rr, yy+rr, zz);
2282  }
2283  }
2284  }
2285  if (GetTerrainType(width-1, y) == kGround)
2286  {
2287  GetOpenGLCoord(width-1, y, xx, yy, zz, rr);
2288  glVertex3f(xx+rr, yy+rr, zz);
2289  glVertex3f(xx+rr, yy-rr, zz);
2290  }
2291  }
2292 
2293 // this will draw the lines for the map, but can be too busy
2294 // for (int y = 0; y < height; y++)
2295 // {
2296 // GetOpenGLCoord(0, y, xx, yy, zz, rr);
2297 // glVertex3f(xx-rr, yy-rr, zz);
2298 // GetOpenGLCoord(width-1, y, xx, yy, zz, rr);
2299 // glVertex3f(xx+rr, yy-rr, zz);
2300 // }
2301 // for (int y = 0; y < height; y++)
2302 // {
2303 // GetOpenGLCoord(x, 0, xx, yy, zz, rr);
2304 // glVertex3f(xx-rr, yy-rr, zz);
2305 // GetOpenGLCoord(x, height-1, xx, yy, zz, rr);
2306 // glVertex3f(xx-rr, yy+rr, zz);
2307 // }
2308  glEnd();
2309 }
2310 
2319 void Map::SetNodeNum(int num, int x, int y, tCorner corner)
2320 {
2321  if ((x < 0) || (y < 0) || (x >= width) || (y >= height))
2322  {
2323  printf("ERROR -- trying to set invalid node number!\n");
2324  return;
2325  }
2326  if ((corner == kBottomRight) || (corner == kTopRight))
2327  land[x][y].tile2.node = num;
2328  land[x][y].tile1.node = num;
2329 }
2330 
2339 int Map::GetNodeNum(int x, int y, tCorner corner)
2340 {
2341  if ((x < 0) || (y < 0) || (x >= width) || (y >= height))
2342  {
2343  //printf("ERROR -- trying to get invalid node number!\n");
2344  return -1;
2345  }
2346  if ((corner == kBottomRight) || (corner == kTopRight))
2347  return land[x][y].tile2.node;
2348  return land[x][y].tile1.node;
2349 }
2350 
2351 /*
2352  *
2353  * Lookup table for the edge widths.
2354  *
2355  * The edges are as follows:
2356  *
2357  * ---------
2358  * | | |
2359  * ---------
2360  * | -|- |
2361  * ---------
2362  *
2363  * To cross the bottom middle edge.
2364  *
2365  * Tile types:
2366  * Empty: 0
2367  * Forward slash: 1
2368  * Backslash: 2
2369  *
2370  *
2371  * To translate into the lookup table index, multiply
2372  * tile 1's type by 27, multiply tile 2's type by 9,
2373  * multiply tile 3's type by 3, and add all the values together,
2374  * along with tile 4.
2375  *
2376  * So you end up with: 27*T1 + 9*T2 + 3*T3 + T4
2377  *
2378  * For example,
2379  *
2380  * ---------
2381  * | \ | / |
2382  * ---------
2383  * | | \ |
2384  * ---------
2385  *
2386  * 27*2 + 9*1 + 3*0 + 2 = 65
2387  *
2388  * The edge width will be found in index 65.
2389  *
2390  */
2391 
2392 extern "C" {
2393 
2394  double edgewidth[81] = {
2395  TWO,
2396  ROOT_TWO,
2397  ONE,
2398  ONE,
2399  ONE,
2400 
2402  ROOT_TWO,
2403  ROOT_TWO,
2404  ONE,
2405  ONE,
2406 
2407  ONE,
2408  ONE,
2409  ONE,
2410  ONE,
2412 
2413  ONE,
2414  ONE,
2415  ONE,
2416  ROOT_TWO,
2417  ROOT_TWO,
2418 
2419  ONE,
2420  ONE,
2421  ONE,
2423  ROOT_TWO,
2424 
2425  ROOT_TWO,
2426  ONE,
2427  ROOT_TWO,
2428  ROOT_TWO,
2429  ONE,
2430 
2431  ONE,
2432  ONE,
2434  ROOT_TWO,
2435  ROOT_TWO,
2436 
2437  ONE,
2438  ONE,
2439  ONE,
2440  ONE,
2441  ONE,
2442 
2443  ONE,
2445  ONE,
2447  ONE,
2448 
2449  ROOT_TWO,
2450  ROOT_TWO,
2451  ONE,
2452  ONE,
2453  ONE,
2454 
2456  ROOT_TWO,
2457  ROOT_TWO,
2458  ONE,
2459  ONE,
2460 
2461  ONE,
2462  ONE,
2463  ONE,
2464  ONE,
2466 
2467  ONE,
2468  ONE,
2469  ONE,
2470  ONE,
2471  ONE,
2472 
2473  ONE,
2474  ONE,
2475  ONE,
2477  ONE,
2478 
2479  ONE,
2480  ONE,
2481  ONE,
2482  ONE,
2483  ONE,
2484 
2485  ONE,
2486  ONE,
2488  ONE,
2489  ONE,
2490 
2491  ONE
2492  };
2493 }
2494 
2498 float Map::GetEdgeWidthX(int x, int y)
2499 {
2500  // Boundary values
2501  if (x < 0 || y-1 < 0 || x+1 >= width || y+1 >= height)
2502  return 0.0f;
2503 
2504  int index1, index2;
2505 
2506  // Check if the edge at (x+1, y) is adjacent (i.e. same height and terrain type)
2507  if (!AdjacentEdges(x, y, kRightEdge))
2508  {
2509  // different height or terrain, so undefined
2510  return 0.0f;
2511  }
2512 
2513  // Check to see that the top edges are both adjacent. If either is not, get the edge width using the bottom two tiles
2514  if (!AdjacentEdges(x, y, kTopEdge) || !AdjacentEdges(x+1, y, kTopEdge))
2515  {
2516  //(x+1, y+1), (x, y+1), (x+1, y), (x, y)
2517  index1 = (27*GetSplit(x+1, y+1)) + (9*GetSplit(x, y+1)) + (3*GetSplit(x+1, y)) + (GetSplit(x, y));
2518  return edgewidth[index1];
2519  }
2520 
2521  // Check to see that the bottom edges are both adjacent. If either is not, get the edge width using the top two tiles
2522  if (!AdjacentEdges(x, y, kBottomEdge) || !AdjacentEdges(x+1, y, kBottomEdge))
2523  {
2524  //(x, y-1), (x+1, y-1), (x, y) (x+1, y)
2525  index1 = (27*GetSplit(x, y-1)) + (9*GetSplit(x+1, y-1)) + (3*GetSplit(x, y)) + (GetSplit(x+1, y));
2526  return edgewidth[index1];
2527  }
2528 
2529  // Otherwise, return the minimum of the edge widths from the top edges and bottom edges
2530  index1 = (27*GetSplit(x+1, y+1)) + (9*GetSplit(x, y+1)) + (3*GetSplit(x+1, y)) + (GetSplit(x, y));
2531  index2 = (27*GetSplit(x, y-1)) + (9*GetSplit(x+1, y-1)) + (3*GetSplit(x, y)) + (GetSplit(x+1, y));
2532 
2533  return (edgewidth[index1] < edgewidth[index2]) ? (edgewidth[index1]) : (edgewidth[index2]);
2534 }
2535 
2536 
2537 
2541 float Map::GetEdgeWidthY(int x, int y)
2542 {
2543  // Boundary values
2544  if (x-1 < 0 || y < 0 || x+1 >= width || y+1 >= height)
2545  return 0.0f;
2546 
2547  int index1, index2;
2548 
2549  // Check if the edge at (x, y+1) is adjacent (i.e. same height and terrain type)
2550  if (!AdjacentEdges(x, y, kBottomEdge))
2551  {
2552  // different height or terrain, so undefined
2553  return 0.0f;
2554  }
2555 
2556  // Check to see that the right edges are both adjacent. If either is not, get the edge width using the left two tiles
2557  if (!AdjacentEdges(x, y, kRightEdge) || !AdjacentEdges(x, y+1, kRightEdge))
2558  {
2559  //(x-1, y-1), (x-1, y), (x, y+1), (x, y)
2560  index1 = (27*GetSplit(x-1, y-1)) + (9*GetSplit(x-1, y)) + (3*GetSplit(x, y+1)) + (GetSplit(x, y));
2561  return edgewidth[index1];
2562  }
2563 
2564  // Check to see that the left edges are both adjacent. If either is not, get the edge width using the right two tiles
2565  if (!AdjacentEdges(x, y, kLeftEdge) || !AdjacentEdges(x, y+1, kLeftEdge))
2566  {
2567  //(x+1, y), (x+1, y+1), (x, y) (x, y+1)
2568  index1 = (27*GetSplit(x+1, y)) + (9*GetSplit(x+1, y+1)) + (3*GetSplit(x, y)) + (GetSplit(x, y+1));
2569  return edgewidth[index1];
2570  }
2571 
2572  // Otherwise, return the minimum of the edge widths from the top edges and bottom edges
2573  index1 = (27*GetSplit(x-1, y-1)) + (9*GetSplit(x-1, y)) + (3*GetSplit(x, y+1)) + (GetSplit(x, y));
2574  index2 = (27*GetSplit(x+1, y)) + (9*GetSplit(x+1, y+1)) + (3*GetSplit(x, y)) + (GetSplit(x, y+1));
2575 
2576  return (edgewidth[index1] < edgewidth[index2]) ? (edgewidth[index1]) : (edgewidth[index2]);
2577 }
2578 
Map::GetEdgeWidthX
float GetEdgeWidthX(int x, int y)
Returns the edge width between (x, y) and (x+1, y)
Definition: Map.cpp:2498
Map::GetEdgeWidthY
float GetEdgeWidthY(int x, int y)
Returns the edge width between (x, y) and (x, y+1)
Definition: Map.cpp:2541
halfTile::corners
long corners[3]
Definition: Map.h:108
kRaw
@ kRaw
Definition: Map.h:124
fieldData::index
uint32_t index
Definition: Map.cpp:512
loc::x
int x
Definition: MapGenerators.cpp:296
BitMapPic
Definition: BitMap.h:46
Map::GetNodeNum
int GetNodeNum(int x, int y, tCorner c=kNone)
Gets the abstract Graph node number for this tile.
Definition: Map.cpp:2339
kRightEdge
@ kRightEdge
Definition: Map.h:83
header::platform
uint32_t platform
Definition: Map.cpp:493
header::structcount
uint32_t structcount
Definition: Map.cpp:496
header::magic
uint32_t magic
Definition: Map.cpp:491
header::dataoffset
uint32_t dataoffset
Definition: Map.cpp:497
recVec
A generic vector (essentially the same as a point, but offers normalization)
Definition: GLUtil.h:78
min
double min(double a, double b)
Definition: FPUtil.h:35
Map::loadOctileCorner
void loadOctileCorner(FILE *f, int height, int width)
Definition: Map.cpp:428
Map::OpenGLDraw
void OpenGLDraw(tDisplay how=kPolygons) const
Does actual OpenGL drawing of the map.
Definition: Map.cpp:1777
kBitmap
@ kBitmap
Definition: Map.h:35
recVec::z
GLdouble z
Definition: GLUtil.h:98
Map::GetCoordinateScale
double GetCoordinateScale()
Returns the scale multiplier between openGL coordinates and map coordinates.
Definition: Map.cpp:1892
fullData::sa
structArray sa
Definition: Map.cpp:517
BitMapPic::GetHeight
int GetHeight()
Definition: BitMap.h:55
terrainBits
const int terrainBits
Definition: Map.h:49
kUndefinedHeight
@ kUndefinedHeight
Definition: Map.h:90
Map::mapType
tMapType mapType
Definition: Map.h:246
loc::y
int y
Definition: MapGenerators.cpp:296
Map::SetNodeNum
void SetNodeNum(int num, int x, int y, tCorner c=kNone)
Sets the abstract Graph node number for this tile.
Definition: Map.cpp:2319
kTrees
@ kTrees
Definition: Map.h:59
Map::drawLand
bool drawLand
Definition: Map.h:240
ONE
static const double ONE
Definition: GLUtil.h:59
kOutOfBounds
@ kOutOfBounds
Definition: Map.h:52
fieldData::label
uint32_t label
Definition: Map.cpp:510
halfTile::halfTile
halfTile()
Construct a half tile, initializing to flat values.
Definition: Map.cpp:61
kFast
@ kFast
Definition: Map.h:34
Map::SetRectHeight
void SetRectHeight(long x1, long y1, long x2, long y2, long h, tTerrain type=kGround)
Set the height and terrain of a set of tiles.
Definition: Map.cpp:1578
Map::SetDrawLand
void SetDrawLand(bool land)
Toggles whether the land is draw when you call OpenGLDraw.
Definition: Map.cpp:1738
kPoints
@ kPoints
Definition: Map.h:41
halfTile::type
tTerrain type
Definition: Map.h:109
Map::GetPointFromCoordinate
void GetPointFromCoordinate(point3d loc, int &px, int &py) const
Definition: Map.cpp:1900
kBlight
@ kBlight
Definition: Map.h:58
header::fileversion
uint32_t fileversion
Definition: Map.cpp:495
kTopRight
@ kTopRight
Definition: Map.h:99
header::filetype
uint32_t filetype
Definition: Map.cpp:494
tEdge
tEdge
Definition: Map.h:80
structArray::fieldCnt
uint32_t fieldCnt
Definition: Map.cpp:503
kWinter
@ kWinter
Definition: Map.h:32
verbose
static const bool verbose
Definition: Map.cpp:23
Map::updated
bool updated
Definition: Map.h:242
width
int width
Definition: SFML_HOG.cpp:54
Map::GetTile
Tile & GetTile(long x, long y)
Return the tile at location x, y.
Definition: Map.cpp:994
tTileset
tTileset
Definition: Map.h:29
Map::Load
void Load(const char *filename)
Resets the current map by loading the file passed in.
Definition: Map.cpp:257
Tile::tile1
halfTile tile1
Definition: Map.h:116
kTopLeft
@ kTopLeft
Definition: Map.h:98
Map::land
Tile ** land
Definition: Map.h:239
Map::saveRaw
void saveRaw(FILE *f)
Definition: Map.cpp:896
Map::AdjacentCorners
bool AdjacentCorners(long x, long y, tCorner corner) const
Definition: Map.cpp:1661
Map::Print
void Print(int scale=1)
Do an ASCII/ANSI print out of the map.
Definition: Map.cpp:917
structArray::structSize
uint32_t structSize
Definition: Map.cpp:505
kOctile
@ kOctile
Definition: Map.h:121
Map::loadOctile
void loadOctile(FILE *f, int height, int width)
Definition: Map.cpp:362
edgewidth
double edgewidth[81]
Definition: Map.cpp:2394
Map::DoNormal
void DoNormal(tSplit split, halfTile *t, int x, int y) const
does a rough approximation of the normal for a particular halfTile.
Definition: Map.cpp:2224
kSokoban
@ kSokoban
Definition: Map.h:123
structArray::fieldOffset
uint32_t fieldOffset
Definition: Map.cpp:504
Map::tileSet
tTileset tileSet
Definition: Map.h:247
Tile::split
tSplit split
Definition: Map.h:117
structArray
Definition: Map.cpp:500
tCorner
tCorner
Definition: Map.h:96
Map::SetCornerHeight
void SetCornerHeight(long x, long y, tCorner which, long height, tSplitSide split=kWholeTile)
Set the height of any one corner of a tile.
Definition: Map.cpp:1335
kNoSplit
@ kNoSplit
Definition: Map.h:68
kGround
@ kGround
Definition: Map.h:55
tSplit
tSplit
Definition: Map.h:67
kBottomLeft
@ kBottomLeft
Definition: Map.h:100
halfTile
Definition: Map.h:104
Tile::tile2
halfTile tile2
Definition: Map.h:116
kNoGraphNode
const int kNoGraphNode
Definition: Map.h:93
Map::DoVertexColor
void DoVertexColor(tTerrain type, int height, bool darken=false) const
Using OpenGL set the correct color for a particular vertex.
Definition: Map.cpp:2147
InitTextures
void InitTextures()
Definition: Map.cpp:25
kSwamp
@ kSwamp
Definition: Map.h:56
kFallTile
@ kFallTile
Definition: Map.h:31
loc
Definition: MapGenerators.cpp:296
BitMapPic::GetWidth
int GetWidth()
Definition: BitMap.h:54
Map::SetSplit
void SetSplit(long x, long y, tSplit split)
Set the split of the tile at x, y.
Definition: Map.cpp:1014
Map::Scale
void Scale(long newWidth, long newHeight)
Definition: Map.cpp:177
kFall
@ kFall
Definition: Map.h:30
Map::width
int width
Definition: Map.h:238
point3d
#define point3d
Definition: GLUtil.h:123
kForwardSplit
@ kForwardSplit
Definition: Map.h:69
kBackwardSplit
@ kBackwardSplit
Definition: Map.h:70
Map::saveOctile
void saveOctile(FILE *f)
Definition: Map.cpp:873
Map::dList
GLuint dList
Definition: Map.h:241
Map::Trim
void Trim()
Definition: Map.cpp:212
header
Definition: Map.cpp:489
ROOT_TWO
static const double ROOT_TWO
Definition: GLUtil.h:61
Map::GetMapWidth
long GetMapWidth() const
return the width of the map
Definition: Map.h:163
fieldData::fieldType
uint32_t fieldType
Definition: Map.cpp:511
Map::SetTileSet
void SetTileSet(tTileset ts)
Choose the tileset used for land colors.
Definition: Map.cpp:1747
Map::Map
Map(long width, long height)
Create a new map of a particular size.
Definition: Map.cpp:84
Map::loadRaw
void loadRaw(FILE *f, int height, int width)
Definition: Map.cpp:340
kInternalEdge
@ kInternalEdge
Definition: Map.h:81
Map::GetTerrainType
long GetTerrainType(long x, long y, tSplitSide split=kWholeTile) const
Get the terrain type of the (split) tile at x, y.
Definition: Map.cpp:1028
kUndefined
@ kUndefined
Definition: Map.h:60
Tile::Tile
Tile()
Construct a tile with no split.
Definition: Map.cpp:75
Map::sizeMultiplier
int sizeMultiplier
Definition: Map.h:243
height
int height
Definition: SFML_HOG.cpp:54
Map::SetHeight
void SetHeight(long x, long y, long height, tSplitSide split=kWholeTile)
Set the (flat) height of the tile at x, y.
Definition: Map.cpp:1173
fieldData
Definition: Map.cpp:508
BitMap.h
Map::GetCornerHeight
long GetCornerHeight(long x, long y, tCorner which, tEdge edge) const
Set the height of any one corner of a tile.
Definition: Map.cpp:1204
Map::height
int height
Definition: Map.h:238
kOutOfBounds2
@ kOutOfBounds2
Definition: Map.h:53
max
#define max(a, b)
Definition: MinimalSectorAbstraction.cpp:40
GLUtil.h
Map::GetMapName
const char * GetMapName()
Definition: Map.cpp:981
kWholeTile
@ kWholeTile
Definition: Map.h:75
TWO
static const double TWO
Definition: GLUtil.h:60
Map::GetHeight
long GetHeight(long x, long y, tSplitSide split=kWholeTile)
Get the (flat) height of the tile at x, y.
Definition: Map.cpp:1144
kOctileCorner
@ kOctileCorner
Definition: Map.h:122
halfTile::node
long node
Definition: Map.h:110
kLeftSide
@ kLeftSide
Definition: Map.h:76
kLines
@ kLines
Definition: Map.h:40
tTerrain
tTerrain
Definition: Map.h:51
kWinterTile
@ kWinterTile
Definition: Map.h:33
BitMapPic::Save
void Save(const char *file)
Definition: BitMap.cpp:169
wall
GLuint wall
Definition: Map.cpp:19
fullData::fields
std::vector< fieldData > fields
Definition: Map.cpp:518
tDisplay
tDisplay
Definition: Map.h:38
Map::CanStep
bool CanStep(long x1, long y1, long x2, long y2) const
Definition: Map.cpp:1694
kWater
@ kWater
Definition: Map.h:54
Map::revision
int revision
Definition: Map.h:244
Colors::red
const rgbColor red
Definition: Colors.h:128
std
Definition: CanonicalGraphEnvironment.h:26
BitMapPic::GetBytes
uint8_t * GetBytes()
Definition: BitMap.h:59
kPolygons
@ kPolygons
Definition: Map.h:39
Map::GetMapHeight
long GetMapHeight() const
return the height of the map
Definition: Map.h:165
Map::~Map
~Map()
Definition: Map.cpp:169
Tile
Definition: Map.h:113
Map::GetTileSet
tTileset GetTileSet()
Get the tileset used for land colors.
Definition: Map.cpp:1758
kBottomRight
@ kBottomRight
Definition: Map.h:101
Map::GetSplit
tSplit GetSplit(long x, long y) const
Return the split of the tile at x, y.
Definition: Map.cpp:1004
Map::drawLandQuickly
void drawLandQuickly() const
Definition: Map.cpp:2254
split
std::vector< std::string > split(const std::string &s, char delim)
Splits a string into elements.
Definition: StringUtils.cpp:16
Map::SmoothSetRectHeight
void SmoothSetRectHeight(long x1, long y1, long x2, long y2, long h, tTerrain type=kGround)
Places a rectangle into the map, but also modifies the edges to make the transition smooth.
Definition: Map.cpp:1395
kTopEdge
@ kTopEdge
Definition: Map.h:84
ONE_OVER_ROOT_TWO
static const double ONE_OVER_ROOT_TWO
Definition: GLUtil.h:62
Colors::blue
const rgbColor blue
Definition: Colors.h:142
Map::map_name
char map_name[128]
Definition: Map.h:245
Map::tryLoadRollingStone
bool tryLoadRollingStone(FILE *f)
Definition: Map.cpp:696
Map::AdjacentEdges
bool AdjacentEdges(long x, long y, tEdge edge) const
Is the tile at x, y adjacent across the edge?
Definition: Map.cpp:1602
Map.h
Map::GetOpenGLCoord
bool GetOpenGLCoord(int _x, int _y, GLdouble &x, GLdouble &y, GLdouble &z, GLdouble &radius) const
Get the openGL coordinates of a given tile.
Definition: Map.cpp:1826
kLeftEdge
@ kLeftEdge
Definition: Map.h:82
kGrass
@ kGrass
Definition: Map.h:57
Map::DrawTile
void DrawTile(Tile *t, int x, int y, tDisplay how) const
Draw a single tile.
Definition: Map.cpp:1941
structArray::id
uint32_t id
Definition: Map.cpp:502
Map::SetTerrainType
void SetTerrainType(int32_t x1, int32_t y1, int32_t x2, int32_t y2, tTerrain t)
Map::SetTerrainType()
Definition: Map.cpp:1049
kBottomEdge
@ kBottomEdge
Definition: Map.h:85
recVec::y
GLdouble y
Definition: GLUtil.h:98
Map::isLegalStone
bool isLegalStone(char c)
Definition: Map.cpp:817
fullData
Definition: Map.cpp:515
Colors::green
const rgbColor green
Definition: Colors.h:135
tSplitSide
tSplitSide
Definition: Map.h:74
recVec::x
GLdouble x
Definition: GLUtil.h:98
Map::Save
void Save(std::stringstream &data)
unimplemented.
Definition: Map.cpp:831
recVec::normalise
void normalise()
Normalize a vector.
Definition: GLUtil.cpp:39
Map::tryDragonAge
bool tryDragonAge(FILE *f)
Definition: Map.cpp:521
Map::paintRoomInside
void paintRoomInside(int x, int y)
Definition: Map.cpp:800
node
Nodes to be stored within a Graph.
Definition: Graph.h:170
Map
A tile-based representation of the world.
Definition: Map.h:142
header::version
uint32_t version
Definition: Map.cpp:492
kNone
@ kNone
Definition: Map.h:97
edge
Edge class for connections between node in a Graph.
Definition: Graph.h:129
kRightSide
@ kRightSide
Definition: Map.h:77