void Position::UnmakeMove() { if (m_undoSize == 0) return; Undo& undo = m_undos[--m_undoSize]; Move mv = undo.m_mv; m_ep = undo.m_ep; m_castlings = undo.m_castlings; m_fifty = undo.m_fifty; FLD from = mv.From(); FLD to = mv.To(); PIECE piece = mv.Piece(); PIECE captured = mv.Captured(); COLOR side = m_side ^ 1; m_hash ^= s_hashSide[1]; Remove(to); Put(from, piece); if (captured) { if (to == m_ep) Put(to + 8 - 16 * side, captured); else Put(to, captured); } --m_ply; m_side ^= 1; if (piece == KW) { m_Kings[WHITE] = from; if (from == E1 && to == G1) { Remove(F1); Put(H1, RW); } else if (from == E1 && to == C1) { Remove(D1); Put(A1, RW); } } else if (piece == KB) { m_Kings[BLACK] = from; if (from == E8 && to == G8) { Remove(F8); Put(H8, RB); } else if (from == E8 && to == C8) { Remove(D8); Put(A8, RB); } } }
bool Position::MakeMove(Move mv) { Undo& undo = _undos[_undoSize++]; undo.m_castlings = m_castlings; undo.m_ep = m_ep; undo.m_fifty = m_fifty; undo.m_hash = m_hash; undo.m_mv = mv; FLD from = mv.From(); FLD to = mv.To(); PIECE piece = mv.Piece(); PIECE captured = mv.Captured(); PIECE promotion = mv.Promotion(); COLOR side = m_side; COLOR opp = side ^ 1; m_hash ^= s_hashSide[1]; ++m_fifty; if (captured) { m_fifty = 0; if (to == m_ep) Remove(to + 8 - 16 * side); else Remove(to); } Remove(from); Put(to, piece); m_ep = NF; switch (piece) { case PW: case PB: m_fifty = 0; if (to - from == -16 + 32 * side) m_ep = to + 8 - 16 * side; else if (promotion) { Remove(to); Put(to, promotion); } break; case KW: m_Kings[WHITE] = to; if (from == E1) { if (to == G1) { Remove(H1); Put(F1, RW); m_castlings ^= WHITE_DID_O_O; } else if (to == C1) { Remove(A1); Put(D1, RW); m_castlings ^= WHITE_DID_O_O_O; } } break; case KB: m_Kings[BLACK] = to; if (from == E8) { if (to == G8) { Remove(H8); Put(F8, RB); m_castlings ^= BLACK_DID_O_O; } else if (to == C8) { Remove(A8); Put(D8, RB); m_castlings ^= BLACK_DID_O_O_O; } } break; default: break; } static const U8 castlingDelta[64] = { 0xf7, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xfe }; m_castlings &= castlingDelta[from]; m_castlings &= castlingDelta[to]; ++m_ply; m_side ^= 1; if (IsAttacked(m_Kings[side], opp)) { UnmakeMove(); return false; } return true; }
string MoveToStrShort(Move mv, Position& pos, MoveList* mvlist) { if (mv.Piece() == KW && mv.From() == E1 && mv.To() == G1) return "O-O"; if (mv.Piece() == KW && mv.From() == E1 && mv.To() == C1) return "O-O-O"; if (mv.Piece() == KB && mv.From() == E8 && mv.To() == G8) return "O-O"; if (mv.Piece() == KB && mv.From() == E8 && mv.To() == C8) return "O-O-O"; FLD from = mv.From(); FLD to = mv.To(); PIECE piece = mv.Piece(); PIECE captured = mv.Captured(); PIECE promotion = mv.Promotion(); string strPiece, strFrom, strTo, strCapture, strPromotion; switch (piece) { case PW: case PB: break; case NW: case NB: strPiece = "N"; break; case BW: case BB: strPiece = "B"; break; case RW: case RB: strPiece = "R"; break; case QW: case QB: strPiece = "Q"; break; case KW: case KB: strPiece = "K"; break; default: break; } strTo = FldToStr(to); if (captured) { strCapture = "x"; if (piece == PW || piece == PB) strFrom = FldToStr(from).substr(0, 1); } switch (promotion) { case QW: case QB: strPromotion += "=Q"; break; case RW: case RB: strPromotion += "=R"; break; case BW: case BB: strPromotion += "=B"; break; case NW: case NB: strPromotion += "=N"; break; } bool ambiguity = false; bool uniqRow = true; bool uniqCol = true; if (piece != PW && piece != PB) { for (MoveList* ptr = mvlist; ptr->mv; ++ptr) { Move mv1 = ptr->mv; if (mv1 == mv) continue; if (mv1.To() != to) continue; if (mv1.Piece() != piece) continue; if (!pos.MakeMove(mv1)) continue; pos.UnmakeMove(); ambiguity = true; if (Row(mv1.From()) == Row(from)) uniqRow = false; if (Col(mv1.From()) == Col(from)) uniqCol = false; } } if (ambiguity) { if (uniqCol) strFrom = FldToStr(from).substr(0, 1); else if (uniqRow) strFrom = FldToStr(from).substr(1, 1); else strFrom = FldToStr(from); } return strPiece + strFrom + strCapture + strTo + strPromotion; }
std::string MoveToStrShort(Move mv, Position& pos) { if (mv == Move(E1, G1, KW) || mv == Move(E8, G8, KB)) return "O-O"; if (mv == Move(E1, C1, KW) || mv == Move(E8, C8, KB)) return "O-O-O"; PIECE piece = mv.Piece(); FLD from = mv.From(); FLD to = mv.To(); PIECE captured = mv.Captured(); PIECE promotion = mv.Promotion(); std::string strFrom, strTo, strPiece, strCaptured, strPromotion; switch (piece) { case PW: case PB: if (captured) strFrom = FldToStr(from).substr(0, 1); break; case NW: case NB: strPiece = "N"; break; case BW: case BB: strPiece = "B"; break; case RW: case RB: strPiece = "R"; break; case QW: case QB: strPiece = "Q"; break; case KW: case KB: strPiece = "K"; break; default: break; } if (captured) strCaptured = "x"; strTo = FldToStr(to); switch (promotion) { case QW: case QB: strPromotion = "=Q"; break; case RW: case RB: strPromotion = "=R"; break; case BW: case BB: strPromotion = "=B"; break; case NW: case NB: strPromotion = "=N"; break; default: break; } // resolve ambiguity int uniq_col = 1; int uniq_row = 1; bool ambiguity = false; int row0 = Row(from); int col0 = Col(from); MoveList mvlist; mvlist.GenAllMoves(pos); for (int i = 0; i < mvlist.Size(); ++i) { Move mvi = mvlist[i].m_mv; if (mvi.To() != to) continue; if (mvi.Piece() != piece) continue; if (mvi.From() == from) continue; if (!pos.MakeMove(mvi)) continue; pos.UnmakeMove(); ambiguity = true; // two or more pieces of the same type can move to field int row1 = Row(mvi.From()); int col1 = Col(mvi.From()); if (row0 == row1) uniq_row = 0; if (col0 == col1) uniq_col = 0; } if (ambiguity) { if (uniq_col) strFrom = FldToStr(from).substr(0, 1); else if (uniq_row) strFrom = FldToStr(from).substr(1, 1); else strFrom = FldToStr(from); } return strPiece + strFrom + strCaptured + strTo + strPromotion; }