1 #include "chess.h"
2 #include "data.h"
3 /* last modified 02/24/14 */
4 /*
5 *******************************************************************************
6 * *
7 * OutputMove() is responsible for converting the internal move format to a *
8 * string that can be displayed. First, it simply converts the from/to *
9 * squares to fully-qualified algebraic (which includes O-O and O-O-O for *
10 * castling moves). Next, we try several "shortcut" forms and call *
11 * input_move(silent=1) to let it silently check the move for uniqueness. *
12 * as soon as we get a non-ambiguous move, we return that text string. *
13 * *
14 *******************************************************************************
15 */
OutputMove(TREE * RESTRICT tree,int ply,int wtm,int move)16 char *OutputMove(TREE * RESTRICT tree, int ply, int wtm, int move) {
17 static char text_move[10], new_text[10];
18 unsigned *mvp;
19 char *text = text_move;
20 static const char piece_names[7] = { ' ', 'P', 'N', 'B', 'R', 'Q', 'K' };
21 /*
22 ************************************************************
23 * *
24 * Special case for null-move which will only be used in a *
25 * search trace which dumps the entire tree. *
26 * *
27 ************************************************************
28 */
29 if (move == 0) {
30 strcpy(text, "null");
31 return text;
32 }
33 do {
34 /*
35 ************************************************************
36 * *
37 * Check for castling moves first. *
38 * *
39 ************************************************************
40 */
41 if ((Piece(move) == king) && (Abs(From(move) - To(move)) == 2)) {
42 if (wtm) {
43 if (To(move) == 2)
44 strcpy(text_move, "O-O-O");
45 else
46 strcpy(text_move, "O-O");
47 } else {
48 if (To(move) == 58)
49 strcpy(text_move, "O-O-O");
50 else
51 strcpy(text_move, "O-O");
52 }
53 break;
54 }
55 /*
56 ************************************************************
57 * *
58 * Not a castling move. Convert the move to a fully- *
59 * qualified algebraic move as a starting point. *
60 * *
61 ************************************************************
62 */
63 text = new_text;
64 if ((int) Piece(move) > pawn)
65 *text++ = piece_names[Piece(move)];
66 *text++ = File(From(move)) + 'a';
67 *text++ = Rank(From(move)) + '1';
68 if (Captured(move))
69 *text++ = 'x';
70 *text++ = File(To(move)) + 'a';
71 *text++ = Rank(To(move)) + '1';
72 if (Promote(move)) {
73 *text++ = '=';
74 *text++ = piece_names[Promote(move)];
75 }
76 *text = '\0';
77 strcpy(text_move, new_text);
78 if (output_format > 0)
79 break;
80 /*
81 ************************************************************
82 * *
83 * Now we try some short forms. If this is a pawn move *
84 * (first character is "P") and the move is not a capture *
85 * move, we can try just the destination square (Pe2e4 *
86 * becomes e4). *
87 * *
88 ************************************************************
89 */
90 if (Piece(move) == pawn) {
91 if (!Captured(move)) {
92 strcpy(text_move, new_text + 2);
93 if (InputMove(tree, ply, wtm, 1, 0, text_move))
94 break;
95 }
96 /*
97 ************************************************************
98 * *
99 * If this is a pawn and it is capturing something, try *
100 * the usual pawn capture format (Pe4xd5 becomes exd5). *
101 * *
102 ************************************************************
103 */
104 text_move[0] = new_text[0];
105 strcpy(text_move + 1, new_text + 2);
106 if (InputMove(tree, ply, wtm, 1, 0, text_move))
107 break;
108 /*
109 ************************************************************
110 * *
111 * It is a pawn move and we can't find a shorter form, so *
112 * leave it as a fully-qualified move and go with it as *
113 * is. (this will not normally happen). *
114 * *
115 ************************************************************
116 */
117 strcpy(text_move, new_text);
118 break;
119 }
120 /*
121 ************************************************************
122 * *
123 * If the move is a normal piece move, and does not *
124 * capture anything, we try the piece + destination format *
125 * first (Ng1f3 becomes Nf3). *
126 * *
127 ************************************************************
128 */
129 if (!Captured(move)) {
130 text_move[0] = new_text[0];
131 strcpy(text_move + 1, new_text + 3);
132 if (InputMove(tree, ply, wtm, 1, 0, text_move))
133 break;
134 /*
135 ************************************************************
136 * *
137 * If that is ambiguous, we will try two alternatives: *
138 * (1) add in the origin file; (2) add in the origin rank *
139 * (Ng1f3 becomes Ngf3 or N1f3). *
140 * *
141 ************************************************************
142 */
143 text_move[0] = new_text[0];
144 text_move[1] = new_text[1];
145 strcpy(text_move + 2, new_text + 3);
146 if (InputMove(tree, ply, wtm, 1, 0, text_move))
147 break;
148 text_move[0] = new_text[0];
149 strcpy(text_move + 1, new_text + 2);
150 if (InputMove(tree, ply, wtm, 1, 0, text_move))
151 break;
152 /*
153 ************************************************************
154 * *
155 * Nothing worked, so we go with the fully-qualified move. *
156 * *
157 ************************************************************
158 */
159 strcpy(text_move, new_text);
160 break;
161 } else {
162 /*
163 ************************************************************
164 * *
165 * If this is a capture, we try the short form of a *
166 * capture move (Ng1xf3 becomes Nxf3) *
167 * *
168 ************************************************************
169 */
170 text_move[0] = new_text[0];
171 strcpy(text_move + 1, new_text + 3);
172 if (InputMove(tree, ply, wtm, 1, 0, text_move))
173 break;
174 /*
175 ************************************************************
176 * *
177 * If that didn't work, we try adding in the origin file *
178 * or the origin rank (Ng1xf3 becomes Ngxf3 or N1xf3). *
179 * *
180 ************************************************************
181 */
182 text_move[0] = new_text[0];
183 text_move[1] = new_text[1];
184 strcpy(text_move + 2, new_text + 3);
185 if (InputMove(tree, ply, wtm, 1, 0, text_move))
186 break;
187 text_move[0] = new_text[0];
188 strcpy(text_move + 1, new_text + 2);
189 if (InputMove(tree, ply, wtm, 1, 0, text_move))
190 break;
191 /*
192 ************************************************************
193 * *
194 * Nothing worked, return the fully-qualified move. *
195 * *
196 ************************************************************
197 */
198 strcpy(text_move, new_text);
199 break;
200 }
201 } while (0);
202 /*
203 ************************************************************
204 * *
205 * If the move is a check, or mate, append either "+" or *
206 * "#" as appropriate. *
207 * *
208 ************************************************************
209 */
210 if (output_format == 0) {
211 text = text_move + strlen(text_move);
212 tree->status[MAXPLY] = tree->status[ply];
213 MakeMove(tree, MAXPLY, wtm, move);
214 if (Check(Flip(wtm))) {
215 mvp =
216 GenerateCheckEvasions(tree, MAXPLY + 1, Flip(wtm),
217 tree->move_list + 4800);
218 if (mvp == (tree->move_list + 4800))
219 *text++ = '#';
220 else
221 *text++ = '+';
222 }
223 UnmakeMove(tree, MAXPLY, wtm, move);
224 *text = 0;
225 }
226 return text_move;
227 }
228