protected bool CreateBlocksConnectionStrategy(Region accessibleLibertiesAvailable, MiaiStrategy miaiStrategy) { List <int> lUsedLiberties = new List <int>((EnclosingBlocks.Count + InteriorDefenderBlocks.Count) * 2); List <GoChain> lGoChains = new List <GoChain>(EnclosingBlocks.Count + InteriorDefenderBlocks.Count); List <GoChain> lCheckList = new List <GoChain>(lGoChains.Count); // future, if any the of the blocks only have one liberty in Accessible, then no strategy foreach (GoBlock lBlock in EnclosingBlocks) { GoChain lGoBlocks = new GoChain(lBlock, accessibleLibertiesAvailable); lGoChains.Add(lGoBlocks); lCheckList.Add(lGoBlocks); } foreach (GoBlock lBlock in InteriorDefenderBlocks) { GoChain lGoBlocks = new GoChain(lBlock, accessibleLibertiesAvailable); lGoChains.Add(lGoBlocks); lCheckList.Add(lGoBlocks); } List <int> lProtectedLiberties = GetProtectedLiberties(); // merge chains based on shared points while (lGoChains.Count != 1) { List <GoChain> lRemoved = new List <GoChain>(lGoChains.Count); List <GoChain> lChanged = new List <GoChain>(lGoChains.Count); if (Version >= 2004) { // merge chains based on protected liberty chaining if (lGoChains.Count > 1) { foreach (int lProtected in lProtectedLiberties) { int lCaptureMove = Board.AnyEmptyLibertyAround(lProtected); // Console.Error.WriteLine("Protected: " + GoBoard.Coord.ToString(lProtected) + " Stop: " + (GoBoard.Coord.ToString(lCaptureMove))); if (!lUsedLiberties.Contains(lCaptureMove)) { List <GoChain> lChains = new List <GoChain>(); foreach (GoChain lGoChain in lGoChains) { if (lGoChain.IsLiberty(lProtected)) { if (!lRemoved.Contains(lGoChain)) { lChains.Add(lGoChain); } } } if (lChains.Count >= 2) { //Console.Error.WriteLine("Merging: " + lChains[0].ToString()); //Console.Error.WriteLine(" with: " + lChains[1].ToString()); lChains[0].MergeGoChain(lChains[1]); lChanged.Add(lChains[0]); lRemoved.Add(lChains[1]); if (lChains.Count == 3) { // Console.Error.WriteLine(" and: " + lChains[1].ToString()); lChains[0].MergeGoChain(lChains[2]); lRemoved.Add(lChains[2]); } miaiStrategy.Add(lProtected, lCaptureMove); lUsedLiberties.Remove(lProtected); lUsedLiberties.Remove(lCaptureMove); } } } } foreach (GoChain lGoChain in lGoChains) { if (!lRemoved.Contains(lGoChain)) { foreach (GoChain lGoChain2 in lCheckList) { if (lGoChain != lGoChain2) { if (!lRemoved.Contains(lGoChain2)) { List <int> lSharedPoints = lGoChain.SharedLibertyPoints(lGoChain2); // sort list by best (near optimal) shared points to use if (lSharedPoints.Count >= 2) { List <int> lBestSharedPoints = new List <int>(2); // find best share points to use for the Miai Stragety // a. find points which only have one empty neightbor foreach (int lIndex in lSharedPoints) { int lEmptyNeighborCount = 0; foreach (int lNieghbor in Board.Coord.GetNeighbors(lIndex)) { if (accessibleLibertiesAvailable.Contains(lNieghbor)) { lEmptyNeighborCount++; } } if (lEmptyNeighborCount == 1) { lBestSharedPoints.Add(lIndex); if (lBestSharedPoints.Count == 2) { break; } } } // b. find point near the last use shared point (from previous step), if any if (lBestSharedPoints.Count == 1) { int lBestSharedPoint = lBestSharedPoints[0]; foreach (int lNieghbor in Board.Coord.GetNeighbors(lBestSharedPoint)) { if (lSharedPoints.Contains(lNieghbor)) { lBestSharedPoints.Add(lNieghbor); break; } } } // c. use any remaining shared points (not always optimal, but okay) if (lBestSharedPoints.Count < 2) { foreach (int lIndex in lSharedPoints) { if (!lBestSharedPoints.Contains(lIndex)) { lBestSharedPoints.Add(lIndex); if (lBestSharedPoints.Count == 2) { break; } } } } lSharedPoints = lBestSharedPoints; lGoChain.MergeGoChain(lGoChain2, lSharedPoints); lChanged.Add(lGoChain); lRemoved.Add(lGoChain2); miaiStrategy.Add(lSharedPoints[0], lSharedPoints[1]); lUsedLiberties.Remove(lSharedPoints[0]); lUsedLiberties.Remove(lSharedPoints[1]); } } } } } } } if (lChanged.Count == 0) { break; } foreach (GoChain lGoChain in lRemoved) { lGoChains.Remove(lGoChain); } lCheckList = lChanged; } if (lGoChains.Count > 1) { return(false); } foreach (int lPoint in lUsedLiberties) { accessibleLibertiesAvailable.Remove(lPoint); } return(true); }
protected bool CreateBlocksConnectionStrategy(Region accessibleLibertiesAvailable, MiaiStrategy miaiStrategy) { List<int> lUsedLiberties = new List<int>((EnclosingBlocks.Count + InteriorDefenderBlocks.Count) * 2); List<GoChain> lGoChains = new List<GoChain>(EnclosingBlocks.Count + InteriorDefenderBlocks.Count); List<GoChain> lCheckList = new List<GoChain>(lGoChains.Count); // future, if any the of the blocks only have one liberty in Accessible, then no strategy foreach (GoBlock lBlock in EnclosingBlocks) { GoChain lGoBlocks = new GoChain(lBlock, accessibleLibertiesAvailable); lGoChains.Add(lGoBlocks); lCheckList.Add(lGoBlocks); } foreach (GoBlock lBlock in InteriorDefenderBlocks) { GoChain lGoBlocks = new GoChain(lBlock, accessibleLibertiesAvailable); lGoChains.Add(lGoBlocks); lCheckList.Add(lGoBlocks); } List<int> lProtectedLiberties = GetProtectedLiberties(); // merge chains based on shared points while (lGoChains.Count != 1) { List<GoChain> lRemoved = new List<GoChain>(lGoChains.Count); List<GoChain> lChanged = new List<GoChain>(lGoChains.Count); if (Version >= 2004) { // merge chains based on protected liberty chaining if (lGoChains.Count > 1) { foreach (int lProtected in lProtectedLiberties) { int lCaptureMove = Board.AnyEmptyLibertyAround(lProtected); // Console.Error.WriteLine("Protected: " + GoBoard.Coord.ToString(lProtected) + " Stop: " + (GoBoard.Coord.ToString(lCaptureMove))); if (!lUsedLiberties.Contains(lCaptureMove)) { List<GoChain> lChains = new List<GoChain>(); foreach (GoChain lGoChain in lGoChains) if (lGoChain.IsLiberty(lProtected)) if (!lRemoved.Contains(lGoChain)) lChains.Add(lGoChain); if (lChains.Count >= 2) { //Console.Error.WriteLine("Merging: " + lChains[0].ToString()); //Console.Error.WriteLine(" with: " + lChains[1].ToString()); lChains[0].MergeGoChain(lChains[1]); lChanged.Add(lChains[0]); lRemoved.Add(lChains[1]); if (lChains.Count == 3) { // Console.Error.WriteLine(" and: " + lChains[1].ToString()); lChains[0].MergeGoChain(lChains[2]); lRemoved.Add(lChains[2]); } miaiStrategy.Add(lProtected, lCaptureMove); lUsedLiberties.Remove(lProtected); lUsedLiberties.Remove(lCaptureMove); } } } } foreach (GoChain lGoChain in lGoChains) if (!lRemoved.Contains(lGoChain)) foreach (GoChain lGoChain2 in lCheckList) if (lGoChain != lGoChain2) if (!lRemoved.Contains(lGoChain2)) { List<int> lSharedPoints = lGoChain.SharedLibertyPoints(lGoChain2); // sort list by best (near optimal) shared points to use if (lSharedPoints.Count >= 2) { List<int> lBestSharedPoints = new List<int>(2); // find best share points to use for the Miai Stragety // a. find points which only have one empty neightbor foreach (int lIndex in lSharedPoints) { int lEmptyNeighborCount = 0; foreach (int lNieghbor in Board.Coord.GetNeighbors(lIndex)) if (accessibleLibertiesAvailable.Contains(lNieghbor)) lEmptyNeighborCount++; if (lEmptyNeighborCount == 1) { lBestSharedPoints.Add(lIndex); if (lBestSharedPoints.Count == 2) break; } } // b. find point near the last use shared point (from previous step), if any if (lBestSharedPoints.Count == 1) { int lBestSharedPoint = lBestSharedPoints[0]; foreach (int lNieghbor in Board.Coord.GetNeighbors(lBestSharedPoint)) if (lSharedPoints.Contains(lNieghbor)) { lBestSharedPoints.Add(lNieghbor); break; } } // c. use any remaining shared points (not always optimal, but okay) if (lBestSharedPoints.Count < 2) foreach (int lIndex in lSharedPoints) if (!lBestSharedPoints.Contains(lIndex)) { lBestSharedPoints.Add(lIndex); if (lBestSharedPoints.Count == 2) break; } lSharedPoints = lBestSharedPoints; lGoChain.MergeGoChain(lGoChain2, lSharedPoints); lChanged.Add(lGoChain); lRemoved.Add(lGoChain2); miaiStrategy.Add(lSharedPoints[0], lSharedPoints[1]); lUsedLiberties.Remove(lSharedPoints[0]); lUsedLiberties.Remove(lSharedPoints[1]); } } } if (lChanged.Count == 0) break; foreach (GoChain lGoChain in lRemoved) lGoChains.Remove(lGoChain); lCheckList = lChanged; } if (lGoChains.Count > 1) return false; foreach (int lPoint in lUsedLiberties) accessibleLibertiesAvailable.Remove(lPoint); return true; }
public bool IsOneVital() { if (Is1Vital.IsKnown) { return(Is1Vital.IsTrue); } if (EnclosingBlocks.Count == 0) { Is1Vital = TriState.False; return(false); } // step 1 // build miai stragety MiaiStrategy = new MiaiStrategy(); Region lAccessibleLibertiesAvailable = new Region(AccessibleLiberties); if (!CreateBlocksConnectionStrategy(lAccessibleLibertiesAvailable, MiaiStrategy)) { Is1Vital = TriState.False; return(false); } // step 2 // future: add miai accessible interior empty points to the set of accessible liberties, // and also use protected liberties for the chaining. Region lNewAccessibleRegion = new Region(AccessibleLiberties); foreach (GoBlock lGoBlock in InteriorDefenderBlocks) { lNewAccessibleRegion.Add(lGoBlock.Liberties); } // step 2a - add miai accessible interior empty points to the set of accessible liberties // rough implementation Region lMiaiAccessibleInteriorRegion = new Region(Board.BoardSize); if (Version >= 2004) { foreach (int lIndex in EmptyArea) { if (!lNewAccessibleRegion.Contains(lIndex)) { List <int> llAccessibleNeighborPoints = new List <int>(4); foreach (int lNeighbor in Board.Coord.GetNeighbors(lIndex)) { if (lNewAccessibleRegion.Contains(lNeighbor)) { llAccessibleNeighborPoints.Add(lNeighbor); } } if (llAccessibleNeighborPoints.Count >= 2) { lMiaiAccessibleInteriorRegion.Add(lIndex); } } } } lNewAccessibleRegion.Add(lMiaiAccessibleInteriorRegion); // step 3 Region lEmptyAndNotAccessible = new Region(EmptyArea); lEmptyAndNotAccessible.Remove(lNewAccessibleRegion); List <int> lList = lEmptyAndNotAccessible.ToList(); int lMinAdjacent = 2; while (lList.Count != 0) { List <int> lRemove = new List <int>(); foreach (int lIndex in lList) { List <int> lAccessibleLibertiesForPoint = new List <int>(4); foreach (int lNeighbor in Board.Coord.GetNeighbors(lIndex)) { if (lNewAccessibleRegion.Contains(lNeighbor)) { lAccessibleLibertiesForPoint.Add(lNeighbor); } } if (lAccessibleLibertiesForPoint.Count < 2) { Is1Vital = TriState.False; return(false); } if ((lAccessibleLibertiesForPoint.Count == 2) || (lAccessibleLibertiesForPoint.Count == lMinAdjacent)) { lNewAccessibleRegion.Remove(lAccessibleLibertiesForPoint[0]); lNewAccessibleRegion.Remove(lAccessibleLibertiesForPoint[1]); MiaiStrategy.Add(lIndex, lAccessibleLibertiesForPoint[0], lAccessibleLibertiesForPoint[1]); lRemove.Add(lIndex); lMinAdjacent = 2; } } if (lList.Count == lRemove.Count) { lList.Clear(); } else { foreach (int lPoint in lRemove) { lList.Remove(lPoint); } } if (lRemove.Count == 0) { lMinAdjacent++; } } Is1Vital = TriState.True; return(true); }
public bool IsOneVital() { if (Is1Vital.IsKnown) return (Is1Vital.IsTrue); if (EnclosingBlocks.Count == 0) { Is1Vital = TriState.False; return false; } // step 1 // build miai stragety MiaiStrategy = new MiaiStrategy(); Region lAccessibleLibertiesAvailable = new Region(AccessibleLiberties); if (!CreateBlocksConnectionStrategy(lAccessibleLibertiesAvailable, MiaiStrategy)) { Is1Vital = TriState.False; return false; } // step 2 // future: add miai accessible interior empty points to the set of accessible liberties, // and also use protected liberties for the chaining. Region lNewAccessibleRegion = new Region(AccessibleLiberties); foreach (GoBlock lGoBlock in InteriorDefenderBlocks) lNewAccessibleRegion.Add(lGoBlock.Liberties); // step 2a - add miai accessible interior empty points to the set of accessible liberties // rough implementation Region lMiaiAccessibleInteriorRegion = new Region(Board.BoardSize); if (Version >= 2004) { foreach (int lIndex in EmptyArea) if (!lNewAccessibleRegion.Contains(lIndex)) { List<int> llAccessibleNeighborPoints = new List<int>(4); foreach (int lNeighbor in Board.Coord.GetNeighbors(lIndex)) if (lNewAccessibleRegion.Contains(lNeighbor)) llAccessibleNeighborPoints.Add(lNeighbor); if (llAccessibleNeighborPoints.Count >= 2) { lMiaiAccessibleInteriorRegion.Add(lIndex); } } } lNewAccessibleRegion.Add(lMiaiAccessibleInteriorRegion); // step 3 Region lEmptyAndNotAccessible = new Region(EmptyArea); lEmptyAndNotAccessible.Remove(lNewAccessibleRegion); List<int> lList = lEmptyAndNotAccessible.ToList(); int lMinAdjacent = 2; while (lList.Count != 0) { List<int> lRemove = new List<int>(); foreach (int lIndex in lList) { List<int> lAccessibleLibertiesForPoint = new List<int>(4); foreach (int lNeighbor in Board.Coord.GetNeighbors(lIndex)) if (lNewAccessibleRegion.Contains(lNeighbor)) lAccessibleLibertiesForPoint.Add(lNeighbor); if (lAccessibleLibertiesForPoint.Count < 2) { Is1Vital = TriState.False; return false; } if ((lAccessibleLibertiesForPoint.Count == 2) || (lAccessibleLibertiesForPoint.Count == lMinAdjacent)) { lNewAccessibleRegion.Remove(lAccessibleLibertiesForPoint[0]); lNewAccessibleRegion.Remove(lAccessibleLibertiesForPoint[1]); MiaiStrategy.Add(lIndex, lAccessibleLibertiesForPoint[0], lAccessibleLibertiesForPoint[1]); lRemove.Add(lIndex); lMinAdjacent = 2; } } if (lList.Count == lRemove.Count) lList.Clear(); else foreach (int lPoint in lRemove) lList.Remove(lPoint); if (lRemove.Count == 0) lMinAdjacent++; } Is1Vital = TriState.True; return true; }