src/game.c

changeset 23
824c9522ce66
parent 22
41bbfd4d17a3
child 25
3ab0c2e1a4e2
equal deleted inserted replaced
22:41bbfd4d17a3 23:824c9522ce66
33 #include <ncurses.h> 33 #include <ncurses.h>
34 #include <string.h> 34 #include <string.h>
35 35
36 static const uint8_t boardx = 10, boardy = 10; 36 static const uint8_t boardx = 10, boardy = 10;
37 37
38 static void draw_board(Board board, MoveListRoot *movelist, uint8_t mycolor) { 38 static void draw_board(GameState *gamestate) {
39 39
40 for (uint8_t y = 0 ; y < 8 ; y++) { 40 for (uint8_t y = 0 ; y < 8 ; y++) {
41 for (uint8_t x = 0 ; x < 8 ; x++) { 41 for (uint8_t x = 0 ; x < 8 ; x++) {
42 uint8_t col = board[y][x] & COLOR_MASK; 42 uint8_t col = gamestate->board[y][x] & COLOR_MASK;
43 uint8_t piece = board[y][x] & PIECE_MASK; 43 uint8_t piece = gamestate->board[y][x] & PIECE_MASK;
44 char piecec; 44 char piecec;
45 if (piece) { 45 if (piece) {
46 piecec = piece == PAWN ? 'P' : getpiecechr(piece); 46 piecec = piece == PAWN ? 'P' : getpiecechr(piece);
47 } else { 47 } else {
48 piecec = ' '; 48 piecec = ' ';
49 } 49 }
50 50
51 attrset((col == WHITE ? A_BOLD : A_DIM) | 51 attrset((col == WHITE ? A_BOLD : A_DIM) |
52 COLOR_PAIR((y&1)==(x&1) ? COL_WB : COL_BW)); 52 COLOR_PAIR((y&1)==(x&1) ? COL_WB : COL_BW));
53 53
54 int cy = mycolor == WHITE ? boardy-y : boardy-7+y; 54 int cy = gamestate->mycolor == WHITE ? boardy-y : boardy-7+y;
55 int cx = mycolor == WHITE ? boardx+x*3 : boardx+21-x*3; 55 int cx = gamestate->mycolor == WHITE ? boardx+x*3 : boardx+21-x*3;
56 mvaddch(cy, cx, ' '); 56 mvaddch(cy, cx, ' ');
57 mvaddch(cy, cx+1, piecec); 57 mvaddch(cy, cx+1, piecec);
58 mvaddch(cy, cx+2, ' '); 58 mvaddch(cy, cx+2, ' ');
59 } 59 }
60 } 60 }
61 61
62 attrset(A_NORMAL); 62 attrset(A_NORMAL);
63 for (uint8_t i = 0 ; i < 8 ; i++) { 63 for (uint8_t i = 0 ; i < 8 ; i++) {
64 int x = mycolor == WHITE ? boardx+i*3+1 : boardx+22-i*3; 64 int x = gamestate->mycolor == WHITE ? boardx+i*3+1 : boardx+22-i*3;
65 int y = mycolor == WHITE ? boardy-i : boardy-7+i; 65 int y = gamestate->mycolor == WHITE ? boardy-i : boardy-7+i;
66 mvaddch(boardy+1, x, 'a'+i); 66 mvaddch(boardy+1, x, 'a'+i);
67 mvaddch(y, boardx-2, '1'+i); 67 mvaddch(y, boardx-2, '1'+i);
68 } 68 }
69 69
70 /* move log */ 70 /* move log */
71 // TODO: introduce window to avoid bugs with a long move log 71 // TODO: introduce window to avoid bugs with a long move log
72 uint8_t logy = 0; 72 uint8_t logy = 0;
73 const uint8_t logx = boardx + 30; 73 const uint8_t logx = boardx + 30;
74 int logi = 1; 74 int logi = 1;
75 MoveList *logelem = movelist->first; 75 MoveList *logelem = gamestate->movelist;
76 76
77 while (logelem) { 77 while (logelem) {
78 logi++; 78 logi++;
79 if (logi % 2 == 0) { 79 if (logi % 2 == 0) {
80 if ((logi - 2) % 4 == 0) { 80 if ((logi - 2) % 4 == 0) {
81 logy++; 81 logy++;
82 wmove(tchess_window, logy, logx); 82 move(logy, logx);
83 } 83 }
84 printw("%d. ", logi / 2); 84 printw("%d. ", logi / 2);
85 } 85 }
86 86
87 if (logelem) { 87 if (logelem) {
106 } 106 }
107 } 107 }
108 } 108 }
109 109
110 110
111 static int sendmove(Board board, MoveListRoot *movelist, 111 static int sendmove(GameState *gamestate, int opponent) {
112 uint8_t mycolor, int opponent) {
113 112
114 const size_t buflen = 8; 113 const size_t buflen = 8;
115 char movestr[buflen]; 114 char movestr[buflen];
116 _Bool remisrejected = FALSE; 115 _Bool remisrejected = FALSE;
117 uint8_t code; 116 uint8_t code;
118 117
119 int inputy = getmaxy(tchess_window) - 6; 118 int inputy = getmaxy(stdscr) - 6;
120 while (1) { 119 while (1) {
121 move(inputy, 0); 120 move(inputy, 0);
122 if (remisrejected) { 121 if (remisrejected) {
123 printw( 122 printw(
124 "Use chess notation to enter your move.\n" 123 "Use chess notation to enter your move.\n"
154 remisrejected = TRUE; 153 remisrejected = TRUE;
155 } 154 }
156 } 155 }
157 } else { 156 } else {
158 Move move; 157 Move move;
159 int eval_result = eval_move(board, mycolor, movestr, &move); 158 int eval_result = eval_move(gamestate, movestr, &move);
160 switch (eval_result) { 159 switch (eval_result) {
161 case VALID_MOVE_SYNTAX: 160 case VALID_MOVE_SYNTAX:
162 net_send_data(opponent, NETCODE_MOVE, &move, sizeof(Move)); 161 net_send_data(opponent, NETCODE_MOVE, &move, sizeof(Move));
163 code = net_recieve_code(opponent); 162 code = net_recieve_code(opponent);
164 move.check = code == NETCODE_CHECK; 163 move.check = code == NETCODE_CHECK;
165 move.checkmate = code == NETCODE_CHECKMATE; 164 move.checkmate = code == NETCODE_CHECKMATE;
166 if (code == NETCODE_DECLINE) { 165 if (code == NETCODE_DECLINE) {
167 printw("Invalid move."); 166 printw("Invalid move.");
168 } else { 167 } else {
169 apply_move(board, &move); 168 apply_move(gamestate, &move);
170 addmove(movelist, &move);
171 if (move.checkmate) { 169 if (move.checkmate) {
172 printw("Checkmate!"); 170 printw("Checkmate!");
173 clrtoeol(); 171 clrtoeol();
174 return 1; 172 return 1;
175 } else { 173 } else {
192 clrtoeol(); 190 clrtoeol();
193 } 191 }
194 } 192 }
195 } 193 }
196 194
197 static int recvmove(Board board, MoveListRoot *movelist, int opponent) { 195 static int recvmove(GameState *gamestate, int opponent) {
198 196
199 int inputy = getmaxy(tchess_window) - 6; 197 int inputy = getmaxy(stdscr) - 6;
200 while (1) { 198 while (1) {
201 move(inputy, 0); 199 move(inputy, 0);
202 printw("Awaiting opponent move..."); 200 printw("Awaiting opponent move...");
203 clrtoeol(); 201 clrtoeol();
204 refresh(); 202 refresh();
223 net_send_code(opponent, NETCODE_DECLINE); 221 net_send_code(opponent, NETCODE_DECLINE);
224 } 222 }
225 break; 223 break;
226 case NETCODE_MOVE: 224 case NETCODE_MOVE:
227 net_recieve_data(opponent, &move, sizeof(Move)); 225 net_recieve_data(opponent, &move, sizeof(Move));
228 if (validate_move(board, &move)) { 226 if (validate_move(gamestate, &move)) {
229 apply_move(board, &move); 227 apply_move(gamestate, &move);
230 addmove(movelist, &move);
231 if (move.check) { 228 if (move.check) {
232 net_send_code(opponent, NETCODE_CHECK); 229 net_send_code(opponent, NETCODE_CHECK);
233 } else if (move.checkmate) { 230 } else if (move.checkmate) {
234 net_send_code(opponent, NETCODE_CHECKMATE); 231 net_send_code(opponent, NETCODE_CHECKMATE);
235 } else { 232 } else {
241 } 238 }
242 } 239 }
243 } 240 }
244 } 241 }
245 242
246 void freemovelist(MoveListRoot* list) {
247 MoveList *elem;
248 elem = list->first;
249 while (elem) {
250 MoveList *cur = elem;
251 elem = elem->next;
252 free(cur);
253 };
254 free(list);
255 }
256
257 void addmove(MoveListRoot* list, Move *move) {
258 MoveList *elem = malloc(sizeof(MoveList));
259 elem->next = NULL;
260 elem->move = *move;
261
262 if (list->last) {
263 list->last->next = elem;
264 list->last = elem;
265 } else {
266 list->first = list->last = elem;
267 }
268 }
269
270 void game_start(Settings *settings, int opponent) { 243 void game_start(Settings *settings, int opponent) {
271 _Bool myturn = is_server(settings) == 244 _Bool myturn = is_server(settings) ==
272 (settings->gameinfo.servercolor == WHITE); 245 (settings->gameinfo.servercolor == WHITE);
273 uint8_t mycolor = myturn ? WHITE:BLACK; 246
274 247 GameState gamestate;
275 _Bool running; 248 Board initboard = {
276
277 MoveListRoot* movelist = calloc(1, sizeof(MoveListRoot));
278
279 Board board = {
280 {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK}, 249 {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK},
281 {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN}, 250 {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN},
282 {0, 0, 0, 0, 0, 0, 0, 0}, 251 {0, 0, 0, 0, 0, 0, 0, 0},
283 {0, 0, 0, 0, 0, 0, 0, 0}, 252 {0, 0, 0, 0, 0, 0, 0, 0},
284 {0, 0, 0, 0, 0, 0, 0, 0}, 253 {0, 0, 0, 0, 0, 0, 0, 0},
285 {0, 0, 0, 0, 0, 0, 0, 0}, 254 {0, 0, 0, 0, 0, 0, 0, 0},
286 {BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN}, 255 {BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN},
287 {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK} 256 {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK}
288 }; 257 };
289 258 memcpy(gamestate.board, initboard, sizeof(Board));
259 gamestate.mycolor = myturn ? WHITE:BLACK;
260 gamestate.movelist = gamestate.lastmove = NULL;
261
262 _Bool running;
290 do { 263 do {
291 clear(); 264 clear();
292 draw_board(board, movelist, mycolor); 265 draw_board(&gamestate);
293 if (myturn) { 266 if (myturn) {
294 running = !sendmove(board, movelist, mycolor, opponent); 267 running = !sendmove(&gamestate, opponent);
295 } else { 268 } else {
296 running = !recvmove(board, movelist, opponent); 269 running = !recvmove(&gamestate, opponent);
297 flushinp(); // flush any input the user hacked in while waiting 270 flushinp(); // flush any input the user hacked in while waiting
298 } 271 }
299 myturn ^= TRUE; 272 myturn ^= TRUE;
300 } while (running); 273 } while (running);
301 274
302 freemovelist(movelist); 275 gamestate_cleanup(&gamestate);
303 276
304 mvaddstr(getmaxy(tchess_window)-1, 0, 277 mvaddstr(getmaxy(stdscr)-1, 0,
305 "Game has ended. Press any key to leave..."); 278 "Game has ended. Press any key to leave...");
306 getch(); 279 getch();
307 } 280 }

mercurial