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