src/game.c

changeset 33
866025982aa9
parent 32
8a0b85303ee8
child 34
c4d4b8a8f902
     1.1 --- a/src/game.c	Wed Apr 09 09:34:07 2014 +0200
     1.2 +++ b/src/game.c	Wed Apr 09 11:12:04 2014 +0200
     1.3 @@ -35,21 +35,36 @@
     1.4  #include <inttypes.h>
     1.5  
     1.6  static const uint8_t boardx = 10, boardy = 10;
     1.7 +static int inputy = 21; /* should be overridden on game startup */
     1.8  
     1.9 -static void draw_time(GameState *gamestate, GameInfo *gameinfo) {
    1.10 +static int timecontrol(GameState *gamestate, GameInfo *gameinfo) {
    1.11      if (gameinfo->timecontrol) {
    1.12 -        // TODO: correct time display
    1.13 -        
    1.14 -        uint16_t whitem = gameinfo->time / 60;
    1.15 -        uint16_t whites = gameinfo->time % 60;
    1.16 -        uint16_t blackm = gameinfo->time / 60;
    1.17 -        uint16_t blacks = gameinfo->time % 60;
    1.18 -        
    1.19 +        uint16_t white = remaining_movetime(gameinfo, gamestate, WHITE);
    1.20 +        uint16_t black = remaining_movetime(gameinfo, gamestate, BLACK);
    1.21          mvprintw(boardy+4, boardx-1,
    1.22 -            "White time: %4" PRIu16 ":%02" PRIu16, whitem, whites);
    1.23 +            "White time: %4" PRIu16 ":%02" PRIu16,
    1.24 +            white / 60, white % 60);
    1.25          mvprintw(boardy+5, boardx-1,
    1.26 -            "Black time: %4" PRIu16 ":%02" PRIu16, blackm, blacks);
    1.27 +            "Black time: %4" PRIu16 ":%02" PRIu16,
    1.28 +            black / 60, black % 60);
    1.29 +    
    1.30 +        if (white == 0) {
    1.31 +            move(inputy, 0);
    1.32 +            printw("Time is over - Black wins!");
    1.33 +            clrtobot();
    1.34 +            refresh();
    1.35 +            return 1;
    1.36 +        }
    1.37 +        if (black == 0) {
    1.38 +            move(inputy, 0);
    1.39 +            printw("Time is over - White wins!");
    1.40 +            clrtobot();
    1.41 +            refresh();
    1.42 +            return 1;
    1.43 +        }
    1.44      }
    1.45 +    
    1.46 +    return 0;
    1.47  }
    1.48  
    1.49  static void draw_board(GameState *gamestate) {
    1.50 @@ -156,16 +171,18 @@
    1.51      size_t bufpos = 0;
    1.52      char movestr[buflen];
    1.53      
    1.54 -    int inputy = getmaxy(stdscr) - 6;
    1.55 +    flushinp();
    1.56      while (1) {
    1.57 -        draw_time(gamestate, gameinfo);
    1.58 +        if (timecontrol(gamestate, gameinfo)) {
    1.59 +            return 1;
    1.60 +        }
    1.61 +        
    1.62          move(inputy, 0);
    1.63          printw(
    1.64              "Use chess notation to enter your move.\n"
    1.65              "Or type 'surr' to surrender or 'remis' to end with remis.\n\n"
    1.66              "Type your move: ");
    1.67          clrtoeol();
    1.68 -        refresh();
    1.69          
    1.70          if (asyncgetnstr(movestr, &bufpos, buflen)) {
    1.71              if (strncmp(movestr, "surr", buflen) == 0) {
    1.72 @@ -210,15 +227,21 @@
    1.73      }
    1.74  }
    1.75  
    1.76 -static int sendmove(GameState *gamestate, int opponent) {
    1.77 +static int sendmove(GameState *gamestate, GameInfo *gameinfo, int opponent) {
    1.78      
    1.79      const size_t buflen = 8;
    1.80 +    size_t bufpos = 0;
    1.81      char movestr[buflen];
    1.82      _Bool remisrejected = FALSE;
    1.83      uint8_t code;
    1.84      
    1.85 -    int inputy = getmaxy(stdscr) - 6;
    1.86 +    flushinp();
    1.87      while (1) {
    1.88 +        if (timecontrol(gamestate, gameinfo)) {
    1.89 +            net_send_code(opponent, NETCODE_TIMEOVER);
    1.90 +            return 1;
    1.91 +        }
    1.92 +        
    1.93          move(inputy, 0);
    1.94          if (remisrejected) {
    1.95              printw(
    1.96 @@ -232,68 +255,69 @@
    1.97                  "Type your move: ");
    1.98          }
    1.99          clrtoeol();
   1.100 -        refresh();
   1.101 -        getnstr(movestr, buflen);
   1.102 -
   1.103 -        if (strncmp(movestr, "surr", buflen) == 0) {
   1.104 -            printw("You surrendered!");
   1.105 -            clrtoeol();
   1.106 -            refresh();
   1.107 -            net_send_code(opponent, NETCODE_SURRENDER);
   1.108 -            return 1;
   1.109 -        } else if (strncmp(movestr, "remis", buflen) == 0) {
   1.110 -            if (!remisrejected) {
   1.111 -                net_send_code(opponent, NETCODE_REMIS);
   1.112 -                printw("Remis offer sent - waiting for acceptance...");
   1.113 +        
   1.114 +        if (asyncgetnstr(movestr, &bufpos, buflen)) {
   1.115 +            if (strncmp(movestr, "surr", buflen) == 0) {
   1.116 +                printw("You surrendered!");
   1.117 +                clrtoeol();
   1.118                  refresh();
   1.119 -                if (net_recieve_code(opponent) == NETCODE_ACCEPT) {
   1.120 -                    printw("\rRemis accepted!");
   1.121 -                    clrtoeol();
   1.122 +                net_send_code(opponent, NETCODE_SURRENDER);
   1.123 +                return 1;
   1.124 +            } else if (strncmp(movestr, "remis", buflen) == 0) {
   1.125 +                if (!remisrejected) {
   1.126 +                    net_send_code(opponent, NETCODE_REMIS);
   1.127 +                    printw("Remis offer sent - waiting for acceptance...");
   1.128                      refresh();
   1.129 -                    return 1;
   1.130 -                } else {
   1.131 -                    remisrejected = TRUE;
   1.132 -                }
   1.133 -            }
   1.134 -        } else {
   1.135 -            Move move;
   1.136 -            int eval_result = eval_move(gamestate, movestr, &move);
   1.137 -            switch (eval_result) {
   1.138 -            case VALID_MOVE_SYNTAX:
   1.139 -                net_send_data(opponent, NETCODE_MOVE, &move, sizeof(Move));
   1.140 -                code = net_recieve_code(opponent);
   1.141 -                move.check = code == NETCODE_CHECK;
   1.142 -                gamestate->checkmate = code == NETCODE_CHECKMATE;
   1.143 -                gamestate->stalemate = code == NETCODE_STALEMATE;
   1.144 -                if (code == NETCODE_DECLINE) {
   1.145 -                    printw("Invalid move.");
   1.146 -                } else {
   1.147 -                    apply_move(gamestate, &move);
   1.148 -                    if (gamestate->checkmate) {
   1.149 -                        printw("Checkmate!");
   1.150 +                    if (net_recieve_code(opponent) == NETCODE_ACCEPT) {
   1.151 +                        printw("\rRemis accepted!");
   1.152                          clrtoeol();
   1.153 -                        return 1;
   1.154 -                    } else if (gamestate->stalemate) {
   1.155 -                        printw("Stalemate!");
   1.156 -                        clrtoeol();
   1.157 +                        refresh();
   1.158                          return 1;
   1.159                      } else {
   1.160 -                        return 0;
   1.161 +                        remisrejected = TRUE;
   1.162                      }
   1.163                  }
   1.164 -                break;
   1.165 -            default:
   1.166 -                eval_move_failed_msg(eval_result);
   1.167 +            } else {
   1.168 +                Move move;
   1.169 +                int eval_result = eval_move(gamestate, movestr, &move);
   1.170 +                switch (eval_result) {
   1.171 +                case VALID_MOVE_SYNTAX:
   1.172 +                    net_send_data(opponent, NETCODE_MOVE, &move, sizeof(Move));
   1.173 +                    code = net_recieve_code(opponent);
   1.174 +                    move.check = code == NETCODE_CHECK;
   1.175 +                    gamestate->checkmate = code == NETCODE_CHECKMATE;
   1.176 +                    gamestate->stalemate = code == NETCODE_STALEMATE;
   1.177 +                    if (code == NETCODE_DECLINE) {
   1.178 +                        printw("Invalid move.");
   1.179 +                    } else {
   1.180 +                        apply_move(gamestate, &move);
   1.181 +                        if (gamestate->checkmate) {
   1.182 +                            printw("Checkmate!");
   1.183 +                            clrtoeol();
   1.184 +                            return 1;
   1.185 +                        } else if (gamestate->stalemate) {
   1.186 +                            printw("Stalemate!");
   1.187 +                            clrtoeol();
   1.188 +                            return 1;
   1.189 +                        } else {
   1.190 +                            return 0;
   1.191 +                        }
   1.192 +                    }
   1.193 +                    break;
   1.194 +                default:
   1.195 +                    eval_move_failed_msg(eval_result);
   1.196 +                }
   1.197 +                clrtoeol();
   1.198              }
   1.199 -            clrtoeol();
   1.200          }
   1.201      }
   1.202  }
   1.203  
   1.204 -static int recvmove(GameState *gamestate, int opponent) {
   1.205 +static int recvmove(GameState *gamestate, GameInfo *gameinfo, int opponent) {
   1.206      
   1.207 -    int inputy = getmaxy(stdscr) - 6;
   1.208      while (1) {
   1.209 +        timecontrol(gamestate, gameinfo);
   1.210 +        
   1.211          move(inputy, 0);
   1.212          printw("Awaiting opponent move...");
   1.213          clrtoeol();
   1.214 @@ -304,44 +328,48 @@
   1.215          
   1.216          Move move;
   1.217          switch (code) {
   1.218 -            case NETCODE_SURRENDER:
   1.219 -                printw("\rYour opponent surrendered!");
   1.220 +        case NETCODE_TIMEOVER:
   1.221 +            printw("\rYour opponent's time ran out - you win!");
   1.222 +            clrtoeol();
   1.223 +            return 1;
   1.224 +        case NETCODE_SURRENDER:
   1.225 +            printw("\rYour opponent surrendered!");
   1.226 +            clrtoeol();
   1.227 +            return 1;
   1.228 +        case NETCODE_REMIS:
   1.229 +            if (prompt_yesno(
   1.230 +                "\rYour opponent offers remis - do you accept")) {
   1.231 +                printw("\rRemis accepted!");
   1.232                  clrtoeol();
   1.233 +                net_send_code(opponent, NETCODE_ACCEPT);
   1.234                  return 1;
   1.235 -            case NETCODE_REMIS:
   1.236 -                if (prompt_yesno(
   1.237 -                    "\rYour opponent offers remis - do you accept")) {
   1.238 -                    printw("\rRemis accepted!");
   1.239 +            } else {
   1.240 +                net_send_code(opponent, NETCODE_DECLINE);
   1.241 +            }
   1.242 +            break;
   1.243 +        case NETCODE_MOVE:
   1.244 +            net_recieve_data(opponent, &move, sizeof(Move));
   1.245 +            if (validate_move(gamestate, &move)) {
   1.246 +                apply_move(gamestate, &move);
   1.247 +                if (move.check) {
   1.248 +                    net_send_code(opponent, NETCODE_CHECK);
   1.249 +                } else if (gamestate->checkmate) {
   1.250 +                    net_send_code(opponent, NETCODE_CHECKMATE);
   1.251 +                    printw("\rCheckmate!");
   1.252                      clrtoeol();
   1.253 -                    net_send_code(opponent, NETCODE_ACCEPT);
   1.254 +                    return 1;
   1.255 +                } else if (gamestate->stalemate) {
   1.256 +                    net_send_code(opponent, NETCODE_STALEMATE);
   1.257 +                    printw("\rStalemate!");
   1.258 +                    clrtoeol();
   1.259                      return 1;
   1.260                  } else {
   1.261 -                    net_send_code(opponent, NETCODE_DECLINE);
   1.262 +                    net_send_code(opponent, NETCODE_ACCEPT);
   1.263                  }
   1.264 -                break;
   1.265 -            case NETCODE_MOVE:
   1.266 -                net_recieve_data(opponent, &move, sizeof(Move));
   1.267 -                if (validate_move(gamestate, &move)) {
   1.268 -                    apply_move(gamestate, &move);
   1.269 -                    if (move.check) {
   1.270 -                        net_send_code(opponent, NETCODE_CHECK);
   1.271 -                    } else if (gamestate->checkmate) {
   1.272 -                        net_send_code(opponent, NETCODE_CHECKMATE);
   1.273 -                        printw("\rCheckmate!");
   1.274 -                        clrtoeol();
   1.275 -                        return 1;
   1.276 -                    } else if (gamestate->stalemate) {
   1.277 -                        net_send_code(opponent, NETCODE_STALEMATE);
   1.278 -                        printw("\rStalemate!");
   1.279 -                        clrtoeol();
   1.280 -                        return 1;
   1.281 -                    } else {
   1.282 -                        net_send_code(opponent, NETCODE_ACCEPT);
   1.283 -                    }
   1.284 -                    return 0;
   1.285 -                } else {
   1.286 -                    net_send_code(opponent, NETCODE_DECLINE);
   1.287 -                }
   1.288 +                return 0;
   1.289 +            } else {
   1.290 +                net_send_code(opponent, NETCODE_DECLINE);
   1.291 +            }
   1.292          }
   1.293      }
   1.294  }
   1.295 @@ -361,6 +389,8 @@
   1.296  }
   1.297  
   1.298  void game_start_singlemachine(Settings *settings) {
   1.299 +    inputy = getmaxy(stdscr) - 6;
   1.300 +    
   1.301      GameState gamestate;
   1.302      memset(&gamestate, 0, sizeof(GameState));
   1.303      init_board(&gamestate);
   1.304 @@ -385,10 +415,11 @@
   1.305  }
   1.306  
   1.307  void game_start(Settings *settings, int opponent) {
   1.308 +    inputy = getmaxy(stdscr) - 6;
   1.309 +    
   1.310      _Bool myturn = is_server(settings) ==
   1.311          (settings->gameinfo.servercolor == WHITE);
   1.312      
   1.313 -    // TODO: time limit
   1.314      GameState gamestate;
   1.315      memset(&gamestate, 0, sizeof(GameState));
   1.316      init_board(&gamestate);
   1.317 @@ -399,10 +430,9 @@
   1.318          clear();
   1.319          draw_board(&gamestate);
   1.320          if (myturn) {
   1.321 -            running = !sendmove(&gamestate, opponent);
   1.322 +            running = !sendmove(&gamestate, &(settings->gameinfo), opponent);
   1.323          } else {
   1.324 -            running = !recvmove(&gamestate, opponent);
   1.325 -            flushinp(); // flush any input the user hacked in while waiting
   1.326 +            running = !recvmove(&gamestate, &(settings->gameinfo), opponent);
   1.327          }
   1.328          myturn ^= TRUE;
   1.329      }  while (running);
   1.330 @@ -415,5 +445,7 @@
   1.331      mvaddstr(getmaxy(stdscr)-1, 0,
   1.332          "Game has ended. Press any key to leave...");
   1.333      refresh();
   1.334 +    cbreak();
   1.335 +    flushinp();
   1.336      getch();
   1.337  }

mercurial