Mon, 07 Apr 2014 17:39:46 +0200
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 |
--- a/src/chess/rules.h Mon Apr 07 14:08:57 2014 +0200 +++ b/src/chess/rules.h Mon Apr 07 17:39:46 2014 +0200 @@ -87,6 +87,14 @@ MoveList* next; }; + +typedef struct { + uint8_t servercolor; + _Bool timecontrol; + uint16_t time; + uint16_t addtime; +} GameInfo; + typedef struct { Board board; uint8_t mycolor;
--- a/src/game.c Mon Apr 07 14:08:57 2014 +0200 +++ b/src/game.c Mon Apr 07 17:39:46 2014 +0200 @@ -32,11 +32,27 @@ #include "input.h" #include <ncurses.h> #include <string.h> +#include <inttypes.h> static const uint8_t boardx = 10, boardy = 10; +static void draw_time(GameState *gamestate, GameInfo *gameinfo) { + if (gameinfo->timecontrol) { + // TODO: correct time display + + uint16_t whitem = gameinfo->time / 60; + uint16_t whites = gameinfo->time % 60; + uint16_t blackm = gameinfo->time / 60; + uint16_t blacks = gameinfo->time % 60; + + mvprintw(boardy+4, boardx-1, + "White time: %4" PRIu16 ":%02" PRIu16, whitem, whites); + mvprintw(boardy+5, boardx-1, + "Black time: %4" PRIu16 ":%02" PRIu16, blackm, blacks); + } +} + static void draw_board(GameState *gamestate) { - for (uint8_t y = 0 ; y < 8 ; y++) { for (uint8_t x = 0 ; x < 8 ; x++) { uint8_t col = gamestate->board[y][x] & COLOR_MASK; @@ -134,13 +150,14 @@ } } -static int domove_singlemachine(GameState *gamestate) { +static int domove_singlemachine(GameState *gamestate, GameInfo *gameinfo) { const size_t buflen = 8; char movestr[buflen]; int inputy = getmaxy(stdscr) - 6; while (1) { + draw_time(gamestate, gameinfo); move(inputy, 0); printw( "Use chess notation to enter your move.\n" @@ -148,45 +165,46 @@ "Type your move: "); clrtoeol(); refresh(); - getnstr(movestr, buflen); - - if (strncmp(movestr, "surr", buflen) == 0) { - printw("%s surrendered!", - gamestate->mycolor==WHITE?"White":"Black"); - clrtoeol(); - refresh(); - return 1; - } else if (strncmp(movestr, "remis", buflen) == 0) { - printw("Game ends remis."); - clrtoeol(); - refresh(); - return 1; - } else { - Move move; - int eval_result = eval_move(gamestate, movestr, &move); - switch (eval_result) { - case VALID_MOVE_SYNTAX: - if (validate_move(gamestate, &move)) { - apply_move(gamestate, &move); - if (gamestate->checkmate) { - printw("Checkmate!"); - clrtoeol(); - return 1; - } else if (gamestate->stalemate) { - printw("Stalemate!"); - clrtoeol(); - return 1; + + if (asyncgetnstr(movestr, buflen)) { + if (strncmp(movestr, "surr", buflen) == 0) { + printw("%s surrendered!", + gamestate->mycolor==WHITE?"White":"Black"); + clrtoeol(); + refresh(); + return 1; + } else if (strncmp(movestr, "remis", buflen) == 0) { + printw("Game ends remis."); + clrtoeol(); + refresh(); + return 1; + } else { + Move move; + int eval_result = eval_move(gamestate, movestr, &move); + switch (eval_result) { + case VALID_MOVE_SYNTAX: + if (validate_move(gamestate, &move)) { + apply_move(gamestate, &move); + if (gamestate->checkmate) { + printw("Checkmate!"); + clrtoeol(); + return 1; + } else if (gamestate->stalemate) { + printw("Stalemate!"); + clrtoeol(); + return 1; + } else { + return 0; + } } else { - return 0; + printw("Invalid move."); } - } else { - printw("Invalid move."); + break; + default: + eval_move_failed_msg(eval_result); } - break; - default: - eval_move_failed_msg(eval_result); + clrtoeol(); } - clrtoeol(); } } } @@ -346,12 +364,12 @@ memset(&gamestate, 0, sizeof(GameState)); init_board(&gamestate); gamestate.mycolor = WHITE; - // TODO: time limit + _Bool running; do { clear(); draw_board(&gamestate); - running = !domove_singlemachine(&gamestate); + running = !domove_singlemachine(&gamestate, &(settings->gameinfo)); gamestate.mycolor = opponent_color(gamestate.mycolor); } while (running); move(0,0);
--- a/src/input.c Mon Apr 07 14:08:57 2014 +0200 +++ b/src/input.c Mon Apr 07 17:39:46 2014 +0200 @@ -28,7 +28,6 @@ */ #include "input.h" -#include <ncurses.h> void init_colorpairs() { init_pair(COL_YB, COLOR_YELLOW, COLOR_BLUE); @@ -48,3 +47,52 @@ return ch == 'y'; } + +/** + * Asynchronous variant of getnstr(). + * + * Needs halfdelay mode enabled! + * + * Warning: you must not call this function for reading into two separate + * buffers at the same time. + * + * Attention: the first byte of the buffer must be zero at the first call, so + * the buffer pointer is initialized correctly. + * + * @param w the window + * @param y the window y position + * @param x the window x position + * @param str the buffer for the read string + * @param len the length of the buffer + * @return 0 if reading is in progress and 1 when a complete line is read + */ +int mvwasyncgetnstr(WINDOW* w, int y, int x, char *str, size_t len) { + static size_t pos = 0; + + if (*str == '\0') { + pos = 0; + } + + mvwaddstr(w,y, x, str); + wrefresh(w); + int c = wgetch(w); + + if (c != ERR) { + switch (c) { + case '\n': + str[pos] = '\0'; + pos = 0; + return 1; + case KEY_BACKSPACE: + case KEY_LEFT: + str[--pos] = '\0'; + break; + default: + if (c < 255 && pos < len-1) { + str[pos++] = (char) c; + } + } + } + + return 0; +}
--- a/src/input.h Mon Apr 07 14:08:57 2014 +0200 +++ b/src/input.h Mon Apr 07 17:39:46 2014 +0200 @@ -30,6 +30,9 @@ #ifndef INPUT_H #define INPUT_H +#include <stdlib.h> +#include <ncurses.h> + #ifdef __cplusplus extern "C" { #endif @@ -42,6 +45,11 @@ int prompt_yesno(char *msg); +int mvwasyncgetnstr(WINDOW* w, int y, int x, char *str, size_t len); +#define mvasyncgetnstr(y,x,str,len) mvwasyncgetnstr(stdscr,y,x,str,len) +#define asyncgetnstr(str,len) mvwasyncgetnstr(stdscr, stdscr->_cury, \ + stdscr->_curx, str, len) + #ifdef __cplusplus }
--- a/src/main.c Mon Apr 07 14:08:57 2014 +0200 +++ b/src/main.c Mon Apr 07 17:39:46 2014 +0200 @@ -59,11 +59,13 @@ timeunit = 1; } - if ((time = strtoul(optarg, &valid, 10)) > TIME_MAX + if ((time = strtoul(optarg, &valid, 10))*timeunit > UINT16_MAX || *valid != '\0') { - fprintf(stderr, "Specified time is invalid (%s)\n", optarg); + fprintf(stderr, "Specified time is invalid (%s)" + "- Maximum: 65535 seconds (1092 minutes)\n", optarg); return 1; } else { + settings->gameinfo.timecontrol = 1; if (opt=='t') { settings->gameinfo.time = timeunit * time; } else { @@ -108,7 +110,7 @@ return settings; } -void dump_gameinfo(Gameinfo *gameinfo) { +void dump_gameinfo(GameInfo *gameinfo) { int serverwhite = gameinfo->servercolor == WHITE; attron(A_UNDERLINE); printw("Game details\n"); @@ -116,7 +118,7 @@ printw(" Server: %s\n Client: %s\n", serverwhite?"white":"black", serverwhite?"black":"White" ); - if (gameinfo->time > 0) { + if (gameinfo->timecontrol) { if (gameinfo->time % 60) { printw(" Time limit: %ds + %ds\n", gameinfo->time, gameinfo->addtime); @@ -163,7 +165,7 @@ return EXIT_SUCCESS; } initscr(); - cbreak(); + halfdelay(10); keypad(stdscr, TRUE); if (has_colors()) { start_color();
--- a/src/server.c Mon Apr 07 14:08:57 2014 +0200 +++ b/src/server.c Mon Apr 07 17:39:46 2014 +0200 @@ -77,7 +77,7 @@ int fd = server.client->fd; net_send_data(fd, NETCODE_GAMEINFO, - &(settings->gameinfo), sizeof(Gameinfo)); + &(settings->gameinfo), sizeof(GameInfo)); printw("\rClient connected - awaiting challenge acceptance..."); refresh(); int code = net_recieve_code(fd);
--- a/src/terminal-chess.h Mon Apr 07 14:08:57 2014 +0200 +++ b/src/terminal-chess.h Mon Apr 07 17:39:46 2014 +0200 @@ -31,6 +31,7 @@ #include <stdio.h> #include <ncurses.h> #include "network.h" +#include "chess/rules.h" #ifndef TERMINAL_CHESS_H #define TERMINAL_CHESS_H @@ -39,16 +40,8 @@ extern "C" { #endif -#define TIME_MAX UINT16_MAX - typedef struct { - uint8_t servercolor; - uint16_t time; - uint16_t addtime; -} Gameinfo; - -typedef struct { - Gameinfo gameinfo; + GameInfo gameinfo; char* port; char* serverhost; /* NULL, if we are about to start a server */ _Bool printhelp; @@ -57,7 +50,7 @@ #define is_server(settings) !((settings)->serverhost) -void dump_gameinfo(Gameinfo *gameinfo); +void dump_gameinfo(GameInfo *gameinfo); int server_run(Settings* settings); int client_run(Settings* settings);