diff options
author | Marvin Borner | 2021-03-30 22:00:27 +0200 |
---|---|---|
committer | Marvin Borner | 2021-03-30 22:00:27 +0200 |
commit | 5f0d7d14bac8679cef9586b1d0b4926364c46328 (patch) | |
tree | 5c0db361895527b933056c0bed97675bf70b431b /apps | |
parent | f86158c6b7b1d9f2cfd7f7f05e0576de643b9c5a (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.c | 189 |
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; } |