30 #include "game.h" |
30 #include "game.h" |
31 #include "network.h" |
31 #include "network.h" |
32 #include "input.h" |
32 #include "input.h" |
33 #include <ncurses.h> |
33 #include <ncurses.h> |
34 #include <string.h> |
34 #include <string.h> |
|
35 #include <inttypes.h> |
35 |
36 |
36 static const uint8_t boardx = 10, boardy = 10; |
37 static const uint8_t boardx = 10, boardy = 10; |
37 |
38 |
|
39 static void draw_time(GameState *gamestate, GameInfo *gameinfo) { |
|
40 if (gameinfo->timecontrol) { |
|
41 // TODO: correct time display |
|
42 |
|
43 uint16_t whitem = gameinfo->time / 60; |
|
44 uint16_t whites = gameinfo->time % 60; |
|
45 uint16_t blackm = gameinfo->time / 60; |
|
46 uint16_t blacks = gameinfo->time % 60; |
|
47 |
|
48 mvprintw(boardy+4, boardx-1, |
|
49 "White time: %4" PRIu16 ":%02" PRIu16, whitem, whites); |
|
50 mvprintw(boardy+5, boardx-1, |
|
51 "Black time: %4" PRIu16 ":%02" PRIu16, blackm, blacks); |
|
52 } |
|
53 } |
|
54 |
38 static void draw_board(GameState *gamestate) { |
55 static void draw_board(GameState *gamestate) { |
39 |
|
40 for (uint8_t y = 0 ; y < 8 ; y++) { |
56 for (uint8_t y = 0 ; y < 8 ; y++) { |
41 for (uint8_t x = 0 ; x < 8 ; x++) { |
57 for (uint8_t x = 0 ; x < 8 ; x++) { |
42 uint8_t col = gamestate->board[y][x] & COLOR_MASK; |
58 uint8_t col = gamestate->board[y][x] & COLOR_MASK; |
43 uint8_t piece = gamestate->board[y][x] & PIECE_MASK; |
59 uint8_t piece = gamestate->board[y][x] & PIECE_MASK; |
44 char piecec; |
60 char piecec; |
132 default: |
148 default: |
133 printw("Can't interpret move - please use algebraic notation."); |
149 printw("Can't interpret move - please use algebraic notation."); |
134 } |
150 } |
135 } |
151 } |
136 |
152 |
137 static int domove_singlemachine(GameState *gamestate) { |
153 static int domove_singlemachine(GameState *gamestate, GameInfo *gameinfo) { |
138 |
154 |
139 const size_t buflen = 8; |
155 const size_t buflen = 8; |
140 char movestr[buflen]; |
156 char movestr[buflen]; |
141 |
157 |
142 int inputy = getmaxy(stdscr) - 6; |
158 int inputy = getmaxy(stdscr) - 6; |
143 while (1) { |
159 while (1) { |
|
160 draw_time(gamestate, gameinfo); |
144 move(inputy, 0); |
161 move(inputy, 0); |
145 printw( |
162 printw( |
146 "Use chess notation to enter your move.\n" |
163 "Use chess notation to enter your move.\n" |
147 "Or type 'surr' to surrender or 'remis' to end with remis.\n\n" |
164 "Or type 'surr' to surrender or 'remis' to end with remis.\n\n" |
148 "Type your move: "); |
165 "Type your move: "); |
149 clrtoeol(); |
166 clrtoeol(); |
150 refresh(); |
167 refresh(); |
151 getnstr(movestr, buflen); |
168 |
152 |
169 if (asyncgetnstr(movestr, buflen)) { |
153 if (strncmp(movestr, "surr", buflen) == 0) { |
170 if (strncmp(movestr, "surr", buflen) == 0) { |
154 printw("%s surrendered!", |
171 printw("%s surrendered!", |
155 gamestate->mycolor==WHITE?"White":"Black"); |
172 gamestate->mycolor==WHITE?"White":"Black"); |
156 clrtoeol(); |
173 clrtoeol(); |
157 refresh(); |
174 refresh(); |
158 return 1; |
175 return 1; |
159 } else if (strncmp(movestr, "remis", buflen) == 0) { |
176 } else if (strncmp(movestr, "remis", buflen) == 0) { |
160 printw("Game ends remis."); |
177 printw("Game ends remis."); |
161 clrtoeol(); |
178 clrtoeol(); |
162 refresh(); |
179 refresh(); |
163 return 1; |
180 return 1; |
164 } else { |
181 } else { |
165 Move move; |
182 Move move; |
166 int eval_result = eval_move(gamestate, movestr, &move); |
183 int eval_result = eval_move(gamestate, movestr, &move); |
167 switch (eval_result) { |
184 switch (eval_result) { |
168 case VALID_MOVE_SYNTAX: |
185 case VALID_MOVE_SYNTAX: |
169 if (validate_move(gamestate, &move)) { |
186 if (validate_move(gamestate, &move)) { |
170 apply_move(gamestate, &move); |
187 apply_move(gamestate, &move); |
171 if (gamestate->checkmate) { |
188 if (gamestate->checkmate) { |
172 printw("Checkmate!"); |
189 printw("Checkmate!"); |
173 clrtoeol(); |
190 clrtoeol(); |
174 return 1; |
191 return 1; |
175 } else if (gamestate->stalemate) { |
192 } else if (gamestate->stalemate) { |
176 printw("Stalemate!"); |
193 printw("Stalemate!"); |
177 clrtoeol(); |
194 clrtoeol(); |
178 return 1; |
195 return 1; |
|
196 } else { |
|
197 return 0; |
|
198 } |
179 } else { |
199 } else { |
180 return 0; |
200 printw("Invalid move."); |
181 } |
201 } |
182 } else { |
202 break; |
183 printw("Invalid move."); |
203 default: |
184 } |
204 eval_move_failed_msg(eval_result); |
185 break; |
205 } |
186 default: |
206 clrtoeol(); |
187 eval_move_failed_msg(eval_result); |
207 } |
188 } |
|
189 clrtoeol(); |
|
190 } |
208 } |
191 } |
209 } |
192 } |
210 } |
193 |
211 |
194 static int sendmove(GameState *gamestate, int opponent) { |
212 static int sendmove(GameState *gamestate, int opponent) { |
344 void game_start_singlemachine(Settings *settings) { |
362 void game_start_singlemachine(Settings *settings) { |
345 GameState gamestate; |
363 GameState gamestate; |
346 memset(&gamestate, 0, sizeof(GameState)); |
364 memset(&gamestate, 0, sizeof(GameState)); |
347 init_board(&gamestate); |
365 init_board(&gamestate); |
348 gamestate.mycolor = WHITE; |
366 gamestate.mycolor = WHITE; |
349 // TODO: time limit |
367 |
350 _Bool running; |
368 _Bool running; |
351 do { |
369 do { |
352 clear(); |
370 clear(); |
353 draw_board(&gamestate); |
371 draw_board(&gamestate); |
354 running = !domove_singlemachine(&gamestate); |
372 running = !domove_singlemachine(&gamestate, &(settings->gameinfo)); |
355 gamestate.mycolor = opponent_color(gamestate.mycolor); |
373 gamestate.mycolor = opponent_color(gamestate.mycolor); |
356 } while (running); |
374 } while (running); |
357 move(0,0); |
375 move(0,0); |
358 draw_board(&gamestate); |
376 draw_board(&gamestate); |
359 |
377 |