diff options
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; } |