# HG changeset patch # User Mike Becker # Date 1396353840 -7200 # Node ID e0a76ee1bb2b91d43a1c15b527b17ab2596c9c86 # Parent 3ab0c2e1a4e2420fef1dbc2beedf89ef5a92998c introduced single machine mode diff -r 3ab0c2e1a4e2 -r e0a76ee1bb2b conf.mk --- a/conf.mk Tue Apr 01 12:30:25 2014 +0200 +++ b/conf.mk Tue Apr 01 14:04:00 2014 +0200 @@ -32,7 +32,7 @@ BIN = terminal-chess CC = gcc -CFLAGS = -g -O2 -std=gnu99 -Wall -Werror -pedantic +CFLAGS = -g -O2 -std=gnu99 -Wall -pedantic LD = gcc LDFLAGS = -lncurses ARFLAGS = -r diff -r 3ab0c2e1a4e2 -r e0a76ee1bb2b src/chess/chess.h --- a/src/chess/chess.h Tue Apr 01 12:30:25 2014 +0200 +++ b/src/chess/chess.h Tue Apr 01 14:04:00 2014 +0200 @@ -33,4 +33,4 @@ #include "knight.h" #include "bishop.h" #include "queen.h" -#include "king.h" \ No newline at end of file +#include "king.h" diff -r 3ab0c2e1a4e2 -r e0a76ee1bb2b src/chess/conf.mk --- a/src/chess/conf.mk Tue Apr 01 12:30:25 2014 +0200 +++ b/src/chess/conf.mk Tue Apr 01 14:04:00 2014 +0200 @@ -31,7 +31,7 @@ AR = ar CC = gcc -CFLAGS = -g -O2 -std=gnu99 -Wall -Werror -pedantic +CFLAGS = -g -O2 -std=gnu99 -Wall -pedantic ARFLAGS = -r MKDIRFLAGS = -p RMFLAGS = -f -R diff -r 3ab0c2e1a4e2 -r e0a76ee1bb2b src/chess/rules.h --- a/src/chess/rules.h Tue Apr 01 12:30:25 2014 +0200 +++ b/src/chess/rules.h Tue Apr 01 14:04:00 2014 +0200 @@ -78,6 +78,7 @@ uint8_t promotion; _Bool check; _Bool checkmate; + _Bool stalemate; // TODO: find a better place for checkmate and stalemate _Bool capture; } Move; diff -r 3ab0c2e1a4e2 -r e0a76ee1bb2b src/game.c --- a/src/game.c Tue Apr 01 12:30:25 2014 +0200 +++ b/src/game.c Tue Apr 01 14:04:00 2014 +0200 @@ -112,6 +112,78 @@ } } +static void eval_move_failed_msg(int code) { + switch (code) { + case AMBIGUOUS_MOVE: + printw("Ambiguous move - please specify the piece to move."); + break; + case INVALID_POSITION: + printw("Cannot find the piece that shall be moved."); + break; + case NEED_PROMOTION: + printw("You need to promote the pawn (append \"=Q\" e.g.)!"); + break; + default: + printw("Can't interpret move - please use algebraic notation."); + } +} + +static int domove_singlemachine(GameState *gamestate) { + + const size_t buflen = 8; + char movestr[buflen]; + + int inputy = getmaxy(stdscr) - 6; + while (1) { + move(inputy, 0); + printw( + "Use chess notation to enter your move.\n" + "Or type 'surr' to surrender or 'remis' to end with remis.\n\n" + "Type your move: "); + clrtoeol(); + refresh(); + getnstr(movestr, buflen); + + if (strncmp(movestr, "surr", buflen) == 0) { + printw("%s surrendered!", + gamestate->mycolor==WHITE?"White":"Black"); + clrtoeol(); + refresh(); + return 1; + } else if (strncmp(movestr, "remis", buflen) == 0) { + printw("Game ends remis."); + clrtoeol(); + refresh(); + return 1; + } else { + Move move; + int eval_result = eval_move(gamestate, movestr, &move); + switch (eval_result) { + case VALID_MOVE_SYNTAX: + if (validate_move(gamestate, &move)) { + apply_move(gamestate, &move); + if (move.checkmate) { + printw("Checkmate!"); + clrtoeol(); + return 1; + } else if (move.stalemate) { + printw("Stalemate!"); + clrtoeol(); + return 1; + } else { + return 0; + } + } else { + printw("Invalid move."); + } + break; + default: + eval_move_failed_msg(eval_result); + } + clrtoeol(); + } + } +} static int sendmove(GameState *gamestate, int opponent) { @@ -167,6 +239,7 @@ code = net_recieve_code(opponent); move.check = code == NETCODE_CHECK; move.checkmate = code == NETCODE_CHECKMATE; + move.stalemate = code == NETCODE_STALEMATE; if (code == NETCODE_DECLINE) { printw("Invalid move."); } else { @@ -175,22 +248,17 @@ printw("Checkmate!"); clrtoeol(); return 1; + } else if (move.stalemate) { + printw("Stalemate!"); + clrtoeol(); + return 1; } else { return 0; } } break; - case AMBIGUOUS_MOVE: - printw("Ambiguous move - please specify the piece to move."); - break; - case INVALID_POSITION: - printw("Cannot find the piece that shall be moved."); - break; - case NEED_PROMOTION: - printw("You need to promote the pawn (append \"=Q\" e.g.)!"); - break; default: - printw("Can't interpret move - please use algebraic notation."); + eval_move_failed_msg(eval_result); } clrtoeol(); } @@ -234,6 +302,14 @@ net_send_code(opponent, NETCODE_CHECK); } else if (move.checkmate) { net_send_code(opponent, NETCODE_CHECKMATE); + printw("\rCheckmate!"); + clrtoeol(); + return 1; + } else if (move.stalemate) { + net_send_code(opponent, NETCODE_STALEMATE); + printw("\rStalemate!"); + clrtoeol(); + return 1; } else { net_send_code(opponent, NETCODE_ACCEPT); } @@ -245,22 +321,49 @@ } } +static void init_board(GameState *gamestate) { + Board initboard = { + {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK}, + {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN}, + {0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0}, + {BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN}, + {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK} + }; + memcpy(gamestate->board, initboard, sizeof(Board)); +} + +void game_start_singlemachine(Settings *settings) { + GameState gamestate; + init_board(&gamestate); + gamestate.mycolor = WHITE; + gamestate.movelist = gamestate.lastmove = NULL; + // TODO: time limit + _Bool running; + do { + clear(); + draw_board(&gamestate); + running = !domove_singlemachine(&gamestate); + gamestate.mycolor = opponent_color(gamestate.mycolor); + } while (running); + + gamestate_cleanup(&gamestate); + + mvaddstr(getmaxy(stdscr)-1, 0, + "Game has ended. Press any key to leave..."); + refresh(); + getch(); +} + void game_start(Settings *settings, int opponent) { _Bool myturn = is_server(settings) == (settings->gameinfo.servercolor == WHITE); + // TODO: time limit GameState gamestate; - Board initboard = { - {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK}, - {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN}, - {0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0}, - {BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN}, - {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK} - }; - memcpy(gamestate.board, initboard, sizeof(Board)); + init_board(&gamestate); gamestate.mycolor = myturn ? WHITE:BLACK; gamestate.movelist = gamestate.lastmove = NULL; @@ -281,5 +384,6 @@ mvaddstr(getmaxy(stdscr)-1, 0, "Game has ended. Press any key to leave..."); + refresh(); getch(); } diff -r 3ab0c2e1a4e2 -r e0a76ee1bb2b src/game.h --- a/src/game.h Tue Apr 01 12:30:25 2014 +0200 +++ b/src/game.h Tue Apr 01 14:04:00 2014 +0200 @@ -38,6 +38,7 @@ #endif void game_start(Settings *settings, int opponent); +void game_start_singlemachine(Settings *settings); #ifdef __cplusplus } diff -r 3ab0c2e1a4e2 -r e0a76ee1bb2b src/main.c --- a/src/main.c Tue Apr 01 12:30:25 2014 +0200 +++ b/src/main.c Tue Apr 01 14:04:00 2014 +0200 @@ -40,7 +40,7 @@ uint8_t timeunit = 60; size_t len; - for (char opt ; (opt = getopt(argc, argv, "a:bhp:rt:")) != -1 ;) { + for (char opt ; (opt = getopt(argc, argv, "a:bhp:rst:")) != -1 ;) { switch (opt) { case 'b': settings->gameinfo.servercolor = BLACK; @@ -48,6 +48,9 @@ case 'r': settings->gameinfo.servercolor = rand() & 1 ? WHITE : BLACK; break; + case 's': + settings->singlemachine = 1; + break; case 't': case 'a': len = strlen(optarg); @@ -150,10 +153,9 @@ " -a