87 (boardblack ? COL_WB : COL_WW) : |
89 (boardblack ? COL_WB : COL_WW) : |
88 (boardblack ? COL_BB : COL_BW) |
90 (boardblack ? COL_BB : COL_BW) |
89 ) |
91 ) |
90 ); |
92 ); |
91 |
93 |
92 int cy = gamestate->mycolor == WHITE ? boardy-y : boardy-7+y; |
94 int cy = perspective == WHITE ? boardy-y : boardy-7+y; |
93 int cx = gamestate->mycolor == WHITE ? boardx+x*3 : boardx+21-x*3; |
95 int cx = perspective == WHITE ? boardx+x*3 : boardx+21-x*3; |
94 mvaddch(cy, cx, ' '); |
96 mvaddch(cy, cx, ' '); |
95 mvaddch(cy, cx+1, piecec); |
97 mvaddch(cy, cx+1, piecec); |
96 mvaddch(cy, cx+2, ' '); |
98 mvaddch(cy, cx+2, ' '); |
97 } |
99 } |
98 } |
100 } |
99 |
101 |
100 attrset(A_NORMAL); |
102 attrset(A_NORMAL); |
101 for (uint8_t i = 0 ; i < 8 ; i++) { |
103 for (uint8_t i = 0 ; i < 8 ; i++) { |
102 int x = gamestate->mycolor == WHITE ? boardx+i*3+1 : boardx+22-i*3; |
104 int x = perspective == WHITE ? boardx+i*3+1 : boardx+22-i*3; |
103 int y = gamestate->mycolor == WHITE ? boardy-i : boardy-7+i; |
105 int y = perspective == WHITE ? boardy-i : boardy-7+i; |
104 mvaddch(boardy+1, x, 'a'+i); |
106 mvaddch(boardy+1, x, 'a'+i); |
105 mvaddch(y, boardx-2, '1'+i); |
107 mvaddch(y, boardx-2, '1'+i); |
106 } |
108 } |
107 |
109 |
108 /* move log */ |
110 /* move log */ |
181 } |
203 } |
182 |
204 |
183 move(inputy, 0); |
205 move(inputy, 0); |
184 printw( |
206 printw( |
185 "Use chess notation to enter your move.\n" |
207 "Use chess notation to enter your move.\n" |
186 "Or type 'resign' to resign or 'remis' to end with remis.\n\n" |
208 "Or use a command: remis, resign, savepgn\n\n" |
187 "Type your move: "); |
209 "Type your move: "); |
188 clrtoeol(); |
210 clrtoeol(); |
189 |
211 |
190 if (asyncgetnstr(movestr, &bufpos, MOVESTR_BUFLEN)) { |
212 if (asyncgetnstr(movestr, &bufpos, MOVESTR_BUFLEN)) { |
191 if (strncmp(movestr, "resign", MOVESTR_BUFLEN) == 0) { |
213 if (strncmp(movestr, "resign", MOVESTR_BUFLEN) == 0) { |
|
214 gamestate->resign = 1; |
192 printw("%s resigned!", |
215 printw("%s resigned!", |
193 gamestate->mycolor==WHITE?"White":"Black"); |
216 curcolor==WHITE?"White":"Black"); |
194 clrtoeol(); |
217 clrtobot(); |
195 refresh(); |
218 refresh(); |
196 return 1; |
219 return 1; |
197 } else if (strncmp(movestr, "remis", MOVESTR_BUFLEN) == 0) { |
220 } else if (strncmp(movestr, "remis", MOVESTR_BUFLEN) == 0) { |
|
221 gamestate->remis = 1; |
198 printw("Game ends remis."); |
222 printw("Game ends remis."); |
199 clrtoeol(); |
223 clrtobot(); |
200 refresh(); |
224 refresh(); |
201 return 1; |
225 return 1; |
|
226 } else if (strncmp(movestr, "savepgn", MOVESTR_BUFLEN) == 0) { |
|
227 save_pgn(gamestate, gameinfo); |
202 } else { |
228 } else { |
203 Move move; |
229 Move move; |
204 int eval_result = eval_move(gamestate, movestr, &move); |
230 int result = eval_move(gamestate, movestr, &move, curcolor); |
205 switch (eval_result) { |
231 switch (result) { |
206 case VALID_MOVE_SYNTAX: |
232 case VALID_MOVE_SYNTAX: |
207 eval_result = validate_move(gamestate, &move); |
233 result = validate_move(gamestate, &move); |
208 if (eval_result == VALID_MOVE_SEMANTICS) { |
234 if (result == VALID_MOVE_SEMANTICS) { |
209 apply_move(gamestate, &move); |
235 apply_move(gamestate, &move); |
210 if (gamestate->checkmate) { |
236 if (gamestate->checkmate) { |
211 printw("Checkmate!"); |
237 printw("Checkmate!"); |
212 clrtoeol(); |
238 clrtoeol(); |
213 return 1; |
239 return 1; |
247 |
274 |
248 move(inputy, 0); |
275 move(inputy, 0); |
249 if (remisrejected) { |
276 if (remisrejected) { |
250 printw( |
277 printw( |
251 "Use chess notation to enter your move.\n" |
278 "Use chess notation to enter your move.\n" |
252 "Remis offer rejected - type 'resign' to resign. \n\n" |
279 "Remis offer rejected \n\n" |
253 "Type your move: "); |
280 "Type your move: "); |
254 } else { |
281 } else { |
255 printw( |
282 printw( |
256 "Use chess notation to enter your move.\n" |
283 "Use chess notation to enter your move.\n" |
257 "Or type 'resign' to resign or 'remis' to offer remis.\n\n" |
284 "Or use a command: remis, resign, savepgn\n\n" |
258 "Type your move: "); |
285 "Type your move: "); |
259 } |
286 } |
260 clrtoeol(); |
287 clrtoeol(); |
261 |
288 |
262 if (asyncgetnstr(movestr, &bufpos, MOVESTR_BUFLEN)) { |
289 if (asyncgetnstr(movestr, &bufpos, MOVESTR_BUFLEN)) { |
263 if (strncmp(movestr, "resign", MOVESTR_BUFLEN) == 0) { |
290 if (strncmp(movestr, "resign", MOVESTR_BUFLEN) == 0) { |
|
291 gamestate->resign = 1; |
264 printw("You resigned!"); |
292 printw("You resigned!"); |
265 clrtoeol(); |
293 clrtoeol(); |
266 refresh(); |
294 refresh(); |
267 net_send_code(opponent, NETCODE_RESIGN); |
295 net_send_code(opponent, NETCODE_RESIGN); |
268 return 1; |
296 return 1; |
|
297 } else if (strncmp(movestr, "savepgn", MOVESTR_BUFLEN) == 0) { |
|
298 save_pgn(gamestate, gameinfo); |
269 } else if (strncmp(movestr, "remis", MOVESTR_BUFLEN) == 0) { |
299 } else if (strncmp(movestr, "remis", MOVESTR_BUFLEN) == 0) { |
270 if (!remisrejected) { |
300 if (!remisrejected) { |
271 net_send_code(opponent, NETCODE_REMIS); |
301 net_send_code(opponent, NETCODE_REMIS); |
272 printw("Remis offer sent - waiting for acceptance..."); |
302 printw("Remis offer sent - waiting for acceptance..."); |
273 refresh(); |
303 refresh(); |
274 code = net_recieve_code(opponent); |
304 code = net_recieve_code(opponent); |
275 if (code == NETCODE_ACCEPT) { |
305 if (code == NETCODE_ACCEPT) { |
|
306 gamestate->remis = 1; |
276 printw("\rRemis accepted!"); |
307 printw("\rRemis accepted!"); |
277 clrtoeol(); |
308 clrtoeol(); |
278 refresh(); |
309 refresh(); |
279 return 1; |
310 return 1; |
280 } else if (code == NETCODE_CONNLOST) { |
311 } else if (code == NETCODE_CONNLOST) { |
419 } |
454 } |
420 } |
455 } |
421 } |
456 } |
422 } |
457 } |
423 |
458 |
424 static void init_board(GameState *gamestate) { |
459 static void post_game(GameState *gamestate, GameInfo *gameinfo) { |
425 Board initboard = { |
460 move(0,0); |
426 {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK}, |
461 draw_board(gamestate, WHITE); |
427 {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN}, |
462 |
428 {0, 0, 0, 0, 0, 0, 0, 0}, |
463 // TODO: network connection is still open here - think about it! |
429 {0, 0, 0, 0, 0, 0, 0, 0}, |
464 |
430 {0, 0, 0, 0, 0, 0, 0, 0}, |
465 mvaddstr(getmaxy(stdscr)-1, 0, |
431 {0, 0, 0, 0, 0, 0, 0, 0}, |
466 "Press 'q' to quit or 's' to save a PGN file..."); |
432 {BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN}, |
467 refresh(); |
433 {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK} |
468 flushinp(); |
434 }; |
469 |
435 memcpy(gamestate->board, initboard, sizeof(Board)); |
470 noecho(); |
|
471 int c; |
|
472 do { |
|
473 c = getch(); |
|
474 if (c == 's') { |
|
475 addch('\r'); |
|
476 echo(); |
|
477 save_pgn(gamestate, gameinfo); |
|
478 addstr(" Press 'q' to quit..."); |
|
479 noecho(); |
|
480 } |
|
481 } while (c != 'q'); |
|
482 echo(); |
|
483 |
|
484 gamestate_cleanup(gamestate); |
436 } |
485 } |
437 |
486 |
438 void game_start_singlemachine(Settings *settings) { |
487 void game_start_singlemachine(Settings *settings) { |
439 inputy = getmaxy(stdscr) - 6; |
488 inputy = getmaxy(stdscr) - 6; |
440 |
489 |
441 GameState gamestate; |
490 GameState gamestate; |
442 memset(&gamestate, 0, sizeof(GameState)); |
491 gamestate_init(&gamestate); |
443 init_board(&gamestate); |
492 uint8_t curcol = WHITE; |
444 gamestate.mycolor = WHITE; |
493 |
|
494 if (settings->continuepgn) { |
|
495 FILE *pgnfile = fopen(settings->continuepgn, "r"); |
|
496 if (pgnfile) { |
|
497 int result = read_pgn(pgnfile, &gamestate, &(settings->gameinfo)); |
|
498 fclose(pgnfile); |
|
499 if (result != EXIT_SUCCESS) { |
|
500 addstr("Invalid PGN file content.\n"); |
|
501 return; |
|
502 } |
|
503 if (!is_game_running(&gamestate)) { |
|
504 addstr("Game has ended. Use -S to analyze it.\n"); |
|
505 return; |
|
506 } |
|
507 curcol = opponent_color(gamestate.lastmove->move.piece&COLOR_MASK); |
|
508 } else { |
|
509 printw("Can't read PGN file (%s)\n", strerror(errno)); |
|
510 return; |
|
511 } |
|
512 } |
445 |
513 |
446 _Bool running; |
514 _Bool running; |
447 do { |
515 do { |
448 clear(); |
516 clear(); |
449 draw_board(&gamestate); |
517 draw_board(&gamestate, curcol); |
450 running = !domove_singlemachine(&gamestate, &(settings->gameinfo)); |
518 running = !domove_singlemachine(&gamestate, |
451 gamestate.mycolor = opponent_color(gamestate.mycolor); |
519 &(settings->gameinfo), curcol); |
|
520 curcol = opponent_color(curcol); |
452 } while (running); |
521 } while (running); |
453 move(0,0); |
522 |
454 draw_board(&gamestate); |
523 post_game(&gamestate, &(settings->gameinfo)); |
455 |
|
456 gamestate_cleanup(&gamestate); |
|
457 } |
524 } |
458 |
525 |
459 void game_start(Settings *settings, int opponent) { |
526 void game_start(Settings *settings, int opponent) { |
460 inputy = getmaxy(stdscr) - 6; |
527 inputy = getmaxy(stdscr) - 6; |
461 |
528 |
462 _Bool myturn = is_server(settings) == |
529 _Bool myturn = is_server(settings) == |
463 (settings->gameinfo.servercolor == WHITE); |
530 (settings->gameinfo.servercolor == WHITE); |
|
531 uint8_t mycolor = myturn ? WHITE : BLACK; |
464 |
532 |
465 GameState gamestate; |
533 GameState gamestate; |
466 memset(&gamestate, 0, sizeof(GameState)); |
534 gamestate_init(&gamestate); |
467 init_board(&gamestate); |
|
468 gamestate.mycolor = myturn ? WHITE:BLACK; |
|
469 |
535 |
470 _Bool running; |
536 _Bool running; |
471 do { |
537 do { |
472 clear(); |
538 clear(); |
473 draw_board(&gamestate); |
539 draw_board(&gamestate, mycolor); |
474 if (myturn) { |
540 if (myturn) { |
475 running = !sendmove(&gamestate, &(settings->gameinfo), opponent); |
541 running = !sendmove(&gamestate, &(settings->gameinfo), |
|
542 opponent, mycolor); |
476 } else { |
543 } else { |
477 running = !recvmove(&gamestate, &(settings->gameinfo), opponent); |
544 running = !recvmove(&gamestate, &(settings->gameinfo), opponent); |
478 } |
545 } |
479 myturn ^= TRUE; |
546 myturn ^= TRUE; |
480 } while (running); |
547 } while (running); |
481 |
548 |
482 move(0,0); |
549 post_game(&gamestate, &(settings->gameinfo)); |
483 draw_board(&gamestate); |
550 } |
484 |
|
485 gamestate_cleanup(&gamestate); |
|
486 } |
|