GNUShogi engine.
[tagua/yd.git] / src / variants / xchess / piece.h
blob865e0b32a132440ff35231661cd9fde3262a8701
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 PIECE_H
12 #define PIECE_H
14 #include <iostream>
16 #include "point.h"
17 #include "move.h"
18 #include "piecetype.h"
19 #include "common.h"
20 #include "pathinfo.h"
23 class ChessPiece {
24 public:
25 typedef PieceType Type;
26 typedef Type PromotionType;
27 typedef PieceColor Color;
28 protected:
29 typedef ChessMove Move;
30 private:
31 Color m_color;
32 Type m_type;
33 public:
34 ChessPiece(Color = INVALID_COLOR, Type = INVALID_TYPE);
35 ChessPiece(const ChessPiece& p);
36 ChessPiece& operator=(const ChessPiece& p);
37 ChessPiece* clone() const;
39 virtual ~ChessPiece() {}
40 inline static Color oppositeColor(Color color) { return color == WHITE ? BLACK :
41 color == BLACK ? WHITE : INVALID_COLOR; }
43 inline Color color() const { return m_color; }
44 inline Type type() const { return m_type; }
45 inline bool valid() const { return m_color != INVALID_COLOR &&
46 m_type != INVALID_TYPE; }
47 QString typeName() const;
48 QString name() const;
50 template <typename Pos>
51 Move::Type canMove(const Pos& position, Point from, Point to) const;
53 bool equals(const ChessPiece& other) const;
54 bool sameColor(const ChessPiece& other) const;
55 int id() const;
56 static Color colorFromId(int);
57 static Type typeFromId(int);
59 static Type getType(const QString& str);
60 static QString typeSymbol(Type type);
61 static ChessPiece fromDescription(const QString& description);
63 inline Point kingStartingPosition() const { return Point(4, color() == WHITE? 7 : 0); }
64 inline int startingRank() const { return color() == WHITE? 6 : 1; }
65 inline Point direction() const { return direction(color()); }
66 static Point direction(Color color) { return Point(0, color == WHITE? -1 : 1); }
67 inline int promotionRank() const { return color() == WHITE? 0 : 7; }
68 bool operator==(const ChessPiece& p) const;
69 bool operator!=(const ChessPiece& p) const { return !operator==(p); }
70 bool operator!() const { return !valid(); }
71 bool operator<(const ChessPiece& p) const {
72 return m_color != p.m_color ?
73 m_color < p.m_color :
74 m_type < p.m_type; }
75 operator bool() const { return valid(); }
78 std::ostream& operator<<(std::ostream& os, const ChessPiece& p);
80 template <typename Pos>
81 ChessPiece::Move::Type ChessPiece::canMove(const Pos& position,
82 Point from, Point to) const {
83 switch (m_type)
86 case ROOK:
88 if (from == to)
89 return Move::Invalid;
90 PathInfo path = position.path(from, to);
91 if (path.parallel() && path.clear() && !sameColor(position[to]))
92 return Move::Normal;
93 else
94 return Move::Invalid;
97 case BISHOP:
99 if (from == to)
100 return Move::Invalid;
101 PathInfo path = position.path(from, to);
102 if (path.diagonal() && path.clear() && !sameColor(position[to]))
103 return Move::Normal;
104 else
105 return Move::Invalid;
108 case KNIGHT:
109 if (sameColor(position[to]))
110 return Move::Invalid;
111 else
113 Point delta = from - to;
114 if (abs(delta.x) == 1 && abs(delta.y) == 2)
115 return Move::Normal;
116 if (abs(delta.y) == 1 && abs(delta.x) == 2)
117 return Move::Normal;
118 return Move::Invalid;
121 case QUEEN:
123 if (from == to)
124 return Move::Invalid;
125 PathInfo path = position.path(from, to);
126 if (path.valid() && path.clear() && !sameColor(position[to]))
127 return Move::Normal;
128 else
129 return Move::Invalid;
132 case KING:
134 if (from == to)
135 return Move::Invalid;
136 Point delta = to - from;
137 if (abs(delta.x) <= 1 && abs(delta.y) <= 1 && !sameColor(position[to]))
138 return Move::Normal;
139 else if (from == kingStartingPosition()) {
140 if (delta == Point(2,0)) {
141 if (!position[from + Point(1,0)] &&
142 !position[to] &&
143 position.castleKing(color()))
144 return Move::KingSideCastling;
146 else if (delta == Point(-2,0)) {
147 if (!position[from - Point(1,0)] &&
148 !position[from - Point(2,0)] &&
149 !position[to] &&
150 position.castleQueen(color()))
151 return Move::QueenSideCastling;
154 return Move::Invalid;
157 case PAWN:
159 ChessPiece destinationPiece = position[to];
160 Point delta = to - from;
161 bool enPassant = position.enPassantSquare() == to;
163 // moving
164 if (!destinationPiece && !enPassant) {
165 if (delta == direction())
166 if (to.y == promotionRank())
167 return Move::Promotion;
168 else
169 return Move::Normal;
170 if (from.y == startingRank() && delta == direction() * 2
171 && !position[from + direction()])
172 return Move::EnPassantTrigger;
173 else
174 return Move::Invalid;
177 // capturing
178 else if (enPassant || !sameColor(destinationPiece))
179 if (delta.y == direction().y && abs(delta.x) == 1)
180 if (enPassant)
181 return Move::EnPassantCapture;
182 else if (to.y == promotionRank())
183 return Move::Promotion;
184 else
185 return Move::Normal;
187 return Move::Invalid;
190 default:
191 return Move::Invalid;
195 #endif // PIECE_H