public GoChain(GoBlock goBlock, Region AccessibleLiberties) { Blocks = new List<GoBlock>(); Blocks.Add(goBlock); Liberities = new Region(goBlock.Liberties, AccessibleLiberties, Region.MergeType.And); UsedLiberities = new List<int>(); }
public Region(Region region) { Width = region.Width; Count = region.Count; Grid = new bool[Width * Width]; region.Grid.CopyTo(Grid, 0); }
public Region(Region region1, Region region2, MergeType mergeType) { Width = region1.Width; Count = region1.Count; Grid = new bool[Width * Width]; if (region1.Width != region2.Width) return; // error: can't merge unlike regions if (mergeType == MergeType.And) { for (int i = 0; i < Width * Width; i++) if ((region1.Grid[i]) && (region2.Grid[i])) Add(i); } else if (mergeType == MergeType.Or) { for (int i = 0; i < Width * Width; i++) if ((region1.Grid[i]) || (region2.Grid[i])) Add(i); } else if (mergeType == MergeType.NAnd) { for (int i = 0; i < Width * Width; i++) if ((region1.Grid[i]) && (!region2.Grid[i])) Add(i); } }
public void AddBlock(GoBlock goBlock) { Blocks.Add(goBlock); if (Liberities != null) Liberities.Add(goBlock.Liberties); else Liberities = new Region(goBlock.Liberties); }
protected static int BlockNbrCounter = 0; // used for debugging #endregion Fields #region Constructors public GoBlockBase(GoBoard goBoard, Color blockColor) { Board = goBoard; BlockColor = blockColor; AdjacentBlocks = new GoBlocksAdjacentCollection(this); Members = new Region(Board.BoardSize); MemberList = new List<int>(); BlockNbr = ++BlockNbrCounter; }
public void Remove(Region region) { if (region.Width != Width) return; // error: can't merge unlike regions if ((Count == 0) || (region.Count == 0)) return; for (int i = 0; i < Width * Width; i++) if (region.Contains(i)) Remove(i); }
public void Or(Region region) { if ((Count == 0) && (region.Count == 0)) return; if (region.Width != Width) return; // error: can't merge unlike regions for (int i = 0; i < Width * Width; i++) if (region.Contains(i)) Add(i); }
public bool IsSame(Region region) { if (Count != region.Count) return false; for (int i = 0; i < Width * Width; i++) if (region.Contains(i) != Contains(i)) return false; return true; }
public GoEmptyBlock(GoEmptyBlock goEmptyBlock, int pCutPoint, int direction) : base(goEmptyBlock.Board, Color.Empty) { Members = new Region(goEmptyBlock.Members, pCutPoint, direction); MemberList = Members.ToList(); }
/// <summary> /// Initializes a new instance of the <see cref="GoBlock"/> class. /// </summary> /// <param name="goBoard">The board.</param> /// <param name="color">The color of the block.</param> public GoBlock(GoBoard goBoard, Color color) : base(goBoard, color) { Liberties = new Region(goBoard.BoardSize); }
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 Region GetEdges() { Region lRegion = new Region(this.Width); for (int i = 0; i < Width * Width; i++) if (!IsInterior(i)) lRegion.Add(i); return lRegion; }
public void Add(Region region) { if (region.Width != Width) return; // error: can't merge unlike regions for (int i = 0; i < Width * Width; i++) if (region.Grid[i] == true) Add(i); }
public Region(Region region, int cutPoint, int start) { Width = region.Width; Count = 0; Grid = new bool[Width * Width]; CoordinateSystem lCoord = CoordinateSystem.GetCoordinateSystem(Width); if (!lCoord.OnBoard(start)) return; Stack<int> lFill = new Stack<int>(); lFill.Push(start); while (lFill.Count > 0) { int lAt = lFill.Pop(); Add(lAt); foreach (int lNeighbor in lCoord.GetNeighbors(lAt)) if ((lNeighbor != cutPoint) && (region.Contains(lNeighbor)) && (!Contains(lNeighbor))) lFill.Push(lNeighbor); } }
public List<int> SharedLibertyPoints(GoChain goChain) { List<int> lSharedLibertyPoints = new List<int>(); if ((Liberities.Count <= 1) || (goChain.Liberities.Count <= 1)) return lSharedLibertyPoints; Region lShared = new Region(Liberities, goChain.Liberities, Region.MergeType.And); foreach (int lPoint in UsedLiberities) lShared.Remove(lPoint); foreach (int lPoint in goChain.UsedLiberities) lShared.Remove(lPoint); lSharedLibertyPoints = lShared.ToList(); return lSharedLibertyPoints; }
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 Region GetInterior() { Region lRegion = new Region(this.Width); if (Count != 0) for (int i = 0; i < Width * Width; i++) if (IsInterior(i)) lRegion.Add(i); return lRegion; }
protected Region _EnclosingBlocksLibertyArea; // lazy evaluation #endregion Fields #region Constructors public ColorEnclosedRegion(GoEmptyBlock goEmptyBlock, Color defender) { Board = goEmptyBlock.Board; Defender = defender; Size = 0; Version = 2004; _RegionNbr = goEmptyBlock.BlockNbr; Members = new List<GoBlockBase>(); EmptyBlocks = new List<GoEmptyBlock>(); Neighbors = new List<GoBlock>(); InteriorAttackerBlocks = new List<GoBlock>(); Is2Vital = TriState.Unknown; Is1Vital = TriState.Unknown; IsSmall = TriState.Unknown; _EnclosedArea = null; _EmptyRegion = null; Stack<GoBlockBase> lWork = new Stack<GoBlockBase>(); lWork.Push(goEmptyBlock); while (lWork.Count != 0) { GoBlockBase lGoBlockBase = lWork.Pop(); if (!Members.Contains(lGoBlockBase)) { Members.Add(lGoBlockBase); if (lGoBlockBase.IsEmptyBlock()) { EmptyBlocks.Add((GoEmptyBlock)lGoBlockBase); Size = Size + ((GoEmptyBlock)lGoBlockBase).EmptySpaceCount; } else { InteriorAttackerBlocks.Add((GoBlock)lGoBlockBase); Size = Size + ((GoBlock)lGoBlockBase).StoneCount; } foreach (GoBlockBase lGoBlockBaseAdjacent in lGoBlockBase.AdjacentBlocks.AllBlocks) if (lGoBlockBaseAdjacent.BlockColor == Defender) { if (!Neighbors.Contains((GoBlock)lGoBlockBaseAdjacent)) Neighbors.Add((GoBlock)lGoBlockBaseAdjacent); } else if (!Members.Contains(lGoBlockBaseAdjacent)) lWork.Push(lGoBlockBaseAdjacent); } } EnclosingBlocks = new List<GoBlock>(Neighbors.Count); InteriorDefenderBlocks = new List<GoBlock>(); foreach (GoBlock lGoBlock in Neighbors) { bool lFound = false; foreach (GoEmptyBlock lGoEmptyBlock in lGoBlock.AdjacentBlocks.EmptyBlocks) { if (!EmptyBlocks.Contains(lGoEmptyBlock)) { lFound = true; break; } } if (lFound) EnclosingBlocks.Add(lGoBlock); else InteriorDefenderBlocks.Add(lGoBlock); } if (EnclosingBlocks.Count == 0) InteriorDefenderBlocks.Clear(); }
public bool Intersects(Region region) { if ((Count == 0) || (region.Count == 0)) return false; for (int i = 0; i < Width * Width; i++) if (region.Contains(i) && Contains(i)) return true; return false; }
public bool IsOnlyAdjacent(Region region) { if ((Count == 0) || (region.Count == 0)) return false; for (int i = 0; i < Width * Width; i++) if (region.Contains(i)) if (!IsAdjacent(i)) return false; return true; }
public GoEmptyBlock(GoBlock goBlock) : base(goBlock.Board, Color.Empty) { Members = new Region(goBlock.Members); MemberList = Members.ToList(); // slow might be a faster way }