From 677385ffdd1e330cfba4dd712ca58595feeea41d Mon Sep 17 00:00:00 2001 From: schneefux Date: Mon, 7 Oct 2013 14:11:24 +0200 Subject: initial commit --- mapgen.c | 414 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 414 insertions(+) create mode 100644 mapgen.c (limited to 'mapgen.c') 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); +} -- cgit v1.3.1