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; }
SgPoint GoLadderUtil::TryLadder(const GoBoard& bd, SgPoint prey, SgBlackWhite firstPlayer) { SgVector<SgPoint> sequence; bool isCaptured = Ladder(bd, prey, firstPlayer, true, &sequence); // if move is same color as prey, we want to escape // else we want to capture. SgPoint p; if (isCaptured != (firstPlayer == bd.GetStone(prey))) p = sequence.IsEmpty() ? SG_PASS : sequence.Front(); else p = SG_NULLMOVE; return p; }