Fri, 04 Apr 2014 17:36:42 +0200
NEED TESTING: implemented check and checkmate - TODO: avoid checkmate by moving another piece in between
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2014 Mike Becker. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
30 #include "knight.h"
31 #include "rules.h"
32 #include <stdlib.h>
34 _Bool knight_chkrules(Move *move) {
35 int dx = abs(move->fromfile - move->tofile);
36 int dy = abs(move->fromrow - move->torow);
38 return (dx == 2 && dy == 1) || (dx == 1 && dy == 2);
39 }
41 static int knight_getloc_fixedrow(GameState *gamestate, Move *move) {
42 int d = 3 - abs(move->fromrow - move->torow);
44 if (d == 1 || d == 2) {
45 if (move->tofile < 6 &&
46 gamestate->board[move->fromrow][move->tofile + d] == move->piece) {
47 if (move->fromfile == POS_UNSPECIFIED) {
48 move->fromfile = move->tofile + d;
49 return VALID_MOVE_SYNTAX;
50 } else {
51 return AMBIGUOUS_MOVE;
52 }
53 }
54 if (move->tofile > 1 &&
55 gamestate->board[move->fromrow][move->tofile - d] == move->piece) {
56 if (move->fromfile == POS_UNSPECIFIED) {
57 move->fromfile = move->tofile - d;
58 return VALID_MOVE_SYNTAX;
59 } else {
60 return AMBIGUOUS_MOVE;
61 }
62 }
63 }
65 return INVALID_POSITION;
66 }
68 static int knight_getloc_fixedfile(GameState *gamestate, Move *move) {
69 int d = 3 - abs(move->fromfile - move->tofile);
71 if (d == 1 || d == 2) {
72 if (move->torow < 6 &&
73 gamestate->board[move->torow + d][move->fromfile] == move->piece) {
74 if (move->fromrow == POS_UNSPECIFIED) {
75 move->fromrow = move->torow + d;
76 return VALID_MOVE_SYNTAX;
77 } else {
78 return AMBIGUOUS_MOVE;
79 }
80 }
81 if (move->torow > 1 &&
82 gamestate->board[move->torow - d][move->fromfile] == move->piece) {
83 if (move->fromrow == POS_UNSPECIFIED) {
84 move->fromrow = move->torow - d;
85 return VALID_MOVE_SYNTAX;
86 } else {
87 return AMBIGUOUS_MOVE;
88 }
89 }
90 }
92 return INVALID_POSITION;
93 }
95 int knight_getlocation(GameState *gamestate, Move *move) {
97 if (move->fromfile != POS_UNSPECIFIED) {
98 return knight_getloc_fixedfile(gamestate, move);
99 }
101 if (move->fromrow != POS_UNSPECIFIED) {
102 return knight_getloc_fixedrow(gamestate, move);
103 }
105 for (int x = -2 ; x <= 2 ; x++) {
106 if (x == 0) {
107 continue;
108 }
109 for (int y = -2 ; y <= 2 ; y++) {
110 if (y == 0 || y == x) {
111 continue;
112 }
113 uint8_t cx = move->tofile + x;
114 uint8_t cy = move->torow + y;
116 if (isidx(cx) && isidx(cy)
117 && gamestate->board[cy][cx] == move->piece) {
118 if (move->fromfile == POS_UNSPECIFIED
119 && move->fromrow == POS_UNSPECIFIED) {
120 move->fromfile = cx;
121 move->fromrow = cy;
122 } else {
123 return AMBIGUOUS_MOVE;
124 }
125 }
126 }
127 }
129 if (move->fromfile == POS_UNSPECIFIED || move->fromrow == POS_UNSPECIFIED) {
130 return INVALID_POSITION;
131 } else {
132 return VALID_MOVE_SYNTAX;
133 }
134 }