aboutsummaryrefslogtreecommitdiff
path: root/src/maps.c
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2023-11-05 11:22:55 +0000
committerJuan J. Martinez <jjm@usebox.net>2023-11-05 11:31:28 +0000
commit2fbdf974338bde8576efdae40a819a76b2391033 (patch)
tree64d41a37470143f142344f9a439d96de3e7918c2 /src/maps.c
downloadkitsunes-curse-2fbdf974338bde8576efdae40a819a76b2391033.tar.gz
kitsunes-curse-2fbdf974338bde8576efdae40a819a76b2391033.zip
Initial import of the open source release
Diffstat (limited to 'src/maps.c')
-rw-r--r--src/maps.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/src/maps.c b/src/maps.c
new file mode 100644
index 0000000..87928b2
--- /dev/null
+++ b/src/maps.c
@@ -0,0 +1,239 @@
+/*
+ Kitsune's Curse
+ Copyright (C) 2020-2023 Juan J. Martinez <jjm@usebox.net>
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+ */
+#include <stdint.h>
+
+#include "aplib.h"
+#include "main.h"
+#include "splib.h"
+
+#include "tiles.h"
+
+#define LOCAL
+#include "maps.h"
+#include "stage.h"
+
+#include "entities.h"
+
+// working map (using 4-bit per tile), 8x8
+static uint8_t ml;
+static const unsigned char *map_ents;
+static uint8_t blocked;
+
+void _expand_map()
+{
+ uint8_t *b = (uint8_t *)BUFF_ADDR;
+ uint16_t i;
+
+ // uncompress at the end of the working area
+ aplib_uncompress(b, (uint8_t *)(map[cmap] + 2));
+
+ // expand from 4-bpt to 8-bpt
+ for (i = 0; i < TMW * TMH; i += 2)
+ {
+ wmap[i] = (*b >> 4) + ts;
+ wmap[i + 1] = (*b & 0x0f) + ts;
+ b++;
+ }
+}
+
+void draw_map()
+{
+ uint8_t i, j, k, c, m;
+
+ validate_screen();
+
+ // draw the bottom to top; invalidate is LIFO
+ for (j = TMH; j; --j)
+ {
+ k = j - 1;
+ for (i = 0; i < TMW; ++i)
+ {
+ c = wmap[i + k * TMW];
+
+ // only if is part of a tileset
+ if (c < LAST_TILE_TILESET)
+ {
+ m = c & 15;
+
+ // special tiles: bricks
+ if (!m || m == 12) {
+ if (k & 1)
+ ++c;
+ }
+ } else if (c == BLOCKED_OPEN_DOOR)
+ c = BLOCKED_OPEN_DOOR_TILE;
+
+ put_tile(bgtiles[c], get_tile_xy(i, k));
+ }
+ }
+}
+
+void init_map(uint8_t m)
+{
+#ifdef DEBUG
+ pad_numbers(wmap, 2, m);
+ set_text_ink(15, 15, 15);
+ put_text(wmap, 0, 192);
+#endif
+
+ cmap = m;
+ // map length (not including tileset or flags)
+ ml = map[cmap][0];
+ // tileset
+ ts = (map[cmap][1] & 0x0f) << 4;
+ blocked = map[cmap][1] & 0xf0;
+ // map_ents
+ map_ents = map[cmap] + 2 + ml;
+
+ _expand_map();
+
+ exit_up = cmap - WMAPS;
+ offset_up = 0;
+ exit_down = cmap + WMAPS;
+ offset_down = 0;
+
+ init_entities();
+ spawn_entities(map_ents);
+
+ draw_map();
+}
+
+void set_map(uint8_t m)
+{
+ init_map(m);
+
+ if (!player_h)
+ {
+ // IMPORTANT: set new player coords before
+ // calling to set_map!
+
+ // checkpoint
+ smap = cmap;
+ spx = px;
+ spy = py;
+ sdir = dir;
+ }
+
+ draw_entities();
+ update_screen();
+}
+
+void set_map_tile(uint8_t x, uint8_t y, uint8_t tile)
+{
+ wmap[x + (y * TMW)] = tile;
+}
+
+static struct st_entity *sp_mit;
+static uint8_t group, last_blocked;
+
+uint8_t is_map_blocked(uint8_t x, uint8_t y)
+{
+ last_blocked = wmap[(x >> 3) + ((y >> 3) * TMW)];
+
+ if (last_blocked == BLOCKED_OPEN_DOOR)
+ return BLOCKED_OPEN_DOOR;
+
+ if (last_blocked < LAST_TILE_TILESET)
+ {
+ if((last_blocked & 15) > LAST_NON_SOLID)
+ return 1;
+ }
+ else
+ // from this on, all solids
+ if (last_blocked > SWITCH_DOOR_TILE - 1)
+ return 1;
+
+ group = 0;
+ for (sp_mit = sp_used; sp_mit; sp_mit = sp_mit->n)
+ {
+ // this requires ET_DOOR and ET_PLATFORM to go grouped
+ switch (sp_mit->type)
+ {
+ case ET_PLATFORM:
+ group = 1;
+ if (check_for_point(sp_mit, x, y, 16, 8))
+ return BLOCKED_PLATFORM;
+ break;
+
+ case ET_DOOR:
+ group = 1;
+ if (check_for_point(sp_mit, x, y, 8, 32) && (sp_it || !keys || magic))
+ return 1;
+ break;
+
+ default:
+ if (group)
+ return 0;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+uint8_t is_map_deadly(uint8_t x, uint8_t y)
+{
+ last_deadly = wmap[(x >> 3) + ((y >> 3) * TMW)];
+
+ // deadly tiles are at the end of the tile table
+ return (last_deadly < 64 && last_deadly > DEADLY_TILE_BASE - 1);
+}
+
+uint8_t exit_map_left()
+{
+ if (blocked & BLOCKED_LEFT)
+ return 0;
+
+ opx = px = (uint8_t)(TW * TMW - 8);
+ set_map(cmap - 1);
+ return 1;
+}
+
+uint8_t exit_map_right()
+{
+ if (blocked & BLOCKED_RIGHT)
+ return 0;
+
+ opx = px = 0;
+ set_map(cmap + 1);
+ return 1;
+}
+
+uint8_t exit_map_up()
+{
+ if (blocked & BLOCKED_UP)
+ return 0;
+
+ px += offset_up;
+ opx = px;
+ opy = py = (uint8_t)(TH * TMH - 24);
+ set_map(exit_up);
+ return 1;
+}
+
+uint8_t exit_map_down()
+{
+ if (blocked & BLOCKED_DOWN)
+ return 0;
+
+ px += offset_down;
+ opx = px;
+ opy = py = 0;
+ set_map(exit_down);
+ return 1;
+}