1 /* DreamChess
2 **
3 ** DreamChess is the legal property of its developers, whose names are too
4 ** numerous to list here. Please refer to the AUTHORS.txt file distributed
5 ** with this source distribution.
6 **
7 ** This program is free software: you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation, either version 3 of the License, or
10 ** (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <stdlib.h>
22
23 #include "move_data.h"
24
25 static int knight_moves[8][2] = {{-1, -2}, {1, -2}, {-2, -1}, {2, -1}, {-2, 1}, {2, 1}, {-1, 2}, {1, 2}};
26 static int king_moves[8][2] = {{-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1}};
27 static int white_pawn_captures[2][2] = {{-1, 1}, {1, 1}};
28 static int black_pawn_captures[2][2] = {{-1, -1}, {1, -1}};
29 static int rook_moves[4][2] = {{0, -1}, {-1, 0}, {1, 0}, {0, 1}};
30 static int bishop_moves[4][2] = {{-1, -1}, {1, -1}, {-1, 1}, {1, 1}};
31 static int queen_moves[8][2] = {{0, -1}, {-1, 0}, {1, 0}, {0, 1}, {-1, -1}, {1, -1}, {-1, 1}, {1, 1}};
32
is_valid(int x,int y)33 static int is_valid(int x, int y) {
34 return (x >= 0 && x <= 7 && y >= 0 && y <= 7);
35 }
36
37 #define generate_moves_single(FUNCNAME, MOVES, SIZE) \
38 int **FUNCNAME(void) { \
39 int x, y, i; \
40 \
41 int **move_table; \
42 move_table = malloc(64 * sizeof(int *)); \
43 for (y = 0; y < 8; y++) \
44 for (x = 0; x < 8; x++) { \
45 int count = 0; \
46 int source = y * 8 + x; \
47 \
48 /* Determine possible moves from this source square. */ \
49 for (i = 0; i < SIZE; i++) \
50 if (is_valid(x + MOVES[i][0], y + MOVES[i][1])) \
51 count++; \
52 \
53 move_table[source] = malloc((count + 1) * sizeof(int)); \
54 \
55 /* Store number of moves in first element of array. */ \
56 move_table[source][0] = count; \
57 \
58 /* Print moves. */ \
59 count = 1; \
60 for (i = 0; i < SIZE; i++) { \
61 if (is_valid(x + MOVES[i][0], y + MOVES[i][1])) { \
62 int dest = source + MOVES[i][1] * 8 + MOVES[i][0]; \
63 move_table[source][count] = dest; \
64 count++; \
65 } \
66 } \
67 } \
68 return move_table; \
69 }
70
71 #define generate_moves_ray(FUNCNAME, MOVES, SIZE) \
72 int ***FUNCNAME(void) { \
73 int x, y, i; \
74 \
75 int ***move_table; \
76 move_table = malloc(64 * sizeof(int **)); \
77 for (y = 0; y < 8; y++) \
78 for (x = 0; x < 8; x++) { \
79 int rays = 0; \
80 int curray = 0; \
81 int source = y * 8 + x; \
82 \
83 /* Determine number of non-zero length rays for this source square. */ \
84 for (i = 0; i < SIZE; i++) \
85 if (is_valid(x + MOVES[i][0], y + MOVES[i][1])) \
86 rays++; \
87 \
88 move_table[source] = malloc((rays + 1) * sizeof(int *)); \
89 \
90 for (i = 0; i < SIZE; i++) { \
91 int raylen = 0; \
92 int curraypos = 1; \
93 int xinc, yinc; \
94 \
95 /* Determine length of current ray. */ \
96 xinc = MOVES[i][0]; \
97 yinc = MOVES[i][1]; \
98 \
99 while (is_valid(x + xinc, y + yinc)) { \
100 raylen++; \
101 xinc += MOVES[i][0]; \
102 yinc += MOVES[i][1]; \
103 } \
104 \
105 /* If this ray has length 0, skip it. */ \
106 if (!raylen) \
107 continue; \
108 \
109 move_table[source][curray] = malloc((raylen + 1) * sizeof(int)); \
110 \
111 /* Store ray length in element 0 of the ray. */ \
112 move_table[source][curray][0] = raylen; \
113 \
114 xinc = MOVES[i][0]; \
115 yinc = MOVES[i][1]; \
116 \
117 /* Print ray elements. */ \
118 while (is_valid(x + xinc, y + yinc)) { \
119 int dest = source + yinc * 8 + xinc; \
120 move_table[source][curray][curraypos] = dest; \
121 curraypos++; \
122 xinc += MOVES[i][0]; \
123 yinc += MOVES[i][1]; \
124 } \
125 \
126 curray++; \
127 } \
128 \
129 /* Add a NULL pointer as sentinel. */ \
130 move_table[source][rays] = NULL; \
131 } \
132 return move_table; \
133 }
134
135 generate_moves_single(all_knight_moves, knight_moves, 8)
136 generate_moves_single(all_king_moves, king_moves, 8)
137 generate_moves_single(all_white_pawn_capture_moves, white_pawn_captures, 2)
138 generate_moves_single(all_black_pawn_capture_moves, black_pawn_captures, 2)
139 generate_moves_ray(all_rook_moves, rook_moves, 4)
140 generate_moves_ray(all_bishop_moves, bishop_moves, 4)
141 generate_moves_ray(all_queen_moves, queen_moves, 8)
142