2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@sns.it>
3 (c) 2006 Maurizio Monge <maurizio.monge@kdemail.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
20 #include <QStringList>
21 #include <boost/shared_ptr.hpp>
26 #include "interactiontype.h"
27 #include "variants/xchess/generator.h"
28 #include "variants/xchess/piecetype.h"
30 class AlgebraicNotation
;
31 class VerboseNotation
;
33 #define POLYMORPHIC_NEW(type, argsdecl, args) \
34 virtual type* _new argsdecl const { return new type args; }
36 template <typename M
, typename P
, typename B
>
39 template <typename M
, typename P
, typename B
>
42 typedef typename
P::Type Type
;
43 typedef typename
P::Color Color
;
48 Point m_enPassantSquare
;
50 bool m_castleWhiteKing
: 1;
51 bool m_castleWhiteQueen
: 1;
52 bool m_castleBlackKing
: 1;
53 bool m_castleBlackQueen
: 1;
60 Position(int = 8, int = 8);
61 Position(const OptList
& l
, int = 8, int = 8);
63 bool castleWhiteKing
, bool castleWhiteQueen
,
64 bool castleBlackKing
, bool castleBlackQueen
,
65 const Point
& enPassant
);
66 Position(const Position
<M
, P
, B
>&);
67 template <typename M1
, typename P1
, typename B1
>
68 Position(const Position
<M1
, P1
, B1
>&);
70 Point
size() const { return m_board
.getSize(); }
72 POLYMORPHIC_NEW(Position
, (), ())
73 POLYMORPHIC_NEW(Position
, (const Position
* other
), (*other
))
74 virtual Position
* clone() const { return new Position(*this); }
77 virtual QString
type() const { return "chess"; }
79 bool operator==(const Position
<M
, P
, B
>&) const;
80 bool operator!=(const Position
<M
, P
, B
>&) const;
84 void debugInfo() const;
86 virtual const Point
first() const { return m_board
.first(); }
87 virtual const Point
last() const { return m_board
.last(); }
88 virtual Point
next(const Point
& p
) const { return m_board
.next(p
); }
89 inline bool valid(const Point
& p
) const { return m_board
.valid(p
); }
91 PathInfo
path(const Point
&, const Point
&) const;
92 const Point
& enPassantSquare() const { return m_enPassantSquare
; }
94 virtual P
get(const Point
& p
) const {
95 return valid(p
) ? m_board
[p
] : P();
97 virtual P
operator[](const Point
& p
) const { return get(p
); }
98 inline void set(const Point
& p
, const P
& piece
) {
103 inline void removePiece(const Point
& p
) { set(p
, 0); }
104 inline void basicMovePiece(const M
&);
106 inline InteractionType
movable(const Point
& p
) const {
107 if(!valid(p
) || !m_board
[p
])
109 return m_board
[p
].color() == m_turn
? Moving
: Premoving
;
111 inline InteractionType
droppable(int p
) const {
112 Color c
= static_cast<Color
>(p
);
113 return c
== m_turn
? Moving
: Premoving
;
115 inline Color
turn() const { return m_turn
; }
116 inline Color
previousTurn() const { return Piece::oppositeColor(m_turn
); }
117 inline const B
& board() const { return m_board
; }
118 inline bool castleKing(Color color
) const { return color
== WHITE
? m_castleWhiteKing
: m_castleBlackKing
; }
119 inline bool castleQueen(Color color
) const { return color
== WHITE
? m_castleWhiteQueen
: m_castleBlackQueen
; }
121 virtual bool attacks(Color
, const Point
& destination
, Point
& source
) const;
122 virtual bool attacks(Color
, const Point
& destination
) const;
123 virtual bool attacks(const Point
& destination
) const;
125 Point
findPiece(Color
, typename
P::Type
) const;
126 virtual void switchTurn();
127 virtual void setTurn(Color turn
);
129 typename
P::Type
promotionType() const { return QUEEN
; }
131 virtual void move(const M
&);
132 virtual Position
<M
, P
, B
>* legallyMove(M
&) const;
133 void stepBack(const Position
<M
, P
, B
>* oldPosition
, const M
& move
);
134 virtual Color
moveTurn(const M
& move
) const;
135 virtual bool checkPromotionType(const M
&) const;
136 virtual bool pseudolegal(M
&) const;
137 virtual bool testMove(M
&) const;
138 virtual bool testPremove(M
) const;
140 virtual M
getMove(const AlgebraicNotation
& san
, bool& ok
) const;
141 // virtual M getMove(const QString& san, bool& ok) const;
142 static M
getVerboseMove(Color
, const VerboseNotation
& m
);
144 //FIXME: Those are really very chess dependent, make them virtual at least
145 static Point
kingStartingPosition(Color color
) { return color
== WHITE
? Point(4,7) : Point(4,0); }
147 inline M
kingCastleMove() const { return m_turn
== WHITE
?
148 M(Point(4, 7), Point(6, 7)) : M(Point(4,0), Point(6,0)); }
149 inline M
queenCastleMove() const { return m_turn
== WHITE
?
150 M(Point(4, 7), Point(2, 7)) : M(Point(4,0), Point(2,0)); }
159 virtual boost::shared_ptr
<AbstractGenerator
<M
> > createLegalGenerator() const;
160 virtual bool stalled() const;
161 // virtual bool pseudoStalled() const;
163 bool check(Color
) const;
165 virtual void basicDropPiece(P
* piece
, const Point
& to
);
166 virtual void executeCaptureOn(const Point
& point
);
168 boost::shared_ptr
<P
> moveHint(const M
&) const;
171 QString
fen(int, int) const;
172 void fromFEN(const QString
& fen
, bool&);
173 QStringList
borderCoords() const;
176 std::ostream
& operator<<(std::ostream
& os
, const class GenericPosition
&);
180 #include "algebraicnotation.h"
182 template <typename M
, typename P
, typename B
>
183 Position
<M
, P
, B
>::Position(int width
, int height
)
185 , m_board(width
, height
)
186 , m_enPassantSquare(Point::invalid())
187 , m_castleWhiteKing(true)
188 , m_castleWhiteQueen(true)
189 , m_castleBlackKing(true)
190 , m_castleBlackQueen(true) { }
192 template <typename M
, typename P
, typename B
>
193 Position
<M
, P
, B
>::Position(const OptList
&, int width
, int height
)
195 , m_board(width
, height
)
196 , m_enPassantSquare(Point::invalid())
197 , m_castleWhiteKing(true)
198 , m_castleWhiteQueen(true)
199 , m_castleBlackKing(true)
200 , m_castleBlackQueen(true) { }
202 template <typename M
, typename P
, typename B
>
203 Position
<M
, P
, B
>::Position(Color turn
, bool castleWhiteKing
,
204 bool castleWhiteQueen
,
205 bool castleBlackKing
,
206 bool castleBlackQueen
,
207 const Point
& enPassant
)
210 , m_enPassantSquare(enPassant
)
211 , m_castleWhiteKing(castleWhiteKing
)
212 , m_castleWhiteQueen(castleWhiteQueen
)
213 , m_castleBlackKing(castleBlackKing
)
214 , m_castleBlackQueen(castleBlackQueen
) { }
216 template <typename M
, typename P
, typename B
>
217 Position
<M
, P
, B
>::Position(const Position
<M
, P
, B
>& other
)
218 : m_turn(other
.m_turn
)
219 , m_board(other
.m_board
)
220 , m_enPassantSquare(other
.m_enPassantSquare
)
221 , m_castleWhiteKing(other
.m_castleWhiteKing
)
222 , m_castleWhiteQueen(other
.m_castleWhiteQueen
)
223 , m_castleBlackKing(other
.m_castleBlackKing
)
224 , m_castleBlackQueen(other
.m_castleBlackQueen
) { }
226 template <typename M
, typename P
, typename B
>
227 template <typename M1
, typename P1
, typename B1
>
228 Position
<M
, P
, B
>::Position(const Position
<M1
, P1
, B1
>& other
)
229 : m_turn(other
.turn())
230 , m_board(other
.board())
231 , m_enPassantSquare(other
.enPassantSquare())
232 , m_castleWhiteKing(other
.castleKing(WHITE
))
233 , m_castleWhiteQueen(other
.castleQueen(WHITE
))
234 , m_castleBlackKing(other
.castleKing(BLACK
))
235 , m_castleBlackQueen(other
.castleQueen(BLACK
)) { }
238 template <typename M
, typename P
, typename B
>
239 Position
<M
, P
, B
>::~Position() {
243 template <typename M
, typename P
, typename B
>
244 QStringList Position
<M
, P
, B
>::borderCoords() const
247 Point p
= m_board
.getSize();
248 for(int i
=0; i
<p
.x
; i
++)
249 retv
<< QChar('a'+i
);
250 for(int i
=1; i
<=p
.y
; i
++)
251 retv
+= QString::number(i
);
255 template <typename M
, typename P
, typename B
>
256 bool Position
<M
, P
, B
>::operator==(const Position
<M
, P
, B
>& other
) const {
258 std::cout
<< "turn: " << m_turn
<< " " << other
.m_turn
<< std::endl
;
259 std::cout
<< "ep: " << m_enPassantSquare
<< " " << other
.m_enPassantSquare
<< std::endl
;
260 std::cout
<< "wk: " << m_castleWhiteKing
<< " " << other
.m_castleWhiteKing
<< std::endl
;
261 std::cout
<< "wq: " << m_castleWhiteQueen
<< " " << other
.m_castleWhiteQueen
<< std::endl
;
262 std::cout
<< "bk: " << m_castleBlackKing
<< " " << other
.m_castleBlackKing
<< std::endl
;
263 std::cout
<< "bq: " << m_castleBlackQueen
<< " " << other
.m_castleBlackQueen
<< std::endl
;
264 if (m_turn
!= other
.m_turn
) {
265 std::cout
<< "turns differ" << std::endl
;
268 if (!(m_board
== other
.m_board
)) {
269 std::cout
<< "boards differ" << std::endl
;
272 if (m_castleWhiteKing
!= other
.m_castleWhiteKing
) {
273 std::cout
<< "wk differ" << std::endl
;
276 if (m_castleWhiteQueen
!= other
.m_castleWhiteQueen
) {
277 std::cout
<< "wq differ" << std::endl
;
280 if (m_castleBlackKing
!= other
.m_castleBlackKing
) {
281 std::cout
<< "bk differ" << std::endl
;
284 if (m_castleBlackQueen
!= other
.m_castleBlackQueen
) {
285 std::cout
<< "bq differ" << std::endl
;
288 std::cout
<< "equal" << std::endl
;
291 return m_turn
== other
.m_turn
&&
292 m_board
== other
.m_board
&&
293 m_enPassantSquare
== other
.m_enPassantSquare
&&
294 m_castleWhiteKing
== other
.m_castleWhiteKing
&&
295 m_castleWhiteQueen
== other
.m_castleWhiteQueen
&&
296 m_castleBlackKing
== other
.m_castleBlackKing
&&
297 m_castleBlackQueen
== other
.m_castleBlackQueen
;
301 template <typename M
, typename P
, typename B
>
302 bool Position
<M
, P
, B
>::operator!=(const Position
& other
) const {
303 return !(*this == other
);
306 template <typename M
, typename P
, typename B
>
307 void Position
<M
, P
, B
>::debugInfo() const {
309 std::cout
<< "board = " << &m_board
<< std::endl
;
313 #define SET_PIECE(i,j, color, type) m_board[Point(i,j)] = P(color, type)
314 template <typename M
, typename P
, typename B
>
315 void Position
<M
, P
, B
>::setup() {
316 for (int i
= 0; i
< 8; i
++) {
317 SET_PIECE(i
, 1, BLACK
, PAWN
);
318 SET_PIECE(i
, 6, WHITE
, PAWN
);
321 SET_PIECE(0,0, BLACK
, ROOK
);
322 SET_PIECE(1,0, BLACK
, KNIGHT
);
323 SET_PIECE(2,0, BLACK
, BISHOP
);
324 SET_PIECE(3,0, BLACK
, QUEEN
);
325 SET_PIECE(4,0, BLACK
, KING
);
326 SET_PIECE(5,0, BLACK
, BISHOP
);
327 SET_PIECE(6,0, BLACK
, KNIGHT
);
328 SET_PIECE(7,0, BLACK
, ROOK
);
330 SET_PIECE(0,7, WHITE
, ROOK
);
331 SET_PIECE(1,7, WHITE
, KNIGHT
);
332 SET_PIECE(2,7, WHITE
, BISHOP
);
333 SET_PIECE(3,7, WHITE
, QUEEN
);
334 SET_PIECE(4,7, WHITE
, KING
);
335 SET_PIECE(5,7, WHITE
, BISHOP
);
336 SET_PIECE(6,7, WHITE
, KNIGHT
);
337 SET_PIECE(7,7, WHITE
, ROOK
);
340 m_enPassantSquare
= Point::invalid();
341 m_castleWhiteKing
= true;
342 m_castleWhiteQueen
= true;
343 m_castleBlackKing
= true;
344 m_castleBlackQueen
= true;
348 template <typename M
, typename P
, typename B
>
349 PathInfo Position
<M
, P
, B
>::path(const Point
& from
, const Point
& to
) const {
350 return m_board
.path(from
, to
);
353 template <typename M, typename P, typename B>
354 void Position<M, P, B>::movePiece(const M& move) {
355 executeCaptureOn(move.to);
356 basicMovePiece(move);
360 template <typename M
, typename P
, typename B
>
361 void Position
<M
, P
, B
>::executeCaptureOn(const Point
& point
) {
362 m_board
[point
] = Piece();
365 template <typename M
, typename P
, typename B
>
366 void Position
<M
, P
, B
>::basicMovePiece(const M
& move
) {
367 P p
= m_board
[move
.from
];
370 m_board
[move
.to
] = p
;
371 m_board
[move
.from
] = Piece();
374 template <typename M
, typename P
, typename B
>
375 void Position
<M
, P
, B
>::basicDropPiece(P
* piece
, const Point
& to
) {
377 m_board
[to
] = *piece
;
381 template <typename M
, typename P
, typename B
>
382 boost::shared_ptr
<P
> Position
<M
, P
, B
>::moveHint(const M
& move
) const {
383 if (move
.type() == M::Promotion
)
384 return boost::shared_ptr
<P
>(new Piece(m_turn
, move
.promotionType
));
386 return boost::shared_ptr
<P
>();
390 template <typename M
, typename P
, typename B
>
391 bool Position
<M
, P
, B
>::checkPromotionType(const M
& m
) const {
392 return (m
.promotionType
== KNIGHT
||
393 m
.promotionType
== BISHOP
||
394 m
.promotionType
== ROOK
||
395 m
.promotionType
== QUEEN
);
398 template <typename M
, typename P
, typename B
>
399 bool Position
<M
, P
, B
>::pseudolegal(M
& move
) const {
400 if (!move
.valid()) return false;
402 if (!valid(move
.from
)) return false;
403 if (!valid(move
.to
)) return false;
404 P piece
= m_board
[move
.from
];
406 Color thisTurn
= piece
.color();
407 Color otherTurn
= P::oppositeColor(thisTurn
);
408 if (piece
&& (turn() == thisTurn
)) {
409 move
.setType(piece
.canMove(*this, move
.from
, move
.to
));
411 if (move
.type() == M::Invalid
) return false;
413 if (move
.type() == M::Promotion
&& !checkPromotionType(move
))
416 if (move
.type() == M::KingSideCastling
) {
417 if (attacks(otherTurn
, move
.from
) ||
418 attacks(otherTurn
, move
.from
+ Point(1,0))) return false;
420 else if (move
.type() == M::QueenSideCastling
) {
421 if (attacks(otherTurn
, move
.from
) ||
422 attacks(otherTurn
, move
.from
+ Point(-1,0))) return false;
430 template <typename M
, typename P
, typename B
>
431 typename
P::Color Position
<M
, P
, B
>::moveTurn(const M
& move
) const {
432 P piece
= m_board
[move
.from
];
434 return piece
.color();
437 template <typename M
, typename P
, typename B
>
438 bool Position
<M
, P
, B
>::testMove(M
& move
) const {
440 if (move
.status
== M::Untested
) {
441 if (pseudolegal(move
)) {
442 Color turn
= moveTurn(move
);
445 std::auto_ptr
<Position
> tempPosition(clone());
446 tempPosition
->move(move
);
447 Point kingPos
= tempPosition
->findPiece(turn
, KING
);
449 if (kingPos
== Point::invalid())
450 move
.status
= M::Illegal
;
451 else if (tempPosition
->attacks(P::oppositeColor(turn
), kingPos
))
452 move
.status
= M::Illegal
;
454 move
.status
= M::Legal
;
457 move
.status
= M::Illegal
;
460 return move
.status
== M::Legal
;
463 template <typename M
, typename P
, typename B
>
464 M Position
<M
, P
, B
>::getMove(const AlgebraicNotation
& san
, bool& ok
) const {
465 M candidate
= M::invalid();
472 if (san
.castling
!= AlgebraicNotation::NoCastling
) {
473 Point from
= kingStartingPosition(turn());
474 Point to
= from
+ (san
.castling
== AlgebraicNotation::KingSide
? Point(2,0) : Point(-2,0));
475 P king
= m_board
[from
];
476 if (!(king
&& king
.type() == KING
)) {
486 if (san
.from
.valid()) {
487 candidate
= M(san
.from
, san
.to
);
490 for (Point i
= first(); i
<= last(); i
= next(i
)) {
492 M
mv(i
, san
.to
, static_cast<typename
P::Type
>(san
.promotion
));
493 if (i
.resembles(san
.from
) && p
&& p
.type() == san
.type
&& p
.color() == turn()
496 if (candidate
.valid()) {
498 return candidate
; // return the first matching move
505 ok
= candidate
.valid();
509 template <typename M, typename P, typename B>
510 M Position<M, P, B>::getMove(const QString& san, bool& ok) const {
511 return getMove(AlgebraicNotation(san), ok);
514 template <typename M
, typename P
, typename B
>
515 M Position
<M
, P
, B
>::getVerboseMove(Color turn
, const VerboseNotation
& m
) {
517 if (m
.castling
== AlgebraicNotation::NoCastling
) {
522 from
= kingStartingPosition(turn
);
523 to
= from
+ (m
.castling
== AlgebraicNotation::KingSide
? Point(2,0) : Point(-2, 0));
527 res
.promotionType
= static_cast<typename
P::Type
>(m
.promotion
);
532 template <typename M
, typename P
, typename B
>
533 Position
<M
, P
, B
>* Position
<M
, P
, B
>::legallyMove(M
& mv
) const {
535 Position
* res
= clone();
543 template <typename M
, typename P
, typename B
>
544 void Position
<M
, P
, B
>::fromFEN(const QString
& fen
, bool& ok
) {
547 QStringList data
= fen
.split(' ', QString::SkipEmptyParts
);
548 const int boardIndex
= 0;
549 const int turnIndex
= 1;
550 const int castlingIndex
= 2;
551 const int enPassantIndex
= 3;
554 QChar turn
= data
[turnIndex
][0].toLower();
557 else if (turn
== 'b')
561 for (int i
= 0; i
< data
[castlingIndex
].length(); i
++) {
562 QChar symbol
= data
[castlingIndex
][i
];
564 m_castleBlackKing
= true;
565 else if (symbol
== 'q')
566 m_castleBlackQueen
= true;
567 else if (symbol
== 'K')
568 m_castleWhiteKing
= true;
569 else if (symbol
== 'Q')
570 m_castleWhiteQueen
= true;
574 m_enPassantSquare
= Point(data
[enPassantIndex
], size().y
);
578 for (int index
= 0; index
< data
[boardIndex
].length(); index
++) {
579 QChar symbol
= data
[boardIndex
][index
];
581 cursor
= Point(0, cursor
.y
+ 1);
583 else if (symbol
.isDigit()) {
584 int k
= symbol
.toAscii() - '0';
588 if (!valid(cursor
)) return;
589 typename
P::Type type
= P::getType(symbol
);
590 if (type
== INVALID_TYPE
) return;
591 Color color
= symbol
.isUpper() ? WHITE
: BLACK
;
592 set(cursor
, P(color
, type
));
600 // adapted from Maurizio Monge's rattatechess
601 template <typename M
, typename P
, typename B
>
602 QString Position
<M
, P
, B
>::fen(int halfmove
, int fullmove
) const {
605 // add board information
607 for (int i
= 0; i
< 8; i
++) {
608 for (int j
= 0; j
< 8; j
++) {
609 Point p
= Point(j
, i
);
610 Piece pc
= m_board
[p
];
615 str
+= QString::number(cn
);
618 QString symbol
= P::typeSymbol(pc
.type());
619 if (pc
.color() == BLACK
)
620 symbol
= symbol
.toLower();
625 str
+= QString::number(cn
);
632 // add turn information
633 str
+= turn() == WHITE
? " w " : " b ";
635 // add castling information
636 QString castleString
;
637 if(m_castleWhiteKing
)
639 if(m_castleWhiteQueen
)
641 if(m_castleBlackKing
)
643 if(m_castleBlackQueen
)
645 if (castleString
== "") castleString
= "-";
646 str
+= castleString
+ " ";
648 // add en passant information
649 if (m_enPassantSquare
== Point::invalid())
652 str
+= m_enPassantSquare
.toString(size().y
);
655 // add move count information
656 str
+= QString::number(halfmove
) + " " + QString::number(fullmove
);
662 template <typename M
, typename P
, typename B
>
663 void Position
<M
, P
, B
>::dump() const {
664 for (Point i
= first(); i
<= last(); i
= next(i
)) {
666 std::cout
<< "+---+---+---+---+---+---+---+---+" << std::endl
;
668 Piece piece
= m_board
[i
];
671 symbol
= Piece::typeSymbol(piece
.type());
672 if (piece
.color() == BLACK
) symbol
= symbol
.toLower();
675 symbol
= ((i
.x
+ i
.y
) % 2 == 0) ? " " : ".";
677 std::cout
<< "| " << symbol
<< " ";
679 std::cout
<< "|" << std::endl
;
681 std::cout
<< "+---+---+---+---+---+---+---+---+" << std::endl
;
684 for(typename
Pool::const_iterator pi
= m_pool
.begin(); pi
!= m_pool
.end(); ++pi
) {
685 if(pi
->first
.color() == BLACK
)
686 std::cout
<< Piece::typeSymbol(pi
->first
.type()).toLower() <<": "<<pi
->second
<<std::endl
;
688 std::cout
<< Piece::typeSymbol(pi
->first
.type()) <<": "<<pi
->second
<<std::endl
;
693 template <typename M
, typename P
, typename B
>
694 void Position
<M
, P
, B
>::move(const M
& move
) {
695 P piece
= m_board
[move
.from
];
698 Color color
= piece
.color();
699 typename
P::Type type
= piece
.type();
701 executeCaptureOn(move
.to
);
702 basicMovePiece(move
);
704 if (move
.type() == M::EnPassantTrigger
)
705 m_enPassantSquare
= (move
.to
+ move
.from
) / 2;
707 m_enPassantSquare
= Point::invalid();
709 if (move
.type() == M::EnPassantCapture
) {
710 Point
phantom(move
.to
.x
, move
.from
.y
);
711 m_board
[phantom
] = Piece();
714 else if (move
.type() == M::Promotion
) {
715 typename
P::Type type
= move
.promotionType
;
716 m_board
[move
.to
] = P(piece
.color(), type
);
719 else if (move
.type() == M::KingSideCastling
) {
720 Point rookSquare
= move
.to
+ Point(1,0);
721 Point rookDestination
= move
.from
+ Point(1,0);
723 P rook
= m_board
[rookSquare
];
726 Q_ASSERT(rook
.type() == ROOK
);
729 basicMovePiece(M(rookSquare
, rookDestination
));
732 else if (move
.type() == M::QueenSideCastling
) {
733 Point rookSquare
= move
.to
- Point(2,0);
734 Point rookDestination
= move
.from
- Point(1,0);
736 P rook
= m_board
[rookSquare
];
739 Q_ASSERT(rook
.type() == ROOK
);
742 basicMovePiece(M(rookSquare
, rookDestination
));
747 if (color
== WHITE
) {
748 m_castleWhiteKing
= false;
749 m_castleWhiteQueen
= false;
752 m_castleBlackKing
= false;
753 m_castleBlackQueen
= false;
757 if (move
.from
== Point(0,0) || move
.to
== Point(0,0))
758 m_castleBlackQueen
= false;
759 else if (move
.from
== Point(7,0) || move
.to
== Point(7,0))
760 m_castleBlackKing
= false;
761 else if (move
.from
== Point(0,7) || move
.to
== Point(0,7))
762 m_castleWhiteQueen
= false;
763 else if (move
.from
== Point(7,7) || move
.to
== Point(7,7))
764 m_castleWhiteKing
= false;
769 template <typename M
, typename P
, typename B
>
770 void Position
<M
, P
, B
>::switchTurn() {
771 m_turn
= P::oppositeColor(turn());
774 template <typename M
, typename P
, typename B
>
775 void Position
<M
, P
, B
>::setTurn(Color turn
) {
779 template <typename M
, typename P
, typename B
>
780 bool Position
<M
, P
, B
>::testPremove(M premove
) const {
781 for (Point p
= first(); p
<= last(); p
= next(p
)) {
782 P piece
= m_board
[p
];
783 if (!piece
|| piece
.color() != turn()) continue;
784 for (Point q
= first(); q
<= last(); q
= next(q
)) {
786 if (testMove(move
)) {
787 Position
tempPosition(*this);
788 tempPosition
.move(move
);
790 if (tempPosition
.testMove(premove
)) return true;
798 template <typename M
, typename P
, typename B
>
799 bool Position
<M
, P
, B
>::attacks(Color color
, const Point
& destination
) const {
801 return attacks(color
, destination
, temp
);
804 template <typename M
, typename P
, typename B
>
805 bool Position
<M
, P
, B
>::attacks(Color color
, const Point
& destination
, Point
& source
) const {
806 for (Point p
= first(); p
<= last(); p
= next(p
)) {
807 P piece
= m_board
[p
];
808 if (piece
&& piece
.color() == color
&& piece
.canMove(*this, p
, destination
)) {
816 template <typename M
, typename P
, typename B
>
817 bool Position
<M
, P
, B
>::attacks(const Point
& destination
) const {
818 return attacks(turn(), destination
);
821 template <typename M
, typename P
, typename B
>
822 Point Position
<M
, P
, B
>::findPiece(Color color
, typename
P::Type type
) const {
823 for (int i
= 0; i
< 8; i
++)
824 for (int j
= 0; j
< 8; j
++) {
825 Point p
= Point(i
,j
);
826 P piece
= m_board
[p
];
827 if (piece
&& piece
.color() == color
&& piece
.type() == type
)
830 return Point::invalid();
833 template <typename M
, typename P
, typename B
>
834 boost::shared_ptr
<AbstractGenerator
<M
> >
835 Position
<M
, P
, B
>::createLegalGenerator() const {
836 return boost::shared_ptr
<AbstractGenerator
<M
> >(
837 new MoveGenerator
<Position
, LegalMove
<Position
> >(*this));
840 // template <typename M, typename P, typename B>
841 // boost::shared_ptr<AbstractGenerator<M> > createPseudoLegalGenerator() const {
842 // return boost::shared_ptr<AbstractGenerator<M> >(
843 // new MoveGenerator<Position, LegalMove<Position> >(*this));
846 template <typename M
, typename P
, typename B
>
847 bool Position
<M
, P
, B
>::stalled() const {
848 boost::shared_ptr
<AbstractGenerator
<M
> > generator
=
849 createLegalGenerator();
850 std::vector
<M
> mv
= generator
->generate();
851 return generator
->generate().size() == 0;
854 template <typename M, typename P, typename B>
855 bool Position<M, P, B>::pseudoStalled() const {
856 MoveGenerator<Position, PseudolegalMove<Position> > generator(*this);
857 return generator.generate().size() == 0;
860 template <typename M
, typename P
, typename B
>
861 bool Position
<M
, P
, B
>::check(Color turn
) const {
862 Point kingPosition
= findPiece(turn
, KING
);
863 if (kingPosition
== Point::invalid()) {
864 // a missing king is considered in check
868 return attacks(P::oppositeColor(turn
), kingPosition
);
871 template <typename M
, typename P
, typename B
>
872 bool Position
<M
, P
, B
>::check() const {
873 return check(turn());
876 template <typename M
, typename P
, typename B
>
877 typename Position
<M
, P
, B
>::State Position
<M
, P
, B
>::state() const {
878 if (!stalled()) return InPlay
;
881 return turn() == WHITE
? BlackWins
: WhiteWins
;