aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am13
-rw-r--r--src/cavegen.h26
-rw-r--r--src/common.h9
-rw-r--r--src/display.h43
-rw-r--r--src/entity.h13
-rw-r--r--src/ht.h29
-rw-r--r--src/main.c146
7 files changed, 279 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..b6114f2
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,13 @@
+bin_PROGRAMS = main
+
+main_SOURCES = \
+ cavegen.c \
+ cavegen.h \
+ display.c \
+ display.h \
+ ht.c \
+ ht.h \
+ common.h \
+ entity.h \
+ main.c
+
diff --git a/src/cavegen.h b/src/cavegen.h
new file mode 100644
index 0000000..b6ed1e4
--- /dev/null
+++ b/src/cavegen.h
@@ -0,0 +1,26 @@
+#ifndef CAVEGEN_H_
+#define CAVEGEN_H_
+
+#include "common.h"
+
+#define HEIGHT 100
+#define WIDTH 180
+
+enum tile_type {
+ WALL,
+ GROUND,
+ UP_STAIR,
+ DOWN_STAIR,
+};
+
+struct map {
+ enum tile_type *map;
+ struct point entry_point;
+
+ int width;
+ int height;
+};
+
+void create_cave(struct map *map);
+
+#endif // CAVEGEN_H_
diff --git a/src/common.h b/src/common.h
new file mode 100644
index 0000000..11b11d4
--- /dev/null
+++ b/src/common.h
@@ -0,0 +1,9 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+struct point {
+ int x;
+ int y;
+};
+
+#endif // COMMON_H_
diff --git a/src/display.h b/src/display.h
new file mode 100644
index 0000000..d9c66bb
--- /dev/null
+++ b/src/display.h
@@ -0,0 +1,43 @@
+#ifndef DISPLAY_H_
+#define DISPLAY_H_
+
+#include <stdbool.h>
+
+#include "cavegen.h"
+#include "entity.h"
+#include "ht.h"
+
+#define MAIN_PANEL_WIDTH 100
+#define MAIN_PANEL_HEIGHT 41
+#define INSTRUCTION_PANEL_WIDTH 32
+#define INSTRUCTION_PANEL_HEIGHT 39
+#define MESSAGE_PANEL_WIDTH 100
+#define MESSAGE_PANEL_HEIGHT 3
+#define STATUS_PANEL_WIDTH 32
+#define STATUS_PANEL_HEIGHT 5
+
+typedef struct windows display_t;
+
+enum action {
+ ACTION_NONE,
+ ACTION_EXIT,
+ ACTION_DOWN,
+ ACTION_UP,
+ ACTION_LEFT,
+ ACTION_RIGHT,
+ ACTION_STAIR_DOWN,
+ ACTION_STAIR_UP,
+ NUM_ACTIONS,
+};
+
+display_t *display_init(void);
+void display_destroy(display_t *disp);
+
+void display_map(display_t *disp, struct map *map, ht_t *entities);
+void display_instructions(display_t *disp);
+void display_message(display_t *disp, char *msg);
+void display_status(display_t *disp, struct entity *entity);
+
+enum action display_process_input(void);
+
+#endif // DISPLAY_H_
diff --git a/src/entity.h b/src/entity.h
new file mode 100644
index 0000000..b003efe
--- /dev/null
+++ b/src/entity.h
@@ -0,0 +1,13 @@
+#ifndef ENTITY_H_
+#define ENTITY_H_
+
+#include "common.h"
+
+struct entity {
+ struct point p;
+ char *disp_ch;
+ bool solid;
+ bool visible;
+};
+
+#endif // ENTITY_H_
diff --git a/src/ht.h b/src/ht.h
new file mode 100644
index 0000000..ef15540
--- /dev/null
+++ b/src/ht.h
@@ -0,0 +1,29 @@
+#ifndef HT_H_
+#define HT_H_
+
+#include <stdbool.h>
+
+typedef struct hash_table ht_t;
+
+struct kvp {
+ char *key;
+ void *val;
+};
+
+// construct and destructor
+ht_t *ht_create(int size);
+void ht_destroy(ht_t *h);
+
+// accessors
+void *ht_find(ht_t *h, char *key);
+void ht_insert(ht_t *h, char *key, void *val);
+void ht_delete(ht_t *h, char *key);
+
+// queries
+int ht_size(ht_t *h);
+
+// iterator
+void ht_iter_init(ht_t *h);
+struct kvp ht_iter_next(ht_t *h);
+
+#endif // HT_H_
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..086a093
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,146 @@
+#include <curses.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "cavegen.h"
+#include "common.h"
+#include "display.h"
+#include "entity.h"
+#include "ht.h"
+
+bool entity_set_pos(struct entity *e, struct point p, struct map *map)
+{
+ if (e->solid) {
+ if (p.y < 0 || p.x < 0 || p.y >= map->height || p.x >= map->width) {
+ return false;
+ }
+ if (map->map[p.y * map->width + p.x] == WALL) {
+ return false;
+ }
+ }
+
+ e->p = p;
+
+ return true;
+}
+
+bool game_update(
+ display_t *disp, enum action action, ht_t *entities, struct map *map
+)
+{
+ struct entity *player = ht_find(entities, "player");
+ struct entity *camera = ht_find(entities, "camera");
+
+ struct point newp = player->p;
+ struct point newp_cam = camera->p;
+ switch (action) {
+ case ACTION_EXIT : return true;
+ case ACTION_UP :
+ --newp.y;
+ --newp_cam.y;
+ display_message(disp, "moving up");
+ break;
+ case ACTION_DOWN :
+ ++newp.y;
+ ++newp_cam.y;
+ display_message(disp, "moving down");
+ break;
+ case ACTION_LEFT :
+ --newp.x;
+ --newp_cam.x;
+ display_message(disp, "moving left");
+ break;
+ case ACTION_RIGHT :
+ ++newp.x;
+ ++newp_cam.x;
+ display_message(disp, "moving right");
+ break;
+ case ACTION_STAIR_DOWN :
+ if (map->map[player->p.y * map->width + player->p.x] == DOWN_STAIR) {
+ free(map->map);
+ create_cave(map);
+
+ newp = map->entry_point;
+ newp_cam.x = map->entry_point.x - MAIN_PANEL_WIDTH / 2 + 1;
+ newp_cam.y = map->entry_point.y - MAIN_PANEL_HEIGHT / 2 + 1;
+ display_message(disp, "moving down stairs");
+ } else {
+ display_message(disp, "no stairs to go down");
+ }
+ break;
+ case ACTION_STAIR_UP :
+ if (map->map[player->p.y * WIDTH + player->p.x] == UP_STAIR) {
+ display_message(disp, "moving up stairs");
+ return true;
+ } else {
+ display_message(disp, "no stairs to go up");
+ }
+ break;
+ default : display_message(disp, "unrecognized command"); break;
+ }
+
+ if (entity_set_pos(player, newp, map))
+ entity_set_pos(camera, newp_cam, map);
+
+ return false;
+}
+
+int main(void)
+{
+ unsigned int seed = time(NULL);
+ srand(seed);
+
+ display_t *disp = display_init();
+
+ // create the map
+ struct map map;
+ create_cave(&map);
+
+ // create the entity map
+ ht_t *entities = ht_create(1);
+
+ // create the camera
+ struct entity camera;
+ camera.disp_ch = "";
+ camera.solid = false;
+ camera.visible = false;
+ ht_insert(entities, "camera", &camera);
+
+ // create the player
+ struct entity player;
+ player.disp_ch = "@";
+ player.solid = true;
+ player.visible = true;
+ ht_insert(entities, "player", &player);
+
+ // set starting point
+ struct point cam_p = {
+ .x = map.entry_point.x - MAIN_PANEL_WIDTH / 2 + 1,
+ .y = map.entry_point.y - MAIN_PANEL_HEIGHT / 2 + 1,
+ };
+ entity_set_pos(&player, map.entry_point, &map);
+ entity_set_pos(&camera, cam_p, &map);
+
+ // start displaying things
+ display_map(disp, &map, entities);
+ display_instructions(disp);
+ display_status(disp, &player);
+ display_message(disp, "");
+
+ int ch;
+ bool done = false;
+ while (!done) {
+ enum action action = display_process_input();
+ done = game_update(disp, action, entities, &map);
+ display_map(disp, &map, entities);
+ }
+
+ free(map.map);
+ ht_destroy(entities);
+ display_destroy(disp);
+
+ endwin();
+
+ return 0;
+}