experimental async input for single machine mode

Mon, 07 Apr 2014 17:39:46 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 07 Apr 2014 17:39:46 +0200
changeset 30
a285ee393860
parent 29
c6a1ad6cf749
child 31
ed440bcd9740

experimental async input for single machine mode

src/chess/rules.h file | annotate | diff | comparison | revisions
src/game.c file | annotate | diff | comparison | revisions
src/input.c file | annotate | diff | comparison | revisions
src/input.h file | annotate | diff | comparison | revisions
src/main.c file | annotate | diff | comparison | revisions
src/server.c file | annotate | diff | comparison | revisions
src/terminal-chess.h file | annotate | diff | comparison | revisions
     1.1 --- a/src/chess/rules.h	Mon Apr 07 14:08:57 2014 +0200
     1.2 +++ b/src/chess/rules.h	Mon Apr 07 17:39:46 2014 +0200
     1.3 @@ -87,6 +87,14 @@
     1.4      MoveList* next;
     1.5  };
     1.6  
     1.7 +    
     1.8 +typedef struct {
     1.9 +    uint8_t servercolor;
    1.10 +    _Bool timecontrol;
    1.11 +    uint16_t time;
    1.12 +    uint16_t addtime;
    1.13 +} GameInfo;
    1.14 +
    1.15  typedef struct {
    1.16      Board board;
    1.17      uint8_t mycolor;
     2.1 --- a/src/game.c	Mon Apr 07 14:08:57 2014 +0200
     2.2 +++ b/src/game.c	Mon Apr 07 17:39:46 2014 +0200
     2.3 @@ -32,11 +32,27 @@
     2.4  #include "input.h"
     2.5  #include <ncurses.h>
     2.6  #include <string.h>
     2.7 +#include <inttypes.h>
     2.8  
     2.9  static const uint8_t boardx = 10, boardy = 10;
    2.10  
    2.11 +static void draw_time(GameState *gamestate, GameInfo *gameinfo) {
    2.12 +    if (gameinfo->timecontrol) {
    2.13 +        // TODO: correct time display
    2.14 +        
    2.15 +        uint16_t whitem = gameinfo->time / 60;
    2.16 +        uint16_t whites = gameinfo->time % 60;
    2.17 +        uint16_t blackm = gameinfo->time / 60;
    2.18 +        uint16_t blacks = gameinfo->time % 60;
    2.19 +        
    2.20 +        mvprintw(boardy+4, boardx-1,
    2.21 +            "White time: %4" PRIu16 ":%02" PRIu16, whitem, whites);
    2.22 +        mvprintw(boardy+5, boardx-1,
    2.23 +            "Black time: %4" PRIu16 ":%02" PRIu16, blackm, blacks);
    2.24 +    }
    2.25 +}
    2.26 +
    2.27  static void draw_board(GameState *gamestate) {
    2.28 -    
    2.29      for (uint8_t y = 0 ; y < 8 ; y++) {
    2.30          for (uint8_t x = 0 ; x < 8 ; x++) {
    2.31              uint8_t col = gamestate->board[y][x] & COLOR_MASK;
    2.32 @@ -134,13 +150,14 @@
    2.33      }
    2.34  }
    2.35  
    2.36 -static int domove_singlemachine(GameState *gamestate) {
    2.37 +static int domove_singlemachine(GameState *gamestate, GameInfo *gameinfo) {
    2.38      
    2.39      const size_t buflen = 8;
    2.40      char movestr[buflen];
    2.41      
    2.42      int inputy = getmaxy(stdscr) - 6;
    2.43      while (1) {
    2.44 +        draw_time(gamestate, gameinfo);
    2.45          move(inputy, 0);
    2.46          printw(
    2.47              "Use chess notation to enter your move.\n"
    2.48 @@ -148,45 +165,46 @@
    2.49              "Type your move: ");
    2.50          clrtoeol();
    2.51          refresh();
    2.52 -        getnstr(movestr, buflen);
    2.53 -
    2.54 -        if (strncmp(movestr, "surr", buflen) == 0) {
    2.55 -            printw("%s surrendered!",
    2.56 -                gamestate->mycolor==WHITE?"White":"Black");
    2.57 -            clrtoeol();
    2.58 -            refresh();
    2.59 -            return 1;
    2.60 -        } else if (strncmp(movestr, "remis", buflen) == 0) {
    2.61 -            printw("Game ends remis.");
    2.62 -            clrtoeol();
    2.63 -            refresh();
    2.64 -            return 1;
    2.65 -        } else {
    2.66 -            Move move;
    2.67 -            int eval_result = eval_move(gamestate, movestr, &move);
    2.68 -            switch (eval_result) {
    2.69 -            case VALID_MOVE_SYNTAX:
    2.70 -                if (validate_move(gamestate, &move)) {
    2.71 -                    apply_move(gamestate, &move);
    2.72 -                    if (gamestate->checkmate) {
    2.73 -                        printw("Checkmate!");
    2.74 -                        clrtoeol();
    2.75 -                        return 1;
    2.76 -                    } else if (gamestate->stalemate) {
    2.77 -                        printw("Stalemate!");
    2.78 -                        clrtoeol();
    2.79 -                        return 1;
    2.80 +        
    2.81 +        if (asyncgetnstr(movestr, buflen)) {
    2.82 +            if (strncmp(movestr, "surr", buflen) == 0) {
    2.83 +                printw("%s surrendered!",
    2.84 +                    gamestate->mycolor==WHITE?"White":"Black");
    2.85 +                clrtoeol();
    2.86 +                refresh();
    2.87 +                return 1;
    2.88 +            } else if (strncmp(movestr, "remis", buflen) == 0) {
    2.89 +                printw("Game ends remis.");
    2.90 +                clrtoeol();
    2.91 +                refresh();
    2.92 +                return 1;
    2.93 +            } else {
    2.94 +                Move move;
    2.95 +                int eval_result = eval_move(gamestate, movestr, &move);
    2.96 +                switch (eval_result) {
    2.97 +                case VALID_MOVE_SYNTAX:
    2.98 +                    if (validate_move(gamestate, &move)) {
    2.99 +                        apply_move(gamestate, &move);
   2.100 +                        if (gamestate->checkmate) {
   2.101 +                            printw("Checkmate!");
   2.102 +                            clrtoeol();
   2.103 +                            return 1;
   2.104 +                        } else if (gamestate->stalemate) {
   2.105 +                            printw("Stalemate!");
   2.106 +                            clrtoeol();
   2.107 +                            return 1;
   2.108 +                        } else {
   2.109 +                            return 0;
   2.110 +                        }
   2.111                      } else {
   2.112 -                        return 0;
   2.113 +                        printw("Invalid move.");
   2.114                      }
   2.115 -                } else {
   2.116 -                    printw("Invalid move.");
   2.117 +                    break;
   2.118 +                default:
   2.119 +                    eval_move_failed_msg(eval_result);
   2.120                  }
   2.121 -                break;
   2.122 -            default:
   2.123 -                eval_move_failed_msg(eval_result);
   2.124 +                clrtoeol();
   2.125              }
   2.126 -            clrtoeol();
   2.127          }
   2.128      }
   2.129  }
   2.130 @@ -346,12 +364,12 @@
   2.131      memset(&gamestate, 0, sizeof(GameState));
   2.132      init_board(&gamestate);
   2.133      gamestate.mycolor = WHITE;
   2.134 -    // TODO: time limit
   2.135 +
   2.136      _Bool running;
   2.137      do {
   2.138          clear();
   2.139          draw_board(&gamestate);
   2.140 -        running = !domove_singlemachine(&gamestate);
   2.141 +        running = !domove_singlemachine(&gamestate, &(settings->gameinfo));
   2.142          gamestate.mycolor = opponent_color(gamestate.mycolor);
   2.143      }  while (running);
   2.144      move(0,0);
     3.1 --- a/src/input.c	Mon Apr 07 14:08:57 2014 +0200
     3.2 +++ b/src/input.c	Mon Apr 07 17:39:46 2014 +0200
     3.3 @@ -28,7 +28,6 @@
     3.4   */
     3.5  
     3.6  #include "input.h"
     3.7 -#include <ncurses.h>
     3.8  
     3.9  void init_colorpairs() {
    3.10      init_pair(COL_YB, COLOR_YELLOW, COLOR_BLUE);
    3.11 @@ -48,3 +47,52 @@
    3.12      
    3.13      return ch == 'y';
    3.14  }
    3.15 +
    3.16 +/**
    3.17 + * Asynchronous variant of getnstr().
    3.18 + * 
    3.19 + * Needs halfdelay mode enabled!
    3.20 + * 
    3.21 + * Warning: you must not call this function for reading into two separate
    3.22 + * buffers at the same time.
    3.23 + * 
    3.24 + * Attention: the first byte of the buffer must be zero at the first call, so
    3.25 + * the buffer pointer is initialized correctly.
    3.26 + * 
    3.27 + * @param w the window
    3.28 + * @param y the window y position
    3.29 + * @param x the window x position
    3.30 + * @param str the buffer for the read string
    3.31 + * @param len the length of the buffer
    3.32 + * @return 0 if reading is in progress and 1 when a complete line is read
    3.33 + */
    3.34 +int mvwasyncgetnstr(WINDOW* w, int y, int x, char *str, size_t len) {
    3.35 +    static size_t pos = 0;
    3.36 +    
    3.37 +    if (*str == '\0') {
    3.38 +        pos = 0;
    3.39 +    }
    3.40 +    
    3.41 +    mvwaddstr(w,y, x, str);
    3.42 +    wrefresh(w);
    3.43 +    int c = wgetch(w);
    3.44 +
    3.45 +    if (c != ERR) {
    3.46 +        switch (c) {
    3.47 +        case '\n':
    3.48 +            str[pos] = '\0';
    3.49 +            pos = 0;
    3.50 +            return 1;
    3.51 +        case KEY_BACKSPACE:
    3.52 +        case KEY_LEFT:
    3.53 +            str[--pos] = '\0';
    3.54 +            break;
    3.55 +        default:
    3.56 +            if (c < 255 && pos < len-1) {
    3.57 +                str[pos++] = (char) c;
    3.58 +            }
    3.59 +        }
    3.60 +    }
    3.61 +    
    3.62 +    return 0;
    3.63 +}
     4.1 --- a/src/input.h	Mon Apr 07 14:08:57 2014 +0200
     4.2 +++ b/src/input.h	Mon Apr 07 17:39:46 2014 +0200
     4.3 @@ -30,6 +30,9 @@
     4.4  #ifndef INPUT_H
     4.5  #define	INPUT_H
     4.6  
     4.7 +#include <stdlib.h>
     4.8 +#include <ncurses.h>
     4.9 +
    4.10  #ifdef	__cplusplus
    4.11  extern "C" {
    4.12  #endif
    4.13 @@ -42,6 +45,11 @@
    4.14  
    4.15  int prompt_yesno(char *msg);
    4.16  
    4.17 +int mvwasyncgetnstr(WINDOW* w, int y, int x, char *str, size_t len);
    4.18 +#define mvasyncgetnstr(y,x,str,len) mvwasyncgetnstr(stdscr,y,x,str,len)
    4.19 +#define asyncgetnstr(str,len) mvwasyncgetnstr(stdscr, stdscr->_cury, \
    4.20 +    stdscr->_curx, str, len)
    4.21 +
    4.22  
    4.23  #ifdef	__cplusplus
    4.24  }
     5.1 --- a/src/main.c	Mon Apr 07 14:08:57 2014 +0200
     5.2 +++ b/src/main.c	Mon Apr 07 17:39:46 2014 +0200
     5.3 @@ -59,11 +59,13 @@
     5.4                  timeunit = 1;
     5.5              }
     5.6              
     5.7 -            if ((time = strtoul(optarg, &valid, 10)) > TIME_MAX
     5.8 +            if ((time = strtoul(optarg, &valid, 10))*timeunit > UINT16_MAX
     5.9                  || *valid != '\0') {
    5.10 -                fprintf(stderr, "Specified time is invalid (%s)\n", optarg);
    5.11 +                fprintf(stderr, "Specified time is invalid (%s)"
    5.12 +                    "- Maximum: 65535 seconds (1092 minutes)\n", optarg);
    5.13                  return 1;
    5.14              } else {
    5.15 +                settings->gameinfo.timecontrol = 1;
    5.16                  if (opt=='t') {
    5.17                      settings->gameinfo.time = timeunit * time;
    5.18                  } else {
    5.19 @@ -108,7 +110,7 @@
    5.20      return settings;
    5.21  }
    5.22  
    5.23 -void dump_gameinfo(Gameinfo *gameinfo) {
    5.24 +void dump_gameinfo(GameInfo *gameinfo) {
    5.25      int serverwhite = gameinfo->servercolor == WHITE;
    5.26      attron(A_UNDERLINE);
    5.27      printw("Game details\n");
    5.28 @@ -116,7 +118,7 @@
    5.29      printw("  Server:     %s\n  Client:     %s\n",
    5.30          serverwhite?"white":"black", serverwhite?"black":"White"
    5.31      );
    5.32 -    if (gameinfo->time > 0) {
    5.33 +    if (gameinfo->timecontrol) {
    5.34          if (gameinfo->time % 60) {
    5.35              printw("  Time limit: %ds + %ds\n",
    5.36                  gameinfo->time, gameinfo->addtime);
    5.37 @@ -163,7 +165,7 @@
    5.38          return EXIT_SUCCESS;
    5.39      }    
    5.40      initscr();
    5.41 -    cbreak();
    5.42 +    halfdelay(10);
    5.43      keypad(stdscr, TRUE);
    5.44      if (has_colors()) {
    5.45          start_color();
     6.1 --- a/src/server.c	Mon Apr 07 14:08:57 2014 +0200
     6.2 +++ b/src/server.c	Mon Apr 07 17:39:46 2014 +0200
     6.3 @@ -77,7 +77,7 @@
     6.4  
     6.5      int fd = server.client->fd;
     6.6      net_send_data(fd, NETCODE_GAMEINFO,
     6.7 -        &(settings->gameinfo), sizeof(Gameinfo));
     6.8 +        &(settings->gameinfo), sizeof(GameInfo));
     6.9      printw("\rClient connected - awaiting challenge acceptance...");
    6.10      refresh();
    6.11      int code = net_recieve_code(fd);
     7.1 --- a/src/terminal-chess.h	Mon Apr 07 14:08:57 2014 +0200
     7.2 +++ b/src/terminal-chess.h	Mon Apr 07 17:39:46 2014 +0200
     7.3 @@ -31,6 +31,7 @@
     7.4  #include <stdio.h>
     7.5  #include <ncurses.h>
     7.6  #include "network.h"
     7.7 +#include "chess/rules.h"
     7.8  
     7.9  #ifndef TERMINAL_CHESS_H
    7.10  #define	TERMINAL_CHESS_H
    7.11 @@ -39,16 +40,8 @@
    7.12  extern "C" {
    7.13  #endif
    7.14  
    7.15 -#define TIME_MAX UINT16_MAX
    7.16 -    
    7.17  typedef struct {
    7.18 -    uint8_t servercolor;
    7.19 -    uint16_t time;
    7.20 -    uint16_t addtime;
    7.21 -} Gameinfo;
    7.22 -
    7.23 -typedef struct {
    7.24 -    Gameinfo gameinfo;
    7.25 +    GameInfo gameinfo;
    7.26      char* port;
    7.27      char* serverhost; /* NULL, if we are about to start a server */
    7.28      _Bool printhelp;
    7.29 @@ -57,7 +50,7 @@
    7.30  
    7.31  #define is_server(settings) !((settings)->serverhost)
    7.32  
    7.33 -void dump_gameinfo(Gameinfo *gameinfo);
    7.34 +void dump_gameinfo(GameInfo *gameinfo);
    7.35  
    7.36  int server_run(Settings* settings);
    7.37  int client_run(Settings* settings);

mercurial