Tue, 01 Apr 2014 14:04:00 +0200
introduced single machine mode
conf.mk | file | annotate | diff | comparison | revisions | |
src/chess/chess.h | file | annotate | diff | comparison | revisions | |
src/chess/conf.mk | file | annotate | diff | comparison | revisions | |
src/chess/rules.h | file | annotate | diff | comparison | revisions | |
src/game.c | file | annotate | diff | comparison | revisions | |
src/game.h | file | annotate | diff | comparison | revisions | |
src/main.c | file | annotate | diff | comparison | revisions | |
src/terminal-chess.h | file | annotate | diff | comparison | revisions |
--- 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
--- 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"
--- 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
--- 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;
--- 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,11 +321,7 @@ } } -void game_start(Settings *settings, int opponent) { - _Bool myturn = is_server(settings) == - (settings->gameinfo.servercolor == WHITE); - - GameState gamestate; +static void init_board(GameState *gamestate) { Board initboard = { {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK}, {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN}, @@ -260,7 +332,38 @@ {BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN}, {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK} }; - memcpy(gamestate.board, initboard, sizeof(Board)); + 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; + 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(); }
--- 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 }
--- 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 <time> Specifies the time to add after each move\n" " -b Server plays black pieces (default: white)\n" " -r Distribute color randomly\n" + " -s Single machine mode\n" " -t <time> Specifies time limit (default: no limit)\n" "\nNotes\n" - "White pieces are displayed as uppercase and black pieces as " - "lowercase letters.\n" "The time unit for -a is seconds and for -t minutes by default. To " "specify\nseconds for the -t option, use the s suffix.\n" "Example: -t 150s\n" @@ -173,6 +175,11 @@ } atexit(leavescr); - return is_server(&settings) ? server_run(&settings) : client_run(&settings); + if (settings.singlemachine) { + game_start_singlemachine(&settings); + } else { + return is_server(&settings) ? + server_run(&settings) : client_run(&settings); + } }
--- a/src/terminal-chess.h Tue Apr 01 12:30:25 2014 +0200 +++ b/src/terminal-chess.h Tue Apr 01 14:04:00 2014 +0200 @@ -48,10 +48,11 @@ } Gameinfo; typedef struct { - uint8_t printhelp; Gameinfo gameinfo; char* port; char* serverhost; /* NULL, if we are about to start a server */ + _Bool printhelp; + _Bool singlemachine; } Settings; #define is_server(settings) !((settings)->serverhost)