aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Petrashin <kirill8201@yandex.ru>2026-03-20 22:57:32 +0300
committerKirill Petrashin <kirill8201@yandex.ru>2026-03-20 22:57:32 +0300
commita08e4c138734fd59246e70260c51b9d7b68be007 (patch)
tree52d8eec4570acbea5d91177a05549abd9798c5b9
parenta0604cc84ef5286d7fe42a1ad125e654ce7eacf6 (diff)
Add ability to read plaintext maps from files
-rw-r--r--main.c15
-rw-r--r--map.c47
-rw-r--r--map.h16
-rw-r--r--maps/test6
4 files changed, 81 insertions, 3 deletions
diff --git a/main.c b/main.c
index 3d9e29c..1142134 100644
--- a/main.c
+++ b/main.c
@@ -12,6 +12,7 @@
/* So, TODO for now:
- Implement Dijkstra and greedy-best-first search algorithms
- Implement the A* algorithm
+ - Implement it with 4 and 8 directions
- Implement adding maps from files (with rle, preferably)
- Implement controls (to change maps, move start/goal, etc.)
- Clean up unused `#include`s */
@@ -43,23 +44,31 @@ int main(void) {
initialize_colors();
/* FIXME: shitty. sometimes leaves enough space on the right for a bigger map */
- size_t height = LINES/2 - DRAW_MAP_OFFSET_Y,
+ /* size_t height = LINES/2 - DRAW_MAP_OFFSET_Y,
width = COLS/4 - 1;
Map map = rbt_maze_map(width, height, (unsigned int) time(NULL));
Position fake_start_position_to_pass_into_draw_map = {0, 0};
- Position fake_goal_position_to_pass_into_draw_map = {width*2-2, height*2-2};
+ Position fake_goal_position_to_pass_into_draw_map = {width*2-2, height*2-2}; */
+
+ size_t width, height;
+ Position start_pos, end_pos;
+ Map map = file_plaintext_map("maps/test", &width, &height, &start_pos, &end_pos);
+
int offset_x = 0, offset_y = 0;
while (1) {
- draw_map(map, width*2-1, height*2-1, offset_x, offset_y, fake_start_position_to_pass_into_draw_map, fake_goal_position_to_pass_into_draw_map);
+ draw_map(map, width, height, offset_x, offset_y, start_pos, end_pos);
char c = getch();
switch (c) {
case 'h': offset_x -= 2; break;
case 'l': offset_x += 2; break;
case 'j': offset_y += 1; break;
case 'k': offset_y -= 1; break;
+ /*
case 'n':
+ FIXME: free it before generating a new one
map = rbt_maze_map(width, height, (unsigned int) time(NULL));
break;
+ */
case 'q': endwin(); return 0;
}
}
diff --git a/map.c b/map.c
index a69affa..9d0a264 100644
--- a/map.c
+++ b/map.c
@@ -5,6 +5,7 @@
#include "map.h"
#include "config.h"
#include "stack.h"
+#include "error.h"
Map empty_map(size_t width, size_t height) {
Map map = malloc(sizeof(MapTile*) * height);
@@ -93,6 +94,52 @@ Map rbt_maze_map(size_t width, size_t height, unsigned int seed) {
return map;
}
+/* Reads the map from a file, saves size in `width` and `height`
+ *
+ * FILE FORMAT IS AS FOLLOWS:
+ * {WIDTH}x{HEIGHT}
+ * {EMPTY_CHAR}{WALL_CHAR}{START_CHAR}{END_CHAR}
+ * {MAP, one line at a time}
+ *
+ * EXAMPLE:
+ * 10x4
+ * .#@x
+ * .......x..
+ * ....###...
+ * ....#.#...
+ * ..@....... */
+/* TODO: handle errors better */
+Map file_plaintext_map(char *filename, size_t *width, size_t *height, Position *start_pos, Position *end_pos) {
+ FILE *file = fopen(filename, "r");
+ if (file == NULL) {
+ error("Failed to open file %s\n", filename);
+ }
+
+ if (fscanf(file, "%zux%zu\n", width, height) != 2) {
+ error("Failed reading size of file %s\n", filename);
+ }
+
+ Map map = empty_map(*width, *height);
+
+ char empty_char, wall_char, start_char, end_char;
+ if (fscanf(file, "%c%c%c%c\n", &empty_char, &wall_char, &start_char, &end_char) != 4) {
+ error("Failed reading chars of file %s\n", filename);
+ }
+
+ for (size_t row = 0; row < *height; row++) {
+ for (size_t col = 0; col < *width; col++) {
+ char c = (char)fgetc(file);
+ if (c == empty_char) continue;
+ if (c == wall_char) { map[row][col] = WALL; continue; }
+ if (c == start_char) { start_pos->x = col; start_pos->y = row; continue; }
+ if (c == end_char) { end_pos->x = col; end_pos->y = row; continue; }
+ }
+ fgetc(file);
+ }
+
+ return map;
+}
+
/* FIXME: I don't think we need DRAW_MAP_OFFSET_{X,Y} anymore
* Although, at the same time, it does make less magic values, so I guess it's fine */
/* TODO: Maybe add an option to render with ▄? that doubles the resolution, but requires us to use ncursesw, probably. */
diff --git a/map.h b/map.h
index 03da971..a4cc971 100644
--- a/map.h
+++ b/map.h
@@ -34,6 +34,22 @@ unsigned int neighbours(Position neighbour_array[], Position pos, size_t width,
* TODO: formula for actual size */
Map rbt_maze_map(size_t width, size_t height, unsigned int seed);
+/* Reads the map from a file, saves size in `width` and `height`
+ *
+ * FILE FORMAT IS AS FOLLOWS:
+ * {WIDTH}x{HEIGHT}
+ * {EMPTY_CHAR}{WALL_CHAR}{START_CHAR}{END_CHAR}
+ * {MAP, one line at a time}
+ *
+ * EXAMPLE:
+ * 10x4
+ * .#@x
+ * .......x..
+ * ....###...
+ * ....#.#...
+ * ..@....... */
+Map file_plaintext_map(char *filename, size_t *width, size_t *height, Position *start_pos, Position *end_pos);
+
/* Draw the map. Bet you didn't expect that. */
void draw_map(Map map, size_t width, size_t height, int offset_x, int offset_y, Position start, Position goal);
diff --git a/maps/test b/maps/test
new file mode 100644
index 0000000..6f21fe9
--- /dev/null
+++ b/maps/test
@@ -0,0 +1,6 @@
+10x4
+.#@x
+.......x..
+....###...
+....#.#...
+..@.......