removed clock pref widget. clock prefs are definitively part of the lua theme.
[kboard.git] / src / variants / xchess / position.h
blob56dc25a0452c47d1ce285f23cc2cf4697ef35642
1 /*
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.
9 */
11 #ifndef POSITION_H
12 #define POSITION_H
14 #include <vector>
15 #include <map>
16 #include <iostream>
17 #include <memory>
19 #include <QString>
20 #include <QStringList>
21 #include <boost/shared_ptr.hpp>
23 #include "common.h"
24 #include "pathinfo.h"
25 #include "option.h"
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>
37 class Position;
39 template <typename M, typename P, typename B>
40 class Position {
41 public:
42 typedef typename P::Type Type;
43 typedef typename P::Color Color;
44 protected:
45 Color m_turn;
47 B m_board;
48 Point m_enPassantSquare;
50 bool m_castleWhiteKing : 1;
51 bool m_castleWhiteQueen : 1;
52 bool m_castleBlackKing : 1;
53 bool m_castleBlackQueen : 1;
55 public:
56 typedef M Move;
57 typedef P Piece;
58 typedef B Board;
60 Position(int = 8, int = 8);
61 Position(const OptList& l, int = 8, int = 8);
62 Position(Color turn,
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); }
75 virtual ~Position();
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;
82 virtual void setup();
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) {
99 if(!valid(p))
100 return;
101 m_board[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])
108 return NoAction;
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)); }
152 enum State {
153 InPlay,
154 WhiteWins,
155 BlackWins,
156 Draw
158 State state() const;
159 virtual boost::shared_ptr<AbstractGenerator<M> > createLegalGenerator() const;
160 virtual bool stalled() const;
161 // virtual bool pseudoStalled() const;
162 bool check() 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;
170 void dump() 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&);
179 #include <iostream>
180 #include "algebraicnotation.h"
182 template <typename M, typename P, typename B>
183 Position<M, P, B>::Position(int width, int height)
184 : m_turn(WHITE)
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)
194 : m_turn(WHITE)
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)
208 : m_turn(turn)
209 , m_board(8, 8)
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
246 QStringList retv;
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);
252 return retv + retv;
255 template <typename M, typename P, typename B>
256 bool Position<M, P, B>::operator==(const Position<M, P, B>& other) const {
257 #if 0
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;
266 return false;
268 if (!(m_board == other.m_board)) {
269 std::cout << "boards differ" << std::endl;
270 return false;
272 if (m_castleWhiteKing != other.m_castleWhiteKing) {
273 std::cout << "wk differ" << std::endl;
274 return false;
276 if (m_castleWhiteQueen != other.m_castleWhiteQueen) {
277 std::cout << "wq differ" << std::endl;
278 return false;
280 if (m_castleBlackKing != other.m_castleBlackKing) {
281 std::cout << "bk differ" << std::endl;
282 return false;
284 if (m_castleBlackQueen != other.m_castleBlackQueen) {
285 std::cout << "bq differ" << std::endl;
286 return false;
288 std::cout << "equal" << std::endl;
289 return true;
290 #else
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;
298 #endif
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 {
308 #if 0
309 std::cout << "board = " << &m_board << std::endl;
310 #endif
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);
339 m_turn = WHITE;
340 m_enPassantSquare = Point::invalid();
341 m_castleWhiteKing = true;
342 m_castleWhiteQueen = true;
343 m_castleBlackKing = true;
344 m_castleBlackQueen = true;
346 #undef SET_PIECE
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);
357 switchTurn();
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];
368 Q_ASSERT(p);
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) {
376 Q_ASSERT(piece);
377 m_board[to] = *piece;
378 switchTurn();
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));
385 else
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];
405 Q_ASSERT(piece);
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))
414 return false;
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;
425 return true;
427 else 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];
433 Q_ASSERT(piece);
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);
444 // check king safety
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;
453 else
454 move.status = M::Legal;
456 else
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();
467 if (san.invalid()) {
468 ok = false;
469 return candidate;
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)) {
477 ok = false;
478 return candidate;
480 else {
481 ok = true;
482 return M(from, to);
486 if (san.from.valid()) {
487 candidate = M(san.from, san.to);
489 else {
490 for (Point i = first(); i <= last(); i = next(i)) {
491 P p = m_board[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()
494 && testMove(mv)) {
496 if (candidate.valid()) {
497 ok = false;
498 return candidate; // return the first matching move
500 else candidate = mv;
505 ok = candidate.valid();
506 return candidate;
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) {
516 Point from, to;
517 if (m.castling == AlgebraicNotation::NoCastling) {
518 from = m.from;
519 to = m.to;
521 else {
522 from = kingStartingPosition(turn);
523 to = from + (m.castling == AlgebraicNotation::KingSide ? Point(2,0) : Point(-2, 0));
526 M res(from, to);
527 res.promotionType = static_cast<typename P::Type>(m.promotion);
529 return res;
532 template <typename M, typename P, typename B>
533 Position<M, P, B>* Position<M, P, B>::legallyMove(M& mv) const {
534 if (testMove(mv)) {
535 Position* res = clone();
536 res->move(mv);
537 return res;
539 else
540 return 0;
543 template <typename M, typename P, typename B>
544 void Position<M, P, B>::fromFEN(const QString& fen, bool& ok) {
545 ok = false;
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;
553 // read turn
554 QChar turn = data[turnIndex][0].toLower();
555 if (turn == 'w')
556 setTurn(WHITE);
557 else if (turn == 'b')
558 setTurn(BLACK);
560 // read castling
561 for (int i = 0; i < data[castlingIndex].length(); i++) {
562 QChar symbol = data[castlingIndex][i];
563 if (symbol == 'k')
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;
573 // read en-passant
574 m_enPassantSquare = Point(data[enPassantIndex], size().y);
576 // read board
577 Point cursor(0, 0);
578 for (int index = 0; index < data[boardIndex].length(); index++) {
579 QChar symbol = data[boardIndex][index];
580 if (symbol == '/') {
581 cursor = Point(0, cursor.y + 1);
583 else if (symbol.isDigit()) {
584 int k = symbol.toAscii() - '0';
585 cursor.x += k;
587 else {
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));
593 cursor.x++;
597 ok = true;
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 {
603 QString str;
605 // add board information
606 int cn = 0;
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];
611 if (!pc)
612 cn++;
613 else {
614 if (cn > 0) {
615 str += QString::number(cn);
616 cn = 0;
618 QString symbol = P::typeSymbol(pc.type());
619 if (pc.color() == BLACK)
620 symbol = symbol.toLower();
621 str += symbol;
624 if (cn > 0) {
625 str += QString::number(cn);
626 cn = 0;
628 if (i != 7)
629 str += "/";
632 // add turn information
633 str += turn() == WHITE ? " w " : " b ";
635 // add castling information
636 QString castleString;
637 if(m_castleWhiteKing)
638 castleString += "K";
639 if(m_castleWhiteQueen)
640 castleString += "Q";
641 if(m_castleBlackKing)
642 castleString += "k";
643 if(m_castleBlackQueen)
644 castleString += "k";
645 if (castleString == "") castleString = "-";
646 str += castleString + " ";
648 // add en passant information
649 if (m_enPassantSquare == Point::invalid())
650 str += "-";
651 else
652 str += m_enPassantSquare.toString(size().y);
653 str += " ";
655 // add move count information
656 str += QString::number(halfmove) + " " + QString::number(fullmove);
658 return str;
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)) {
665 if (i.x == 0)
666 std::cout << "+---+---+---+---+---+---+---+---+" << std::endl;
668 Piece piece = m_board[i];
669 QString symbol;
670 if (piece) {
671 symbol = Piece::typeSymbol(piece.type());
672 if (piece.color() == BLACK) symbol = symbol.toLower();
674 else
675 symbol = ((i.x + i.y) % 2 == 0) ? " " : ".";
677 std::cout << "| " << symbol << " ";
678 if (i.x == 7)
679 std::cout << "|" << std::endl;
681 std::cout << "+---+---+---+---+---+---+---+---+" << std::endl;
683 #if 0 // BROKEN
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;
687 else
688 std::cout << Piece::typeSymbol(pi->first.type()) <<": "<<pi->second<<std::endl;
690 #endif
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];
696 Q_ASSERT(piece);
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;
706 else {
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];
725 Q_ASSERT(rook);
726 Q_ASSERT(rook.type() == ROOK);
727 Q_UNUSED(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];
738 Q_ASSERT(rook);
739 Q_ASSERT(rook.type() == ROOK);
740 Q_UNUSED(rook);
742 basicMovePiece(M(rookSquare, rookDestination));
746 if (type == KING) {
747 if (color == WHITE) {
748 m_castleWhiteKing = false;
749 m_castleWhiteQueen = false;
751 else {
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;
766 switchTurn();
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) {
776 m_turn = 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)) {
785 M move(p,q);
786 if (testMove(move)) {
787 Position tempPosition(*this);
788 tempPosition.move(move);
790 if (tempPosition.testMove(premove)) return true;
795 return false;
798 template <typename M, typename P, typename B>
799 bool Position<M, P, B>::attacks(Color color, const Point& destination) const {
800 Point temp;
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)) {
809 source = p;
810 return true;
813 return false;
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)
828 return p;
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));
844 // }
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
865 return true;
867 else
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;
880 if (check())
881 return turn() == WHITE? BlackWins : WhiteWins;
882 else
883 return Draw;
887 //END Implementation
896 #endif // POSITION_H