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) { |
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 { |
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 } |