void GoBook::Add(const GoBoard& bd, SgPoint move) { if (move != SG_PASS && bd.Occupied(move)) throw SgException("point is not empty"); if (! bd.IsLegal(move)) throw SgException("move is not legal"); const GoBook::MapEntry* mapEntry = LookupEntry(bd); if (mapEntry == 0) { vector<SgPoint> moves; moves.push_back(move); GoBoard tempBoard; InsertEntry(GetSequence(bd), moves, bd.Size(), tempBoard, 0); } else { size_t id = mapEntry->m_id; SG_ASSERT(id < m_entries.size()); Entry& entry = m_entries[id]; int invRotation = SgPointUtil::InvRotation(mapEntry->m_rotation); SgPoint rotMove = SgPointUtil::Rotate(invRotation, move, bd.Size()); if (! Contains(entry.m_moves, rotMove)) entry.m_moves.push_back(rotMove); } }
GoSetup GoSetupUtil::CurrentPosSetup(const GoBoard& bd) { GoSetup setup; setup.m_player = bd.ToPlay(); for (GoBoard::Iterator it2(bd); it2; ++it2) { SgPoint p = *it2; if (bd.Occupied(p)) setup.m_stones[bd.GetColor(p)].Include(p); } return setup; }
int GoEyeUtil::CountSinglePointEyes2(const GoBoard& board, SgPoint p) { if (! board.Occupied(p)) return 0; SgBlackWhite color = board.GetColor(p); int numeyes = 0; for (GoBoard::LibertyIterator lib(board, p); lib; ++lib) { if (IsSinglePointEye2(board, *lib, color)) numeyes++; } return numeyes; }
GoLadderStatus GoLadderUtil::LadderStatus(const GoBoard& bd, SgPoint prey, bool twoLibIsEscape, SgPoint* toCapture, SgPoint* toEscape) { SG_ASSERT(bd.IsValidPoint(prey)); SG_ASSERT(bd.Occupied(prey)); #ifndef NDEBUG SgHashCode oldHash = bd.GetHashCode(); #endif // Unsettled only if can capture when hunter plays first, and can escape // if prey plays first. GoLadder ladder; SgBlackWhite preyColor = bd.GetStone(prey); SgVector<SgPoint> captureSequence; GoLadderStatus status = GO_LADDER_ESCAPED; if (ladder.Ladder(bd, prey, SgOppBW(preyColor), &captureSequence, twoLibIsEscape) < 0) { SgVector<SgPoint> escapeSequence; if (ladder.Ladder(bd, prey, preyColor, &escapeSequence, twoLibIsEscape) < 0) status = GO_LADDER_CAPTURED; else { status = GO_LADDER_UNSETTLED; // Unsettled = ladder depends on who plays first, so there must // be a move that can be played. SG_ASSERT(captureSequence.NonEmpty()); // escapeSequence can be empty in 2 libs, prey to play case SG_ASSERT(twoLibIsEscape || escapeSequence.NonEmpty()); if (toCapture) *toCapture = captureSequence.Front(); if (toEscape) *toEscape = escapeSequence.IsEmpty() ? SG_PASS : escapeSequence.Front(); } } #ifndef NDEBUG // Make sure Ladder didn't change the board position. SG_ASSERT(oldHash == bd.GetHashCode()); #endif return status; }
bool GoLadderUtil::Ladder(const GoBoard& bd, SgPoint prey, SgBlackWhite toPlay, bool twoLibIsEscape, SgVector<SgPoint>* sequence) { SG_ASSERT(bd.IsValidPoint(prey)); SG_ASSERT(bd.Occupied(prey)); // @todo for an unsettled block with 2 liberties, it // immediately says it can escape, but does not return a move. // Sequence is empty. Have to special case this and look for // moves that escape from ladder myself. #ifndef NDEBUG SgHashCode oldHash = bd.GetHashCode(); #endif GoLadder ladder; int result = ladder.Ladder(bd, prey, toPlay, sequence, twoLibIsEscape); #ifndef NDEBUG // Make sure Ladder didn't change the board position. SG_ASSERT(oldHash == bd.GetHashCode()); #endif SG_ASSERT(result != 0); return (result < 0); }
void GoBoardUpdater::Update(const SgNode* node, GoBoard& bd) { ////SG_ASSERT(node != 0); m_nodes.clear(); while (node != 0) { m_nodes.push_back(node); node = node->Father(); } const SgNode* root = m_nodes[m_nodes.size() - 1]; int size = GO_DEFAULT_SIZE; SgPropInt* boardSize = static_cast<SgPropInt*>(root->Get(SG_PROP_SIZE)); if (boardSize) { size = boardSize->Value(); ////SG_ASSERT(SgUtil::InRange(size, SG_MIN_SIZE, SG_MAX_SIZE)); } bd.Init(size); for (vector<const SgNode*>::reverse_iterator it = m_nodes.rbegin(); it != m_nodes.rend(); ++it) { const SgNode* node = *it; SgEmptyBlackWhite player = GetPlayer(node); if (node->HasProp(SG_PROP_ADD_EMPTY) || node->HasProp(SG_PROP_ADD_BLACK) || node->HasProp(SG_PROP_ADD_WHITE)) { // Compute the new initial setup position to re-initialize the // board with GoSetup setup = GoSetupUtil::CurrentPosSetup(bd); if (player != SG_EMPTY) setup.m_player = player; if (node->HasProp(SG_PROP_ADD_BLACK)) { SgPropAddStone* prop = dynamic_cast<SgPropAddStone*>(node->Get(SG_PROP_ADD_BLACK)); const SgVector<SgPoint>& addBlack = prop->Value(); for (SgVectorIterator<SgPoint> it2(addBlack); it2; ++it2) { SgPoint p = *it2; setup.m_stones[SG_WHITE].Exclude(p); if (! setup.m_stones[SG_BLACK].Contains(p)) setup.AddBlack(p); } } if (node->HasProp(SG_PROP_ADD_WHITE)) { SgPropAddStone* prop = dynamic_cast<SgPropAddStone*>(node->Get(SG_PROP_ADD_WHITE)); const SgVector<SgPoint>& addWhite = prop->Value(); for (SgVectorIterator<SgPoint> it2(addWhite); it2; ++it2) { SgPoint p = *it2; setup.m_stones[SG_BLACK].Exclude(p); if (! setup.m_stones[SG_WHITE].Contains(p)) setup.AddWhite(p); } } if (node->HasProp(SG_PROP_ADD_EMPTY)) { SgPropAddStone* prop = dynamic_cast<SgPropAddStone*>(node->Get(SG_PROP_ADD_EMPTY)); const SgVector<SgPoint>& addEmpty = prop->Value(); for (SgVectorIterator<SgPoint> it2(addEmpty); it2; ++it2) { SgPoint p = *it2; setup.m_stones[SG_BLACK].Exclude(p); setup.m_stones[SG_WHITE].Exclude(p); } } bd.Init(bd.Size(), setup); } else if (player != SG_EMPTY) bd.SetToPlay(player); if (node->HasProp(SG_PROP_MOVE)) { SgPropMove* prop = dynamic_cast<SgPropMove*>(node->Get(SG_PROP_MOVE)); SgPoint p = prop->Value(); if (p == SG_PASS || ! bd.Occupied(p)) bd.Play(p, prop->Player()); } } }