aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Janzen <jacob.a.s.janzen@gmail.com>2024-02-12 17:47:00 -0600
committerJacob Janzen <jacob.a.s.janzen@gmail.com>2024-02-12 17:47:00 -0600
commit04ce76d5dc222b2bd031ebd24ede6114b76a2d52 (patch)
tree7c20f6fff63e715e100e76f94fb34de85d5e00ad
parent362dcec55b292e3eb605f9aab35c7596dd5c1b13 (diff)
refactor
-rw-r--r--cavegen.c59
-rw-r--r--cavegen.h13
-rw-r--r--main.c234
3 files changed, 189 insertions, 117 deletions
diff --git a/cavegen.c b/cavegen.c
index 9c3a4af..1365e9d 100644
--- a/cavegen.c
+++ b/cavegen.c
@@ -15,16 +15,16 @@ enum direction {
NUM_DIRS,
};
-void create_cave(
- enum tile_type **map, struct point **open_tiles, int *num_open_tiles,
- struct point *up, struct point *down
-)
+void create_cave(struct map *map)
{
+ map->width = WIDTH;
+ map->height = HEIGHT;
+
// create a map consisting entirely of walls
- *map = malloc(sizeof(enum tile_type) * HEIGHT * WIDTH);
+ map->map = malloc(sizeof(enum tile_type) * HEIGHT * WIDTH);
for (int i = 0; i < HEIGHT; ++i) {
for (int j = 0; j < WIDTH; ++j) {
- (*map)[i * WIDTH + j] = WALL;
+ map->map[i * WIDTH + j] = WALL;
}
}
@@ -33,15 +33,18 @@ void create_cave(
int start_y = HEIGHT / 2;
// make the starting point GROUND
- (*map)[start_y * WIDTH + start_x] = GROUND;
- *open_tiles = malloc(sizeof(struct point) * HEIGHT * WIDTH);
- *num_open_tiles = 1;
- (*open_tiles)[0].x = start_x;
- (*open_tiles)[0].y = start_y;
+ map->map[start_y * WIDTH + start_x] = GROUND;
+
+ // setup the open tiles
+ struct point *open_tiles = malloc(sizeof(struct point) * HEIGHT * WIDTH);
+
+ int num_open_tiles = 1;
+ open_tiles[0].x = start_x;
+ open_tiles[0].y = start_y;
for (int i = 0; i < NUM_WALKERS; ++i) {
// get a random open point
- struct point curr_point = (*open_tiles)[rand() % *num_open_tiles];
+ struct point curr_point = open_tiles[rand() % num_open_tiles];
int x_pos = curr_point.x;
int y_pos = curr_point.y;
@@ -51,13 +54,13 @@ void create_cave(
y_pos < HEIGHT - 1 && y_pos >= 1;
++j) {
// add new open point if the current point is still a wall
- if ((*map)[y_pos * WIDTH + x_pos] == WALL) {
- (*open_tiles)[*num_open_tiles].x = x_pos;
- (*open_tiles)[*num_open_tiles].y = y_pos;
- ++(*num_open_tiles);
+ if (map->map[y_pos * WIDTH + x_pos] == WALL) {
+ open_tiles[num_open_tiles].x = x_pos;
+ open_tiles[num_open_tiles].y = y_pos;
+ ++num_open_tiles;
}
- (*map)[y_pos * WIDTH + x_pos] = GROUND; // assign ground
+ map->map[y_pos * WIDTH + x_pos] = GROUND; // assign ground
// move in a random direction
enum direction dir = rand() % NUM_DIRS;
@@ -72,16 +75,18 @@ void create_cave(
}
// assign the up stair and remove from open tiles
- int in = rand() % *num_open_tiles;
- *up = (*open_tiles)[in];
- (*open_tiles)[in] = (*open_tiles)[*num_open_tiles - 1];
- --(*num_open_tiles);
- (*map)[up->y * WIDTH + up->x] = UP_STAIR;
+ int in = rand() % num_open_tiles;
+ map->entry_point = open_tiles[in];
+ open_tiles[in] = open_tiles[num_open_tiles - 1];
+ --num_open_tiles;
+ map->map[map->entry_point.y * WIDTH + map->entry_point.x] = UP_STAIR;
// assign the down stair and remove from open tiles
- in = rand() % *num_open_tiles;
- *down = (*open_tiles)[in];
- (*open_tiles)[in] = (*open_tiles)[*num_open_tiles - 1];
- --(*num_open_tiles);
- (*map)[down->y * WIDTH + down->x] = DOWN_STAIR;
+ in = rand() % num_open_tiles;
+ struct point down = open_tiles[in];
+ open_tiles[in] = open_tiles[num_open_tiles - 1];
+ --num_open_tiles;
+ map->map[down.y * WIDTH + down.x] = DOWN_STAIR;
+
+ free(open_tiles);
}
diff --git a/cavegen.h b/cavegen.h
index 450f905..05d2fd2 100644
--- a/cavegen.h
+++ b/cavegen.h
@@ -18,9 +18,14 @@ struct point {
int y;
};
-void create_cave(
- enum tile_type **map, struct point **open, int *open_tiles,
- struct point *up, struct point *down
-);
+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/main.c b/main.c
index 3fc97eb..67a8d07 100644
--- a/main.c
+++ b/main.c
@@ -8,17 +8,27 @@
#define MAIN_PANEL_WIDTH 100
#define MAIN_PANEL_HEIGHT 41
#define INSTRUCTION_PANEL_WIDTH 32
-#define INSTRUCTION_PANEL_HEIGHT 43
+#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
#define MAX_ENTITIES 100
struct entity {
- char *name;
- int xpos;
- int ypos;
- char *disp_ch;
+ char *name;
+ struct point p;
+ char *disp_ch;
+ bool solid;
+ bool visible;
+};
+
+struct windows {
+ WINDOW *main;
+ WINDOW *inst;
+ WINDOW *msgs;
+ WINDOW *stat;
};
WINDOW *create_newwin(int height, int width, int starty, int startx)
@@ -39,13 +49,14 @@ void initialize(void)
initscr(); // initialize curses
// exit on unsupported consoles
- if (LINES < INSTRUCTION_PANEL_HEIGHT ||
+ if (LINES < MAIN_PANEL_HEIGHT + MESSAGE_PANEL_HEIGHT ||
COLS < MAIN_PANEL_WIDTH + INSTRUCTION_PANEL_WIDTH || !has_colors()) {
endwin();
fprintf(
stderr,
"a color terminal is required with at least %dx%d characters\n",
- INSTRUCTION_PANEL_WIDTH + MAIN_PANEL_WIDTH, INSTRUCTION_PANEL_HEIGHT
+ INSTRUCTION_PANEL_WIDTH + MAIN_PANEL_WIDTH,
+ MAIN_PANEL_HEIGHT + MESSAGE_PANEL_HEIGHT
);
exit(1);
}
@@ -59,45 +70,61 @@ void initialize(void)
// setup colours
init_pair(1, COLOR_WHITE, COLOR_BLACK);
+ init_pair(2, COLOR_BLACK, COLOR_RED);
wattron(stdscr, COLOR_PAIR(1));
refresh();
}
void display_map(
- WINDOW *win, enum tile_type *map, struct entity *entities, int num_entities
+ WINDOW *win, struct map *map, struct entity *entities, int num_entities
)
{
+ // print map
for (int i = 1; i < MAIN_PANEL_HEIGHT - 1; ++i) {
for (int j = 1; j < MAIN_PANEL_WIDTH - 1; ++j) {
- int i1 = i - 1 + entities[0].ypos;
- int j1 = j - 1 + entities[0].xpos;
- if (i1 > HEIGHT || j1 > WIDTH || i1 < 0 || j1 < 0) {
+ int map_i = i - 1 + entities[0].p.y;
+ int map_j = j - 1 + entities[0].p.x;
+
+ if (map_i > map->height || map_j > map->width || map_i < 0 ||
+ map_j < 0) {
mvwaddch(win, i, j, ' ');
- } else if (map[i1 * WIDTH + j1] == GROUND) {
- mvwaddch(win, i, j, '.');
- } else if (map[i1 * WIDTH + j1] == UP_STAIR) {
- mvwaddch(win, i, j, '<');
- } else if (map[i1 * WIDTH + j1] == DOWN_STAIR) {
- mvwaddch(win, i, j, '>');
- } else if (i1 > 0 && map[(i1 - 1) * WIDTH + j1] != WALL) {
- mvwprintw(win, i, j, "█");
- } else if (i1 < HEIGHT - 1 && map[(i1 + 1) * WIDTH + j1] != WALL) {
- mvwprintw(win, i, j, "█");
- } else if (j1 > 0 && map[i1 * WIDTH + j1 - 1] != WALL) {
- mvwprintw(win, i, j, "█");
- } else if (j1 < WIDTH - 1 && map[i1 * WIDTH + j1 + 1] != WALL) {
- mvwprintw(win, i, j, "█");
} else {
- mvwaddch(win, i, j, ' ');
+ switch (map->map[map_i * map->width + map_j]) {
+ case GROUND : mvwaddch(win, i, j, '.'); break;
+ case UP_STAIR : mvwaddch(win, i, j, '<'); break;
+ case DOWN_STAIR :
+ wattron(win, COLOR_PAIR(2));
+ mvwaddch(win, i, j, '>');
+ wattroff(win, COLOR_PAIR(2));
+ break;
+ case WALL :
+ if (map_i > 0 &&
+ map->map[(map_i - 1) * map->width + map_j] != WALL) {
+ mvwprintw(win, i, j, "█");
+ } else if (map_i < map->width - 1 && map->map[(map_i + 1) * map->width + map_j] != WALL) {
+ mvwprintw(win, i, j, "█");
+ } else if (map_j > 0 && map->map[map_i * map->width + map_j - 1] != WALL) {
+ mvwprintw(win, i, j, "█");
+ } else if (map_j < map->width - 1 && map->map[map_i * map->width + map_j + 1] != WALL) {
+ mvwprintw(win, i, j, "█");
+ } else {
+ mvwaddch(win, i, j, ' ');
+ }
+ break;
+ default : mvwaddch(win, i, j, ' ');
+ }
}
}
}
+ // print entities
for (int i = 1; i < num_entities; ++i) {
- mvwprintw(
- win, entities[i].ypos - entities[0].ypos + 1,
- entities[i].xpos - entities[0].xpos + 1, entities[i].disp_ch
- );
+ if (entities[i].visible) {
+ mvwprintw(
+ win, entities[i].p.y - entities[0].p.y + 1,
+ entities[i].p.x - entities[0].p.x + 1, entities[i].disp_ch
+ );
+ }
}
wrefresh(win);
}
@@ -123,113 +150,148 @@ void display_message(WINDOW *win, char *msg)
wrefresh(win);
}
-int main(void)
+void display_status(WINDOW *win, struct entity *entity)
{
- initialize();
+ for (int i = 1; i < STATUS_PANEL_HEIGHT - 1; ++i) {
+ for (int j = 1; j < STATUS_PANEL_WIDTH - 1; ++j) {
+ mvwaddch(win, i, j, ' ');
+ }
+ }
+
+ mvwprintw(win, 1, 2, "HP:");
+ mvwprintw(win, 2, 2, "STAMINA:");
+ mvwprintw(win, 3, 2, "MANA:");
+
+ wrefresh(win);
+}
+
+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;
+}
- // create the windows
- WINDOW *inst = create_newwin(
+void create_windows(struct windows *wins)
+{
+ wins->inst = create_newwin(
INSTRUCTION_PANEL_HEIGHT, INSTRUCTION_PANEL_WIDTH,
- (LINES - INSTRUCTION_PANEL_HEIGHT) / 2,
+ (LINES - INSTRUCTION_PANEL_HEIGHT - STATUS_PANEL_HEIGHT) / 2 + 1,
(COLS - MAIN_PANEL_WIDTH - INSTRUCTION_PANEL_WIDTH) / 2 +
MAIN_PANEL_WIDTH - 1
);
- WINDOW *msgs = create_newwin(
+ wins->msgs = create_newwin(
MESSAGE_PANEL_HEIGHT, MESSAGE_PANEL_WIDTH,
(LINES - MAIN_PANEL_HEIGHT - MESSAGE_PANEL_HEIGHT) / 2 +
MAIN_PANEL_HEIGHT,
(COLS - MESSAGE_PANEL_WIDTH - INSTRUCTION_PANEL_WIDTH) / 2
);
- WINDOW *main_win = create_newwin(
+ wins->stat = create_newwin(
+ STATUS_PANEL_HEIGHT, STATUS_PANEL_WIDTH,
+ (LINES - INSTRUCTION_PANEL_HEIGHT - STATUS_PANEL_HEIGHT) / 2 +
+ INSTRUCTION_PANEL_HEIGHT,
+ (COLS - MAIN_PANEL_WIDTH - INSTRUCTION_PANEL_WIDTH) / 2 +
+ MAIN_PANEL_WIDTH - 1
+ );
+ wins->main = create_newwin(
MAIN_PANEL_HEIGHT, MAIN_PANEL_WIDTH,
(LINES - MAIN_PANEL_HEIGHT - MESSAGE_PANEL_HEIGHT) / 2 + 1,
(COLS - MAIN_PANEL_WIDTH - INSTRUCTION_PANEL_WIDTH) / 2
);
+}
+
+int main(void)
+{
+ initialize();
+
+ // create windows
+ struct windows windows;
+ create_windows(&windows);
// create the map
- enum tile_type *map;
- struct point *open_tiles;
- int num_open_tiles;
- struct point up;
- struct point down;
- create_cave(&map, &open_tiles, &num_open_tiles, &up, &down);
+ struct map map;
+ create_cave(&map);
// create the camera and player at the up stairs
struct entity *entities = malloc(sizeof(struct entity) * MAX_ENTITIES);
entities[0].disp_ch = "";
entities[0].name = "camera";
- entities[0].xpos = up.x - MAIN_PANEL_WIDTH / 2 + 1;
- entities[0].ypos = up.y - MAIN_PANEL_HEIGHT / 2 + 1;
+ entities[0].p.x = map.entry_point.x - MAIN_PANEL_WIDTH / 2 + 1;
+ entities[0].p.y = map.entry_point.y - MAIN_PANEL_HEIGHT / 2 + 1;
+ entities[0].solid = false;
+ entities[0].visible = false;
entities[1].disp_ch = "@";
entities[1].name = "player";
- entities[1].xpos = up.x;
- entities[1].ypos = up.y;
+ entities[1].p = map.entry_point;
+ entities[1].solid = true;
+ entities[1].visible = true;
int num_entities = 2;
// start displaying things
- display_map(main_win, map, entities, num_entities);
- display_instructions(inst);
- display_message(msgs, "TODO: put a message here");
+ display_map(windows.main, &map, entities, num_entities);
+ display_instructions(windows.inst);
+ display_status(windows.stat, &entities[1]);
+ display_message(windows.msgs, "");
int ch;
bool done = false;
while (!done && (ch = getch()) != KEY_F(1)) {
+ struct point newp = entities[1].p;
+ struct point newp_cam = entities[0].p;
switch (ch) {
case 'k' :
- if (entities[1].ypos > 0) {
- if (map[(entities[1].ypos - 1) * WIDTH + entities[1].xpos]) {
- --entities[0].ypos;
- --entities[1].ypos;
- }
- }
+ --newp.y;
+ --newp_cam.y;
break;
case 'j' :
- if (entities[1].ypos < HEIGHT - 1) {
- if (map[(entities[1].ypos + 1) * WIDTH + entities[1].xpos]) {
- ++entities[0].ypos;
- ++entities[1].ypos;
- }
- }
+ ++newp.y;
+ ++newp_cam.y;
break;
case 'h' :
- if (entities[1].xpos > 0) {
- if (map[entities[1].ypos * WIDTH + entities[1].xpos - 1]) {
- --entities[0].xpos;
- --entities[1].xpos;
- }
- }
+ --newp.x;
+ --newp_cam.x;
break;
case 'l' :
- if (entities[1].xpos < WIDTH - 1) {
- if (map[entities[1].ypos * WIDTH + entities[1].xpos + 1]) {
- ++entities[0].xpos;
- ++entities[1].xpos;
- }
- }
+ ++newp.x;
+ ++newp_cam.x;
break;
case '>' :
- if (map[entities[1].ypos * WIDTH + entities[1].xpos] ==
+ if (map.map[entities[1].p.y * map.width + entities[1].p.x] ==
DOWN_STAIR) {
- free(map);
- free(open_tiles);
- create_cave(&map, &open_tiles, &num_open_tiles, &up, &down);
- entities[0].xpos = up.x - MAIN_PANEL_WIDTH / 2 + 1;
- entities[0].ypos = up.y - MAIN_PANEL_HEIGHT / 2 + 1;
- entities[1].xpos = up.x;
- entities[1].ypos = up.y;
+ 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(windows.msgs, "Entered new level");
}
break;
case '<' :
- if (map[entities[1].ypos * WIDTH + entities[1].xpos] == UP_STAIR) {
+ if (map.map[entities[1].p.y * WIDTH + entities[1].p.x] ==
+ UP_STAIR) {
done = true;
}
break;
}
- display_map(main_win, map, entities, num_entities);
+
+ if (entity_set_pos(&entities[1], newp, &map))
+ entity_set_pos(&entities[0], newp_cam, &map);
+
+ display_map(windows.main, &map, entities, num_entities);
}
- free(map);
- free(open_tiles);
+ free(map.map);
free(entities);
endwin();