Import existing source tree; original VCS history is no longer available. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
221 lines
4.9 KiB
C++
221 lines
4.9 KiB
C++
/*(GPL)
|
|
------------------------------------------------------------
|
|
Kobo Deluxe - An enhanced SDL port of XKobo
|
|
------------------------------------------------------------
|
|
* Copyright (C) 1995, 1996 Akira Higuchi
|
|
* Copyright (C) 2002, 2007 David Olofson
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
* option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "map.h"
|
|
#include "random.h"
|
|
|
|
void _map::init()
|
|
{
|
|
int i, j;
|
|
for(i = 0; i < MAP_SIZEX; i++)
|
|
for(j = 0; j < MAP_SIZEY; j++)
|
|
pos(i, j) = SPACE;
|
|
}
|
|
|
|
void _map::make_maze(int x, int y, int difx, int dify)
|
|
{
|
|
int i, j;
|
|
int vx, vy;
|
|
|
|
/* clear */
|
|
for(i = x - difx; i <= x + difx; i++)
|
|
for(j = y - dify; j <= y + dify; j++)
|
|
pos(i, j) = SPACE;
|
|
|
|
/* push initial sites */
|
|
site_max = 0;
|
|
if(gamerand.get(8) < 128)
|
|
{
|
|
pos(x, y) = CORE | R_MASK | L_MASK;
|
|
maze_push(x - 1, y);
|
|
maze_push(x + 1, y);
|
|
}
|
|
else
|
|
{
|
|
pos(x, y) = CORE | U_MASK | D_MASK;
|
|
maze_push(x, y - 1);
|
|
maze_push(x, y + 1);
|
|
}
|
|
|
|
for(;;)
|
|
{
|
|
/* get one */
|
|
if(maze_pop())
|
|
break;
|
|
vx = sitex[site_max];
|
|
vy = sitey[site_max];
|
|
|
|
int dirs[4];
|
|
for(i = 0; i < 4; i++)
|
|
dirs[i] = 0;
|
|
int dirs_max = 0;
|
|
if(maze_judge(x, y, difx, dify, vx + 2, vy + 0))
|
|
dirs[dirs_max++] = 1;
|
|
if(maze_judge(x, y, difx, dify, vx + 0, vy + 2))
|
|
dirs[dirs_max++] = 2;
|
|
if(maze_judge(x, y, difx, dify, vx - 2, vy + 0))
|
|
dirs[dirs_max++] = 3;
|
|
if(maze_judge(x, y, difx, dify, vx + 0, vy - 2))
|
|
dirs[dirs_max++] = 4;
|
|
if(dirs_max == 0)
|
|
continue; /* there are no places to go */
|
|
i = gamerand.get() % dirs_max;
|
|
maze_move_and_push(vx, vy, dirs[i]);
|
|
maze_push(vx, vy);
|
|
}
|
|
}
|
|
|
|
int _map::maze_pop()
|
|
{
|
|
if(site_max == 0)
|
|
return 1;
|
|
int i = gamerand.get() % site_max;
|
|
site_max--;
|
|
if(i != site_max)
|
|
{
|
|
int tmpx = sitex[site_max];
|
|
int tmpy = sitey[site_max];
|
|
sitex[site_max] = sitex[i];
|
|
sitey[site_max] = sitey[i];
|
|
sitex[i] = tmpx;
|
|
sitey[i] = tmpy;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void _map::maze_push(int x, int y)
|
|
{
|
|
sitex[site_max] = x;
|
|
sitey[site_max++] = y;
|
|
pos(x, y) = WALL;
|
|
}
|
|
|
|
void _map::maze_move_and_push(int x, int y, int d)
|
|
{
|
|
int x1 = x;
|
|
int y1 = y;
|
|
switch (d)
|
|
{
|
|
case 1:
|
|
{
|
|
x1 += 2;
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
y1 += 2;
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
x1 -= 2;
|
|
break;
|
|
}
|
|
case 4:
|
|
{
|
|
y1 -= 2;
|
|
break;
|
|
}
|
|
}
|
|
maze_push(x1, y1);
|
|
pos((x + x1) / 2, (y + y1) / 2) = WALL;
|
|
}
|
|
|
|
int _map::maze_judge(int cx, int cy, int dx, int dy, int x, int y)
|
|
{
|
|
if((x < cx - dx) || (x > cx + dx) || (y < cy - dy)
|
|
|| (y > cy + dy))
|
|
return 0;
|
|
if(pos(x, y) == WALL)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
// Translate map "tile state bits" into tile index
|
|
//
|
|
// The hard end nodes need some special treatment here. There are 16 direction
|
|
// mask combinations, but only 4 are valid in this case. So, we use a 16 x 2
|
|
// bit lookup "table" (packed into an 'int') to get the right tile index.
|
|
//
|
|
// 00 01 10 11 <-- mask bits 1 (right) and 0 (up)
|
|
// -----------------------------------------------------
|
|
// 00 -- 00 01 --
|
|
// 01 10 -- -- -- <-- Tile indices
|
|
// 10 11 -- -- --
|
|
// 11 -- -- -- --
|
|
// ^
|
|
// '- mask bits 3 (left) and 2 (down)
|
|
//
|
|
// Thus, our table is 00000000 00000011 00000010 00010000 == 0x00030210
|
|
//
|
|
static inline int bits2tile(int n)
|
|
{
|
|
if(n & CORE) // Core
|
|
return n & (U_MASK | D_MASK) ? 6 : 7;
|
|
else if(n & HARD) // One of the 4 indestructible end nodes
|
|
return (0x00030210 >> ((n & 15) << 1)) & 3;
|
|
else if(n == 5) // Vertical pipe
|
|
return pubrand.get(2) ? 13 : 4;
|
|
else if(n == 10) // Vertical pipe
|
|
return pubrand.get(2) ? 18 : 5;
|
|
else // Other pipe parts or normal end nodes
|
|
return n + 8;
|
|
}
|
|
|
|
void _map::convert(unsigned ratio)
|
|
{
|
|
int i, j;
|
|
int p = 0;
|
|
for(i = 0; i < MAP_SIZEX; i++)
|
|
for(j = 0; j < MAP_SIZEY; j++)
|
|
{
|
|
p = pos(i, j) & CORE;
|
|
if(IS_SPACE(pos(i, j)))
|
|
{
|
|
clearpos(i, j);
|
|
continue;
|
|
}
|
|
if((j > 0) && !IS_SPACE(pos(i, j - 1)))
|
|
p |= U_MASK;
|
|
if((i < MAP_SIZEX - 1) && !IS_SPACE(pos(i + 1, j)))
|
|
p |= R_MASK;
|
|
if((j < MAP_SIZEY - 1) && !IS_SPACE(pos(i, j + 1)))
|
|
p |= D_MASK;
|
|
if((i > 0) && !IS_SPACE(pos(i - 1, j)))
|
|
p |= L_MASK;
|
|
if((p == U_MASK) || (p == R_MASK) || (p == D_MASK)
|
|
|| (p == L_MASK))
|
|
{
|
|
if(gamerand.get(8) < ratio)
|
|
p |= HARD;
|
|
}
|
|
pos(i, j) = (bits2tile(p) << 8) | p;
|
|
}
|
|
}
|
|
|
|
|
|
void _map::clearpos(int x, int y)
|
|
{
|
|
pos(x, y) = (gamerand.get(6) << 8) | SPACE;
|
|
}
|