Update codebase to remove clang warnings (and a couple of legit errors
[typhoon.git] / src / ics.c
1 /**
2
3 Copyright (c) Scott Gasch
4
5 Module Name:
6
7     ics.c
8
9 Abstract:
10
11     Routines to convert internal move structs into ICS (d2d4 style)
12     move strings and vice versa.
13
14     See also san.c.
15
16 Author:
17
18     Scott Gasch ([email protected]) 16 May 2004
19
20 Revision History:
21
22     $Id: ics.c 345 2007-12-02 22:56:42Z scott $
23
24 **/
25
26 #include "chess.h"
27
28
29 CHAR *
30 MoveToIcs(MOVE mv)
31 /**
32
33 Routine description:
34
35     Convert a MOVE into an ICS ("d2d4" style) string.  Note: not
36     thread safe.
37
38 Parameters:
39
40     MOVE mv : the move to convert
41
42 Return value:
43
44     CHAR *
45
46 **/
47 {
48     static char szTextMove[10];
49     char *p = szTextMove;
50
51     if (0 == mv.uMove)
52     {
53         return(NULL);
54     }
55     memset(szTextMove, 0, sizeof(szTextMove));
56
57     ASSERT(IS_ON_BOARD(mv.cFrom));
58     ASSERT(IS_ON_BOARD(mv.cTo));
59     *p++ = FILE(mv.cFrom) + 'a';
60     *p++ = RANK(mv.cFrom) + '0';
61     *p++ = FILE(mv.cTo) + 'a';
62     *p++ = RANK(mv.cTo) + '0';
63     
64     if (mv.pPromoted)
65     {
66         if (IS_QUEEN(mv.pPromoted))
67         {
68             *p++ = 'Q';
69         }
70         else if (IS_ROOK(mv.pPromoted))
71         {
72             *p++ = 'R';
73         }
74         else if (IS_BISHOP(mv.pPromoted))
75         {
76             *p++ = 'B';
77         }
78         else if (IS_KNIGHT(mv.pPromoted))
79         {
80             *p++ = 'N';
81         }
82         else
83         {
84             ASSERT(FALSE);
85             return(NULL);
86         }
87     }
88     *p = 0;
89     return(szTextMove);
90 }             
91
92
93 MOVE 
94 ParseMoveIcs(CHAR *szInput, POSITION *pos)
95 /**
96
97 Routine description:
98
99     Parse a move in ICS format (i.e. "d2d4") and create a MOVE struct.
100
101 Parameters:
102
103     CHAR *szInput,
104     POSITION *pos
105
106 Return value:
107
108     MOVE
109
110 **/
111 {
112     MOVE mv;
113     COOR cFrom, cTo;
114     PIECE pMoved, pCaptured, pProm;
115     CHAR *szMoveText = StripMove(szInput);
116     static CHAR *szPieces = "nbrq";
117     CHAR *p;
118     
119     mv.uMove = 0;
120     if (InCheck(pos, pos->uToMove))
121     {
122         mv.bvFlags |= MOVE_FLAG_ESCAPING_CHECK;
123     }
124
125     cFrom = FILE_RANK_TO_COOR((tolower(szMoveText[0]) - 'a'),
126                               (tolower(szMoveText[1]) - '0'));
127     cTo = FILE_RANK_TO_COOR((tolower(szMoveText[2]) - 'a'),
128                             (tolower(szMoveText[3]) - '0'));
129     
130     //
131     // check for castling moves in o-o style notation.
132     //
133     if ((!STRCMPI(szMoveText, "OO")) ||
134         (!STRCMPI(szMoveText, "00")) ||
135         (((E1 == cFrom) && (G1 == cTo)) && 
136          (pos->rgSquare[E1].pPiece == WHITE_KING)) ||
137         (((E8 == cFrom) && (G8 == cTo)) &&
138          (pos->rgSquare[E8].pPiece == BLACK_KING)))
139     {
140         if (pos->uToMove == WHITE) 
141         {
142             if (pos->bvCastleInfo & CASTLE_WHITE_SHORT) 
143             {
144                 ASSERT(pos->rgSquare[E1].pPiece == WHITE_KING);
145                 mv.uMove = 
146                     MAKE_MOVE(E1, G1, WHITE_KING, 0, 0, MOVE_FLAG_SPECIAL);
147             }
148         } 
149         else // black to move
150         {
151             if (pos->bvCastleInfo & CASTLE_BLACK_SHORT) 
152             {
153                 ASSERT(pos->rgSquare[E8].pPiece == BLACK_KING);
154                 mv.uMove = 
155                     MAKE_MOVE(E8, G8, BLACK_KING, 0, 0, MOVE_FLAG_SPECIAL);
156             }
157         }
158         goto done;
159     } 
160     else if ((!STRCMPI(szMoveText, "OOO")) ||
161              (!STRCMPI(szMoveText, "000")) ||
162              (((E1 == cFrom) && (C1 == cTo)) &&
163               (pos->rgSquare[E1].pPiece == WHITE_KING)) ||
164              (((E8 == cFrom) && (C8 == cTo)) &&
165               (pos->rgSquare[E8].pPiece == BLACK_KING)))
166     {
167         if (pos->uToMove == WHITE) 
168         {
169             if (pos->bvCastleInfo & CASTLE_WHITE_LONG) 
170             {
171                 ASSERT(pos->rgSquare[E1].pPiece == WHITE_KING);
172                 mv.uMove = 
173                     MAKE_MOVE(E1, C1, WHITE_KING, 0, 0, MOVE_FLAG_SPECIAL);
174             }
175         } 
176         else // black to move
177         {
178             if (pos->bvCastleInfo & CASTLE_BLACK_LONG) 
179             {
180                 ASSERT(pos->rgSquare[E8].pPiece == BLACK_KING);
181                 mv.uMove = 
182                     MAKE_MOVE(E8, C8, BLACK_KING, 0, 0, MOVE_FLAG_SPECIAL);
183             }
184         }
185         goto done;
186     }
187     
188     if ((!IS_ON_BOARD(cFrom)) ||
189         (!IS_ON_BOARD(cTo)))
190     {
191         goto illegal;
192     }
193
194     pMoved = pos->rgSquare[cFrom].pPiece;
195     if ((IS_EMPTY(pMoved)) || (GET_COLOR(pMoved) != pos->uToMove))
196     {
197         goto illegal;
198     }
199
200     pCaptured = pos->rgSquare[cTo].pPiece;
201     if ((pCaptured != 0) && (GET_COLOR(pCaptured) == pos->uToMove))
202     {
203         goto illegal;
204     }
205     
206     mv.cFrom = cFrom;
207     mv.cTo = cTo;
208     mv.pMoved = pMoved;
209     mv.pCaptured = pCaptured;
210
211     if (IS_PAWN(pMoved))
212     {
213         //
214         // Promotion
215         //
216         if ((szMoveText[4] != 0) && (szMoveText[4] != '\n')) 
217         {
218             if (IS_PAWN(mv.pMoved))
219             {
220                 if (((BLACK == GET_COLOR(mv.pMoved)) && (RANK(cTo) != 1)) ||
221                     ((WHITE == GET_COLOR(mv.pMoved)) && (RANK(cTo) != 8)))
222                 {
223                     goto illegal;
224                 }
225             }
226             p = strchr(szPieces, tolower(szMoveText[4]));
227             if (NULL == p)
228             {
229                 goto illegal;
230             }
231             pProm = (PIECE)((BYTE *)p - (BYTE *)szPieces);
232             pProm += 2;
233             pProm <<= 1;
234             pProm |= pos->uToMove;
235             mv.pPromoted = pProm;
236             mv.bvFlags = MOVE_FLAG_SPECIAL;
237         }
238         
239         //
240         // Handle en passant captures.
241         //
242         if (cTo == pos->cEpSquare)
243         {
244             mv.bvFlags = MOVE_FLAG_SPECIAL;
245             if (WHITE == pos->uToMove)
246             {
247                 mv.pCaptured = pos->rgSquare[cTo + 0x10].pPiece;
248                 ASSERT(mv.pCaptured == BLACK_PAWN);
249             }
250             else
251             {
252                 mv.pCaptured = pos->rgSquare[cTo - 0x10].pPiece;
253                 ASSERT(mv.pCaptured == WHITE_PAWN);
254             }
255         }
256
257         //
258         // Handle double jumps.
259         //
260         if (RANK(cTo) - RANK(cFrom) > 1)
261         {
262             mv.bvFlags = MOVE_FLAG_SPECIAL;
263         }
264     }
265     
266  done:
267     return(mv);
268     
269  illegal:
270     mv.uMove = 0;
271     return(mv);
272 }