src/main.c

changeset 210
7ad6c62f6bdc
parent 208
e9c3d3e89465
child 211
141813037e99
equal deleted inserted replaced
208:e9c3d3e89465 210:7ad6c62f6bdc
258 uint16_t white = remaining_movetime(gamestate, WHITE); 258 uint16_t white = remaining_movetime(gamestate, WHITE);
259 uint16_t black = remaining_movetime(gamestate, BLACK); 259 uint16_t black = remaining_movetime(gamestate, BLACK);
260 char clkstr[16]; 260 char clkstr[16];
261 bool always_hours = gamestate->info.time >= 3600; 261 bool always_hours = gamestate->info.time >= 3600;
262 print_clk(white, clkstr, always_hours); 262 print_clk(white, clkstr, always_hours);
263 mvprintw(boardy+4, boardx-1, "White time: %s", clkstr); 263 mvaddstr(boardy+4, boardx-1, "White time: ");
264 addstr(clkstr);
264 print_clk(black, clkstr, always_hours); 265 print_clk(black, clkstr, always_hours);
265 mvprintw(boardy+5, boardx-1, "Black time: %s", clkstr); 266 mvaddstr(boardy+5, boardx-1, "Black time: ");
267 addstr(clkstr);
266 268
267 if (white == 0) { 269 if (white == 0) {
268 move(inputy, 0); 270 move(inputy, 0);
269 printw("Time is over - Black wins!"); 271 addstr("Time is over - Black wins!");
270 clrtobot(); 272 clrtobot();
271 refresh(); 273 refresh();
272 return 1; 274 return 1;
273 } 275 }
274 if (black == 0) { 276 if (black == 0) {
275 move(inputy, 0); 277 move(inputy, 0);
276 printw("Time is over - White wins!"); 278 addstr("Time is over - White wins!");
277 clrtobot(); 279 clrtobot();
278 refresh(); 280 refresh();
279 return 1; 281 return 1;
280 } 282 }
281 } 283 }
318 ) 320 )
319 ); 321 );
320 322
321 int cy = perspective == WHITE ? boardy-y : boardy-7+y; 323 int cy = perspective == WHITE ? boardy-y : boardy-7+y;
322 int cx = perspective == WHITE ? boardx+x*3 : boardx+21-x*3; 324 int cx = perspective == WHITE ? boardx+x*3 : boardx+21-x*3;
323 mvprintw(cy, cx, " %s ", piecestr); 325 mvaddch(cy, cx, ' ');
326 addstr(piecestr);
327 addch(' ');
324 } 328 }
325 } 329 }
326 330
327 attrset(A_NORMAL); 331 attrset(A_NORMAL);
328 for (uint8_t i = 0 ; i < 8 ; i++) { 332 for (uint8_t i = 0 ; i < 8 ; i++) {
362 } 366 }
363 367
364 static void eval_move_failed_msg(int code) { 368 static void eval_move_failed_msg(int code) {
365 switch (code) { 369 switch (code) {
366 case AMBIGUOUS_MOVE: 370 case AMBIGUOUS_MOVE:
367 printw("Ambiguous move - please specify the piece to move."); 371 addstr("Ambiguous move - please specify the piece to move.");
368 break; 372 break;
369 case PIECE_NOT_FOUND: 373 case PIECE_NOT_FOUND:
370 printw("No piece can be moved this way."); 374 addstr("No piece can be moved this way.");
371 break; 375 break;
372 case NEED_PROMOTION: 376 case NEED_PROMOTION:
373 printw("You need to promote the pawn (append \"=Q\" e.g.)!"); 377 addstr("You need to promote the pawn (append \"=Q\" e.g.)!");
374 break; 378 break;
375 case KING_IN_CHECK: 379 case KING_IN_CHECK:
376 printw("Your king is in check!"); 380 addstr("Your king is in check!");
377 break; 381 break;
378 case PIECE_PINNED: 382 case PIECE_PINNED:
379 printw("This piece is pinned!"); 383 addstr("This piece is pinned!");
380 break; 384 break;
381 case INVALID_MOVE_SYNTAX: 385 case INVALID_MOVE_SYNTAX:
382 printw("Can't interpret move - please use algebraic notation."); 386 addstr("Can't interpret move - please use algebraic notation.");
383 break; 387 break;
384 case RULES_VIOLATED: 388 case RULES_VIOLATED:
385 printw("Move does not comply with chess rules."); 389 addstr("Move does not comply with chess rules.");
386 break; 390 break;
387 case KING_MOVES_INTO_CHECK: 391 case KING_MOVES_INTO_CHECK:
388 printw("Can't move the king into a check position."); 392 addstr("Can't move the king into a check position.");
389 break; 393 break;
390 case MISSING_CHECK: 394 case MISSING_CHECK:
391 printw("Move does not indicate check."); 395 addstr("Move does not indicate check.");
392 break; 396 break;
393 case MISSING_CHECKMATE: 397 case MISSING_CHECKMATE:
394 printw("Move does not indicate checkmate."); 398 addstr("Move does not indicate checkmate.");
395 break; 399 break;
396 case INVALID_CHECK: 400 case INVALID_CHECK:
397 printw("Move incorrectly indicates check."); 401 addstr("Move incorrectly indicates check.");
398 break; 402 break;
399 case INVALID_CHECKMATE: 403 case INVALID_CHECKMATE:
400 printw("Move incorrectly indicates checkmate."); 404 addstr("Move incorrectly indicates checkmate.");
401 break; 405 break;
402 default: 406 default:
403 printw("Unknown move parser error."); 407 addstr("Unknown move parser error.");
404 } 408 }
405 } 409 }
406 410
407 static void save_pgn(GameState *gamestate) { 411 static void save_pgn(GameState *gamestate) {
408 int y; 412 int y;
429 move(y, 0); 433 move(y, 0);
430 } 434 }
431 435
432 bool export_comments = prompt_yesno("Export with comments"); 436 bool export_comments = prompt_yesno("Export with comments");
433 437
434 printw("\rFilename: "); 438 addstr("\rFilename: ");
435 clrtoeol(); 439 clrtoeol();
436 440
437 char filename[64]; 441 char filename[64];
438 if (getnstr(filename, 64) == OK && filename[0] != '\0') { 442 if (getnstr(filename, 64) == OK && filename[0] != '\0') {
439 move(y, 0); 443 move(y, 0);
440 FILE *file = fopen(filename, "w"); 444 FILE *file = fopen(filename, "w");
441 if (file) { 445 if (file) {
442 write_pgn(file, gamestate, export_comments); 446 write_pgn(file, gamestate, export_comments);
443 fclose(file); 447 fclose(file);
444 printw("File saved."); 448 addstr("File saved.");
445 } else { 449 } else {
446 printw("Can't write to file (%s).", strerror(errno)); 450 printw("Can't write to file (%s).", strerror(errno));
447 } 451 }
448 clrtoeol(); 452 clrtoeol();
449 } 453 }
585 net_send_code(opponent, NETCODE_TIMEOVER); 589 net_send_code(opponent, NETCODE_TIMEOVER);
586 return 1; 590 return 1;
587 } 591 }
588 592
589 move(inputy, 0); 593 move(inputy, 0);
590 printw("Use chess notation to enter your move.\n"); 594 addstr("Use chess notation to enter your move.\n");
591 if (resign_suggested) { 595 if (resign_suggested) {
592 if (remis_suggested) { 596 if (remis_suggested) {
593 printw("The opponent asks you to resign or accept remis. \n\n"); 597 addstr("The opponent asks you to resign or accept remis. \n\n");
594 } else { 598 } else {
595 printw("The opponent asks you to resign. \n\n"); 599 addstr("The opponent asks you to resign. \n\n");
596 } 600 }
597 } else if (remis_suggested) { 601 } else if (remis_suggested) {
598 printw("The opponent offers remis. Type remis to accept. \n\n"); 602 addstr("The opponent offers remis. Type remis to accept. \n\n");
599 } else if (remis_rejected) { 603 } else if (remis_rejected) {
600 printw("Remis offer rejected. \n\n"); 604 addstr("Remis offer rejected. \n\n");
601 } else if (remis_offered) { 605 } else if (remis_offered) {
602 printw("Remis offer sent. \n\n"); 606 addstr("Remis offer sent. \n\n");
603 } else { 607 } else {
604 printw("Or use a command: remis, resign, savepgn \n\n"); 608 addstr("Or use a command: remis, resign, savepgn \n\n");
605 } 609 }
606 printw("Type your move: "); 610 addstr("Type your move: ");
607 clrtoeol(); 611 clrtoeol();
608 612
609 /* check if the opponent sent us something */ 613 /* check if the opponent sent us something */
610 code = net_recieve_code_async(opponent); 614 code = net_recieve_code_async(opponent);
611 switch (code) { 615 switch (code) {
628 return 1; 632 return 1;
629 case NETCODE_CONNLOST: 633 case NETCODE_CONNLOST:
630 gamestate->ragequit = true; 634 gamestate->ragequit = true;
631 return 1; 635 return 1;
632 case NETCODE_ERROR: 636 case NETCODE_ERROR:
633 printw("\rCannot perform asynchronous network IO"); 637 addstr("\rCannot perform asynchronous network IO");
634 cbreak(); getch(); 638 cbreak(); getch();
635 exit(EXIT_FAILURE); 639 exit(EXIT_FAILURE);
636 case NETCODE_AGAIN: 640 case NETCODE_AGAIN:
637 /* try again */ 641 /* try again */
638 break; 642 break;
639 default: 643 default:
640 printw("\nThe opponent sent an invalid network pacakge."); 644 addstr("\nThe opponent sent an invalid network pacakge.");
641 } 645 }
642 646
643 /* read move */ 647 /* read move */
644 if (use_premove || asyncgetnstr(movestr, &bufpos, MOVESTR_BUFLEN)) { 648 if (use_premove || asyncgetnstr(movestr, &bufpos, MOVESTR_BUFLEN)) {
645 bool was_premove = use_premove; 649 bool was_premove = use_premove;
685 * we want to receive the "game end" code from the 689 * we want to receive the "game end" code from the
686 * other party. 690 * other party.
687 */ 691 */
688 return 0; 692 return 0;
689 } else if (code == NETCODE_CONNLOST) { 693 } else if (code == NETCODE_CONNLOST) {
690 printw("Your opponent left the game."); 694 addstr("Your opponent left the game.");
691 return 1; 695 return 1;
692 } else { 696 } else {
693 printw("Invalid network response."); 697 addstr("Invalid network response.");
694 } 698 }
695 } else { 699 } else {
696 if (was_premove) { 700 if (was_premove) {
697 printw("\nThe prepared move could not be executed."); 701 addstr("\nThe prepared move could not be executed.");
698 } else { 702 } else {
699 eval_move_failed_msg(eval_result); 703 eval_move_failed_msg(eval_result);
700 } 704 }
701 } 705 }
702 clrtoeol(); 706 clrtoeol();
714 bool resign_suggested = false; 718 bool resign_suggested = false;
715 while (1) { 719 while (1) {
716 timecontrol(gamestate); 720 timecontrol(gamestate);
717 721
718 move(inputy, 0); 722 move(inputy, 0);
719 printw("Waiting for opponent. Use chess notation to prepare a move.\n"); 723 addstr("Waiting for opponent. Use chess notation to prepare a move.\n");
720 if (*gamestate->premove) { 724 if (*gamestate->premove) {
721 printw("Current pre-move: %s \n", 725 printw("Current pre-move: %s \n",
722 gamestate->premove); 726 gamestate->premove);
723 } else if (remis_suggested && !resign_suggested) { 727 } else if (remis_suggested && !resign_suggested) {
724 printw("Suggested remis. \n"); 728 addstr("Suggested remis. \n");
725 } else if (resign_suggested) { 729 } else if (resign_suggested) {
726 if (remis_suggested) { 730 if (remis_suggested) {
727 printw("Suggested to resign or at least to accept remis. \n"); 731 addstr("Suggested to resign or at least to accept remis. \n");
728 } else { 732 } else {
729 printw("Suggested to resign. \n"); 733 addstr("Suggested to resign. \n");
730 } 734 }
731 } else { 735 } else {
732 printw("Or use a command: remis, resign, taunt, savepgn \n"); 736 addstr("Or use a command: remis, resign, taunt, savepgn \n");
733 } 737 }
734 if (remis_offered) { 738 if (remis_offered) {
735 printw("Opponent offered remis. Type 'remis' to accept.\n"); 739 addstr("Opponent offered remis. Type 'remis' to accept.\n");
736 } else { 740 } else {
737 printw("\n"); 741 addch('\n');
738 } 742 }
739 printw("Prepare your next move: "); 743 addstr("Prepare your next move: ");
740 clrtoeol(); 744 clrtoeol();
741 refresh(); 745 refresh();
742 746
743 /* allow the player to prepare a move */ 747 /* allow the player to prepare a move */
744 if (asyncgetnstr(movestr, &bufpos, MOVESTR_BUFLEN)) { 748 if (asyncgetnstr(movestr, &bufpos, MOVESTR_BUFLEN)) {
870 net_send_data(opponent, NETCODE_DECLINE_MOVE, &code, 1); 874 net_send_data(opponent, NETCODE_DECLINE_MOVE, &code, 1);
871 } 875 }
872 break; 876 break;
873 } 877 }
874 case NETCODE_ERROR: 878 case NETCODE_ERROR:
875 printw("\rCannot perform asynchronous network IO"); 879 addstr("\rCannot perform asynchronous network IO");
876 cbreak(); getch(); 880 cbreak(); getch();
877 exit(EXIT_FAILURE); 881 exit(EXIT_FAILURE);
878 case NETCODE_AGAIN: 882 case NETCODE_AGAIN:
879 /* try again */ 883 /* try again */
880 break; 884 break;
881 default: 885 default:
882 printw("\nInvalid network request."); 886 addstr("\nInvalid network request.");
883 } 887 }
884 } 888 }
885 } 889 }
886 890
887 static void game_review(GameState *gamestate) { 891 static void game_review(GameState *gamestate) {
913 } else if (gamestate->threefold) { 917 } else if (gamestate->threefold) {
914 addstr("The game was drawn after threefold repetition.\n"); 918 addstr("The game was drawn after threefold repetition.\n");
915 } else if (gamestate->nomaterial) { 919 } else if (gamestate->nomaterial) {
916 addstr("The game is drawn due to insufficient material.\n"); 920 addstr("The game is drawn due to insufficient material.\n");
917 } else if (gamestate->checkmate) { 921 } else if (gamestate->checkmate) {
918 printw("%s was checkmated.\n", 922 addstr(gamestate->movecount % 2 == 0 ? "White" : "Black");
919 gamestate->movecount % 2 == 0 ? "White" : "Black"); 923 addstr(" was checkmated.\n");
920 } else if (gamestate->ragequit) { 924 } else if (gamestate->ragequit) {
921 printw("Your opponent disconnected.\n"); 925 addstr("Your opponent disconnected.\n");
922 } 926 }
923 addstr("\nPress 'q' to quit, 's' to save the position as PGN, or\n" 927 addstr("\nPress 'q' to quit, 's' to save the position as PGN, or\n"
924 "arrow keys, home/end, page up/down to review the game.\n"); 928 "arrow keys, home/end, page up/down to review the game.\n");
925 flushinp(); 929 flushinp();
926 redraw = false; 930 redraw = false;
1007 1011
1008 static void dump_gameinfo(GameState *gamestate) { 1012 static void dump_gameinfo(GameState *gamestate) {
1009 GameInfo *gameinfo = &gamestate->info; 1013 GameInfo *gameinfo = &gamestate->info;
1010 int serverwhite = gameinfo->servercolor == WHITE; 1014 int serverwhite = gameinfo->servercolor == WHITE;
1011 attron(A_UNDERLINE); 1015 attron(A_UNDERLINE);
1012 printw("Game details\n"); 1016 addstr("Game details\n");
1013 attroff(A_UNDERLINE); 1017 attroff(A_UNDERLINE);
1014 printw(" Server: %s\n Client: %s\n", 1018 printw(" Server: %s\n Client: %s\n",
1015 serverwhite?"White":"Black", serverwhite?"Black":"White" 1019 serverwhite?"White":"Black", serverwhite?"Black":"White"
1016 ); 1020 );
1017 if (gameinfo->timecontrol) { 1021 if (gameinfo->timecontrol) {
1025 if (gameinfo->delay) { 1029 if (gameinfo->delay) {
1026 printw(" (with %us delay)", gameinfo->delay); 1030 printw(" (with %us delay)", gameinfo->delay);
1027 } 1031 }
1028 addch('\n'); 1032 addch('\n');
1029 } else { 1033 } else {
1030 printw(" No time limit\n"); 1034 addstr(" No time limit\n");
1031 } 1035 }
1032 addch('\n'); 1036 addch('\n');
1033 for (unsigned i = 0 ; i < gamestate->movecount ; i++) { 1037 for (unsigned i = 0 ; i < gamestate->movecount ; i++) {
1034 if (i % 2 == 0) { 1038 if (i % 2 == 0) {
1035 printw("%d. %s", 1+i/2, gamestate->moves[i].string); 1039 printw("%d. %s", 1+i/2, gamestate->moves[i].string);
1054 close(server_fd); 1058 close(server_fd);
1055 } 1059 }
1056 } 1060 }
1057 1061
1058 static int server_open(Server *server) { 1062 static int server_open(Server *server) {
1059 printw("\nListening for client...\n"); 1063 addstr("\nListening for client...\n");
1060 refresh(); 1064 refresh();
1061 if (settings.usedomainsocket 1065 if (settings.usedomainsocket
1062 ? net_create_sock(server, settings.serverhost) 1066 ? net_create_sock(server, settings.serverhost)
1063 : net_create_tcp(server, settings.port)) { 1067 : net_create_tcp(server, settings.port)) {
1064 addstr("Server creation failed"); 1068 addstr("Server creation failed");
1180 if (server_version != NETCODE_VERSION) { 1184 if (server_version != NETCODE_VERSION) {
1181 addstr("Server uses an incompatible software version."); 1185 addstr("Server uses an incompatible software version.");
1182 return 1; 1186 return 1;
1183 } 1187 }
1184 1188
1185 printw("Connection established!\n\n"); 1189 addstr("Connection established!\n\n");
1186 refresh(); 1190 refresh();
1187 1191
1188 return 0; 1192 return 0;
1189 } 1193 }
1190 1194

mercurial