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"
28 #include "variants/xchess/generator.h"
29 #include "variants/xchess/piecetype.h"
31 class AlgebraicNotation
;
32 class VerboseNotation
;
34 #define POLYMORPHIC_NEW(type, argsdecl, args) \
35 virtual type* _new argsdecl const { return new type args; }
37 template <typename M
, typename P
, typename B
>
40 template <typename M
, typename P
, typename B
>
43 typedef typename
P::Type Type
;
44 typedef typename
P::Color Color
;
49 Point m_enPassantSquare
;
51 bool m_castleWhiteKing
: 1;
52 bool m_castleWhiteQueen
: 1;
53 bool m_castleBlackKing
: 1;
54 bool m_castleBlackQueen
: 1;
61 Position(int = 8, int = 8);
62 Position(const OptList
& l
, int = 8, int = 8);
64 bool castleWhiteKing
, bool castleWhiteQueen
,
65 bool castleBlackKing
, bool castleBlackQueen
,
66 const Point
& enPassant
);
67 Position(const Position
<M
, P
, B
>&);
68 template <typename M1
, typename P1
, typename B1
>
69 Position(const Position
<M1
, P1
, B1
>&);
71 Point
size() const { return m_board
.getSize(); }
73 POLYMORPHIC_NEW(Position
, (), ())
74 POLYMORPHIC_NEW(Position
, (const Position
* other
), (*other
))
75 virtual Position
* clone() const { return new Position(*this); }
78 virtual QString
type() const { return "chess"; }
80 bool operator==(const Position
<M
, P
, B
>&) const;
81 bool operator!=(const Position
<M
, P
, B
>&) const;
85 void debugInfo() const;
87 virtual const Point
first() const { return m_board
.first(); }
88 virtual const Point
last() const { return m_board
.last(); }
89 virtual Point
next(const Point
& p
) const { return m_board
.next(p
); }
90 inline bool valid(const Point
& p
) const { return m_board
.valid(p
); }
92 PathInfo
path(const Point
&, const Point
&) const;
93 const Point
& enPassantSquare() const { return m_enPassantSquare
; }
95 virtual P
get(const Point
& p
) const {
96 return valid(p
) ? m_board
[p
] : P();
98 virtual P
operator[](const Point
& p
) const { return get(p
); }
99 inline void set(const Point
& p
, const P
& piece
) {
104 inline void removePiece(const Point
& p
) { set(p
, 0); }
105 inline void basicMovePiece(const M
&);
107 inline InteractionType
movable(const TurnTest
& test
, const Point
& p
) const {
108 if (!valid(p
) || !m_board
[p
] || !test(m_turn
))
111 return m_board
[p
].color() == m_turn
? Moving
: Premoving
;
113 inline InteractionType
droppable(const TurnTest
& test
, int p
) const {
117 Color c
= static_cast<Color
>(p
);
118 return c
== m_turn
? Moving
: Premoving
;
120 inline Color
turn() const { return m_turn
; }
121 inline Color
previousTurn() const { return Piece::oppositeColor(m_turn
); }
122 inline const B
& board() const { return m_board
; }
123 inline bool castleKing(Color color
) const { return color
== WHITE
? m_castleWhiteKing
: m_castleBlackKing
; }
124 inline bool castleQueen(Color color
) const { return color
== WHITE
? m_castleWhiteQueen
: m_castleBlackQueen
; }
126 virtual bool attacks(Color
, const Point
& destination
, Point
& source
) const;
127 virtual bool attacks(Color
, const Point
& destination
) const;
128 virtual bool attacks(const Point
& destination
) const;
130 Point
findPiece(Color
, typename
P::Type
) const;
131 virtual void switchTurn();
132 virtual void setTurn(Color turn
);
134 typename
P::Type
promotionType() const { return QUEEN
; }
136 virtual void move(const M
&);
137 virtual Position
<M
, P
, B
>* legallyMove(M
&) const;
138 void stepBack(const Position
<M
, P
, B
>* oldPosition
, const M
& move
);
139 virtual Color
moveTurn(const M
& move
) const;
140 virtual bool checkPromotionType(const M
&) const;
141 virtual bool pseudolegal(M
&) const;
142 virtual bool testMove(M
&) const;
143 virtual bool testPremove(M
) const;
145 virtual M
getMove(const AlgebraicNotation
& san
, bool& ok
) const;
146 // virtual M getMove(const QString& san, bool& ok) const;
147 static M
getVerboseMove(Color
, const VerboseNotation
& m
);
149 //FIXME: Those are really very chess dependent, make them virtual at least
150 static Point
kingStartingPosition(Color color
) { return color
== WHITE
? Point(4,7) : Point(4,0); }
152 inline M
kingCastleMove() const { return m_turn
== WHITE
?
153 M(Point(4, 7), Point(6, 7)) : M(Point(4,0), Point(6,0)); }
154 inline M
queenCastleMove() const { return m_turn
== WHITE
?
155 M(Point(4, 7), Point(2, 7)) : M(Point(4,0), Point(2,0)); }
164 virtual boost::shared_ptr
<AbstractGenerator
<M
> > createLegalGenerator() const;
165 virtual bool stalled() const;
166 // virtual bool pseudoStalled() const;
168 bool check(Color
) const;
170 virtual void basicDropPiece(P
* piece
, const Point
& to
);
171 virtual void executeCaptureOn(const Point
& point
);
173 boost::shared_ptr
<P
> moveHint(const M
&) const;
176 QString
fen(int, int) const;
177 void fromFEN(const QString
& fen
, bool&);
178 QStringList
borderCoords() const;
181 std::ostream
& operator<<(std::ostream
& os
, const class GenericPosition
&);
185 #include "algebraicnotation.h"
187 template <typename M
, typename P
, typename B
>
188 Position
<M
, P
, B
>::Position(int width
, int height
)
190 , m_board(width
, height
)
191 , m_enPassantSquare(Point::invalid())
192 , m_castleWhiteKing(true)
193 , m_castleWhiteQueen(true)
194 , m_castleBlackKing(true)
195 , m_castleBlackQueen(true) { }
197 template <typename M
, typename P
, typename B
>
198 Position
<M
, P
, B
>::Position(const OptList
&, int width
, int height
)
200 , m_board(width
, height
)
201 , m_enPassantSquare(Point::invalid())
202 , m_castleWhiteKing(true)
203 , m_castleWhiteQueen(true)
204 , m_castleBlackKing(true)
205 , m_castleBlackQueen(true) { }
207 template <typename M
, typename P
, typename B
>
208 Position
<M
, P
, B
>::Position(Color turn
, bool castleWhiteKing
,
209 bool castleWhiteQueen
,
210 bool castleBlackKing
,
211 bool castleBlackQueen
,
212 const Point
& enPassant
)
215 , m_enPassantSquare(enPassant
)
216 , m_castleWhiteKing(castleWhiteKing
)
217 , m_castleWhiteQueen(castleWhiteQueen
)
218 , m_castleBlackKing(castleBlackKing
)
219 , m_castleBlackQueen(castleBlackQueen
) { }
221 template <typename M
, typename P
, typename B
>
222 Position
<M
, P
, B
>::Position(const Position
<M
, P
, B
>& other
)
223 : m_turn(other
.m_turn
)
224 , m_board(other
.m_board
)
225 , m_enPassantSquare(other
.m_enPassantSquare
)
226 , m_castleWhiteKing(other
.m_castleWhiteKing
)
227 , m_castleWhiteQueen(other
.m_castleWhiteQueen
)
228 , m_castleBlackKing(other
.m_castleBlackKing
)
229 , m_castleBlackQueen(other
.m_castleBlackQueen
) { }
231 template <typename M
, typename P
, typename B
>
232 template <typename M1
, typename P1
, typename B1
>
233 Position
<M
, P
, B
>::Position(const Position
<M1
, P1
, B1
>& other
)
234 : m_turn(other
.turn())
235 , m_board(other
.board())
236 , m_enPassantSquare(other
.enPassantSquare())
237 , m_castleWhiteKing(other
.castleKing(WHITE
))
238 , m_castleWhiteQueen(other
.castleQueen(WHITE
))
239 , m_castleBlackKing(other
.castleKing(BLACK
))
240 , m_castleBlackQueen(other
.castleQueen(BLACK
)) { }
243 template <typename M
, typename P
, typename B
>
244 Position
<M
, P
, B
>::~Position() {
248 template <typename M
, typename P
, typename B
>
249 QStringList Position
<M
, P
, B
>::borderCoords() const
252 Point p
= m_board
.getSize();
253 for(int i
=0; i
<p
.x
; i
++)
254 retv
<< QChar('a'+i
);
255 for(int i
=1; i
<=p
.y
; i
++)
256 retv
+= QString::number(i
);
260 template <typename M
, typename P
, typename B
>
261 bool Position
<M
, P
, B
>::operator==(const Position
<M
, P
, B
>& other
) const {
263 std::cout
<< "turn: " << m_turn
<< " " << other
.m_turn
<< std::endl
;
264 std::cout
<< "ep: " << m_enPassantSquare
<< " " << other
.m_enPassantSquare
<< std::endl
;
265 std::cout
<< "wk: " << m_castleWhiteKing
<< " " << other
.m_castleWhiteKing
<< std::endl
;
266 std::cout
<< "wq: " << m_castleWhiteQueen
<< " " << other
.m_castleWhiteQueen
<< std::endl
;
267 std::cout
<< "bk: " << m_castleBlackKing
<< " " << other
.m_castleBlackKing
<< std::endl
;
268 std::cout
<< "bq: " << m_castleBlackQueen
<< " " << other
.m_castleBlackQueen
<< std::endl
;
269 if (m_turn
!= other
.m_turn
) {
270 std::cout
<< "turns differ" << std::endl
;
273 if (!(m_board
== other
.m_board
)) {
274 std::cout
<< "boards differ" << std::endl
;
277 if (m_castleWhiteKing
!= other
.m_castleWhiteKing
) {
278 std::cout
<< "wk differ" << std::endl
;
281 if (m_castleWhiteQueen
!= other
.m_castleWhiteQueen
) {
282 std::cout
<< "wq differ" << std::endl
;
285 if (m_castleBlackKing
!= other
.m_castleBlackKing
) {
286 std::cout
<< "bk differ" << std::endl
;
289 if (m_castleBlackQueen
!= other
.m_castleBlackQueen
) {
290 std::cout
<< "bq differ" << std::endl
;
293 std::cout
<< "equal" << std::endl
;
296 return m_turn
== other
.m_turn
&&
297 m_board
== other
.m_board
&&
298 m_enPassantSquare
== other
.m_enPassantSquare
&&
299 m_castleWhiteKing
== other
.m_castleWhiteKing
&&
300 m_castleWhiteQueen
== other
.m_castleWhiteQueen
&&
301 m_castleBlackKing
== other
.m_castleBlackKing
&&
302 m_castleBlackQueen
== other
.m_castleBlackQueen
;
306 template <typename M
, typename P
, typename B
>
307 bool Position
<M
, P
, B
>::operator!=(const Position
& other
) const {
308 return !(*this == other
);
311 template <typename M
, typename P
, typename B
>
312 void Position
<M
, P
, B
>::debugInfo() const {
314 std::cout
<< "board = " << &m_board
<< std::endl
;
318 #define SET_PIECE(i,j, color, type) m_board[Point(i,j)] = P(color, type)
319 template <typename M
, typename P
, typename B
>
320 void Position
<M
, P
, B
>::setup() {
321 for (int i
= 0; i
< 8; i
++) {
322 SET_PIECE(i
, 1, BLACK
, PAWN
);
323 SET_PIECE(i
, 6, WHITE
, PAWN
);
326 SET_PIECE(0,0, BLACK
, ROOK
);
327 SET_PIECE(1,0, BLACK
, KNIGHT
);
328 SET_PIECE(2,0, BLACK
, BISHOP
);
329 SET_PIECE(3,0, BLACK
, QUEEN
);
330 SET_PIECE(4,0, BLACK
, KING
);
331 SET_PIECE(5,0, BLACK
, BISHOP
);
332 SET_PIECE(6,0, BLACK
, KNIGHT
);
333 SET_PIECE(7,0, BLACK
, ROOK
);
335 SET_PIECE(0,7, WHITE
, ROOK
);
336 SET_PIECE(1,7, WHITE
, KNIGHT
);
337 SET_PIECE(2,7, WHITE
, BISHOP
);
338 SET_PIECE(3,7, WHITE
, QUEEN
);
339 SET_PIECE(4,7, WHITE
, KING
);
340 SET_PIECE(5,7, WHITE
, BISHOP
);
341 SET_PIECE(6,7, WHITE
, KNIGHT
);
342 SET_PIECE(7,7, WHITE
, ROOK
);
345 m_enPassantSquare
= Point::invalid();
346 m_castleWhiteKing
= true;
347 m_castleWhiteQueen
= true;
348 m_castleBlackKing
= true;
349 m_castleBlackQueen
= true;
353 template <typename M
, typename P
, typename B
>
354 PathInfo Position
<M
, P
, B
>::path(const Point
& from
, const Point
& to
) const {
355 return m_board
.path(from
, to
);
358 template <typename M, typename P, typename B>
359 void Position<M, P, B>::movePiece(const M& move) {
360 executeCaptureOn(move.to);
361 basicMovePiece(move);
365 template <typename M
, typename P
, typename B
>
366 void Position
<M
, P
, B
>::executeCaptureOn(const Point
& point
) {
367 m_board
[point
] = Piece();
370 template <typename M
, typename P
, typename B
>
371 void Position
<M
, P
, B
>::basicMovePiece(const M
& move
) {
372 P p
= m_board
[move
.from
];
374 m_board
[move
.to
] = p
;
375 m_board
[move
.from
] = Piece();
379 template <typename M
, typename P
, typename B
>
380 void Position
<M
, P
, B
>::basicDropPiece(P
* piece
, const Point
& to
) {
382 m_board
[to
] = *piece
;
387 template <typename M
, typename P
, typename B
>
388 boost::shared_ptr
<P
> Position
<M
, P
, B
>::moveHint(const M
& move
) const {
389 if (move
.type() == M::Promotion
)
390 return boost::shared_ptr
<P
>(new Piece(m_turn
, move
.promotionType
));
392 return boost::shared_ptr
<P
>();
396 template <typename M
, typename P
, typename B
>
397 bool Position
<M
, P
, B
>::checkPromotionType(const M
& m
) const {
398 return (m
.promotionType
== KNIGHT
||
399 m
.promotionType
== BISHOP
||
400 m
.promotionType
== ROOK
||
401 m
.promotionType
== QUEEN
);
404 template <typename M
, typename P
, typename B
>
405 bool Position
<M
, P
, B
>::pseudolegal(M
& move
) const {
406 if (!move
.valid()) return false;
408 if (!valid(move
.from
)) return false;
409 if (!valid(move
.to
)) return false;
410 P piece
= m_board
[move
.from
];
411 if (!piece
) return false;
412 Color thisTurn
= piece
.color();
413 Color otherTurn
= P::oppositeColor(thisTurn
);
414 if (piece
&& (turn() == thisTurn
)) {
415 move
.setType(piece
.canMove(*this, move
.from
, move
.to
));
417 if (move
.type() == M::Invalid
) return false;
419 if (move
.type() == M::Promotion
&& !checkPromotionType(move
))
422 if (move
.type() == M::KingSideCastling
) {
423 if (attacks(otherTurn
, move
.from
) ||
424 attacks(otherTurn
, move
.from
+ Point(1,0))) return false;
426 else if (move
.type() == M::QueenSideCastling
) {
427 if (attacks(otherTurn
, move
.from
) ||
428 attacks(otherTurn
, move
.from
+ Point(-1,0))) return false;
436 template <typename M
, typename P
, typename B
>
437 typename
P::Color Position
<M
, P
, B
>::moveTurn(const M
& move
) const {
438 P piece
= m_board
[move
.from
];
440 return piece
.color();
444 template <typename M
, typename P
, typename B
>
445 bool Position
<M
, P
, B
>::testMove(M
& move
) const {
447 if (move
.status
== M::Untested
) {
448 if (pseudolegal(move
)) {
449 Color turn
= moveTurn(move
);
452 std::auto_ptr
<Position
> tempPosition(clone());
453 tempPosition
->move(move
);
454 Point kingPos
= tempPosition
->findPiece(turn
, KING
);
456 if (kingPos
== Point::invalid())
457 move
.status
= M::Illegal
;
458 else if (tempPosition
->attacks(P::oppositeColor(turn
), kingPos
))
459 move
.status
= M::Illegal
;
461 move
.status
= M::Legal
;
464 move
.status
= M::Illegal
;
467 return move
.status
== M::Legal
;
470 template <typename M
, typename P
, typename B
>
471 M Position
<M
, P
, B
>::getMove(const AlgebraicNotation
& san
, bool& ok
) const {
472 M candidate
= M::invalid();
479 if (san
.castling
!= AlgebraicNotation::NoCastling
) {
480 Point from
= kingStartingPosition(turn());
481 Point to
= from
+ (san
.castling
== AlgebraicNotation::KingSide
? Point(2,0) : Point(-2,0));
482 P king
= m_board
[from
];
483 if (!(king
&& king
.type() == KING
)) {
493 if (san
.from
.valid()) {
494 candidate
= M(san
.from
, san
.to
);
497 for (Point i
= first(); i
<= last(); i
= next(i
)) {
499 M
mv(i
, san
.to
, static_cast<typename
P::Type
>(san
.promotion
));
500 if (i
.resembles(san
.from
) && p
&& p
.type() == san
.type
&& p
.color() == turn()
503 if (candidate
.valid()) {
505 return candidate
; // return the first matching move
512 ok
= candidate
.valid();
516 template <typename M, typename P, typename B>
517 M Position<M, P, B>::getMove(const QString& san, bool& ok) const {
518 return getMove(AlgebraicNotation(san), ok);
521 template <typename M
, typename P
, typename B
>
522 M Position
<M
, P
, B
>::getVerboseMove(Color turn
, const VerboseNotation
& m
) {
524 if (m
.castling
== AlgebraicNotation::NoCastling
) {
529 from
= kingStartingPosition(turn
);
530 to
= from
+ (m
.castling
== AlgebraicNotation::KingSide
? Point(2,0) : Point(-2, 0));
534 res
.promotionType
= static_cast<typename
P::Type
>(m
.promotion
);
539 template <typename M
, typename P
, typename B
>
540 Position
<M
, P
, B
>* Position
<M
, P
, B
>::legallyMove(M
& mv
) const {
542 Position
* res
= clone();
550 template <typename M
, typename P
, typename B
>
551 void Position
<M
, P
, B
>::fromFEN(const QString
& fen
, bool& ok
) {
554 QStringList data
= fen
.split(' ', QString::SkipEmptyParts
);
555 const int boardIndex
= 0;
556 const int turnIndex
= 1;
557 const int castlingIndex
= 2;
558 const int enPassantIndex
= 3;
561 QChar turn
= data
[turnIndex
][0].toLower();
564 else if (turn
== 'b')
568 for (int i
= 0; i
< data
[castlingIndex
].length(); i
++) {
569 QChar symbol
= data
[castlingIndex
][i
];
571 m_castleBlackKing
= true;
572 else if (symbol
== 'q')
573 m_castleBlackQueen
= true;
574 else if (symbol
== 'K')
575 m_castleWhiteKing
= true;
576 else if (symbol
== 'Q')
577 m_castleWhiteQueen
= true;
581 m_enPassantSquare
= Point(data
[enPassantIndex
], size().y
);
585 for (int index
= 0; index
< data
[boardIndex
].length(); index
++) {
586 QChar symbol
= data
[boardIndex
][index
];
588 cursor
= Point(0, cursor
.y
+ 1);
590 else if (symbol
.isDigit()) {
591 int k
= symbol
.toAscii() - '0';
595 if (!valid(cursor
)) return;
596 typename
P::Type type
= P::getType(symbol
);
597 if (type
== INVALID_TYPE
) return;
598 Color color
= symbol
.isUpper() ? WHITE
: BLACK
;
599 set(cursor
, P(color
, type
));
607 // adapted from Maurizio Monge's rattatechess
608 template <typename M
, typename P
, typename B
>
609 QString Position
<M
, P
, B
>::fen(int halfmove
, int fullmove
) const {
612 // add board information
614 for (int i
= 0; i
< 8; i
++) {
615 for (int j
= 0; j
< 8; j
++) {
616 Point p
= Point(j
, i
);
617 Piece pc
= m_board
[p
];
622 str
+= QString::number(cn
);
625 QString symbol
= P::typeSymbol(pc
.type());
626 if (pc
.color() == BLACK
)
627 symbol
= symbol
.toLower();
632 str
+= QString::number(cn
);
639 // add turn information
640 str
+= turn() == WHITE
? " w " : " b ";
642 // add castling information
643 QString castleString
;
644 if(m_castleWhiteKing
)
646 if(m_castleWhiteQueen
)
648 if(m_castleBlackKing
)
650 if(m_castleBlackQueen
)
652 if (castleString
== "") castleString
= "-";
653 str
+= castleString
+ " ";
655 // add en passant information
656 if (m_enPassantSquare
== Point::invalid())
659 str
+= m_enPassantSquare
.toString(size().y
);
662 // add move count information
663 str
+= QString::number(halfmove
) + " " + QString::number(fullmove
);
669 template <typename M
, typename P
, typename B
>
670 void Position
<M
, P
, B
>::dump() const {
671 for (Point i
= first(); i
<= last(); i
= next(i
)) {
673 std::cout
<< "+---+---+---+---+---+---+---+---+" << std::endl
;
675 Piece piece
= m_board
[i
];
678 symbol
= Piece::typeSymbol(piece
.type());
679 if (piece
.color() == BLACK
) symbol
= symbol
.toLower();
682 symbol
= ((i
.x
+ i
.y
) % 2 == 0) ? " " : ".";
684 std::cout
<< "| " << symbol
<< " ";
686 std::cout
<< "|" << std::endl
;
688 std::cout
<< "+---+---+---+---+---+---+---+---+" << std::endl
;
691 template <typename M
, typename P
, typename B
>
692 void Position
<M
, P
, B
>::move(const M
& move
) {
693 P piece
= m_board
[move
.from
];
696 Color color
= piece
.color();
697 typename
P::Type type
= piece
.type();
699 executeCaptureOn(move
.to
);
700 basicMovePiece(move
);
702 if (move
.type() == M::EnPassantTrigger
)
703 m_enPassantSquare
= (move
.to
+ move
.from
) / 2;
705 m_enPassantSquare
= Point::invalid();
707 if (move
.type() == M::EnPassantCapture
) {
708 Point
phantom(move
.to
.x
, move
.from
.y
);
709 m_board
[phantom
] = Piece();
712 else if (move
.type() == M::Promotion
) {
713 typename
P::Type type
= move
.promotionType
;
714 m_board
[move
.to
] = P(piece
.color(), type
);
717 else if (move
.type() == M::KingSideCastling
) {
718 Point rookSquare
= move
.to
+ Point(1,0);
719 Point rookDestination
= move
.from
+ Point(1,0);
720 basicMovePiece(M(rookSquare
, rookDestination
));
723 else if (move
.type() == M::QueenSideCastling
) {
724 Point rookSquare
= move
.to
- Point(2,0);
725 Point rookDestination
= move
.from
- Point(1,0);
726 basicMovePiece(M(rookSquare
, rookDestination
));
731 if (color
== WHITE
) {
732 m_castleWhiteKing
= false;
733 m_castleWhiteQueen
= false;
736 m_castleBlackKing
= false;
737 m_castleBlackQueen
= false;
741 if (move
.from
== Point(0,0) || move
.to
== Point(0,0))
742 m_castleBlackQueen
= false;
743 else if (move
.from
== Point(7,0) || move
.to
== Point(7,0))
744 m_castleBlackKing
= false;
745 else if (move
.from
== Point(0,7) || move
.to
== Point(0,7))
746 m_castleWhiteQueen
= false;
747 else if (move
.from
== Point(7,7) || move
.to
== Point(7,7))
748 m_castleWhiteKing
= false;
753 template <typename M
, typename P
, typename B
>
754 void Position
<M
, P
, B
>::switchTurn() {
755 m_turn
= P::oppositeColor(turn());
758 template <typename M
, typename P
, typename B
>
759 void Position
<M
, P
, B
>::setTurn(Color turn
) {
763 template <typename M
, typename P
, typename B
>
764 bool Position
<M
, P
, B
>::testPremove(M premove
) const {
765 for (Point p
= first(); p
<= last(); p
= next(p
)) {
766 P piece
= m_board
[p
];
767 if (!piece
|| piece
.color() != turn()) continue;
768 for (Point q
= first(); q
<= last(); q
= next(q
)) {
770 if (testMove(move
)) {
771 Position
tempPosition(*this);
772 tempPosition
.move(move
);
774 if (tempPosition
.testMove(premove
)) return true;
782 template <typename M
, typename P
, typename B
>
783 bool Position
<M
, P
, B
>::attacks(Color color
, const Point
& destination
) const {
785 return attacks(color
, destination
, temp
);
788 template <typename M
, typename P
, typename B
>
789 bool Position
<M
, P
, B
>::attacks(Color color
, const Point
& destination
, Point
& source
) const {
790 for (Point p
= first(); p
<= last(); p
= next(p
)) {
791 P piece
= m_board
[p
];
792 if (piece
&& piece
.color() == color
&& piece
.canMove(*this, p
, destination
)) {
800 template <typename M
, typename P
, typename B
>
801 bool Position
<M
, P
, B
>::attacks(const Point
& destination
) const {
802 return attacks(turn(), destination
);
805 template <typename M
, typename P
, typename B
>
806 Point Position
<M
, P
, B
>::findPiece(Color color
, typename
P::Type type
) const {
807 for (int i
= 0; i
< 8; i
++)
808 for (int j
= 0; j
< 8; j
++) {
809 Point p
= Point(i
,j
);
810 P piece
= m_board
[p
];
811 if (piece
&& piece
.color() == color
&& piece
.type() == type
)
814 return Point::invalid();
817 template <typename M
, typename P
, typename B
>
818 boost::shared_ptr
<AbstractGenerator
<M
> >
819 Position
<M
, P
, B
>::createLegalGenerator() const {
820 return boost::shared_ptr
<AbstractGenerator
<M
> >(
821 new MoveGenerator
<Position
, LegalMove
<Position
> >(*this));
824 // template <typename M, typename P, typename B>
825 // boost::shared_ptr<AbstractGenerator<M> > createPseudoLegalGenerator() const {
826 // return boost::shared_ptr<AbstractGenerator<M> >(
827 // new MoveGenerator<Position, LegalMove<Position> >(*this));
830 template <typename M
, typename P
, typename B
>
831 bool Position
<M
, P
, B
>::stalled() const {
832 boost::shared_ptr
<AbstractGenerator
<M
> > generator
=
833 createLegalGenerator();
834 std::vector
<M
> mv
= generator
->generate();
835 return generator
->generate().size() == 0;
838 template <typename M, typename P, typename B>
839 bool Position<M, P, B>::pseudoStalled() const {
840 MoveGenerator<Position, PseudolegalMove<Position> > generator(*this);
841 return generator.generate().size() == 0;
844 template <typename M
, typename P
, typename B
>
845 bool Position
<M
, P
, B
>::check(Color turn
) const {
846 Point kingPosition
= findPiece(turn
, KING
);
847 if (kingPosition
== Point::invalid()) {
848 // a missing king is considered in check
852 return attacks(P::oppositeColor(turn
), kingPosition
);
855 template <typename M
, typename P
, typename B
>
856 bool Position
<M
, P
, B
>::check() const {
857 return check(turn());
860 template <typename M
, typename P
, typename B
>
861 typename Position
<M
, P
, B
>::State Position
<M
, P
, B
>::state() const {
862 if (!stalled()) return InPlay
;
865 return turn() == WHITE
? BlackWins
: WhiteWins
;