aboutsummaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorMarvin Borner2021-03-30 22:00:27 +0200
committerMarvin Borner2021-03-30 22:00:27 +0200
commit5f0d7d14bac8679cef9586b1d0b4926364c46328 (patch)
tree5c0db361895527b933056c0bed97675bf70b431b /apps
parentf86158c6b7b1d9f2cfd7f7f05e0576de643b9c5a (diff)
Basic FEN parsing, buggy af
The entire GUI system is kinda buggy and sluggish. Might need to rethink some design choices. I've got some ideas to improve everything though.
Diffstat (limited to 'apps')
-rw-r--r--apps/chess.c189
1 files changed, 163 insertions, 26 deletions
diff --git a/apps/chess.c b/apps/chess.c
index 3c4c0c3..b4808b9 100644
--- a/apps/chess.c
+++ b/apps/chess.c
@@ -6,12 +6,13 @@
#include <libgui/gui.h>
#include <print.h>
+// Config
#define SIZE 8
#define TILE 36
#define WHITE_STARTS 1
-
#define DARK_COLOR 0xff946f51
#define LIGHT_COLOR 0xfff0d9b5
+#define START_FEN "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
// Pieces
#define NONE 0
@@ -41,7 +42,7 @@
struct piece {
u32 piece;
u32 widget;
- const char *icon;
+ char name[8];
struct {
u8 moved : 1;
// idk
@@ -52,49 +53,183 @@ typedef struct piece board[SIZE][SIZE];
static u32 win = 0; // Window
static board tiles = { 0 }; // Matrix
+static vec2 selected = { -1, -1 }; // Selected tile
+
+static void load_image(struct piece *tile)
+{
+ char icon[48] = { 0 };
+ sprintf(icon, "/icons/chess-%s-%d.png", tile->name, TILE);
+ enum gfx_filter filter = IS_COLOR(tile->piece, BLACK) ? GFX_FILTER_NONE : GFX_FILTER_INVERT;
+
+ /* assert(gui_fill(win, tile->widget, GUI_LAYER_FG, 0) == EOK); */
+ assert(gui_load_image_filter(win, tile->widget, GUI_LAYER_FG, vec2(0, 0), vec2(TILE, TILE),
+ filter, icon) == EOK);
+}
static void mouseclick(u32 widget_id, vec2 pos)
{
UNUSED(pos);
- /* log("%d: %d %d\n", widget_id, pos.x, pos.y); */
- u32 x = widget_id / SIZE;
- u32 y = (widget_id % SIZE) - 1;
- u32 widget = tiles[x][y].widget;
- assert(gui_fill(win, widget, GUI_LAYER_BG, COLOR_MAGENTA) == EOK);
- gui_redraw_widget(win, widget);
+ vec2 clicked = vec2(0, 0);
+ for (u32 x = 0; x < SIZE; x++)
+ for (u32 y = 0; y < SIZE; y++)
+ if (tiles[x][y].widget == widget_id)
+ clicked = vec2(x, y);
+
+ struct piece *clicked_piece = &tiles[clicked.x][clicked.y];
+
+ if (selected.x != (u32)-1) {
+ struct piece *selected_piece = &tiles[selected.x][selected.y];
+
+ clicked_piece->piece = selected_piece->piece;
+ selected_piece->piece = 0;
+
+ strcpy(clicked_piece->name, selected_piece->name);
+ selected_piece->name[0] = '\0';
+
+ /* assert(gui_fill(win, selected_piece->widget, GUI_LAYER_FG, 0) == EOK); */
+ load_image(clicked_piece);
+
+ assert(gui_redraw_window(win) == EOK);
+
+ selected = vec2(-1, -1);
+ } else if (clicked_piece->piece) {
+ assert(gui_redraw_widget(win, clicked_piece->widget) == EOK);
+ selected = clicked;
+ }
}
-static void create_board(void)
+static const char *resolve_name(u32 piece, char *buf)
+{
+ const char *name = NULL;
+ switch (piece & TYPE_MASK) {
+ case KING:
+ name = "king";
+ break;
+ case PAWN:
+ name = "pawn";
+ break;
+ case KNIGHT:
+ name = "knight";
+ break;
+ case BISHOP:
+ name = "bishop";
+ break;
+ case ROOK:
+ name = "rook";
+ break;
+ case QUEEN:
+ name = "queen";
+ break;
+ default:
+ err(1, "Unknown piece %d\n", piece);
+ }
+
+ strcpy(buf, name);
+
+ return buf;
+}
+
+static u32 fen_resolve_letter(char ch)
+{
+ u32 piece = 0;
+
+ switch (ch) {
+ case 'k':
+ piece = KING | BLACK;
+ break;
+ case 'K':
+ piece = KING | WHITE;
+ break;
+ case 'p':
+ piece = PAWN | BLACK;
+ break;
+ case 'P':
+ piece = PAWN | WHITE;
+ break;
+ case 'n':
+ piece = KNIGHT | BLACK;
+ break;
+ case 'N':
+ piece = KNIGHT | WHITE;
+ break;
+ case 'b':
+ piece = BISHOP | BLACK;
+ break;
+ case 'B':
+ piece = BISHOP | WHITE;
+ break;
+ case 'r':
+ piece = ROOK | BLACK;
+ break;
+ case 'R':
+ piece = ROOK | WHITE;
+ break;
+ case 'q':
+ piece = QUEEN | BLACK;
+ break;
+ case 'Q':
+ piece = QUEEN | WHITE;
+ break;
+ default:
+ err(1, "Invalid letter (%c)!\n", ch);
+ }
+
+ return piece;
+}
+
+// TODO: Add more than basic fen support
+static void fen_parse(const char *fen)
+{
+ if (!fen || !*fen)
+ return;
+
+ u8 x = 0, y = 0;
+ for (const char *p = fen; p && *p; p++) {
+ if (*p == ' ')
+ break;
+
+ if (*p == '/') {
+ x = 0;
+ y++;
+ continue;
+ }
+
+ if (*p >= '0' && *p <= '9')
+ continue;
+
+ u32 piece = fen_resolve_letter(*p);
+
+ tiles[x][y].piece = piece;
+ resolve_name(piece, (char *)&tiles[x][y].name);
+
+ x++;
+ }
+}
+
+static void draw_board(void)
{
- u32 widget;
for (u8 x = 0; x < 8; x++) {
for (u8 y = 0; y < 8; y++) {
- widget = gui_new_widget(win, vec2(TILE, TILE), vec2(TILE * x, TILE * y));
- assert(widget > 0);
+ u32 widget =
+ gui_new_widget(win, vec2(TILE, TILE), vec2(TILE * x, TILE * y));
+ assert((signed)widget > 0);
u8 colored = (x + y + 1) % 2 == 0;
- u8 colored_piece = y < SIZE / 2;
#if !WHITE_STARTS
colored = !colored;
- colored_piece = !colored_piece;
#endif
-
- struct piece *tile = &tiles[x][y];
- tile->piece |= colored_piece ? BLACK : WHITE;
- tile->widget = widget;
- tile->icon = "/icons/chess-king-36.png";
-
assert(gui_fill(win, widget, GUI_LAYER_BG,
colored ? DARK_COLOR : LIGHT_COLOR) == EOK);
- enum gfx_filter filter =
- colored_piece ? GFX_FILTER_NONE : GFX_FILTER_INVERT;
- assert(gui_load_image_filter(win, widget, GUI_LAYER_FG, vec2(0, 0),
- vec2(TILE, TILE), filter, tile->icon) == EOK);
-
+ struct piece *tile = &tiles[x][y];
assert(gui_listen_widget(win, widget, GUI_LISTEN_MOUSECLICK,
(u32)mouseclick) == EOK);
+
+ tile->widget = widget;
+
+ if (tile->piece)
+ load_image(tile);
}
}
@@ -104,7 +239,9 @@ static void create_board(void)
int main(void)
{
assert((win = gui_new_window()) > 0);
- create_board();
+ fen_parse(START_FEN);
+ draw_board();
+
gui_loop();
return 0;
}