1 //////////////////////////////////////////////////////////////////////
2 //
3 //  FILE:       position.h
4 //              Position class
5 //
6 //  Part of:    Scid (Shane's Chess Information Database)
7 //  Version:    3.5
8 //
9 //  Notice:     Copyright (c) 1999-2003 Shane Hudson.  All rights reserved.
10 //
11 //  Author:     Shane Hudson (sgh@users.sourceforge.net)
12 //
13 //////////////////////////////////////////////////////////////////////
14 
15 
16 #ifndef SCID_POSITION_H
17 #define SCID_POSITION_H
18 
19 #include "common.h"
20 #include "movelist.h"
21 #include <stdio.h>
22 
23 class DString;
24 class SquareSet;
25 class SquareList;
26 
27 
28 //////////////////////////////////////////////////////////////////////
29 //  Position:  Constants
30 
31 const byte  WQ_CASTLE = 1,    WK_CASTLE = 2,
32             BQ_CASTLE = 4,    BK_CASTLE = 8;
33 
34 // SANFlag: since checking if a move is check (to add the "+" to its
35 //      SAN string) takes time, and checking for mate takes even
36 //      longer, we specify whether we want this done with a flag.
37 typedef byte      sanFlagT;
38 const sanFlagT    SAN_NO_CHECKTEST   = 0,
39                   SAN_CHECKTEST      = 1,
40                   SAN_MATETEST       = 2;
41 
42 
43 // Flags that Position::PrintFEN() recognises:
44 //
45 const uint
46     FEN_COMPACT = 0,
47     FEN_BOARD = 1,
48     FEN_CASTLING_EP = 2,
49     FEN_ALL_FIELDS = 3;
50 
51 
52 // Flags that Position::GenerateMoves() recognises:
53 //
54 typedef uint genMovesT;
55 const genMovesT
56     GEN_CAPTURES = 1,
57     GEN_NON_CAPS = 2,
58     GEN_ALL_MOVES = (GEN_CAPTURES | GEN_NON_CAPS);
59 
60 
61 // SANList: list of legal move strings in SAN.
62 //
63 struct sanListT
64 {
65     bool        current;
66     ushort      num;
67     sanStringT  list [MAX_LEGAL_MOVES];
68 };
69 
70 
71 ///////////////////////////////////////////////////////////////////////////
72 //  Position:  Class definition
73 
74 class Position
75 {
76 
77 private:
78     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
79     //  Position:  Data structures
80 
81     pieceT          Board[66];      // the actual board + a color square
82                                     // and a NULL square.
83     uint            Count[2];       // count of pieces & pawns each
84     byte            Material[16];   // count of each type of piece
85     byte            ListPos[64];    // ListPos stores the position in
86                                         // List[][] for the piece on
87                                         // square x.
88     squareT         List[2][16];    // list of piece squares for each side
89     byte            NumOnRank[16][8];
90     byte            NumOnFyle[16][8];
91     byte            NumOnLeftDiag[16][16];  // Num Queens/Bishops
92     byte            NumOnRightDiag[16][16];
93     byte            NumOnSquareColor[16][2];
94 
95     directionT      Pinned[16];     // For each List[ToMove][x], stores
96                                         // whether piece is pinned to its
97                                         // own king and dir from king.
98 
99     squareT         EPTarget;       // square pawns can EP capture to
100     colorT          ToMove;
101     ushort          HalfMoveClock;  // Count of halfmoves since last capture
102                                     // or pawn move.
103     ushort          PlyCounter;
104     byte            Castling;       // castling flags
105 
106     uint            Hash;           // Hash value.
107     uint            PawnHash;       // Pawn structure hash value.
108 
109     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
110     //  Position:  Private Functions
111 
112     inline void AddHash (pieceT p, squareT sq);
113     inline void UnHash (pieceT p, squareT sq);
114 
115     inline void AddToBoard (pieceT p, squareT sq);
116     inline void RemoveFromBoard (pieceT p, squareT sq);
117 
118     void  CalcPinsDir (directionT dir, pieceT attacker);
119 
120     void  GenSliderMoves (MoveList * mlist, colorT c, squareT sq,
121                           directionT dir, SquareSet * sqset,
122                           bool capturesOnly);
123     void  GenKnightMoves (MoveList * mlist, colorT c, squareT sq,
124                           SquareSet * sqset, bool capturesOnly);
125 
126     void  AddLegalMove (MoveList * mlist, squareT from, squareT to, pieceT promo);
127     void  GenCastling (MoveList * mlist);
128     void  GenKingMoves (MoveList * mlist, genMovesT genType, bool castling);
129     void  AddPromotions (MoveList * mlist, squareT from, squareT dest);
130     bool  IsValidEnPassant (squareT from, squareT to);
131     void  GenPawnMoves (MoveList * mlist, squareT from, directionT dir,
132                         SquareSet * sqset, genMovesT genType);
133 
134     void GenCheckEvasions(MoveList* mlist, pieceT mask, genMovesT genType,
135                           SquareList* checkSquares);
136     errorT MatchPawnMove(MoveList* mlist, fyleT fromFyle, squareT to,
137                          pieceT promote);
138 
139     errorT ReadMove(simpleMoveT* sm, const char* str, int slen, pieceT p);
140     errorT ReadMoveCastle(simpleMoveT* sm, const char* str, int slen);
141     errorT ReadMovePawn(simpleMoveT* sm, const char* str, int slen, fyleT from);
142     errorT ReadMoveKing(simpleMoveT* sm, const char* str, int slen);
143 
144 
145     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
146     //  Position:  Public Functions
147 public:
148     Position();
149     static const Position& getStdStart();
150 
151     void        Clear();        // No pieces on board
StdStart()152     void        StdStart() { *this = getStdStart(); }
153     bool        IsStdStart() const;
154     errorT      AddPiece (pieceT p, squareT sq);
155 
156     // Set and Get attributes -- one-liners
PieceCount(pieceT p)157     byte        PieceCount (pieceT p)    { return Material[p]; }
GetMaterial()158     const byte* GetMaterial() const      { return Material; }
SetEPTarget(squareT s)159     void        SetEPTarget (squareT s)  { EPTarget = s; }
GetEPTarget()160     squareT     GetEPTarget () const     { return EPTarget; }
SetToMove(colorT c)161     void        SetToMove (colorT c)     { ToMove = c; }
GetToMove()162     colorT      GetToMove () const       { return ToMove; }
SetPlyCounter(ushort x)163     void        SetPlyCounter (ushort x) { PlyCounter = x; }
GetPlyCounter()164     ushort      GetPlyCounter () const   { return PlyCounter; }
GetFullMoveCount()165     ushort      GetFullMoveCount() const { return PlyCounter / 2 + 1; }
166 
167     // Methods to get the Board or piece lists -- used in game.cpp to
168     // decode moves:
GetList(colorT c)169     const squareT* GetList(colorT c) const { return List[c]; }
GetList(colorT c)170     squareT *   GetList (colorT c)    { return List[c]; }
GetCount(colorT c)171     uint        GetCount (colorT c) const { return Count[c]; }
TotalMaterial()172     uint        TotalMaterial ()      { return Count[WHITE] + Count[BLACK]; }
NumNonPawns(colorT c)173     uint        NumNonPawns (colorT c) {
174         return Count[c] - Material[piece_Make(c,PAWN)];
175     }
InPawnEnding()176     bool        InPawnEnding () {
177         return (NumNonPawns(WHITE) == 1  &&  NumNonPawns(BLACK) == 1);
178     }
179     uint        MaterialValue (colorT c);
FyleCount(pieceT p,fyleT f)180     inline uint FyleCount (pieceT p, fyleT f) const {
181         return NumOnFyle[p][f];
182     }
RankCount(pieceT p,rankT r)183     inline uint RankCount (pieceT p, rankT r) const {
184         return NumOnRank[p][r];
185     }
LeftDiagCount(pieceT p,leftDiagT diag)186     inline uint LeftDiagCount (pieceT p, leftDiagT diag) {
187         return NumOnLeftDiag[p][diag];
188     }
RightDiagCount(pieceT p,rightDiagT diag)189     inline uint RightDiagCount (pieceT p, rightDiagT diag) {
190         return NumOnRightDiag[p][diag];
191     }
SquareColorCount(pieceT p,colorT sqColor)192     inline uint SquareColorCount (pieceT p, colorT sqColor) {
193         return NumOnSquareColor[p][sqColor];
194     }
195     uint        GetSquares (pieceT p, SquareList * sqlist);
196 
GetBoard()197     const pieceT* GetBoard() const {
198         const_cast<Position*>(this)->Board[COLOR_SQUARE] = COLOR_CHAR[ToMove];
199         return Board;
200     }
201 
GetPiece(squareT sq)202     pieceT GetPiece(squareT sq) const {
203         ASSERT(sq < 64);
204         return Board[sq];
205     }
206 
207     // Other one-line methods
GetKingSquare(colorT c)208     squareT     GetKingSquare (colorT c)  { return List[c][0]; }
GetKingSquare()209     squareT     GetKingSquare ()          { return List[ToMove][0]; }
GetEnemyKingSquare()210     squareT     GetEnemyKingSquare ()     { return List[1-ToMove][0]; }
211 
212     // Castling flags
213     inline void SetCastling (colorT c, castleDirT dir, bool flag);
GetCastling(colorT c,castleDirT dir)214     bool GetCastling(colorT c, castleDirT dir) const {
215         int b = (c == WHITE) ? 1 : 4;
216         if (dir == KSIDE)
217             b += b;
218         // Now b == 1 or 2 (white flags), or 4 or 8 (black flags)
219         return Castling & b;
220     }
CastlingPossible()221     inline bool CastlingPossible () { return (Castling ? true : false); }
GetCastlingFlags()222     byte        GetCastlingFlags () { return Castling; }
SetCastlingFlags(byte b)223     void        SetCastlingFlags (byte b) { Castling = b; }
224 
225     // Hashing
HashValue(void)226     inline uint HashValue (void) { return Hash; }
PawnHashValue(void)227     inline uint PawnHashValue (void) { return PawnHash; }
228     uint        GetHPSig ();
229 
230     // Move generation and execution
231     void        CalcPins();
232     void        GenPieceMoves (MoveList * mlist, squareT sq,
233                                SquareSet * sqset, bool capturesOnly);
234 
235     // Generate all legal moves:
236     void  GenerateMoves (MoveList* mlist, pieceT mask, genMovesT genType, bool maybeInCheck);
GenerateMoves(MoveList * mlist)237     void  GenerateMoves (MoveList * mlist) { GenerateMoves (mlist, EMPTY, GEN_ALL_MOVES, true); }
GenerateMoves(MoveList * mlist,genMovesT genType)238     void  GenerateMoves (MoveList * mlist, genMovesT genType) { GenerateMoves (mlist, EMPTY, genType, true); }
GenerateCaptures(MoveList * mlist)239     void  GenerateCaptures (MoveList * mlist) { GenerateMoves (mlist, EMPTY, GEN_CAPTURES, true); }
240     bool  IsLegalMove (simpleMoveT * sm);
241 
242     uint        CalcAttacks (colorT toMove, squareT kingSq, SquareList * squares);
243     int         TreeCalcAttacks (colorT toMove, squareT target);
CalcNumChecks()244     uint        CalcNumChecks () {
245                     return CalcAttacks (1-ToMove, GetKingSquare(), NULL);
246                 }
CalcNumChecks(squareT kingSq)247     uint        CalcNumChecks (squareT kingSq) {
248                     return CalcAttacks (1-ToMove, kingSq, NULL);
249                 }
CalcNumChecks(squareT kingSq,SquareList * checkSquares)250     uint        CalcNumChecks (squareT kingSq, SquareList * checkSquares) {
251                     return CalcAttacks (1-ToMove, kingSq, checkSquares);
252                 }
253 
254     uint        Mobility (pieceT p, colorT color, squareT from);
IsKingInCheck()255     bool        IsKingInCheck () { return (CalcNumChecks() > 0); }
256     bool        IsKingInCheckDir (directionT dir);
257     bool        IsKingInCheck (simpleMoveT * sm);
258     bool        IsKingInMate ();
259     bool        IsLegal ();
260 
261     bool        IsPromoMove (squareT from, squareT to);
262 
263     void        DoSimpleMove (simpleMoveT * sm);    // move execution ...
264     void        UndoSimpleMove (simpleMoveT * sm);  // ... and taking back
265 
266     errorT      RelocatePiece (squareT fromSq, squareT toSq);
267 
268     void        MakeSANString (simpleMoveT * sm, char * s, sanFlagT flag);
269     void        MakeUCIString (simpleMoveT * sm, char * s);
270 	void        CalcSANStrings (sanListT *sanList, sanFlagT flag);
271 
272     errorT      ReadCoordMove(simpleMoveT* m, const char* s, int slen, bool reverse);
273     errorT      ParseMove(simpleMoveT* sm, const char* str);
274     errorT      ParseMove(simpleMoveT* sm, const char* begin, const char* end);
275 
276     // Board I/O
277     void        MakeLongStr (char * str);
278     errorT      ReadFromLongStr (const char * str);
279     errorT      ReadFromCompactStr (const byte * str);
280     errorT      ReadFromFEN (const char * s);
281     void        PrintCompactStr (char * cboard);
282     void        PrintCompactStrFlipped (char * cboard);
CompactStrFirstByte()283     byte        CompactStrFirstByte () {
284         return (Board[0] << 4) | Board[1];
285     }
286     void        PrintFEN(char* str, uint flags) const;
287     void        DumpLatexBoard (DString * dstr, bool flip);
DumpLatexBoard(DString * dstr)288     void        DumpLatexBoard (DString * dstr) {
289         DumpLatexBoard (dstr, false);
290     }
291     void        DumpHtmlBoard (DString * dstr, uint style, const char * dir,
292                                bool flip);
DumpHtmlBoard(DString * dstr,uint style,const char * dir)293     void        DumpHtmlBoard (DString * dstr, uint style, const char * dir) {
294         DumpHtmlBoard (dstr, style, dir, false);
295     }
296 
297     // Copy, compare positions
298     int         Compare (Position * p);
CopyFrom(Position * src)299     void        CopyFrom (Position * src) { *this = *src; }
300 
301     // Set up a random position:
302     errorT      Random (const char * material);
303 };
304 
305 
306 
307 //////////////////////////////////////////////////////////////////////
308 //  Position:  Public Inline Functions
309 
310 
311 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
312 // Position::SetCastling():
313 //      Set a castling flag.
314 //
315 inline void
SetCastling(colorT c,castleDirT dir,bool flag)316 Position::SetCastling (colorT c, castleDirT dir, bool flag)
317 {
318     byte b = (c==WHITE ? 1 : 4);
319     if (dir == KSIDE) b += b;
320     // Now b = 1 or 2 (white flags), or 4 or 8 (black flags)
321     if (flag) { Castling |= b; } else { Castling &= (255-b); }
322     return;
323 }
324 
325 #endif  // SCID_POSITION_H
326 
327 //////////////////////////////////////////////////////////////////////
328 //  EOF: position.h
329 //////////////////////////////////////////////////////////////////////
330 
331