110 logelem = logelem->next; |
110 logelem = logelem->next; |
111 } |
111 } |
112 } |
112 } |
113 } |
113 } |
114 |
114 |
|
115 static void eval_move_failed_msg(int code) { |
|
116 switch (code) { |
|
117 case AMBIGUOUS_MOVE: |
|
118 printw("Ambiguous move - please specify the piece to move."); |
|
119 break; |
|
120 case INVALID_POSITION: |
|
121 printw("Cannot find the piece that shall be moved."); |
|
122 break; |
|
123 case NEED_PROMOTION: |
|
124 printw("You need to promote the pawn (append \"=Q\" e.g.)!"); |
|
125 break; |
|
126 default: |
|
127 printw("Can't interpret move - please use algebraic notation."); |
|
128 } |
|
129 } |
|
130 |
|
131 static int domove_singlemachine(GameState *gamestate) { |
|
132 |
|
133 const size_t buflen = 8; |
|
134 char movestr[buflen]; |
|
135 |
|
136 int inputy = getmaxy(stdscr) - 6; |
|
137 while (1) { |
|
138 move(inputy, 0); |
|
139 printw( |
|
140 "Use chess notation to enter your move.\n" |
|
141 "Or type 'surr' to surrender or 'remis' to end with remis.\n\n" |
|
142 "Type your move: "); |
|
143 clrtoeol(); |
|
144 refresh(); |
|
145 getnstr(movestr, buflen); |
|
146 |
|
147 if (strncmp(movestr, "surr", buflen) == 0) { |
|
148 printw("%s surrendered!", |
|
149 gamestate->mycolor==WHITE?"White":"Black"); |
|
150 clrtoeol(); |
|
151 refresh(); |
|
152 return 1; |
|
153 } else if (strncmp(movestr, "remis", buflen) == 0) { |
|
154 printw("Game ends remis."); |
|
155 clrtoeol(); |
|
156 refresh(); |
|
157 return 1; |
|
158 } else { |
|
159 Move move; |
|
160 int eval_result = eval_move(gamestate, movestr, &move); |
|
161 switch (eval_result) { |
|
162 case VALID_MOVE_SYNTAX: |
|
163 if (validate_move(gamestate, &move)) { |
|
164 apply_move(gamestate, &move); |
|
165 if (move.checkmate) { |
|
166 printw("Checkmate!"); |
|
167 clrtoeol(); |
|
168 return 1; |
|
169 } else if (move.stalemate) { |
|
170 printw("Stalemate!"); |
|
171 clrtoeol(); |
|
172 return 1; |
|
173 } else { |
|
174 return 0; |
|
175 } |
|
176 } else { |
|
177 printw("Invalid move."); |
|
178 } |
|
179 break; |
|
180 default: |
|
181 eval_move_failed_msg(eval_result); |
|
182 } |
|
183 clrtoeol(); |
|
184 } |
|
185 } |
|
186 } |
115 |
187 |
116 static int sendmove(GameState *gamestate, int opponent) { |
188 static int sendmove(GameState *gamestate, int opponent) { |
117 |
189 |
118 const size_t buflen = 8; |
190 const size_t buflen = 8; |
119 char movestr[buflen]; |
191 char movestr[buflen]; |
165 case VALID_MOVE_SYNTAX: |
237 case VALID_MOVE_SYNTAX: |
166 net_send_data(opponent, NETCODE_MOVE, &move, sizeof(Move)); |
238 net_send_data(opponent, NETCODE_MOVE, &move, sizeof(Move)); |
167 code = net_recieve_code(opponent); |
239 code = net_recieve_code(opponent); |
168 move.check = code == NETCODE_CHECK; |
240 move.check = code == NETCODE_CHECK; |
169 move.checkmate = code == NETCODE_CHECKMATE; |
241 move.checkmate = code == NETCODE_CHECKMATE; |
|
242 move.stalemate = code == NETCODE_STALEMATE; |
170 if (code == NETCODE_DECLINE) { |
243 if (code == NETCODE_DECLINE) { |
171 printw("Invalid move."); |
244 printw("Invalid move."); |
172 } else { |
245 } else { |
173 apply_move(gamestate, &move); |
246 apply_move(gamestate, &move); |
174 if (move.checkmate) { |
247 if (move.checkmate) { |
175 printw("Checkmate!"); |
248 printw("Checkmate!"); |
176 clrtoeol(); |
249 clrtoeol(); |
177 return 1; |
250 return 1; |
|
251 } else if (move.stalemate) { |
|
252 printw("Stalemate!"); |
|
253 clrtoeol(); |
|
254 return 1; |
178 } else { |
255 } else { |
179 return 0; |
256 return 0; |
180 } |
257 } |
181 } |
258 } |
182 break; |
259 break; |
183 case AMBIGUOUS_MOVE: |
|
184 printw("Ambiguous move - please specify the piece to move."); |
|
185 break; |
|
186 case INVALID_POSITION: |
|
187 printw("Cannot find the piece that shall be moved."); |
|
188 break; |
|
189 case NEED_PROMOTION: |
|
190 printw("You need to promote the pawn (append \"=Q\" e.g.)!"); |
|
191 break; |
|
192 default: |
260 default: |
193 printw("Can't interpret move - please use algebraic notation."); |
261 eval_move_failed_msg(eval_result); |
194 } |
262 } |
195 clrtoeol(); |
263 clrtoeol(); |
196 } |
264 } |
197 } |
265 } |
198 } |
266 } |
243 } |
319 } |
244 } |
320 } |
245 } |
321 } |
246 } |
322 } |
247 |
323 |
248 void game_start(Settings *settings, int opponent) { |
324 static void init_board(GameState *gamestate) { |
249 _Bool myturn = is_server(settings) == |
|
250 (settings->gameinfo.servercolor == WHITE); |
|
251 |
|
252 GameState gamestate; |
|
253 Board initboard = { |
325 Board initboard = { |
254 {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK}, |
326 {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK}, |
255 {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN}, |
327 {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN}, |
256 {0, 0, 0, 0, 0, 0, 0, 0}, |
328 {0, 0, 0, 0, 0, 0, 0, 0}, |
257 {0, 0, 0, 0, 0, 0, 0, 0}, |
329 {0, 0, 0, 0, 0, 0, 0, 0}, |
258 {0, 0, 0, 0, 0, 0, 0, 0}, |
330 {0, 0, 0, 0, 0, 0, 0, 0}, |
259 {0, 0, 0, 0, 0, 0, 0, 0}, |
331 {0, 0, 0, 0, 0, 0, 0, 0}, |
260 {BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN}, |
332 {BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN}, |
261 {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK} |
333 {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK} |
262 }; |
334 }; |
263 memcpy(gamestate.board, initboard, sizeof(Board)); |
335 memcpy(gamestate->board, initboard, sizeof(Board)); |
|
336 } |
|
337 |
|
338 void game_start_singlemachine(Settings *settings) { |
|
339 GameState gamestate; |
|
340 init_board(&gamestate); |
|
341 gamestate.mycolor = WHITE; |
|
342 gamestate.movelist = gamestate.lastmove = NULL; |
|
343 // TODO: time limit |
|
344 _Bool running; |
|
345 do { |
|
346 clear(); |
|
347 draw_board(&gamestate); |
|
348 running = !domove_singlemachine(&gamestate); |
|
349 gamestate.mycolor = opponent_color(gamestate.mycolor); |
|
350 } while (running); |
|
351 |
|
352 gamestate_cleanup(&gamestate); |
|
353 |
|
354 mvaddstr(getmaxy(stdscr)-1, 0, |
|
355 "Game has ended. Press any key to leave..."); |
|
356 refresh(); |
|
357 getch(); |
|
358 } |
|
359 |
|
360 void game_start(Settings *settings, int opponent) { |
|
361 _Bool myturn = is_server(settings) == |
|
362 (settings->gameinfo.servercolor == WHITE); |
|
363 |
|
364 // TODO: time limit |
|
365 GameState gamestate; |
|
366 init_board(&gamestate); |
264 gamestate.mycolor = myturn ? WHITE:BLACK; |
367 gamestate.mycolor = myturn ? WHITE:BLACK; |
265 gamestate.movelist = gamestate.lastmove = NULL; |
368 gamestate.movelist = gamestate.lastmove = NULL; |
266 |
369 |
267 _Bool running; |
370 _Bool running; |
268 do { |
371 do { |