public void DrawLayout(Graphics g) { if (layout_ == null) { return; } SolidBrush blackBrush = new SolidBrush(Color.Black); Pen inLinePen = new Pen(blackBrush); foreach (Pieces pieces in piecesList_) { GoPoint dian = layout_.GetPoint(pieces.Coord.Row, pieces.Coord.Col); if (dian.Type == GoPointType.BLACK) { PointF center = GetCenter(pieces.Coord); g.DrawImage(Pieces.black_, center.X - 9, center.Y - 9, 18, 18); //g.FillRectangle(blackBrush, center.X - 5, center.Y - 5, 10, 10); } else if (dian.Type == GoPointType.WHITE) { PointF center = GetCenter(pieces.Coord); g.DrawImage(Pieces.white_, center.X - 9, center.Y - 9, 18, 18); //g.DrawRectangle(inLinePen, center.X - 5, center.Y - 5, 10, 10); } } }
// @return True if the specified color can play in the given Point public bool IsValidPlay(Vector2 point, GoColor colorStone) { int x = (int)point.x; int y = (int)point.y; // Check: If Point is empty. If not, we cannot play there if (!IsPointEmpty(point)) { Debug.Log("[GB] Could not create @ ( " + x + ", " + y + "); already occupied"); return(false); } // Check: If new Stone would be immediately be captured if (IsGroupCaptured(point, colorStone)) { // If a Stone would immediately be captured, we can play it // IFF that move would capture enemy Stone(s) // AND we aren't violating the rule of Ko List <Vector2> list_blocked = new List <Vector2>(); list_blocked.Add(point); // Check adjacent spots to see if we can capture enemy Stone(s) List <Vector2> list_adjacent = GetAdjacentPoints(point); bool b_capture_detected = false; foreach (Vector2 point_adj in list_adjacent) { GoPoint gp_adj = gridPoints[(int)point_adj.x, (int)point_adj.y]; // We only care about checking against enemy stones GoStone stone_adj = gp_adj.GetStone(); if (stone_adj.Color != colorStone) { b_capture_detected |= IsGroupCaptured(point_adj, stone_adj.Color, list_blocked); } } // If no captured were found, play is illegal if (!b_capture_detected) { Debug.Log("[GB] Could not create @ ( " + x + ", " + y + "); illegal move (surrounded)"); return(false); } // Check for Ko else { GoTurn turn_prev = gameStateManager.GetTurnPrev(); if (turn_prev.piecesCaptured == 1 && IsGroupCaptured(turn_prev.pointPlay, turn_prev.turnColor, list_blocked)) { Debug.Log("[GB] Could not create @ ( " + x + ", " + y + "); illegal move (Ko)"); return(false); } } } return(true); }
private void CheckDian(GoLayout layout, int row, int col, GoPointType type) { GoPoint dian = layout.GetPoint(row, col); if (dian == null) { throw new Exception("Dian get error"); } Assert.AreEqual(dian.Type, type); }
// Place piece on the board and handle board state management private void PlacePiece(GoStone piece, Vector2 pointGrid) { int point_x = (int)pointGrid.x; int point_y = (int)pointGrid.y; GoPoint point_center = gridPoints[point_x, point_y]; GoColor color_attacker = piece.Color; GoColor color_enemy = (color_attacker == GoColor.GC_Black ? GoColor.GC_White : GoColor.GC_Black); // Place GoPiece GameObject in the GoPoint point_center.SetPiece(piece); //// Decrement neighboring point's empty count //UpdateAdjacentEmptySpaces(pointGrid, (color_attacker == GoColor.GC_Black)); // Check if we have captured any enemy pieces (Up/Down/Left/Right Queue <Vector2> queue_adjacents = new Queue <Vector2>(); List <Vector2> list_adj = GetAdjacentPoints(pointGrid); foreach (Vector2 point_adj in list_adj) { queue_adjacents.Enqueue(point_adj); } int count_captured = 0; while (queue_adjacents.Count > 0) { // Retrieve Vector2 Vector2 vec_curr = queue_adjacents.Dequeue(); // Check if valid if (IsValidPoint(vec_curr)) { // Retrieve GoPoint GoPoint point_curr = gridPoints[(int)vec_curr.x, (int)vec_curr.y]; // Check if valid, if enemy color if (!point_curr.IsEmpty() && point_curr.GetStone().Color == color_enemy) { // If so, check if surrounded. if (IsGroupCaptured(vec_curr, color_enemy)) { // If so, remove group and report score to GoStateManager count_captured += TryCaptureGroup(vec_curr, color_enemy); } } } } // Report captured stones if (count_captured > 0) { gameStateManager.OnStonesCaptured(color_attacker, count_captured); } }
public void CheckVisitStatus(GoLayout layout) { for (int i = 0; i < layout.Size; i++) { for (int j = 0; j < layout.Size; j++) { GoPoint dian = layout.GetPoint(i, j); Assert.AreEqual(false, dian.IsVisited()); } } }
void Layout_DianChanged() { piecesList_.Clear(); if (layout_ == null) { return; } for (int i = 0; i < GoLayout.SIZE; i++) { for (int j = 0; j < GoLayout.SIZE; j++) { GoPoint dian = layout_.GetPoint(i, j); if (dian.Type != GoPointType.EMPTY) { piecesList_.Add(new Pieces(i, j, dian.Type)); } } } }
// Use this for initialization void Start() { // Calculate the length of a grid square's size, in pixels :NOTE: assuming our board's grid is square txtGridSquareLengthSide = texturePlayfieldDimensions.x / (gridSize - 1); // Calculate grid pos radius (squared) txtGridPosRadiusSq = (txtGridSquareLengthSide) * 0.25f; txtGridPosRadiusSq *= txtGridPosRadiusSq; // Populate the grid points 2D array gridPoints = new GoPoint[gridSize, gridSize]; for (int x = 0; x < gridSize; x++) { for (int y = 0; y < gridSize; y++) { // Calculate vectors Vector2 point_board = new Vector2(x, y); Vector2 pos_txt = textureCoordsUL + (txtGridSquareLengthSide * new Vector2(x, y)); // Convert grid position to board's local position float pos_x = transform.localScale.x * (((point_board.x * txtGridSquareLengthSide) + textureCoordsUL.x) / textureDimensions.x); pos_x -= (0.5f * transform.localScale.x); float pos_z = transform.localScale.z * (((point_board.y * txtGridSquareLengthSide) + textureCoordsUL.y) / textureDimensions.y); pos_z -= (0.5f * transform.localScale.z); Vector3 pos_3D = new Vector3(pos_x, 0.0f, pos_z); // Set up adjacency flags for current point (Up/Right/Down/Left) int flags_adjacent = 0x0000; flags_adjacent |= ((y == (gridSize - 1) ? GoPoint.FLAG_NONE : GoPoint.FLAG_EMPTY) << GoPoint.OFFSET_U); flags_adjacent |= ((y == 0 ? GoPoint.FLAG_NONE : GoPoint.FLAG_EMPTY) << GoPoint.OFFSET_D); flags_adjacent |= ((x == 0 ? GoPoint.FLAG_NONE : GoPoint.FLAG_EMPTY) << GoPoint.OFFSET_L); flags_adjacent |= ((x == (gridSize - 1) ? GoPoint.FLAG_NONE : GoPoint.FLAG_EMPTY) << GoPoint.OFFSET_R); // Create Point gridPoints[x, y] = new GoPoint(point_board, pos_txt, pos_3D, flags_adjacent); } } }
// Retrieve immediately adjacent liberties for a given point. // Allied adjacent stones do NOT count as liberties. // @param point Point on the board to check for liberties // @return # of empy adjacent spaces public int GetLibertiesAdjacent(Vector2 point) { // Return -1 if invalid point if (!IsValidPoint(point)) { return(-1); } // Otherwise, count # of empty adjacent points int count_liberties = 0; List <Vector2> list_adj = GetAdjacentPoints(point); foreach (Vector2 point_adj in list_adj) { GoPoint gp_adj = gridPoints[(int)point_adj.x, (int)point_adj.y]; if (gp_adj.IsEmpty()) { count_liberties++; } } return(count_liberties); }
// Factory // Create new Group for a given point on the board public static GroupInfo CreateGroup(GoBoard board, Vector2 point) { // Sanity Check: Cannot create group if point is not valid if (!board.IsValidPoint(point)) { return(null); } GroupInfo group = new GroupInfo(); // Create hash to store all points that have been checked HashSet <GoPoint> hash_group = new HashSet <GoPoint>(); // Create queue to store list of points that need to be checked Queue <GoPoint> queue_points = new Queue <GoPoint>(); int x_curr = (int)point.x; int y_curr = (int)point.y; // Use initial point to determine the group's State (Empty/Black/White) GoPoint point_curr = board.gridPoints[x_curr, y_curr]; group.groupType = point_curr.PointState; // Queue initial point queue_points.Enqueue(board.gridPoints[x_curr, y_curr]); while (queue_points.Count > 0) { // Retrieve next point point_curr = queue_points.Dequeue(); x_curr = (int)point_curr.PointBoard.x; y_curr = (int)point_curr.PointBoard.y; bool b_state_same = false; // Only proceed if we haven't seen this point yet if (!hash_group.Contains(point_curr)) { // Check current point is the same state as our Group if (point_curr.PointState == group.GroupType) { b_state_same = true; } } // If same, then we want to add it to our Group and check adjacent points if (b_state_same) { // Add Point to Group group.GroupPoints.Add(point_curr.PointBoard); // Retrieve adjacent points if allied List <Vector2> list_adj = board.GetAdjacentPoints(point_curr.PointBoard); foreach (Vector2 point_adj in list_adj) { queue_points.Enqueue(board.gridPoints[(int)point_adj.x, (int)point_adj.y]); } } // Mark GoPoint as checked hash_group.Add(point_curr); } // If our Group's type is not territory, check for liberties if (group.GroupType != GoColor.GC_Empty) { foreach (Vector2 gp_curr in group.GroupPoints) { List <Vector2> points_adj = board.GetAdjacentPoints(gp_curr); foreach (Vector2 point_adj in points_adj) { if (board.GetPoint(point_adj).IsEmpty()) { group.groupLiberties.Add(point_adj); } } } } return(group); }
// @param listExcludes List of board Points that will not be checkable. Used to simulate empty spaces actually having enemy Stones within public bool IsGroupCaptured(Vector2 point, GoColor groupColor, List <Vector2> listExcludes) { // Check: Bounds if (!IsValidPoint(point)) { return(false); } int x_start = (int)point.x; int y_start = (int)point.y; // Create hash to store all points that have been checked HashSet <GoPoint> hash_group = new HashSet <GoPoint>(); // Create queue to store list of points that need to be checked Queue <GoPoint> queue_points = new Queue <GoPoint>(); // Insert excluded points into our HashSet foreach (Vector2 point_exclude in listExcludes) { if (IsValidPoint(point_exclude)) { hash_group.Add(gridPoints[(int)point_exclude.x, (int)point_exclude.y]); } } int x_curr = x_start; int y_curr = y_start; GoPoint point_curr = gridPoints[x_curr, y_curr]; bool b_first = true; // We don't want to check the Point/Stone at the initial position; so we can check even if no Stone is placed yet while (b_first || queue_points.Count > 0) { bool b_allied_piece = (b_first || false); // Check current point's Stone (or lack thereof) if (!b_first) { // Retrieve next point point_curr = queue_points.Dequeue(); x_curr = (int)point_curr.PointBoard.x; y_curr = (int)point_curr.PointBoard.y; // Only proceed if we haven't seen this point yet if (!hash_group.Contains(point_curr)) { // If we don't find a stone, then there is at least one open space and the group is not captured if (point_curr.IsEmpty()) { return(false); } // Next, check if we have found an enemy Stone. If so, we don't want to check adjacent spaces if (point_curr.GetStone().Color == groupColor) { b_allied_piece = true; } } } // We only want to skip the checks for our initial point b_first = false; // Retrieve adjacent points if allied if (b_allied_piece) { List <Vector2> list_adj = GetAdjacentPoints(point_curr.PointBoard); foreach (Vector2 point_adj in list_adj) { queue_points.Enqueue(gridPoints[(int)point_adj.x, (int)point_adj.y]); } } // Mark GoPoint as checked hash_group.Add(point_curr); } // If we run out of points to check without having found an empty spot, this group is captured return(true); }