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 |