2 #include "controllers/game.impl.h"
3 #include "controllers/examination.h"
4 #include "controllers/localexamination.h"
5 #include "controllers/editposition.impl.h"
6 #include "controllers/observedgame.h"
7 #include "controllers/editgame.impl.h"
8 #include "piecepoolwidget.h"
9 #include "variant.impl.h"
10 #include "graphicalinfo.impl.h"
11 #include "poolgraphicalinfo.impl.h"
12 #include "animator.impl.h"
13 #include "boardmanager.impl.h"
14 #include "moveserializer.impl.h"
19 QString UltimaPiece::typeName() const {
40 QString UltimaPiece::typeSymbol(Type type) {
61 bool UltimaPiece::canMove(UltimaMove& m, const UltimaPosition& position) const {
62 if (m_type == Chameleon) {
63 typedef map<Type, vector<Point> > Map;
66 bool valid = canMoveAs(m, position, m.targets, UltimaPiece::Chameleon);
68 for (int i = 0; i < 7; i++) {
69 Type t = static_cast<Type>(i);
71 possible_targets[t] = vector<Point>();
72 bool keep_this = true;
73 if (!canMoveAs(m, position, possible_targets[t], t))
76 if (possible_targets[t].size() == 0) {
79 possible_targets[t].push_back(m.to);
85 for (uint j = 0; j < possible_targets[t].size(); j++) {
86 Q_ASSERT(position[possible_targets[t][j]]);
87 if (position[possible_targets[t][j]]->type() != t) {
96 std::cout << "removing possible targets of type " << typeSymbol(t) << std::endl;
97 possible_targets.erase(t);
102 for (Map::iterator i = possible_targets.begin();
103 i != possible_targets.end(); ++i) {
104 std::cout << "remaining targets of type " << typeSymbol(i->first) << std::endl;
106 copy(i->second.begin(),
108 back_insert_iterator<vector<Point> >(m.targets));
114 return canMoveAs(m, position, m.targets, m_type);
117 bool UltimaPiece::checkPawnCapture(const UltimaPosition& position, const Point& p,
118 const Point& direction, vector<Point>& targets) const {
119 Point opp = p + direction;
120 Point f = opp + direction;
122 if (!position.valid(f)) return false;
123 if (position[opp] && position[opp]->color() != color()
124 && position[f] && position[f]->color() == color()) {
125 targets.push_back(opp);
131 bool UltimaPiece::canMoveAs(const UltimaMove& m, const UltimaPosition& position,
132 vector<Point>& targets, Type actualType) const {
133 Point delta = m.to - m.from;
134 if (actualType == King)
135 // the king moves exactly like a chess king
136 return abs(delta.x) <= 1 && abs(delta.y) <= 1 && !sameColor(position[m.to]);
138 PathInfo path = position.path(m.from, m.to);
139 if (path.valid() && !position[m.to]) {
141 // a long leaper is the only one that can jump
142 if (actualType == LongLeaper) {
143 Point step = delta.normalizeInfinity();
144 // a long leaper move is pseudolegal if
145 // between from and to there are only
146 // opponent pieces, and they are not
150 while ((p += step) != m.to) {
152 if (last || position[p]->color() == color()) return false;
153 targets.push_back(p);
161 if (!path.clear()) return false;
163 switch (actualType) {
166 if (!path.parallel()) return false;
168 // called specialized capture checks for each direction
169 checkPawnCapture(position, m.to, Point(1,0), targets);
170 checkPawnCapture(position, m.to, Point(0,1), targets);
171 checkPawnCapture(position, m.to, Point(-1,0), targets);
172 checkPawnCapture(position, m.to, Point(0,-1), targets);
177 // find king position
178 Point kingPos = position.findKing(m_color);
179 Q_ASSERT(kingPos != Point::invalid());
181 // capture on the other vertices of the rectangle
182 // determined by m.to and kingPos
183 Point t1(m.to.x, kingPos.y);
184 Point t2(kingPos.x, m.to.y);
186 if (position[t1] && position[t1]->color() != m_color)
187 targets.push_back(t1);
188 if (position[t2] && position[t2]->color() != m_color)
189 targets.push_back(t2);
193 // the immobilizer cannot capture
197 Point dir = delta.normalizeInfinity();
198 Point opp = m.from - dir;
199 if (position.valid(opp) && position[opp] && position[opp]->color() != color())
200 targets.push_back(opp);
219 bool UltimaPiece::equals(const UltimaPiece* other) const {
220 return other && m_color == other->m_color && m_type == other->m_type;
224 bool UltimaPiece::sameColor(const UltimaPiece* other) const {
225 return other && m_color == other->m_color;
228 UltimaPosition::UltimaPosition()
232 UltimaPosition::~UltimaPosition() { }
234 #define SET_PIECE(i, j, color, type) \
235 m_board[Point(i,j)] = new Piece(color, UltimaPiece::type)
236 void UltimaPosition::setup() {
237 for (int i = 0; i < 8; i++) {
238 SET_PIECE(i, 1, BLACK, Pawn);
239 SET_PIECE(i, 6, WHITE, Pawn);
242 SET_PIECE(0,0, BLACK, Coordinator);
243 SET_PIECE(1,0, BLACK, LongLeaper);
244 SET_PIECE(2,0, BLACK, Chameleon);
245 SET_PIECE(3,0, BLACK, Withdrawer);
246 SET_PIECE(4,0, BLACK, King);
247 SET_PIECE(5,0, BLACK, Chameleon);
248 SET_PIECE(6,0, BLACK, LongLeaper);
249 SET_PIECE(7,0, BLACK, Immobilizer);
251 SET_PIECE(0,7, WHITE, Immobilizer);
252 SET_PIECE(1,7, WHITE, LongLeaper);
253 SET_PIECE(2,7, WHITE, Chameleon);
254 SET_PIECE(3,7, WHITE, King);
255 SET_PIECE(4,7, WHITE, Withdrawer);
256 SET_PIECE(5,7, WHITE, Chameleon);
257 SET_PIECE(6,7, WHITE, LongLeaper);
258 SET_PIECE(7,7, WHITE, Coordinator);
264 bool UltimaPosition::operator==(const UltimaPosition& other) const {
265 return m_turn == other.m_turn
266 && m_board == other.m_board;
269 UltimaPiece* UltimaPosition::operator[](const Point& p) const {
273 void UltimaPosition::setPiece(const Point& p, Piece* piece) {
278 Point UltimaPosition::findKing(Piece::Color color) const {
279 return m_board.find(UltimaPiece(color, UltimaPiece::King));
282 void UltimaPosition::dump() const { }
285 bool UltimaPosition::valid(const Point& p) const {
286 return m_board.valid(p);
289 bool UltimaPosition::testMove(Move& m) const {
290 return pseudolegal(m);
293 bool UltimaPosition::pseudolegal(Move& m) const {
294 if (!m.valid()) return false;
295 Q_ASSERT(valid(m.from));
296 Piece* piece = m_board[m.from];
299 if (m.from == m.to) return false;
301 // a piece cannot move if it is near an opponent immobilizer
302 // or near a chameleon if it is an immobilizer
303 bool immobilized = false;
304 for (int i = -1; i <= 1; ++i)
305 for (int j = -1; j <= 1; ++j) {
306 Point p = m.from + Point(i,j);
307 if (!valid(p)) continue;
309 && m_board[p]->color() != piece->color()) {
310 Piece::Type type = m_board[p]->type();
311 if (type == Piece::Immobilizer ||
312 (piece->type() == Piece::Immobilizer && type == Piece::Chameleon)) {
319 // an immobilized piece can move
320 // if an only if the move is a suicide
321 return m.to == Point::invalid();
324 if (piece->canMove(m, *this)) {
330 void UltimaPosition::move(const Move& m) {
334 for (uint i = 0; i < m.targets.size(); i++)
335 if (m.targets[i] != Point::invalid()) setPiece(m.targets[i], 0);
337 if (m.to == Point::invalid()) {
339 // setPiece(m.from, 0);
340 std::cout << "suicide on " << m.from << std::endl;
344 delete m_board[m.to];
345 m_board[m.to] = m_board[m.from];
352 void UltimaPosition::switchTurn() {
353 m_turn = ChessPiece::oppositeColor(m_turn);
356 template class EditGameController<UltimaPosition>;