Wed, 19 Mar 2014 15:36:54 +0100
implemented chess board and remis/surrender messages
src/client.c | file | annotate | diff | comparison | revisions | |
src/game.c | file | annotate | diff | comparison | revisions | |
src/game.h | 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/network.c | file | annotate | diff | comparison | revisions | |
src/network.h | file | annotate | diff | comparison | revisions | |
src/terminal-chess.h | file | annotate | diff | comparison | revisions |
1.1 --- a/src/client.c Wed Mar 19 10:08:25 2014 +0100 1.2 +++ b/src/client.c Wed Mar 19 15:36:54 2014 +0100 1.3 @@ -77,8 +77,7 @@ 1.4 net_recieve_data(server.fd, &(settings->gameinfo), 1.5 sizeof(settings->gameinfo)); 1.6 dump_gameinfo(&(settings->gameinfo)); 1.7 - printw("Accept challenge (y/n)? "); 1.8 - if (prompt_yesno()) { 1.9 + if (prompt_yesno("Accept challenge")) { 1.10 net_send_code(server.fd, NETCODE_ACCEPT); 1.11 game_start(settings, server.fd); 1.12 } else {
2.1 --- a/src/game.c Wed Mar 19 10:08:25 2014 +0100 2.2 +++ b/src/game.c Wed Mar 19 15:36:54 2014 +0100 2.3 @@ -28,7 +28,153 @@ 2.4 */ 2.5 2.6 #include "game.h" 2.7 +#include "input.h" 2.8 +#include <ncurses.h> 2.9 +#include <string.h> 2.10 + 2.11 +static const uint8_t boardx = 10, boardy = 10; 2.12 + 2.13 +static void draw_board(Board board) { 2.14 + 2.15 + for (uint8_t y = 0 ; y < 8 ; y++) { 2.16 + for (uint8_t x = 0 ; x < 8 ; x++) { 2.17 + uint8_t col = board[y][x] & COLOR_MASK; 2.18 + uint8_t piece = board[y][x] & PIECE_MASK; 2.19 + char piecec = ' '; 2.20 + switch (piece) { 2.21 + case PAWN: piecec = 'P'; break; 2.22 + case ROOK: piecec = 'R'; break; 2.23 + case KNIGHT: piecec = 'N'; break; 2.24 + case BISHOP: piecec = 'B'; break; 2.25 + case QUEEN: piecec = 'Q'; break; 2.26 + case KING: piecec = 'K'; break; 2.27 + } 2.28 + 2.29 + attrset((col == WHITE ? A_BOLD : A_DIM) | 2.30 + COLOR_PAIR((y&1)==(x&1) ? COL_WB : COL_BW)); 2.31 + 2.32 + mvaddch(boardy-y, boardx+x*3, ' '); 2.33 + mvaddch(boardy-y, boardx+x*3+1, piecec); 2.34 + mvaddch(boardy-y, boardx+x*3+2, ' '); 2.35 + } 2.36 + } 2.37 + 2.38 + attrset(A_NORMAL); 2.39 + for (uint8_t i = 0 ; i < 8 ; i++) { 2.40 + mvaddch(boardy+1, boardx+i*3+1, 'a'+i); 2.41 + mvaddch(boardy-i, boardx-2, '1'+i); 2.42 + } 2.43 +} 2.44 + 2.45 +static int sendmove(int opponent) { 2.46 + const size_t buflen = 8; 2.47 + char move[buflen]; 2.48 + _Bool remisrejected = FALSE; 2.49 + 2.50 + while (1) { 2.51 + move(boardy+3, 0); 2.52 + if (remisrejected) { 2.53 + printw( 2.54 + "Use chess notation to enter your move.\n" 2.55 + "Remis offer rejected - type 'surr' to surrender. \n\n" 2.56 + "Type your move: "); 2.57 + } else { 2.58 + printw( 2.59 + "Use chess notation to enter your move.\n" 2.60 + "Or type 'surr' to surrender or 'remis' to offer remis.\n\n" 2.61 + "Type your move: "); 2.62 + } 2.63 + clrtoeol(); 2.64 + refresh(); 2.65 + getnstr(move, buflen); 2.66 + 2.67 + if (strncmp(move, "surr", buflen) == 0) { 2.68 + printw("You surrendered!"); 2.69 + net_send_code(opponent, NETCODE_SURRENDER); 2.70 + return 1; 2.71 + } else if (strncmp(move, "remis", buflen) == 0) { 2.72 + if (!remisrejected) { 2.73 + net_send_code(opponent, NETCODE_REMIS); 2.74 + printw("Remis offer sent - waiting for acceptance..."); 2.75 + refresh(); 2.76 + if (net_recieve_code(opponent) == NETCODE_ACCEPT) { 2.77 + printw("\rRemis accepted!"); 2.78 + clrtoeol(); 2.79 + return 1; 2.80 + } else { 2.81 + remisrejected = TRUE; 2.82 + } 2.83 + } 2.84 + } else { 2.85 + // TODO: validate move syntactically 2.86 + // TODO: send move and await acceptance 2.87 + } 2.88 + } 2.89 +} 2.90 + 2.91 +static int recvmove(int opponent) { 2.92 + 2.93 + while (1) { 2.94 + move(boardy+3, 0); 2.95 + printw("Awaiting opponent move..."); 2.96 + clrtoeol(); 2.97 + refresh(); 2.98 + 2.99 + // TODO: nonblocking 2.100 + uint32_t code = net_recieve_code(opponent); 2.101 + switch (code) { 2.102 + case NETCODE_SURRENDER: 2.103 + printw("\rYour opponent surrendered!"); 2.104 + clrtoeol(); 2.105 + return 1; 2.106 + case NETCODE_REMIS: 2.107 + if (prompt_yesno( 2.108 + "\rYour opponent offers remis - do you accept")) { 2.109 + printw("\rRemis accepted!"); 2.110 + clrtoeol(); 2.111 + net_send_code(opponent, NETCODE_ACCEPT); 2.112 + return 1; 2.113 + } else { 2.114 + net_send_code(opponent, NETCODE_DECLINE); 2.115 + } 2.116 + break; 2.117 + case NETCODE_MOVE: 2.118 + // TODO: receive move 2.119 + // TODO: validate move and accept/reject 2.120 + return 0; 2.121 + } 2.122 + } 2.123 +} 2.124 2.125 void game_start(Settings *settings, int opponent) { 2.126 + _Bool myturn = is_server(settings) == 2.127 + (settings->gameinfo.servercolor == WHITE); 2.128 + _Bool running; 2.129 2.130 + Board board = { 2.131 + {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK}, 2.132 + {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN}, 2.133 + {0, 0, 0, 0, 0, 0, 0, 0}, 2.134 + {0, 0, 0, 0, 0, 0, 0, 0}, 2.135 + {0, 0, 0, 0, 0, 0, 0, 0}, 2.136 + {0, 0, 0, 0, 0, 0, 0, 0}, 2.137 + {BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN}, 2.138 + {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK} 2.139 + }; 2.140 + 2.141 + do { 2.142 + clear(); 2.143 + draw_board(board); 2.144 + if (myturn) { 2.145 + running = !sendmove(opponent); 2.146 + } else { 2.147 + running = !recvmove(opponent); 2.148 + flushinp(); // flush any input the user hacked in while waiting 2.149 + } 2.150 + myturn ^= 1; 2.151 + } while (running); 2.152 + 2.153 + mvaddstr(getmaxy(tchess_window)-1, 0, 2.154 + "Game has ended. Press any key to leave..."); 2.155 + getch(); 2.156 }
3.1 --- a/src/game.h Wed Mar 19 10:08:25 2014 +0100 3.2 +++ b/src/game.h Wed Mar 19 15:36:54 2014 +0100 3.3 @@ -31,11 +31,40 @@ 3.4 #define GAME_H 3.5 3.6 #include "terminal-chess.h" 3.7 +#include <stdint.h> 3.8 3.9 #ifdef __cplusplus 3.10 extern "C" { 3.11 #endif 3.12 3.13 +#define PIECE_MASK 0x0F 3.14 +#define COLOR_MASK 0xF0 3.15 + 3.16 +#define WHITE 0x10 3.17 +#define BLACK 0x20 3.18 + 3.19 +#define PAWN 0x01 3.20 +#define ROOK 0x02 3.21 +#define KNIGHT 0x03 3.22 +#define BISHOP 0x04 3.23 +#define QUEEN 0x05 3.24 +#define KING 0x06 3.25 + 3.26 +#define WPAWN (WHITE|PAWN) 3.27 +#define WROOK (WHITE|ROOK) 3.28 +#define WKNIGHT (WHITE|KNIGHT) 3.29 +#define WBISHOP (WHITE|BISHOP) 3.30 +#define WQUEEN (WHITE|QUEEN) 3.31 +#define WKING (WHITE|KING) 3.32 +#define BPAWN (BLACK|PAWN) 3.33 +#define BROOK (BLACK|ROOK) 3.34 +#define BKNIGHT (BLACK|KNIGHT) 3.35 +#define BBISHOP (BLACK|BISHOP) 3.36 +#define BQUEEN (BLACK|QUEEN) 3.37 +#define BKING (BLACK|KING) 3.38 + 3.39 +typedef uint8_t Board[8][8]; 3.40 + 3.41 void game_start(Settings *settings, int opponent); 3.42 3.43 #ifdef __cplusplus
4.1 --- a/src/input.c Wed Mar 19 10:08:25 2014 +0100 4.2 +++ b/src/input.c Wed Mar 19 15:36:54 2014 +0100 4.3 @@ -30,7 +30,15 @@ 4.4 #include "input.h" 4.5 #include <ncurses.h> 4.6 4.7 -int prompt_yesno() { 4.8 +void init_colorpairs() { 4.9 + init_pair(COL_YB, COLOR_YELLOW, COLOR_BLUE); 4.10 + init_pair(COL_BW, COLOR_BLACK, COLOR_WHITE); 4.11 + init_pair(COL_WB, COLOR_WHITE, COLOR_BLACK); 4.12 +} 4.13 + 4.14 +int prompt_yesno(char *msg) { 4.15 + printw("%s (y/n)? ", msg); 4.16 + refresh(); 4.17 noecho(); 4.18 int ch; 4.19 do {
5.1 --- a/src/input.h Wed Mar 19 10:08:25 2014 +0100 5.2 +++ b/src/input.h Wed Mar 19 15:36:54 2014 +0100 5.3 @@ -34,7 +34,13 @@ 5.4 extern "C" { 5.5 #endif 5.6 5.7 -int prompt_yesno(); 5.8 +#define COL_YB 1 5.9 +#define COL_BW 2 5.10 +#define COL_WB 3 5.11 + 5.12 +void init_colorpairs(); 5.13 + 5.14 +int prompt_yesno(char *msg); 5.15 5.16 5.17 #ifdef __cplusplus
6.1 --- a/src/main.c Wed Mar 19 10:08:25 2014 +0100 6.2 +++ b/src/main.c Wed Mar 19 15:36:54 2014 +0100 6.3 @@ -28,9 +28,11 @@ 6.4 */ 6.5 6.6 #include "terminal-chess.h" 6.7 +#include "game.h" 6.8 +#include "input.h" 6.9 #include <string.h> 6.10 #include <time.h> 6.11 -#include <ncurses.h> 6.12 +#include <getopt.h> 6.13 6.14 int get_settings(int argc, char **argv, Settings *settings) { 6.15 char *valid; 6.16 @@ -44,7 +46,7 @@ 6.17 settings->gameinfo.servercolor = BLACK; 6.18 break; 6.19 case 'r': 6.20 - settings->gameinfo.servercolor = (rand()>>5) & 1 ? WHITE : BLACK; 6.21 + settings->gameinfo.servercolor = rand() & 1 ? WHITE : BLACK; 6.22 break; 6.23 case 't': 6.24 case 'a': 6.25 @@ -125,11 +127,7 @@ 6.26 refresh(); 6.27 } 6.28 6.29 -static WINDOW* window; 6.30 - 6.31 void leavescr() { 6.32 - mvprintw(getmaxy(window)-1, 0, "Leaving terminal-chess. Press any key..."); 6.33 - getch(); 6.34 endwin(); 6.35 } 6.36 6.37 @@ -162,9 +160,17 @@ 6.38 ); 6.39 return EXIT_SUCCESS; 6.40 } 6.41 - 6.42 - window = initscr(); 6.43 + tchess_window = initscr(); 6.44 cbreak(); 6.45 + if (has_colors()) { 6.46 + start_color(); 6.47 + init_colorpairs(); 6.48 + bkgd(COLOR_PAIR(COL_YB)); 6.49 + } else { 6.50 + fprintf(stderr, "Non-colored terminals are not supported yet."); 6.51 + endwin(); 6.52 + return EXIT_FAILURE; 6.53 + } 6.54 atexit(leavescr); 6.55 6.56 return is_server(&settings) ? server_run(&settings) : client_run(&settings);
7.1 --- a/src/network.c Wed Mar 19 10:08:25 2014 +0100 7.2 +++ b/src/network.c Wed Mar 19 15:36:54 2014 +0100 7.3 @@ -122,7 +122,7 @@ 7.4 send(socket, data, len, 0); 7.5 } 7.6 7.7 -int net_recieve_code(int socket) { 7.8 +uint32_t net_recieve_code(int socket) { 7.9 uint32_t code; 7.10 recv(socket, &code, sizeof(uint32_t), 0); 7.11 return ntohl(code);
8.1 --- a/src/network.h Wed Mar 19 10:08:25 2014 +0100 8.2 +++ b/src/network.h Wed Mar 19 15:36:54 2014 +0100 8.3 @@ -40,8 +40,11 @@ 8.4 #define NETCODE_ACCEPT 0x00 8.5 #define NETCODE_DECLINE 0x01 8.6 #define NETCODE_GAMEINFO 0x10 8.7 +#define NETCODE_MOVE 0x20 8.8 +#define NETCODE_SURRENDER 0x21 8.9 +#define NETCODE_REMIS 0x22 8.10 8.11 -#define NETCODE_VERSION 1 8.12 +#define NETCODE_VERSION 3 8.13 8.14 typedef struct { 8.15 int fd; /* -1, if we are the client */ 8.16 @@ -64,7 +67,7 @@ 8.17 8.18 void net_send_code(int socket, uint32_t code); 8.19 void net_send_data(int socket, void *data, size_t len); 8.20 -int net_recieve_code(int socket); 8.21 +uint32_t net_recieve_code(int socket); 8.22 void net_recieve_data(int socket, void *data, size_t len); 8.23 8.24
9.1 --- a/src/terminal-chess.h Wed Mar 19 10:08:25 2014 +0100 9.2 +++ b/src/terminal-chess.h Wed Mar 19 15:36:54 2014 +0100 9.3 @@ -29,7 +29,7 @@ 9.4 9.5 #include <stdlib.h> 9.6 #include <stdio.h> 9.7 -#include <getopt.h> 9.8 +#include <ncurses.h> 9.9 #include "network.h" 9.10 9.11 #ifndef TERMINAL_CHESS_H 9.12 @@ -38,9 +38,9 @@ 9.13 #ifdef __cplusplus 9.14 extern "C" { 9.15 #endif 9.16 - 9.17 -#define WHITE 0 9.18 -#define BLACK 1 9.19 + 9.20 +WINDOW* tchess_window; 9.21 + 9.22 #define TIME_MAX UINT16_MAX 9.23 9.24 typedef struct {