| 51 } |
51 } |
| 52 |
52 |
| 53 attrset((col == WHITE ? A_BOLD : A_DIM) | |
53 attrset((col == WHITE ? A_BOLD : A_DIM) | |
| 54 COLOR_PAIR((y&1)==(x&1) ? COL_WB : COL_BW)); |
54 COLOR_PAIR((y&1)==(x&1) ? COL_WB : COL_BW)); |
| 55 |
55 |
| 56 mvaddch(boardy-y, boardx+x*3, ' '); |
56 int cy = mycolor == WHITE ? boardy-y : boardy-7+y; |
| 57 mvaddch(boardy-y, boardx+x*3+1, piecec); |
57 int cx = mycolor == WHITE ? boardx+x*3 : boardx+21-x*3; |
| 58 mvaddch(boardy-y, boardx+x*3+2, ' '); |
58 mvaddch(cy, cx, ' '); |
| |
59 mvaddch(cy, cx+1, piecec); |
| |
60 mvaddch(cy, cx+2, ' '); |
| 59 } |
61 } |
| 60 } |
62 } |
| 61 |
63 |
| 62 attrset(A_NORMAL); |
64 attrset(A_NORMAL); |
| 63 for (uint8_t i = 0 ; i < 8 ; i++) { |
65 for (uint8_t i = 0 ; i < 8 ; i++) { |
| 64 mvaddch(boardy+1, boardx+i*3+1, 'a'+i); |
66 int x = mycolor == WHITE ? boardx+i*3+1 : boardx+22-i*3; |
| 65 mvaddch(boardy-i, boardx-2, '1'+i); |
67 int y = mycolor == WHITE ? boardy-i : boardy-7+i; |
| 66 } |
68 mvaddch(boardy+1, x, 'a'+i); |
| 67 } |
69 mvaddch(y, boardx-2, '1'+i); |
| 68 |
70 } |
| 69 static int sendmove(int opponent) { |
71 } |
| |
72 |
| |
73 static void apply_move(Board board, Move *move) { |
| |
74 board[move->fromrow][move->fromfile] = 0; |
| |
75 // TODO: care for en passant capture |
| |
76 board[move->torow][move->tofile] = move->piece; |
| |
77 } |
| |
78 |
| |
79 static _Bool validate_move(Board board, uint8_t mycolor, Move *move) { |
| |
80 _Bool result = TRUE; |
| |
81 |
| |
82 /* does piece exist */ |
| |
83 result &= board[move->fromrow][move->fromfile] == move->piece; |
| |
84 |
| |
85 /* is move rule conform */ |
| |
86 // TODO: make it so |
| |
87 |
| |
88 /* is piece blocked */ |
| |
89 // TODO: make it so |
| |
90 |
| |
91 /* is piece pinned */ |
| |
92 // TODO: make it so |
| |
93 |
| |
94 return result; |
| |
95 } |
| |
96 |
| |
97 static _Bool eval_move(Board board, uint8_t mycolor, char *movestr, Move *move) { |
| |
98 memset(move, 0, sizeof(Move)); |
| |
99 |
| |
100 size_t len = strlen(movestr); |
| |
101 |
| |
102 /* remove check */ |
| |
103 if (movestr[len-1] == '+') { |
| |
104 len--; movestr[len] = '\0'; |
| |
105 move->check = TRUE; |
| |
106 } |
| |
107 |
| |
108 if (len == 2) { |
| |
109 /* pawn move (e.g. "e4") */ |
| |
110 if (isfile(movestr[0]) && isrow(movestr[1])) { |
| |
111 move->piece = PAWN; |
| |
112 move->fromfile = move->tofile = fileidx(movestr[0]); |
| |
113 move->torow = rowidx(movestr[1]); |
| |
114 move->fromrow = rowidx(movestr[1]) + (mycolor == WHITE ? -1 : 1); |
| |
115 if (move->fromrow > 6) { |
| |
116 move->piece = 0; |
| |
117 } else { |
| |
118 /* advanced first move */ |
| |
119 if (move->fromrow == (mycolor == WHITE ? 2 : 5) && |
| |
120 board[move->fromrow][move->fromfile] != (mycolor|PAWN)) { |
| |
121 |
| |
122 move->fromrow += (mycolor == WHITE ? -1 : 1); |
| |
123 if (move->fromrow > 6) { |
| |
124 move->piece = 0; |
| |
125 } |
| |
126 } |
| |
127 } |
| |
128 } |
| |
129 } else if (len == 3) { |
| |
130 if (strcmp(movestr, "0-0") == 0) { |
| |
131 /* king side castling */ |
| |
132 move->piece = KING; |
| |
133 move->fromfile = fileidx('e'); |
| |
134 move->fromfile = fileidx('g'); |
| |
135 move->fromrow = move->torow = mycolor == WHITE ? 0 : 7; |
| |
136 } else { |
| |
137 /* unambiguous move (e.g. "Nf3") */ |
| |
138 } |
| |
139 |
| |
140 } else if (len == 4) { |
| |
141 /* ambiguous move (e.g. "Ndf3") */ |
| |
142 |
| |
143 /* unambiguous capture (e.g. "Nxf3", "dxe5") */ |
| |
144 |
| |
145 } else if (len == 5) { |
| |
146 /* queen side castling "O-O-O" */ |
| |
147 |
| |
148 /* ambiguous capture (e.g. "Ndxf3") */ |
| |
149 |
| |
150 /* long notation move (e.g. "Nc5a4") */ |
| |
151 |
| |
152 /* long notation capture (e.g. "e5xf6") */ |
| |
153 } else if (len == 6) { |
| |
154 /* long notation capture (e.g. "Nc5xf3") */ |
| |
155 } |
| |
156 |
| |
157 if (move->piece) { |
| |
158 move->piece |= mycolor; |
| |
159 return TRUE; |
| |
160 } else { |
| |
161 return FALSE; |
| |
162 } |
| |
163 } |
| |
164 |
| |
165 static int sendmove(Board board, uint8_t mycolor, int opponent) { |
| 70 const size_t buflen = 8; |
166 const size_t buflen = 8; |
| 71 char move[buflen]; |
167 char movestr[buflen]; |
| 72 _Bool remisrejected = FALSE; |
168 _Bool remisrejected = FALSE; |
| 73 |
169 |
| 74 while (1) { |
170 while (1) { |
| 75 move(boardy+3, 0); |
171 move(boardy+3, 0); |
| 76 if (remisrejected) { |
172 if (remisrejected) { |
| 84 "Or type 'surr' to surrender or 'remis' to offer remis.\n\n" |
180 "Or type 'surr' to surrender or 'remis' to offer remis.\n\n" |
| 85 "Type your move: "); |
181 "Type your move: "); |
| 86 } |
182 } |
| 87 clrtoeol(); |
183 clrtoeol(); |
| 88 refresh(); |
184 refresh(); |
| 89 getnstr(move, buflen); |
185 getnstr(movestr, buflen); |
| 90 |
186 |
| 91 if (strncmp(move, "surr", buflen) == 0) { |
187 if (strncmp(movestr, "surr", buflen) == 0) { |
| 92 printw("You surrendered!"); |
188 printw("You surrendered!"); |
| |
189 refresh(); |
| 93 net_send_code(opponent, NETCODE_SURRENDER); |
190 net_send_code(opponent, NETCODE_SURRENDER); |
| 94 return 1; |
191 return 1; |
| 95 } else if (strncmp(move, "remis", buflen) == 0) { |
192 } else if (strncmp(movestr, "remis", buflen) == 0) { |
| 96 if (!remisrejected) { |
193 if (!remisrejected) { |
| 97 net_send_code(opponent, NETCODE_REMIS); |
194 net_send_code(opponent, NETCODE_REMIS); |
| 98 printw("Remis offer sent - waiting for acceptance..."); |
195 printw("Remis offer sent - waiting for acceptance..."); |
| 99 refresh(); |
196 refresh(); |
| 100 if (net_recieve_code(opponent) == NETCODE_ACCEPT) { |
197 if (net_recieve_code(opponent) == NETCODE_ACCEPT) { |
| 101 printw("\rRemis accepted!"); |
198 printw("\rRemis accepted!"); |
| 102 clrtoeol(); |
199 clrtoeol(); |
| |
200 refresh(); |
| 103 return 1; |
201 return 1; |
| 104 } else { |
202 } else { |
| 105 remisrejected = TRUE; |
203 remisrejected = TRUE; |
| 106 } |
204 } |
| 107 } |
205 } |
| 108 } else { |
206 } else { |
| 109 // TODO: validate move syntactically |
207 Move move; |
| 110 // TODO: send move and await acceptance |
208 if (eval_move(board, mycolor, movestr, &move)) { |
| 111 } |
209 net_send_code(opponent, NETCODE_MOVE); |
| 112 } |
210 net_send_data(opponent, &move, sizeof(Move)); |
| 113 } |
211 if (net_recieve_code(opponent) == NETCODE_ACCEPT) { |
| 114 |
212 apply_move(board, &move); |
| 115 static int recvmove(int opponent) { |
213 return 0; |
| |
214 } else { |
| |
215 printw("Invalid move."); |
| |
216 clrtoeol(); |
| |
217 } |
| |
218 } else { |
| |
219 printw("Can't interpret move - please use algebraic notation."); |
| |
220 } |
| |
221 } |
| |
222 } |
| |
223 } |
| |
224 |
| |
225 static int recvmove(Board board, uint8_t mycolor, int opponent) { |
| 116 |
226 |
| 117 while (1) { |
227 while (1) { |
| 118 move(boardy+3, 0); |
228 move(boardy+3, 0); |
| 119 printw("Awaiting opponent move..."); |
229 printw("Awaiting opponent move..."); |
| 120 clrtoeol(); |
230 clrtoeol(); |
| 121 refresh(); |
231 refresh(); |
| 122 |
232 |
| 123 // TODO: nonblocking |
233 // TODO: nonblocking |
| 124 uint32_t code = net_recieve_code(opponent); |
234 uint32_t code = net_recieve_code(opponent); |
| |
235 |
| |
236 Move move; |
| 125 switch (code) { |
237 switch (code) { |
| 126 case NETCODE_SURRENDER: |
238 case NETCODE_SURRENDER: |
| 127 printw("\rYour opponent surrendered!"); |
239 printw("\rYour opponent surrendered!"); |
| 128 clrtoeol(); |
240 clrtoeol(); |
| 129 return 1; |
241 return 1; |
| 137 } else { |
249 } else { |
| 138 net_send_code(opponent, NETCODE_DECLINE); |
250 net_send_code(opponent, NETCODE_DECLINE); |
| 139 } |
251 } |
| 140 break; |
252 break; |
| 141 case NETCODE_MOVE: |
253 case NETCODE_MOVE: |
| 142 // TODO: receive move |
254 net_recieve_data(opponent, &move, sizeof(Move)); |
| 143 // TODO: validate move and accept/reject |
255 if (validate_move(board, mycolor, &move)) { |
| 144 return 0; |
256 apply_move(board, &move); |
| |
257 net_send_code(opponent, NETCODE_ACCEPT); |
| |
258 return 0; |
| |
259 } else { |
| |
260 net_send_code(opponent, NETCODE_DECLINE); |
| |
261 } |
| 145 } |
262 } |
| 146 } |
263 } |
| 147 } |
264 } |
| 148 |
265 |
| 149 void game_start(Settings *settings, int opponent) { |
266 void game_start(Settings *settings, int opponent) { |
| 150 _Bool myturn = is_server(settings) == |
267 _Bool myturn = is_server(settings) == |
| 151 (settings->gameinfo.servercolor == WHITE); |
268 (settings->gameinfo.servercolor == WHITE); |
| |
269 uint8_t mycolor = myturn ? WHITE:BLACK; |
| |
270 |
| 152 _Bool running; |
271 _Bool running; |
| 153 |
272 |
| 154 Board board = { |
273 Board board = { |
| 155 {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK}, |
274 {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK}, |
| 156 {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN}, |
275 {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN}, |
| 162 {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK} |
281 {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK} |
| 163 }; |
282 }; |
| 164 |
283 |
| 165 do { |
284 do { |
| 166 clear(); |
285 clear(); |
| 167 draw_board(board); |
286 draw_board(board, mycolor); |
| 168 if (myturn) { |
287 if (myturn) { |
| 169 running = !sendmove(opponent); |
288 running = !sendmove(board, mycolor, opponent); |
| 170 } else { |
289 } else { |
| 171 running = !recvmove(opponent); |
290 running = !recvmove(board, mycolor, opponent); |
| 172 flushinp(); // flush any input the user hacked in while waiting |
291 flushinp(); // flush any input the user hacked in while waiting |
| 173 } |
292 } |
| 174 myturn ^= 1; |
293 myturn ^= 1; |
| 175 } while (running); |
294 } while (running); |
| 176 |
295 |