]> MadKous Network Git Server - rogue.git/commitdiff
Initial Commit
authorMatthew Kousoulas <shaman.kous@gmail.com>
Wed, 3 Jan 2024 02:59:27 +0000 (21:59 -0500)
committerMatthew Kousoulas <shaman.kous@gmail.com>
Wed, 3 Jan 2024 02:59:27 +0000 (21:59 -0500)
Makefile [new file with mode: 0644]
src/board.c [new file with mode: 0644]
src/board.h [new file with mode: 0644]
src/main.c [new file with mode: 0644]
src/term.c [new file with mode: 0644]
src/term.h [new file with mode: 0644]
src/util.c [new file with mode: 0644]
src/util.h [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..b3344ba
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,29 @@
+TARGET := rogue
+BIN_DIR := .
+BUILD_DIR := ./build
+SRC_DIR := ./src
+
+SRC := $(shell find $(SRC_DIR) -name '*.c')
+OBJ := $(SRC:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)
+DEP := $(OBJ:.o=.d)
+
+CFLAGS := -Wall -Wextra -Wpedantic -pedantic
+CPPFLAGS := $(addprefix -I,$(shell find $(SRC_DIR) -type d)) -MMD -MP
+LDFLAGS :=
+LDLIBS :=
+
+.SECONDEXPANSION:
+$(BIN_DIR)/$(TARGET): $(OBJ)
+       $(CC) $(LDFLAGS) $(LDLIBS) $^ -o $@
+
+$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
+       mkdir -p $(BUILD_DIR)
+       $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
+
+-include $(DEP)
+
+.PHONY: clean
+clean:
+       $(RM) -r $(BUILD_DIR)
+       $(RM) $(BIN_DIR)/$(TARGET)
+
diff --git a/src/board.c b/src/board.c
new file mode 100644 (file)
index 0000000..6111cc7
--- /dev/null
@@ -0,0 +1,104 @@
+#include <stdlib.h>
+
+#include "board.h"
+
+board* make_board(int mines, int width, int height)
+{
+       board *b = malloc(sizeof(board));
+
+       b->board_x = width;
+       b->board_y = height;
+       b->mines = mines;
+       b->grid = calloc(width * height, sizeof(tile));
+       b->neighbors = calloc(width * height, sizeof(char));
+
+       for (int n = 0; n < b->mines;)
+       {
+               int x = rand() % b->board_x;
+               int y = rand() % b->board_y;
+               if (!(b->grid[INDEX(b, x, y)] & MINED))
+               {
+                       b->grid[INDEX(b, x, y)] |= MINED;
+                       ++n;
+               }
+       }
+
+       for (int x = 0; x < b->board_x; ++x)
+               for (int y = 0; y < b->board_y; ++y)
+               {
+                       char c = '0';
+
+                       if (x + 1 < b->board_x)
+                       {
+                               if (y + 1 < b->board_y)
+                                       c += b->grid[INDEX(b, x+1, y+1)] & MINED ? 1 : 0;
+                               c += b->grid[INDEX(b, x+1, y)] & MINED ? 1 : 0;
+                               if (y > 0)
+                                       c += b->grid[INDEX(b, x+1, y-1)] & MINED ? 1 : 0;
+                       }
+                       if (y + 1 < b->board_y)
+                               c += b->grid[INDEX(b, x, y+1)] & MINED ? 1 : 0;
+                       if (y > 0)
+                               c += b->grid[INDEX(b, x, y-1)] & MINED ? 1 : 0;
+                       if (x > 0)
+                       {
+                               if (y + 1 < b->board_y)
+                                       c += b->grid[INDEX(b, x-1, y+1)] & MINED ? 1 : 0;
+                               c += b->grid[INDEX(b, x-1, y)] & MINED ? 1 : 0;
+                               if (y > 0)
+                                       c += b->grid[INDEX(b, x-1, y-1)] & MINED ? 1 : 0;
+                       }
+
+                       if (c == '0')
+                               c = '.';
+
+                       b->neighbors[INDEX(b, x, y)] = c;
+               }
+
+       return b;
+}
+
+void destruct_board(board *b)
+{
+       free(b->grid);
+       free(b->neighbors);
+       free(b);
+}
+
+void clear_tile(board *b, int x, int y)
+{
+       if (x < 0 || x >= b->board_x
+        || y < 0 || y >= b->board_y)
+               return;
+
+       tile t = b->grid[INDEX(b, x, y)];
+       char n = b->neighbors[INDEX(b, x, y)];
+
+       /* if (n == '.' && !(t & MINED)) */
+       if (1)
+       {
+               b->grid[INDEX(b, b->cursor_x, b->cursor_y)] |= CLEARED;
+
+               if (x + 1 < b->board_x)
+               {
+                       /* if (y + 1 < b->board_y) */
+                       /*      clear_tile(b, x+1, y+1); */
+                       /* clear_tile(b, x+1, y); */
+                       /* if (y > 0) */
+                               /* clear_tile(b, x+1, y-1); */
+               }
+               /* if (y + 1 < b->board_y) */
+               /*      clear_tile(b, x, y+1); */
+               if (y > 0)
+                       clear_tile(b, x, y-1);
+               if (x > 0)
+               {
+                       /* if (y + 1 < b->board_y) */
+                       /*      clear_tile(b, x-1, y+1); */
+                       clear_tile(b, x-1, y);
+                       if (y > 0)
+                               clear_tile(b, x-1, y-1);
+               }
+       }
+}
+
diff --git a/src/board.h b/src/board.h
new file mode 100644 (file)
index 0000000..94eafb1
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef BOARD_H
+#define BOARD_H
+
+#define CLEARED 0000001
+#define MINED   0000002
+#define FLAGGED 0000004
+
+#define INDEX(B, X, Y) (((Y) * B->board_y) + (X))
+
+typedef unsigned char tile;
+
+typedef struct board {
+       int board_x;
+       int board_y;
+       int cursor_x;
+       int cursor_y;
+       int mines;
+       tile *grid;
+       char *neighbors;
+} board;
+
+board* make_board(int mines, int width, int height);
+void destruct_board(board *b);
+void clear_tile(board *b, int x, int y);
+
+#endif
+
diff --git a/src/main.c b/src/main.c
new file mode 100644 (file)
index 0000000..3bf06a3
--- /dev/null
@@ -0,0 +1,183 @@
+#include <ctype.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "term.h"
+#include "board.h"
+
+typedef enum
+{
+       nop,
+       quit,
+       up,
+       down,
+       left,
+       right,
+       flag,
+       clear,
+} action;
+
+action proc_key(char c)
+{
+       action a;
+       switch (c)
+       {
+               case 'f':
+                       a = flag;
+                       break;
+               case ' ':
+                       a = clear;
+                       break;
+               case 'h':
+                       a = left;
+                       break;
+               case 'j':
+                       a = down;
+                       break;
+               case 'k':
+                       a = up;
+                       break;
+               case 'l':
+                       a = right;
+                       break;
+               case CTRL_KEY('q'):
+                       a = quit;
+                       break;
+               default:
+                       a = nop;
+       }
+       return a;
+}
+
+void take_action(action a, board *b)
+{
+       switch(a)
+       {
+               case nop:
+                       break;
+               case quit:
+                       exit(0);
+                       break;
+               case up:
+                       if (b->cursor_y > 0)
+                               b->cursor_y -= 1;
+                       break;
+               case down:
+                       if (b->cursor_y + 1 < b->board_y)
+                               b->cursor_y += 1;
+                       break;
+               case left:
+                       if (b->cursor_x > 0)
+                               b->cursor_x -= 1;
+                       break;
+               case right:
+                       if (b->cursor_x + 1 < b->board_x)
+                               b->cursor_x += 1;
+                       break;
+               case flag:
+                       b->grid[INDEX(b, b->cursor_x, b->cursor_y)] ^= FLAGGED;
+                       break;
+               case clear:
+                       clear_tile(b, b->cursor_x, b->cursor_y);
+                       break;
+       }
+}
+
+void draw_grid(board *b)
+{
+       for (int y = 0; y < b->board_y; ++y)
+       {
+               for (int x = 0; x < b->board_x; ++x)
+               {
+                       if (x == b->cursor_x && y == b->cursor_y)
+                               WRITE_CTRL("[7m");
+
+                       tile t = b->grid[INDEX(b, x, y)];
+                       if (t & FLAGGED)
+                       {
+                               write(STDOUT_FILENO, "?", 1);
+                       }
+                       else if (t & CLEARED)
+                       {
+                               if (t & MINED)
+                               {
+                                       write(STDOUT_FILENO, "*", 1);
+                               }
+                               else
+                               {
+                                       write(STDOUT_FILENO, b->neighbors + INDEX(b, x, y), 1);
+                               }
+                       }
+                       else
+                       {
+                               write(STDOUT_FILENO, "#", 1);
+                       }
+
+                       if (x == b->cursor_x && y == b->cursor_y)
+                               WRITE_CTRL("[27m");
+               }
+               write(STDOUT_FILENO, "\n\r", 2);
+       }
+
+       write(STDOUT_FILENO, "\n\rDebug: ", 9);
+
+       char buf[16];
+       sprintf(buf, "(%d,%d) %d", b->cursor_x, b->cursor_y, INDEX(b, b->cursor_x, b->cursor_y));
+       write(STDOUT_FILENO, buf, 16);
+
+       write(STDOUT_FILENO, "\n\r\n\r", 4);
+
+       int x = b->cursor_x;
+       int y = b->cursor_y;
+
+       if (x + 1 < b->board_x)
+       {
+               if (y + 1 < b->board_y)
+                       write(STDOUT_FILENO, "1", 1);
+               write(STDOUT_FILENO, "2", 1);
+               if (y > 0)
+                       write(STDOUT_FILENO, "3", 1);
+       }
+       if (y + 1 < b->board_y)
+               write(STDOUT_FILENO, "4", 1);
+       if (y > 0)
+               write(STDOUT_FILENO, "5", 1);
+       if (x > 0)
+       {
+               if (y + 1 < b->board_y)
+                       write(STDOUT_FILENO, "6", 1);
+               write(STDOUT_FILENO, "7", 1);
+               if (y > 0)
+                       write(STDOUT_FILENO, "8", 1);
+       }
+}
+
+int main(int argc, char** argv)
+{
+       init_term();
+       srand(time(NULL));
+
+       board *b = make_board(10, 10, 10);
+
+       char c = '\0';
+       action a = nop;
+
+       while (true)
+       {
+               clear_screen();
+               draw_grid(b);
+
+               c = read_key();
+               a = proc_key(c);
+               take_action(a, b);
+       }
+
+       destruct_board(b);
+
+       return argc;
+}
diff --git a/src/term.c b/src/term.c
new file mode 100644 (file)
index 0000000..29d7b95
--- /dev/null
@@ -0,0 +1,54 @@
+#include <errno.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "term.h"
+#include "util.h"
+
+struct termios orig_termios;
+void reset_term()
+{
+       tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios);
+       WRITE_CTRL("[?47l");
+       WRITE_CTRL("8");
+}
+
+void init_term()
+{
+       tcgetattr(STDIN_FILENO, &orig_termios);
+       atexit(reset_term);
+       
+       struct termios raw = orig_termios;
+       raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+       raw.c_oflag &= ~(OPOST);
+       raw.c_cflag |= (CS8);
+       raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
+       raw.c_cc[VMIN] = 0;
+       raw.c_cc[VTIME] = 1;
+
+       tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
+
+       WRITE_CTRL("[2J");
+       WRITE_CTRL("[H");
+       WRITE_CTRL("7");
+       WRITE_CTRL("[?47h");
+}
+
+char read_key()
+{
+       int nread;
+       char c;
+       /* nread = read(STDIN_FILENO, &c, 1); */
+       while ((nread = read(STDIN_FILENO, &c, 1)) != 1)
+               if (nread == -1 && errno != EAGAIN) die("read");
+
+       return c;
+}
+
+void clear_screen()
+{
+       WRITE_CTRL("[2J");
+       WRITE_CTRL("[H");
+}
+
diff --git a/src/term.h b/src/term.h
new file mode 100644 (file)
index 0000000..1fa08aa
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef TERM_H
+#define TERM_H
+
+#define ESC(S) "\x1b" S
+#define WRITE_CTRL(S) write(STDOUT_FILENO, ESC(S), sizeof (S))
+#define CTRL_KEY(K) ((K) & 0x1f)
+
+void reset_term();
+void init_term();
+char read_key();
+void clear_screen();
+
+#endif
diff --git a/src/util.c b/src/util.c
new file mode 100644 (file)
index 0000000..4e033e3
--- /dev/null
@@ -0,0 +1,10 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "util.h"
+
+void die(const char* s)
+{
+       perror(s);
+       exit(1);
+}
diff --git a/src/util.h b/src/util.h
new file mode 100644 (file)
index 0000000..7e3071b
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+void die(const char* s);
+
+#endif
+