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 |
1.1 --- a/conf.mk Tue Apr 01 12:30:25 2014 +0200 1.2 +++ b/conf.mk Tue Apr 01 14:04:00 2014 +0200 1.3 @@ -32,7 +32,7 @@ 1.4 1.5 BIN = terminal-chess 1.6 CC = gcc 1.7 -CFLAGS = -g -O2 -std=gnu99 -Wall -Werror -pedantic 1.8 +CFLAGS = -g -O2 -std=gnu99 -Wall -pedantic 1.9 LD = gcc 1.10 LDFLAGS = -lncurses 1.11 ARFLAGS = -r
2.1 --- a/src/chess/chess.h Tue Apr 01 12:30:25 2014 +0200 2.2 +++ b/src/chess/chess.h Tue Apr 01 14:04:00 2014 +0200 2.3 @@ -33,4 +33,4 @@ 2.4 #include "knight.h" 2.5 #include "bishop.h" 2.6 #include "queen.h" 2.7 -#include "king.h" 2.8 \ No newline at end of file 2.9 +#include "king.h"
3.1 --- a/src/chess/conf.mk Tue Apr 01 12:30:25 2014 +0200 3.2 +++ b/src/chess/conf.mk Tue Apr 01 14:04:00 2014 +0200 3.3 @@ -31,7 +31,7 @@ 3.4 AR = ar 3.5 3.6 CC = gcc 3.7 -CFLAGS = -g -O2 -std=gnu99 -Wall -Werror -pedantic 3.8 +CFLAGS = -g -O2 -std=gnu99 -Wall -pedantic 3.9 ARFLAGS = -r 3.10 MKDIRFLAGS = -p 3.11 RMFLAGS = -f -R
4.1 --- a/src/chess/rules.h Tue Apr 01 12:30:25 2014 +0200 4.2 +++ b/src/chess/rules.h Tue Apr 01 14:04:00 2014 +0200 4.3 @@ -78,6 +78,7 @@ 4.4 uint8_t promotion; 4.5 _Bool check; 4.6 _Bool checkmate; 4.7 + _Bool stalemate; // TODO: find a better place for checkmate and stalemate 4.8 _Bool capture; 4.9 } Move; 4.10
5.1 --- a/src/game.c Tue Apr 01 12:30:25 2014 +0200 5.2 +++ b/src/game.c Tue Apr 01 14:04:00 2014 +0200 5.3 @@ -112,6 +112,78 @@ 5.4 } 5.5 } 5.6 5.7 +static void eval_move_failed_msg(int code) { 5.8 + switch (code) { 5.9 + case AMBIGUOUS_MOVE: 5.10 + printw("Ambiguous move - please specify the piece to move."); 5.11 + break; 5.12 + case INVALID_POSITION: 5.13 + printw("Cannot find the piece that shall be moved."); 5.14 + break; 5.15 + case NEED_PROMOTION: 5.16 + printw("You need to promote the pawn (append \"=Q\" e.g.)!"); 5.17 + break; 5.18 + default: 5.19 + printw("Can't interpret move - please use algebraic notation."); 5.20 + } 5.21 +} 5.22 + 5.23 +static int domove_singlemachine(GameState *gamestate) { 5.24 + 5.25 + const size_t buflen = 8; 5.26 + char movestr[buflen]; 5.27 + 5.28 + int inputy = getmaxy(stdscr) - 6; 5.29 + while (1) { 5.30 + move(inputy, 0); 5.31 + printw( 5.32 + "Use chess notation to enter your move.\n" 5.33 + "Or type 'surr' to surrender or 'remis' to end with remis.\n\n" 5.34 + "Type your move: "); 5.35 + clrtoeol(); 5.36 + refresh(); 5.37 + getnstr(movestr, buflen); 5.38 + 5.39 + if (strncmp(movestr, "surr", buflen) == 0) { 5.40 + printw("%s surrendered!", 5.41 + gamestate->mycolor==WHITE?"White":"Black"); 5.42 + clrtoeol(); 5.43 + refresh(); 5.44 + return 1; 5.45 + } else if (strncmp(movestr, "remis", buflen) == 0) { 5.46 + printw("Game ends remis."); 5.47 + clrtoeol(); 5.48 + refresh(); 5.49 + return 1; 5.50 + } else { 5.51 + Move move; 5.52 + int eval_result = eval_move(gamestate, movestr, &move); 5.53 + switch (eval_result) { 5.54 + case VALID_MOVE_SYNTAX: 5.55 + if (validate_move(gamestate, &move)) { 5.56 + apply_move(gamestate, &move); 5.57 + if (move.checkmate) { 5.58 + printw("Checkmate!"); 5.59 + clrtoeol(); 5.60 + return 1; 5.61 + } else if (move.stalemate) { 5.62 + printw("Stalemate!"); 5.63 + clrtoeol(); 5.64 + return 1; 5.65 + } else { 5.66 + return 0; 5.67 + } 5.68 + } else { 5.69 + printw("Invalid move."); 5.70 + } 5.71 + break; 5.72 + default: 5.73 + eval_move_failed_msg(eval_result); 5.74 + } 5.75 + clrtoeol(); 5.76 + } 5.77 + } 5.78 +} 5.79 5.80 static int sendmove(GameState *gamestate, int opponent) { 5.81 5.82 @@ -167,6 +239,7 @@ 5.83 code = net_recieve_code(opponent); 5.84 move.check = code == NETCODE_CHECK; 5.85 move.checkmate = code == NETCODE_CHECKMATE; 5.86 + move.stalemate = code == NETCODE_STALEMATE; 5.87 if (code == NETCODE_DECLINE) { 5.88 printw("Invalid move."); 5.89 } else { 5.90 @@ -175,22 +248,17 @@ 5.91 printw("Checkmate!"); 5.92 clrtoeol(); 5.93 return 1; 5.94 + } else if (move.stalemate) { 5.95 + printw("Stalemate!"); 5.96 + clrtoeol(); 5.97 + return 1; 5.98 } else { 5.99 return 0; 5.100 } 5.101 } 5.102 break; 5.103 - case AMBIGUOUS_MOVE: 5.104 - printw("Ambiguous move - please specify the piece to move."); 5.105 - break; 5.106 - case INVALID_POSITION: 5.107 - printw("Cannot find the piece that shall be moved."); 5.108 - break; 5.109 - case NEED_PROMOTION: 5.110 - printw("You need to promote the pawn (append \"=Q\" e.g.)!"); 5.111 - break; 5.112 default: 5.113 - printw("Can't interpret move - please use algebraic notation."); 5.114 + eval_move_failed_msg(eval_result); 5.115 } 5.116 clrtoeol(); 5.117 } 5.118 @@ -234,6 +302,14 @@ 5.119 net_send_code(opponent, NETCODE_CHECK); 5.120 } else if (move.checkmate) { 5.121 net_send_code(opponent, NETCODE_CHECKMATE); 5.122 + printw("\rCheckmate!"); 5.123 + clrtoeol(); 5.124 + return 1; 5.125 + } else if (move.stalemate) { 5.126 + net_send_code(opponent, NETCODE_STALEMATE); 5.127 + printw("\rStalemate!"); 5.128 + clrtoeol(); 5.129 + return 1; 5.130 } else { 5.131 net_send_code(opponent, NETCODE_ACCEPT); 5.132 } 5.133 @@ -245,22 +321,49 @@ 5.134 } 5.135 } 5.136 5.137 +static void init_board(GameState *gamestate) { 5.138 + Board initboard = { 5.139 + {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK}, 5.140 + {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN}, 5.141 + {0, 0, 0, 0, 0, 0, 0, 0}, 5.142 + {0, 0, 0, 0, 0, 0, 0, 0}, 5.143 + {0, 0, 0, 0, 0, 0, 0, 0}, 5.144 + {0, 0, 0, 0, 0, 0, 0, 0}, 5.145 + {BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN}, 5.146 + {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK} 5.147 + }; 5.148 + memcpy(gamestate->board, initboard, sizeof(Board)); 5.149 +} 5.150 + 5.151 +void game_start_singlemachine(Settings *settings) { 5.152 + GameState gamestate; 5.153 + init_board(&gamestate); 5.154 + gamestate.mycolor = WHITE; 5.155 + gamestate.movelist = gamestate.lastmove = NULL; 5.156 + // TODO: time limit 5.157 + _Bool running; 5.158 + do { 5.159 + clear(); 5.160 + draw_board(&gamestate); 5.161 + running = !domove_singlemachine(&gamestate); 5.162 + gamestate.mycolor = opponent_color(gamestate.mycolor); 5.163 + } while (running); 5.164 + 5.165 + gamestate_cleanup(&gamestate); 5.166 + 5.167 + mvaddstr(getmaxy(stdscr)-1, 0, 5.168 + "Game has ended. Press any key to leave..."); 5.169 + refresh(); 5.170 + getch(); 5.171 +} 5.172 + 5.173 void game_start(Settings *settings, int opponent) { 5.174 _Bool myturn = is_server(settings) == 5.175 (settings->gameinfo.servercolor == WHITE); 5.176 5.177 + // TODO: time limit 5.178 GameState gamestate; 5.179 - Board initboard = { 5.180 - {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK}, 5.181 - {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN}, 5.182 - {0, 0, 0, 0, 0, 0, 0, 0}, 5.183 - {0, 0, 0, 0, 0, 0, 0, 0}, 5.184 - {0, 0, 0, 0, 0, 0, 0, 0}, 5.185 - {0, 0, 0, 0, 0, 0, 0, 0}, 5.186 - {BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN}, 5.187 - {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK} 5.188 - }; 5.189 - memcpy(gamestate.board, initboard, sizeof(Board)); 5.190 + init_board(&gamestate); 5.191 gamestate.mycolor = myturn ? WHITE:BLACK; 5.192 gamestate.movelist = gamestate.lastmove = NULL; 5.193 5.194 @@ -281,5 +384,6 @@ 5.195 5.196 mvaddstr(getmaxy(stdscr)-1, 0, 5.197 "Game has ended. Press any key to leave..."); 5.198 + refresh(); 5.199 getch(); 5.200 }
6.1 --- a/src/game.h Tue Apr 01 12:30:25 2014 +0200 6.2 +++ b/src/game.h Tue Apr 01 14:04:00 2014 +0200 6.3 @@ -38,6 +38,7 @@ 6.4 #endif 6.5 6.6 void game_start(Settings *settings, int opponent); 6.7 +void game_start_singlemachine(Settings *settings); 6.8 6.9 #ifdef __cplusplus 6.10 }
7.1 --- a/src/main.c Tue Apr 01 12:30:25 2014 +0200 7.2 +++ b/src/main.c Tue Apr 01 14:04:00 2014 +0200 7.3 @@ -40,7 +40,7 @@ 7.4 uint8_t timeunit = 60; 7.5 size_t len; 7.6 7.7 - for (char opt ; (opt = getopt(argc, argv, "a:bhp:rt:")) != -1 ;) { 7.8 + for (char opt ; (opt = getopt(argc, argv, "a:bhp:rst:")) != -1 ;) { 7.9 switch (opt) { 7.10 case 'b': 7.11 settings->gameinfo.servercolor = BLACK; 7.12 @@ -48,6 +48,9 @@ 7.13 case 'r': 7.14 settings->gameinfo.servercolor = rand() & 1 ? WHITE : BLACK; 7.15 break; 7.16 + case 's': 7.17 + settings->singlemachine = 1; 7.18 + break; 7.19 case 't': 7.20 case 'a': 7.21 len = strlen(optarg); 7.22 @@ -150,10 +153,9 @@ 7.23 " -a <time> Specifies the time to add after each move\n" 7.24 " -b Server plays black pieces (default: white)\n" 7.25 " -r Distribute color randomly\n" 7.26 + " -s Single machine mode\n" 7.27 " -t <time> Specifies time limit (default: no limit)\n" 7.28 "\nNotes\n" 7.29 - "White pieces are displayed as uppercase and black pieces as " 7.30 - "lowercase letters.\n" 7.31 "The time unit for -a is seconds and for -t minutes by default. To " 7.32 "specify\nseconds for the -t option, use the s suffix.\n" 7.33 "Example: -t 150s\n" 7.34 @@ -173,6 +175,11 @@ 7.35 } 7.36 atexit(leavescr); 7.37 7.38 - return is_server(&settings) ? server_run(&settings) : client_run(&settings); 7.39 + if (settings.singlemachine) { 7.40 + game_start_singlemachine(&settings); 7.41 + } else { 7.42 + return is_server(&settings) ? 7.43 + server_run(&settings) : client_run(&settings); 7.44 + } 7.45 } 7.46
8.1 --- a/src/terminal-chess.h Tue Apr 01 12:30:25 2014 +0200 8.2 +++ b/src/terminal-chess.h Tue Apr 01 14:04:00 2014 +0200 8.3 @@ -48,10 +48,11 @@ 8.4 } Gameinfo; 8.5 8.6 typedef struct { 8.7 - uint8_t printhelp; 8.8 Gameinfo gameinfo; 8.9 char* port; 8.10 char* serverhost; /* NULL, if we are about to start a server */ 8.11 + _Bool printhelp; 8.12 + _Bool singlemachine; 8.13 } Settings; 8.14 8.15 #define is_server(settings) !((settings)->serverhost)