introduced single machine mode

Tue, 01 Apr 2014 14:04:00 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 01 Apr 2014 14:04:00 +0200
changeset 26
e0a76ee1bb2b
parent 25
3ab0c2e1a4e2
child 27
efeb98bc69c9

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)

mercurial