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
>
41 Position
<M
, P
, B
>* m_position
;
45 PoolRef(Position
<M
, P
, B
>* position
, int pool
)
46 : m_position(position
)
50 int insert(int idx
, const P
& p
);
55 template <typename M
, typename P
, typename B
>
58 friend class PoolRef
<M
, P
, B
>;
59 typedef std::map
<P
, int> Pool
;
62 typedef typename
P::Color Color
;
67 Point m_enPassantSquare
;
69 bool m_castleWhiteKing
: 1;
70 bool m_castleWhiteQueen
: 1;
71 bool m_castleBlackKing
: 1;
72 bool m_castleBlackQueen
: 1;
75 typedef PoolRef
<M
, P
, B
> PoolReference
;
80 Position(int = 8, int = 8);
81 Position(const OptList
& l
, int = 8, int = 8);
83 bool castleWhiteKing
, bool castleWhiteQueen
,
84 bool castleBlackKing
, bool castleBlackQueen
,
85 const Point
& enPassant
);
86 Position(const Position
<M
, P
, B
>&);
87 template <typename M1
, typename P1
, typename B1
>
88 Position(const Position
<M1
, P1
, B1
>&);
90 Point
size() const { return m_board
.getSize(); }
92 POLYMORPHIC_NEW(Position
, (), ())
93 POLYMORPHIC_NEW(Position
, (const Position
* other
), (*other
))
94 virtual Position
* clone() const { return new Position(*this); }
97 virtual QString
type() const { return "chess"; }
99 bool operator==(const Position
<M
, P
, B
>&) const;
100 bool operator!=(const Position
<M
, P
, B
>&) const;
102 virtual void setup();
104 void debugInfo() const;
106 virtual const Point
first() const { return m_board
.first(); }
107 virtual const Point
last() const { return m_board
.last(); }
108 virtual Point
next(const Point
& p
) const { return m_board
.next(p
); }
109 inline bool valid(const Point
& p
) const { return m_board
.valid(p
); }
111 PathInfo
path(const Point
&, const Point
&) const;
112 const Point
& enPassantSquare() const { return m_enPassantSquare
; }
114 virtual PoolRef
<M
,P
,B
> pool(int index
) { return PoolRef
<M
,P
,B
>(this, index
); }
116 virtual P
get(const Point
& p
) const {
117 return valid(p
) ? m_board
[p
] : P();
119 virtual P
operator[](const Point
& p
) const { return get(p
); }
120 inline void set(const Point
& p
, const P
& piece
) {
125 inline void removePiece(const Point
& p
) { set(p
, 0); }
126 inline void basicMovePiece(const M
&);
128 inline InteractionType
movable(const Point
& p
) const {
129 if(!valid(p
) || !m_board
[p
])
131 return m_board
[p
].color() == m_turn
? Moving
: Premoving
;
133 inline Color
turn() const { return m_turn
; }
134 inline Color
previousTurn() const { return Piece::oppositeColor(m_turn
); }
135 inline const B
& board() const { return m_board
; }
136 inline bool castleKing(Color color
) const { return color
== WHITE
? m_castleWhiteKing
: m_castleBlackKing
; }
137 inline bool castleQueen(Color color
) const { return color
== WHITE
? m_castleWhiteQueen
: m_castleBlackQueen
; }
139 virtual bool attacks(Color
, const Point
& destination
, Point
& source
) const;
140 virtual bool attacks(Color
, const Point
& destination
) const;
141 virtual bool attacks(const Point
& destination
) const;
143 Point
findPiece(Color
, typename
P::Type
) const;
144 virtual void switchTurn();
145 virtual void setTurn(Color turn
);
147 typename
P::Type
promotionType() const { return QUEEN
; }
149 virtual void move(const M
&);
150 virtual Position
<M
, P
, B
>* legallyMove(M
&) const;
151 void stepBack(const Position
<M
, P
, B
>* oldPosition
, const M
& move
);
152 virtual Color
moveTurn(const M
& move
) const;
153 virtual bool checkPromotionType(const M
&) const;
154 virtual bool pseudolegal(M
&) const;
155 virtual bool testMove(M
&) const;
156 virtual bool testPremove(M
) const;
158 virtual M
getMove(const AlgebraicNotation
& san
, bool& ok
) const;
159 // virtual M getMove(const QString& san, bool& ok) const;
160 static M
getVerboseMove(Color
, const VerboseNotation
& m
);
162 //FIXME: Those are really very chess dependent, make them virtual at least
163 static Point
kingStartingPosition(Color color
) { return color
== WHITE
? Point(4,7) : Point(4,0); }
165 inline M
kingCastleMove() const { return m_turn
== WHITE
?
166 M(Point(4, 7), Point(6, 7)) : M(Point(4,0), Point(6,0)); }
167 inline M
queenCastleMove() const { return m_turn
== WHITE
?
168 M(Point(4, 7), Point(2, 7)) : M(Point(4,0), Point(2,0)); }
177 virtual boost::shared_ptr
<AbstractGenerator
<M
> > createLegalGenerator() const;
178 virtual bool stalled() const;
179 // virtual bool pseudoStalled() const;
181 bool check(Color
) const;
183 virtual void basicDropPiece(P
* piece
, const Point
& to
);
184 virtual void executeCaptureOn(const Point
& point
);
186 boost::shared_ptr
<P
> moveHint(const M
&) const;
189 QString
fen(int, int) const;
190 void fromFEN(const QString
& fen
, bool&);
191 QStringList
borderCoords() const;
194 //typedef Position<ChessMove, ChessPiece, PieceGrid> ChessPosition;
195 std::ostream
& operator<<(std::ostream
& os
, const class GenericPosition
&);
199 #include "algebraicnotation.h"
201 template <typename M
, typename P
, typename B
>
202 int PoolRef
<M
, P
, B
>::size() {
206 template <typename M
, typename P
, typename B
>
207 int PoolRef
<M
, P
, B
>::insert(int idx
, const P
& p
) {
211 template <typename M
, typename P
, typename B
>
212 P PoolRef
<M
, P
, B
>::get(int idx
) {
216 template <typename M
, typename P
, typename B
>
217 P PoolRef
<M
, P
, B
>::take(int idx
) {
221 template <typename M
, typename P
, typename B
>
222 Position
<M
, P
, B
>::Position(int width
, int height
)
224 , m_board(width
, height
)
225 , m_enPassantSquare(Point::invalid())
226 , m_castleWhiteKing(true)
227 , m_castleWhiteQueen(true)
228 , m_castleBlackKing(true)
229 , m_castleBlackQueen(true) { }
231 template <typename M
, typename P
, typename B
>
232 Position
<M
, P
, B
>::Position(const OptList
&, int width
, int height
)
234 , m_board(width
, height
)
235 , m_enPassantSquare(Point::invalid())
236 , m_castleWhiteKing(true)
237 , m_castleWhiteQueen(true)
238 , m_castleBlackKing(true)
239 , m_castleBlackQueen(true) { }
241 template <typename M
, typename P
, typename B
>
242 Position
<M
, P
, B
>::Position(Color turn
, bool castleWhiteKing
,
243 bool castleWhiteQueen
,
244 bool castleBlackKing
,
245 bool castleBlackQueen
,
246 const Point
& enPassant
)
249 , m_enPassantSquare(enPassant
)
250 , m_castleWhiteKing(castleWhiteKing
)
251 , m_castleWhiteQueen(castleWhiteQueen
)
252 , m_castleBlackKing(castleBlackKing
)
253 , m_castleBlackQueen(castleBlackQueen
) { }
255 template <typename M
, typename P
, typename B
>
256 Position
<M
, P
, B
>::Position(const Position
<M
, P
, B
>& other
)
257 : m_turn(other
.m_turn
)
258 , m_board(other
.m_board
)
259 , m_pool(other
.m_pool
)
260 , m_enPassantSquare(other
.m_enPassantSquare
)
261 , m_castleWhiteKing(other
.m_castleWhiteKing
)
262 , m_castleWhiteQueen(other
.m_castleWhiteQueen
)
263 , m_castleBlackKing(other
.m_castleBlackKing
)
264 , m_castleBlackQueen(other
.m_castleBlackQueen
) { }
266 template <typename M
, typename P
, typename B
>
267 template <typename M1
, typename P1
, typename B1
>
268 Position
<M
, P
, B
>::Position(const Position
<M1
, P1
, B1
>& other
)
269 : m_turn(other
.turn())
270 , m_board(other
.board())
271 , m_enPassantSquare(other
.enPassantSquare())
272 , m_castleWhiteKing(other
.castleKing(WHITE
))
273 , m_castleWhiteQueen(other
.castleQueen(WHITE
))
274 , m_castleBlackKing(other
.castleKing(BLACK
))
275 , m_castleBlackQueen(other
.castleQueen(BLACK
)) { }
278 template <typename M
, typename P
, typename B
>
279 Position
<M
, P
, B
>::~Position() {
283 template <typename M
, typename P
, typename B
>
284 QStringList Position
<M
, P
, B
>::borderCoords() const
287 Point p
= m_board
.getSize();
288 for(int i
=0; i
<p
.x
; i
++)
289 retv
<< QChar('a'+i
);
290 for(int i
=1; i
<=p
.y
; i
++)
291 retv
+= QString::number(i
);
295 template <typename M
, typename P
, typename B
>
296 bool Position
<M
, P
, B
>::operator==(const Position
<M
, P
, B
>& other
) const {
298 std::cout
<< "turn: " << m_turn
<< " " << other
.m_turn
<< std::endl
;
299 std::cout
<< "ep: " << m_enPassantSquare
<< " " << other
.m_enPassantSquare
<< std::endl
;
300 std::cout
<< "wk: " << m_castleWhiteKing
<< " " << other
.m_castleWhiteKing
<< std::endl
;
301 std::cout
<< "wq: " << m_castleWhiteQueen
<< " " << other
.m_castleWhiteQueen
<< std::endl
;
302 std::cout
<< "bk: " << m_castleBlackKing
<< " " << other
.m_castleBlackKing
<< std::endl
;
303 std::cout
<< "bq: " << m_castleBlackQueen
<< " " << other
.m_castleBlackQueen
<< std::endl
;
304 if (m_turn
!= other
.m_turn
) {
305 std::cout
<< "turns differ" << std::endl
;
308 if (!(m_board
== other
.m_board
)) {
309 std::cout
<< "boards differ" << std::endl
;
312 if (m_castleWhiteKing
!= other
.m_castleWhiteKing
) {
313 std::cout
<< "wk differ" << std::endl
;
316 if (m_castleWhiteQueen
!= other
.m_castleWhiteQueen
) {
317 std::cout
<< "wq differ" << std::endl
;
320 if (m_castleBlackKing
!= other
.m_castleBlackKing
) {
321 std::cout
<< "bk differ" << std::endl
;
324 if (m_castleBlackQueen
!= other
.m_castleBlackQueen
) {
325 std::cout
<< "bq differ" << std::endl
;
328 std::cout
<< "equal" << std::endl
;
331 return m_turn
== other
.m_turn
&&
332 m_board
== other
.m_board
&&
333 m_enPassantSquare
== other
.m_enPassantSquare
&&
334 m_castleWhiteKing
== other
.m_castleWhiteKing
&&
335 m_castleWhiteQueen
== other
.m_castleWhiteQueen
&&
336 m_castleBlackKing
== other
.m_castleBlackKing
&&
337 m_castleBlackQueen
== other
.m_castleBlackQueen
;
341 template <typename M
, typename P
, typename B
>
342 bool Position
<M
, P
, B
>::operator!=(const Position
& other
) const {
343 return !(*this == other
);
346 template <typename M
, typename P
, typename B
>
347 void Position
<M
, P
, B
>::debugInfo() const {
349 std::cout
<< "board = " << &m_board
<< std::endl
;
353 #define SET_PIECE(i,j, color, type) m_board[Point(i,j)] = P(color, type)
354 template <typename M
, typename P
, typename B
>
355 void Position
<M
, P
, B
>::setup() {
356 for (int i
= 0; i
< 8; i
++) {
357 SET_PIECE(i
, 1, BLACK
, PAWN
);
358 SET_PIECE(i
, 6, WHITE
, PAWN
);
361 SET_PIECE(0,0, BLACK
, ROOK
);
362 SET_PIECE(1,0, BLACK
, KNIGHT
);
363 SET_PIECE(2,0, BLACK
, BISHOP
);
364 SET_PIECE(3,0, BLACK
, QUEEN
);
365 SET_PIECE(4,0, BLACK
, KING
);
366 SET_PIECE(5,0, BLACK
, BISHOP
);
367 SET_PIECE(6,0, BLACK
, KNIGHT
);
368 SET_PIECE(7,0, BLACK
, ROOK
);
370 SET_PIECE(0,7, WHITE
, ROOK
);
371 SET_PIECE(1,7, WHITE
, KNIGHT
);
372 SET_PIECE(2,7, WHITE
, BISHOP
);
373 SET_PIECE(3,7, WHITE
, QUEEN
);
374 SET_PIECE(4,7, WHITE
, KING
);
375 SET_PIECE(5,7, WHITE
, BISHOP
);
376 SET_PIECE(6,7, WHITE
, KNIGHT
);
377 SET_PIECE(7,7, WHITE
, ROOK
);
380 m_enPassantSquare
= Point::invalid();
381 m_castleWhiteKing
= true;
382 m_castleWhiteQueen
= true;
383 m_castleBlackKing
= true;
384 m_castleBlackQueen
= true;
388 template <typename M
, typename P
, typename B
>
389 PathInfo Position
<M
, P
, B
>::path(const Point
& from
, const Point
& to
) const {
390 return m_board
.path(from
, to
);
393 template <typename M, typename P, typename B>
394 void Position<M, P, B>::movePiece(const M& move) {
395 executeCaptureOn(move.to);
396 basicMovePiece(move);
400 template <typename M
, typename P
, typename B
>
401 void Position
<M
, P
, B
>::executeCaptureOn(const Point
& point
) {
402 m_board
[point
] = Piece();
405 template <typename M
, typename P
, typename B
>
406 void Position
<M
, P
, B
>::basicMovePiece(const M
& move
) {
407 P p
= m_board
[move
.from
];
410 m_board
[move
.to
] = p
;
411 m_board
[move
.from
] = Piece();
414 template <typename M
, typename P
, typename B
>
415 void Position
<M
, P
, B
>::basicDropPiece(P
* piece
, const Point
& to
) {
417 m_board
[to
] = *piece
;
421 template <typename M
, typename P
, typename B
>
422 boost::shared_ptr
<P
> Position
<M
, P
, B
>::moveHint(const M
& move
) const {
423 if (move
.type() == M::Promotion
)
424 return boost::shared_ptr
<P
>(new Piece(m_turn
, move
.promotionType
));
426 return boost::shared_ptr
<P
>();
430 template <typename M
, typename P
, typename B
>
431 bool Position
<M
, P
, B
>::checkPromotionType(const M
& m
) const {
432 return (m
.promotionType
== KNIGHT
||
433 m
.promotionType
== BISHOP
||
434 m
.promotionType
== ROOK
||
435 m
.promotionType
== QUEEN
);
438 template <typename M
, typename P
, typename B
>
439 bool Position
<M
, P
, B
>::pseudolegal(M
& move
) const {
440 if (!move
.valid()) return false;
442 if (!valid(move
.from
)) return false;
443 if (!valid(move
.to
)) return false;
444 P piece
= m_board
[move
.from
];
446 Color thisTurn
= piece
.color();
447 Color otherTurn
= P::oppositeColor(thisTurn
);
448 if (piece
&& (turn() == thisTurn
)) {
449 move
.setType(piece
.canMove(*this, move
.from
, move
.to
));
451 if (move
.type() == M::Invalid
) return false;
453 if (move
.type() == M::Promotion
&& !checkPromotionType(move
))
456 if (move
.type() == M::KingSideCastling
) {
457 if (attacks(otherTurn
, move
.from
) ||
458 attacks(otherTurn
, move
.from
+ Point(1,0))) return false;
460 else if (move
.type() == M::QueenSideCastling
) {
461 if (attacks(otherTurn
, move
.from
) ||
462 attacks(otherTurn
, move
.from
+ Point(-1,0))) return false;
470 template <typename M
, typename P
, typename B
>
471 typename
P::Color Position
<M
, P
, B
>::moveTurn(const M
& move
) const {
472 P piece
= m_board
[move
.from
];
474 return piece
.color();
477 template <typename M
, typename P
, typename B
>
478 bool Position
<M
, P
, B
>::testMove(M
& move
) const {
480 if (move
.status
== M::Untested
) {
481 if (pseudolegal(move
)) {
482 Color turn
= moveTurn(move
);
485 std::auto_ptr
<Position
> tempPosition(clone());
486 tempPosition
->move(move
);
487 Point kingPos
= tempPosition
->findPiece(turn
, KING
);
489 if (kingPos
== Point::invalid())
490 move
.status
= M::Illegal
;
491 else if (tempPosition
->attacks(P::oppositeColor(turn
), kingPos
))
492 move
.status
= M::Illegal
;
494 move
.status
= M::Legal
;
497 move
.status
= M::Illegal
;
500 return move
.status
== M::Legal
;
503 template <typename M
, typename P
, typename B
>
504 M Position
<M
, P
, B
>::getMove(const AlgebraicNotation
& san
, bool& ok
) const {
505 M candidate
= M::invalid();
512 if (san
.castling
!= AlgebraicNotation::NoCastling
) {
513 Point from
= kingStartingPosition(turn());
514 Point to
= from
+ (san
.castling
== AlgebraicNotation::KingSide
? Point(2,0) : Point(-2,0));
515 P king
= m_board
[from
];
516 if (!(king
&& king
.type() == KING
)) {
526 if (san
.from
.valid()) {
527 candidate
= M(san
.from
, san
.to
);
530 for (Point i
= first(); i
<= last(); i
= next(i
)) {
532 M
mv(i
, san
.to
, static_cast<typename
P::Type
>(san
.promotion
));
533 if (i
.resembles(san
.from
) && p
&& p
.type() == san
.type
&& p
.color() == turn()
536 if (candidate
.valid()) {
538 return candidate
; // return the first matching move
545 ok
= candidate
.valid();
549 template <typename M, typename P, typename B>
550 M Position<M, P, B>::getMove(const QString& san, bool& ok) const {
551 return getMove(AlgebraicNotation(san), ok);
554 template <typename M
, typename P
, typename B
>
555 M Position
<M
, P
, B
>::getVerboseMove(Color turn
, const VerboseNotation
& m
) {
557 if (m
.castling
== AlgebraicNotation::NoCastling
) {
562 from
= kingStartingPosition(turn
);
563 to
= from
+ (m
.castling
== AlgebraicNotation::KingSide
? Point(2,0) : Point(-2, 0));
567 res
.promotionType
= static_cast<typename
P::Type
>(m
.promotion
);
572 template <typename M
, typename P
, typename B
>
573 Position
<M
, P
, B
>* Position
<M
, P
, B
>::legallyMove(M
& mv
) const {
575 Position
* res
= clone();
583 template <typename M
, typename P
, typename B
>
584 void Position
<M
, P
, B
>::fromFEN(const QString
& fen
, bool& ok
) {
587 QStringList data
= fen
.split(' ', QString::SkipEmptyParts
);
588 const int boardIndex
= 0;
589 const int turnIndex
= 1;
590 const int castlingIndex
= 2;
591 const int enPassantIndex
= 3;
594 QChar turn
= data
[turnIndex
][0].toLower();
597 else if (turn
== 'b')
601 for (int i
= 0; i
< data
[castlingIndex
].length(); i
++) {
602 QChar symbol
= data
[castlingIndex
][i
];
604 m_castleBlackKing
= true;
605 else if (symbol
== 'q')
606 m_castleBlackQueen
= true;
607 else if (symbol
== 'K')
608 m_castleWhiteKing
= true;
609 else if (symbol
== 'Q')
610 m_castleWhiteQueen
= true;
614 m_enPassantSquare
= Point(data
[enPassantIndex
], size().y
);
618 for (int index
= 0; index
< data
[boardIndex
].length(); index
++) {
619 QChar symbol
= data
[boardIndex
][index
];
621 cursor
= Point(0, cursor
.y
+ 1);
623 else if (symbol
.isDigit()) {
624 int k
= symbol
.toAscii() - '0';
628 if (!valid(cursor
)) return;
629 typename
P::Type type
= P::getType(symbol
);
630 if (type
== INVALID_TYPE
) return;
631 Color color
= symbol
.isUpper() ? WHITE
: BLACK
;
632 set(cursor
, P(color
, type
));
640 // adapted from Maurizio Monge's rattatechess
641 template <typename M
, typename P
, typename B
>
642 QString Position
<M
, P
, B
>::fen(int halfmove
, int fullmove
) const {
645 // add board information
647 for (int i
= 0; i
< 8; i
++) {
648 for (int j
= 0; j
< 8; j
++) {
649 Point p
= Point(j
, i
);
650 Piece pc
= m_board
[p
];
655 str
+= QString::number(cn
);
658 QString symbol
= P::typeSymbol(pc
.type());
659 if (pc
.color() == BLACK
)
660 symbol
= symbol
.toLower();
665 str
+= QString::number(cn
);
672 // add turn information
673 str
+= turn() == WHITE
? " w " : " b ";
675 // add castling information
676 QString castleString
;
677 if(m_castleWhiteKing
)
679 if(m_castleWhiteQueen
)
681 if(m_castleBlackKing
)
683 if(m_castleBlackQueen
)
685 if (castleString
== "") castleString
= "-";
686 str
+= castleString
+ " ";
688 // add en passant information
689 if (m_enPassantSquare
== Point::invalid())
692 str
+= m_enPassantSquare
.toString(size().y
);
695 // add move count information
696 str
+= QString::number(halfmove
) + " " + QString::number(fullmove
);
702 template <typename M
, typename P
, typename B
>
703 void Position
<M
, P
, B
>::dump() const {
704 for (Point i
= first(); i
<= last(); i
= next(i
)) {
706 std::cout
<< "+---+---+---+---+---+---+---+---+" << std::endl
;
708 Piece piece
= m_board
[i
];
711 symbol
= Piece::typeSymbol(piece
.type());
712 if (piece
.color() == BLACK
) symbol
= symbol
.toLower();
715 symbol
= ((i
.x
+ i
.y
) % 2 == 0) ? " " : ".";
717 std::cout
<< "| " << symbol
<< " ";
719 std::cout
<< "|" << std::endl
;
721 std::cout
<< "+---+---+---+---+---+---+---+---+" << std::endl
;
723 for(typename
Pool::const_iterator pi
= m_pool
.begin(); pi
!= m_pool
.end(); ++pi
) {
724 if(pi
->first
.color() == BLACK
)
725 std::cout
<< Piece::typeSymbol(pi
->first
.type()).toLower() <<": "<<pi
->second
<<std::endl
;
727 std::cout
<< Piece::typeSymbol(pi
->first
.type()) <<": "<<pi
->second
<<std::endl
;
731 template <typename M
, typename P
, typename B
>
732 void Position
<M
, P
, B
>::move(const M
& move
) {
733 P piece
= m_board
[move
.from
];
736 Color color
= piece
.color();
737 typename
P::Type type
= piece
.type();
739 executeCaptureOn(move
.to
);
740 basicMovePiece(move
);
742 if (move
.type() == M::EnPassantTrigger
)
743 m_enPassantSquare
= (move
.to
+ move
.from
) / 2;
745 m_enPassantSquare
= Point::invalid();
747 if (move
.type() == M::EnPassantCapture
) {
748 Point
phantom(move
.to
.x
, move
.from
.y
);
749 m_board
[phantom
] = Piece();
752 else if (move
.type() == M::Promotion
) {
753 typename
P::Type type
= move
.promotionType
;
754 m_board
[move
.to
] = P(piece
.color(), type
);
757 else if (move
.type() == M::KingSideCastling
) {
758 Point rookSquare
= move
.to
+ Point(1,0);
759 Point rookDestination
= move
.from
+ Point(1,0);
761 P rook
= m_board
[rookSquare
];
764 Q_ASSERT(rook
.type() == ROOK
);
767 basicMovePiece(M(rookSquare
, rookDestination
));
770 else if (move
.type() == M::QueenSideCastling
) {
771 Point rookSquare
= move
.to
- Point(2,0);
772 Point rookDestination
= move
.from
- Point(1,0);
774 P rook
= m_board
[rookSquare
];
777 Q_ASSERT(rook
.type() == ROOK
);
780 basicMovePiece(M(rookSquare
, rookDestination
));
785 if (color
== WHITE
) {
786 m_castleWhiteKing
= false;
787 m_castleWhiteQueen
= false;
790 m_castleBlackKing
= false;
791 m_castleBlackQueen
= false;
795 if (move
.from
== Point(0,0) || move
.to
== Point(0,0))
796 m_castleBlackQueen
= false;
797 else if (move
.from
== Point(7,0) || move
.to
== Point(7,0))
798 m_castleBlackKing
= false;
799 else if (move
.from
== Point(0,7) || move
.to
== Point(0,7))
800 m_castleWhiteQueen
= false;
801 else if (move
.from
== Point(7,7) || move
.to
== Point(7,7))
802 m_castleWhiteKing
= false;
807 template <typename M
, typename P
, typename B
>
808 void Position
<M
, P
, B
>::switchTurn() {
809 m_turn
= P::oppositeColor(turn());
812 template <typename M
, typename P
, typename B
>
813 void Position
<M
, P
, B
>::setTurn(Color turn
) {
817 template <typename M
, typename P
, typename B
>
818 bool Position
<M
, P
, B
>::testPremove(M premove
) const {
819 for (Point p
= first(); p
<= last(); p
= next(p
)) {
820 P piece
= m_board
[p
];
821 if (!piece
|| piece
.color() != turn()) continue;
822 for (Point q
= first(); q
<= last(); q
= next(q
)) {
824 if (testMove(move
)) {
825 Position
tempPosition(*this);
826 tempPosition
.move(move
);
828 if (tempPosition
.testMove(premove
)) return true;
836 template <typename M
, typename P
, typename B
>
837 bool Position
<M
, P
, B
>::attacks(Color color
, const Point
& destination
) const {
839 return attacks(color
, destination
, temp
);
842 template <typename M
, typename P
, typename B
>
843 bool Position
<M
, P
, B
>::attacks(Color color
, const Point
& destination
, Point
& source
) const {
844 for (Point p
= first(); p
<= last(); p
= next(p
)) {
845 P piece
= m_board
[p
];
846 if (piece
&& piece
.color() == color
&& piece
.canMove(*this, p
, destination
)) {
854 template <typename M
, typename P
, typename B
>
855 bool Position
<M
, P
, B
>::attacks(const Point
& destination
) const {
856 return attacks(turn(), destination
);
859 template <typename M
, typename P
, typename B
>
860 Point Position
<M
, P
, B
>::findPiece(Color color
, typename
P::Type type
) const {
861 for (int i
= 0; i
< 8; i
++)
862 for (int j
= 0; j
< 8; j
++) {
863 Point p
= Point(i
,j
);
864 P piece
= m_board
[p
];
865 if (piece
&& piece
.color() == color
&& piece
.type() == type
)
868 return Point::invalid();
871 template <typename M
, typename P
, typename B
>
872 boost::shared_ptr
<AbstractGenerator
<M
> >
873 Position
<M
, P
, B
>::createLegalGenerator() const {
874 return boost::shared_ptr
<AbstractGenerator
<M
> >(
875 new MoveGenerator
<Position
, LegalMove
<Position
> >(*this));
878 // template <typename M, typename P, typename B>
879 // boost::shared_ptr<AbstractGenerator<M> > createPseudoLegalGenerator() const {
880 // return boost::shared_ptr<AbstractGenerator<M> >(
881 // new MoveGenerator<Position, LegalMove<Position> >(*this));
884 template <typename M
, typename P
, typename B
>
885 bool Position
<M
, P
, B
>::stalled() const {
886 boost::shared_ptr
<AbstractGenerator
<M
> > generator
=
887 createLegalGenerator();
888 std::vector
<M
> mv
= generator
->generate();
889 return generator
->generate().size() == 0;
892 template <typename M, typename P, typename B>
893 bool Position<M, P, B>::pseudoStalled() const {
894 MoveGenerator<Position, PseudolegalMove<Position> > generator(*this);
895 return generator.generate().size() == 0;
898 template <typename M
, typename P
, typename B
>
899 bool Position
<M
, P
, B
>::check(Color turn
) const {
900 Point kingPosition
= findPiece(turn
, KING
);
901 if (kingPosition
== Point::invalid()) {
902 // a missing king is considered in check
906 return attacks(P::oppositeColor(turn
), kingPosition
);
909 template <typename M
, typename P
, typename B
>
910 bool Position
<M
, P
, B
>::check() const {
911 return check(turn());
914 template <typename M
, typename P
, typename B
>
915 typename Position
<M
, P
, B
>::State Position
<M
, P
, B
>::state() const {
916 if (!stalled()) return InPlay
;
919 return turn() == WHITE
? BlackWins
: WhiteWins
;