-
Notifications
You must be signed in to change notification settings - Fork 0
/
output.c
360 lines (352 loc) · 13.4 KB
/
output.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
#include "chess.h"
#include "data.h"
/* last modified 01/17/09 */
/*
*******************************************************************************
* *
* OutputMoveExtended() is responsible for converting the internal move *
* format to a string that can be sent out to a robot *
* *
*******************************************************************************
*/
char *OutputMoveExtended(TREE * RESTRICT tree, int move, int ply, int wtm) {
static char text_move[10], new_text[10];
int *mvp;
char *text;
static const char piece_names[7] = { ' ', 'P', 'N', 'B', 'R', 'Q', 'K' };
text = text_move;
if (move == 0) {
strcpy(text, "null");
return (text);
}
do {
// castle
if ((Piece(move) == king) && (abs(From(move) - To(move)) == 2)) {
if (wtm) {
if (To(move) == 2)
strcpy(text_move, "O-O-O");
else
strcpy(text_move, "O-O");
} else {
if (To(move) == 58)
strcpy(text_move, "O-O-O");
else
strcpy(text_move, "O-O");
}
break;
}
// not a castling move. Convert the move to a fully-qualified algebraic move as a starting point.
text = new_text;
if ((int) Piece(move) > pawn)
*text++ = piece_names[Piece(move)];
*text++ = File(From(move)) + 'a';
*text++ = Rank(From(move)) + '1';
if (Captured(move))
*text++ = 'x';
*text++ = File(To(move)) + 'a';
*text++ = Rank(To(move)) + '1';
if (Promote(move)) {
*text++ = '=';
*text++ = piece_names[Promote(move)];
}
*text = '\0';
strcpy(text_move, new_text);
if (output_format > 0)
break;
// this should be the full qualified move
strcpy(text_move, new_text);
} while (0);
/*
************************************************************
* *
* If the move is a check, or mate, append either "+" or *
* "#" as appropriate. *
* *
************************************************************
*/
text = text_move + strlen(text_move);
tree->position[MAXPLY] = tree->position[ply];
MakeMove(tree, MAXPLY, move, wtm);
if (Check(Flip(wtm))) {
mvp =
GenerateCheckEvasions(tree, MAXPLY + 1, Flip(wtm),
tree->move_list + 4800);
if (mvp == (tree->move_list + 4800))
*text++ = '#';
else
*text++ = '+';
}
UnmakeMove(tree, MAXPLY, move, wtm);
*text = 0;
return (text_move);
}
/*
*******************************************************************************
* *
* OutputMove() is responsible for converting the internal move format to a *
* string that can be displayed. First, it simply converts the from/to *
* squares to fully-qualified algebraic (which includes O-O and O-O-O for *
* castling moves). Next, we try several "shortcut" forms and call *
* input_move(silent=1) to let it silently check the move for uniqueness. *
* as soon as we get a non-ambiguous move, we return that text string. *
* *
*******************************************************************************
*/
char *OutputMove(TREE * RESTRICT tree, int move, int ply, int wtm) {
static char text_move[10], new_text[10];
int *mvp;
char *text;
static const char piece_names[7] = { ' ', 'P', 'N', 'B', 'R', 'Q', 'K' };
text = text_move;
/*
************************************************************
* *
* Special case for null-move which will only be used *
* in a search trace which dumps the entire tree. *
* return. *
* *
************************************************************
*/
if (move == 0) {
strcpy(text, "null");
return (text);
}
do {
/*
************************************************************
* *
* Check for castling moves first. *
* *
************************************************************
*/
if ((Piece(move) == king) && (abs(From(move) - To(move)) == 2)) {
if (wtm) {
if (To(move) == 2)
strcpy(text_move, "O-O-O");
else
strcpy(text_move, "O-O");
} else {
if (To(move) == 58)
strcpy(text_move, "O-O-O");
else
strcpy(text_move, "O-O");
}
break;
}
/*
************************************************************
* *
* Not a castling move. Convert the move to a fully- *
* qualified algebraic move as a starting point. *
* *
************************************************************
*/
text = new_text;
//if ((int) Piece(move) > pawn)
*text++ = piece_names[Piece(move)];
*text++ = File(From(move)) + 'a';
*text++ = Rank(From(move)) + '1';
if (Captured(move))
*text++ = 'x';
*text++ = File(To(move)) + 'a';
*text++ = Rank(To(move)) + '1';
if (Promote(move)) {
*text++ = '=';
*text++ = piece_names[Promote(move)];
}
*text = '\0';
strcpy(text_move, new_text);
if (output_format > 0)
break;
/*
************************************************************
* *
* Now we try some short forms. If this is a pawn move *
* (first character is "P") and the move is not a capture *
* move, we can try just the destination square (Pe2e4 *
* becomes e4). *
* *
************************************************************
*/
if (Piece(move) == pawn) {
if (!Captured(move)) {
strcpy(text_move, new_text + 2);
if (OutputGood(tree, text_move, ply, wtm))
break;
}
/*
************************************************************
* *
* If this is a pawn and it is capturing something, try *
* the usual pawn capture format (Pe4xd5 becomes exd5). *
* *
************************************************************
*/
text_move[0] = new_text[0];
strcpy(text_move + 1, new_text + 2);
if (OutputGood(tree, text_move, ply, wtm))
break;
/*
************************************************************
* *
* It is a pawn move and we can't find a shorter form, so *
* leave it as a fully-qualified move and go with it as *
* is. (this will not normally happen). *
* *
************************************************************
*/
strcpy(text_move, new_text);
break;
}
/*
************************************************************
* *
* If the move is a normal piece move, and does not *
* capture anything, we try the piece + destination *
* format first (Ng1f3 becomes Nf3). *
* *
************************************************************
*/
if (!Captured(move)) {
text_move[0] = new_text[0];
strcpy(text_move + 1, new_text + 3);
if (OutputGood(tree, text_move, ply, wtm))
break;
/*
************************************************************
* *
* If that is ambiguous, we will try two alternatives: *
* (1) add in the origin file; (2) add in the origin *
* rank (Ng1f3 becomes Ngf3 or N1f3). *
* *
************************************************************
*/
text_move[0] = new_text[0];
text_move[1] = new_text[1];
strcpy(text_move + 2, new_text + 3);
if (OutputGood(tree, text_move, ply, wtm))
break;
text_move[0] = new_text[0];
strcpy(text_move + 1, new_text + 2);
if (OutputGood(tree, text_move, ply, wtm))
break;
/*
************************************************************
* *
* Nothing worked, so we go with the fully-qualified *
* move. *
* *
************************************************************
*/
strcpy(text_move, new_text);
break;
} else {
/*
************************************************************
* *
* If this is a capture, we try the short form of a *
* capture move (Ng1xf3 becomes Nxf3) *
* *
************************************************************
*/
text_move[0] = new_text[0];
strcpy(text_move + 1, new_text + 3);
if (OutputGood(tree, text_move, ply, wtm))
break;
/*
************************************************************
* *
* If that didn't work, we try adding in the origin file *
* or the origin rank (Ng1xf3 becomes Ngxf3 or N1xf3). *
* *
************************************************************
*/
text_move[0] = new_text[0];
text_move[1] = new_text[1];
strcpy(text_move + 2, new_text + 3);
if (OutputGood(tree, text_move, ply, wtm))
break;
text_move[0] = new_text[0];
strcpy(text_move + 1, new_text + 2);
if (OutputGood(tree, text_move, ply, wtm))
break;
/*
************************************************************
* *
* Nothing worked, return the fully-qualified move. *
* *
************************************************************
*/
strcpy(text_move, new_text);
break;
}
} while (0);
/*
************************************************************
* *
* If the move is a check, or mate, append either "+" or *
* "#" as appropriate. *
* *
************************************************************
*/
text = text_move + strlen(text_move);
tree->position[MAXPLY] = tree->position[ply];
MakeMove(tree, MAXPLY, move, wtm);
if (Check(Flip(wtm))) {
mvp =
GenerateCheckEvasions(tree, MAXPLY + 1, Flip(wtm),
tree->move_list + 4800);
if (mvp == (tree->move_list + 4800))
*text++ = '#';
else
*text++ = '+';
}
UnmakeMove(tree, MAXPLY, move, wtm);
*text = 0;
return (text_move);
}
/* last modified 01/17/09 */
/*
*******************************************************************************
* *
* OutputMoveICS() is responsible for producing the rather primitive move *
* format that the ics interface wants, namely [from][to][promote]. *
* *
*******************************************************************************
*/
char *OutputMoveICS(int move) {
static char text_move[10];
char *text;
static const char piece_names[7] = { ' ', 'P', 'N', 'B', 'R', 'Q', 'K' };
/*
************************************************************
* *
* Chess server software likes a simple 5-character move *
* format, source square, destination square, and a *
* promotion piece if needed. *
* *
************************************************************
*/
text = text_move;
*text++ = File(From(move)) + 'a';
*text++ = Rank(From(move)) + '1';
*text++ = File(To(move)) + 'a';
*text++ = Rank(To(move)) + '1';
if (Promote(move))
*text++ = piece_names[Promote(move)];
*text = '\0';
return (text_move);
}
/*
*******************************************************************************
* *
* OutputGood() is used to test a move for legality when trying to convert *
* from long algebraic to SAN (Short Algebraic Notation). *
* *
*******************************************************************************
*/
int OutputGood(TREE * RESTRICT tree, char *text, int ply, int wtm) {
int new_move;
new_move = InputMove(tree, text, ply, wtm, 1, 0);
return (Piece(new_move));
}