aboutsummaryrefslogtreecommitdiff
path: root/apps/chess.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/chess.c')
-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;
}