diff options
Diffstat (limited to 'mapgen.c')
| -rw-r--r-- | mapgen.c | 414 |
1 files changed, 414 insertions, 0 deletions
diff --git a/mapgen.c b/mapgen.c new file mode 100644 index 0000000..f18df4d --- /dev/null +++ b/mapgen.c @@ -0,0 +1,414 @@ +#include "global.h"
+#include "mapgen.h"
+#include "draw.h"
+#include "hardware.h"
+#include "sprites.h"
+
+static int cntunvisit(union st_field cnt)
+{
+ int c = 0;
+ if(cnt.side.west != SPACE)c++;
+ if(cnt.side.east != SPACE)c++;
+ if(cnt.side.north != SPACE)c++;
+ if(cnt.side.south != SPACE)c++;
+
+ return (c > 1)?c:0;
+}
+
+static int cntempty(int x, int y)
+{
+ union st_field c;
+ int cnt = 0;
+
+ c.byte = 0;
+
+ if(x - 1 > 0)c.side.west = map[x - 1][y];else c.side.west = WALL;
+ if(x + 1 < MAPSIZE - 1)c.side.east = map[x + 1][y];else c.side.east = WALL;
+ if(y - 1 > 0)c.side.north = map[x][y - 1];else c.side.north = WALL;
+ if(y + 1 < MAPSIZE - 1)c.side.south = map[x][y + 1];else c.side.south = WALL;
+
+ if(c.side.west == SPACE)cnt++;
+ if(c.side.east == SPACE)cnt++;
+ if(c.side.north == SPACE)cnt++;
+ if(c.side.south == SPACE)cnt++;
+
+ return cnt;
+}
+
+static int cntwall(int x, int y)
+{
+ union st_field c;
+ int cnt = 0;
+
+ c.byte = 0;
+
+ if(x - 1 > 0)c.side.west = map[x - 1][y];else c.side.west = WALL;
+ if(x + 1 < MAPSIZE - 1)c.side.east = map[x + 1][y];else c.side.east = WALL;
+ if(y - 1 > 0)c.side.north = map[x][y - 1];else c.side.north = WALL;
+ if(y + 1 < MAPSIZE - 1)c.side.south = map[x][y + 1];else c.side.south = WALL;
+
+ if(c.side.west == WALL)cnt++;
+ if(c.side.east == WALL)cnt++;
+ if(c.side.north == WALL)cnt++;
+ if(c.side.south == WALL)cnt++;
+
+ return cnt;
+}
+
+static union st_field get(int x, int y)
+{
+ union st_field c;
+
+ c.byte = 0;
+
+ if(x - 1 > 0)c.side.west = map[x - 1][y];
+ if(x + 1 < MAPSIZE - 1)c.side.east = map[x + 1][y];
+ if(y - 1 > 0)c.side.north = map[x][y - 1];
+ if(y + 1 < MAPSIZE - 1)c.side.south = map[x][y + 1];
+
+ return c;
+}
+
+static int hunt(int *x, int *y)
+{
+ for(*x = 1; *x < MAPSIZE - 1; *x+=2)
+ {
+ for(*y = 1; *y < MAPSIZE - 1; *y+=2)
+ {
+ if(map[*x][*y] == WALL)
+ {
+ if(cntunvisit(get(*x, *y)) > 1)
+ {
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+
+static int kill(int *x, int *y, union st_field this)
+{
+ int fail1 = FALSE, fail2 = FALSE, fail3 = FALSE, fail4 = FALSE;
+ while(!keydown(31))
+ {
+ if(cntunvisit(this) == 0)fail1 = fail2 = fail3 = fail4 = TRUE;
+
+ switch(random() % 4)
+ {
+ case 0:
+ if(this.side.west == WALL && fail1 == FALSE)
+ {
+ if(cntunvisit(get(*x - 2, *y)) > 0)
+ {
+ map[*x - 1][*y] = SPACE;
+ *x -= 2;
+ return TRUE;
+ }
+ else
+ {
+ fail1 = TRUE;
+ }
+ }
+ else
+ {
+ fail1 = TRUE;
+ }
+ break;
+
+ case 1:
+ if(this.side.east == WALL && fail2 == FALSE)
+ {
+ if(cntunvisit(get(*x + 2, *y)) > 0)
+ {
+ map[*x + 1][*y] = SPACE;
+ *x += 2;
+ return TRUE;
+ }
+ else
+ {
+ fail2 = TRUE;
+ }
+ }
+ else
+ {
+ fail2 = TRUE;
+ }
+ break;
+
+ case 2:
+ if(this.side.north == WALL && fail3 == FALSE)
+ {
+ if(cntunvisit(get(*x, *y - 2)) > 0)
+ {
+ map[*x][*y - 1] = SPACE;
+ *y -= 2;
+ return TRUE;
+ }
+ else
+ {
+ fail3 = TRUE;
+ }
+ }
+ else
+ {
+ fail3 = TRUE;
+ }
+ break;
+
+ case 3:
+ if(this.side.south == WALL && fail4 == FALSE)
+ {
+ if(cntunvisit(get(*x, *y + 2)) > 0)
+ {
+ map[*x][*y + 1] = SPACE;
+ *y += 2;
+ return TRUE;
+ }
+ else
+ {
+ fail4 = TRUE;
+ }
+ }
+ else
+ {
+ fail4 = TRUE;
+ }
+ break;
+ }
+
+ if(fail1 == TRUE && fail2 == TRUE && fail3 == TRUE && fail4 == TRUE)
+ {
+ return hunt(x, y);
+ }
+ }
+ return FALSE;
+}
+
+static int solve()
+{
+ int priotable[4];
+ int curx = 1, cury = 1;
+ int prex = 0, prey = -1;
+ int deltax = 1, deltay = 0;
+ int dir, dirx, diry;
+start:
+ for(curx = 0; curx < MAPSIZE; curx++)
+ {
+ for(cury = 0; cury < MAPSIZE; cury++)
+ {
+ if((curx != 1 && cury != 1) && (curx != MAPSIZE - 2 && cury != MAPSIZE - 2))
+ {
+ if(map[curx][cury] == SPACE)
+ {
+ if(cntempty(curx, cury) == 1)
+ {
+ map[curx][cury] = CHECKED;
+ clear_vram();
+ drawgenmap();
+ display_vram();
+ goto start;
+ }
+ }
+ }
+ }
+ }
+
+ curx = cury = 1;
+
+ while(curx != MAPSIZE - 2 || cury != MAPSIZE - 2)
+ {
+ deltax = curx - prex;
+ deltay = cury - prey;
+
+ if(deltax == 0)
+ {
+ if(deltay == 1)
+ dir = SOUTH;
+ else
+ dir = NORTH;
+ }
+ else
+ {
+ if(deltax == 1)
+ dir = EAST;
+ else
+ dir = WEST;
+ }
+
+ switch(dir)
+ {
+ case NORTH:
+ priotable[0] = EAST;
+ priotable[1] = NORTH;
+ priotable[2] = WEST;
+ priotable[3] = SOUTH;
+ break;
+ case SOUTH:
+ priotable[0] = WEST;
+ priotable[1] = SOUTH;
+ priotable[2] = EAST;
+ priotable[3] = NORTH;
+ break;
+ case EAST:
+ priotable[0] = SOUTH;
+ priotable[1] = EAST;
+ priotable[2] = NORTH;
+ priotable[3] = WEST;
+ break;
+ case WEST:
+ priotable[0] = NORTH;
+ priotable[1] = WEST;
+ priotable[2] = SOUTH;
+ priotable[3] = EAST;
+ }
+
+ for(dir = 0; dir < 4; dir++)
+ {
+ switch(priotable[dir])
+ {
+ case NORTH:
+ dirx = 0;
+ diry = -1;
+ break;
+ case EAST:
+ dirx = 1;
+ diry = 0;
+ break;
+ case SOUTH:
+ dirx = 0;
+ diry = 1;
+ break;
+ case WEST:
+ dirx = -1;
+ diry = 0;
+ break;
+ }
+ if(curx + dirx < MAPSIZE - 1 && curx + dirx > 0 && cury + diry < MAPSIZE - 1 && cury + diry > 0 && map[curx + dirx][cury + diry] == SPACE)
+ {
+ prex = curx;
+ prey = cury;
+ curx += dirx;
+ cury += diry;
+ break;
+ }
+ }
+
+ if(curx == 1 && cury == 1)
+ {
+ return FALSE;
+ }
+
+ if(IsEmulator())
+ {
+ clear_vram();
+ drawgenmap();
+ pixel((int)(curx * sizex + 1), (int)(cury * sizey + 1));
+ display_vram();
+ }
+ }
+
+ for(curx = 0; curx < MAPSIZE; curx++)
+ {
+ for(cury = 0; cury < MAPSIZE; cury++)
+ {
+ if(map[curx][cury] == 1)
+ {
+ map[curx][cury] = 1;
+ solids[curx][cury] = SOLID;
+ }
+ else
+ {
+ map[curx][cury] = 0;
+ solids[curx][cury] = UNSOLID;
+ }
+ }
+ }
+
+ for(curx = 0; curx < MAPSIZE; curx++)
+ {
+ for(cury = 0; cury < MAPSIZE; cury++)
+ {
+ if(map[curx][cury] == SPACE)
+ {
+ if(cntwall(curx, cury) >= 3)
+ {
+ sprites = (struct st_sprite *) realloc(sprites, (spritecnt + 1) * sizeof(struct st_sprite));
+ if(sprites == NULL)error();
+ sprites[spritecnt].x = curx + 0.5;
+ sprites[spritecnt].y = cury + 0.5;
+ sprites[spritecnt].texture.ptr = &pack;
+ sprites[spritecnt].texture.width = 8;
+ sprites[spritecnt].texture.height = 8;
+ sprites[spritecnt].type = TYPE_PACK;
+ sprites[spritecnt].effect = 50;
+ spritecnt++;
+ solids[curx][cury] = SPRITE;
+ }
+ }
+ else if(map[curx][cury] == WALL)
+ {
+ if(cntwall(curx, cury) == 2)
+ {
+ heights[curx][cury] = 32;
+ }
+ }
+ }
+ }
+
+ for(curx = 0; curx < MAPSIZE; curx++)
+ {
+ for(cury = 0; cury < MAPSIZE; cury++)
+ {
+ if(map[curx][cury] == SPACE && cntwall(curx, cury) < 2)
+ {
+ int dx, dy, fail1, fail2, fail3, fail4;
+ fail1 = fail2 = fail3 = fail4 = FALSE;
+
+ while(fail1 == FALSE && fail2 == FALSE && fail3 == FALSE & fail4 == FALSE)
+ {
+ switch(random() % 4)
+ {
+ case 0: dx = 0; dy = 1; fail1 = TRUE; break;
+ case 1: dx = 0; dy = -1; fail2 = TRUE; break;
+ case 2: dx = 1; dy = 0; fail3 = TRUE; break;
+ case 3: dx = -1; dy = 0; fail4 = TRUE; break;
+ }
+ if(curx + dx < MAPSIZE && curx + dx >= 0 && cury + dy < MAPSIZE && cury + dy >= 0)
+ {
+ if(map[curx + dx][cury + dy] == SPACE)
+ {
+ map[curx + dx][cury + dy] = DOOR;
+ solids[curx + dx][cury + dy] = SOLID;
+ fail1 = fail2 = fail3 = fail4 = TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ clear_vram();
+ drawgenmap();
+ display_vram();
+
+ return TRUE;
+}
+
+void maze()
+{
+ do
+ {
+ int x = 1, y = 1, exit = TRUE;
+
+ fill(&map, WALL, MAPSIZE * MAPSIZE);
+ while(exit == TRUE)
+ {
+ map[x][y] = SPACE;
+ exit = kill(&x, &y, get(x, y));
+ clear_vram();
+ drawgenmap();
+ display_vram();
+ }
+ }while(solve() == FALSE);
+}
|
