public void TestGetPoints() { var hex = new HexEdge(0, 0, 1, 0); var points = hex.GetPoints(); Assert.AreEqual(2, points.Count, "A hex edge must have 2 points."); var msg = "Hex edge is missing a point."; Assert.IsTrue(points.Contains(new HexPoint(0, 0, 1, 0, 1, 1)), msg); Assert.IsTrue(points.Contains(new HexPoint(0, 0, 1, 0, 0, -1)), msg); }
public void TestGetEdges() { var hex = new HexEdge(0, 0, 1, 0); var edges = hex.GetHexagons(); Assert.AreEqual(2, edges.Count, "A hex edge must have 2 hexagons."); string msg = "Hex edge is missing a hexagon."; Assert.IsTrue(edges.Contains(new Hexagon(0, 0)), msg); Assert.IsTrue(edges.Contains(new Hexagon(1, 0)), msg); }
public void TestGetNeighborEdges() { var hex = new HexEdge(0, 0, 1, 0); var neighbors = hex.GetNeighborEdges(); Assert.AreEqual(4, neighbors.Count, "A hex edge must have 4 neighbors."); var msg = "Hex edge is missing a neighbor."; Assert.IsTrue(neighbors.Contains(new HexEdge(0, 0, 0, -1)), msg); Assert.IsTrue(neighbors.Contains(new HexEdge(1, 0, 0, -1)), msg); Assert.IsTrue(neighbors.Contains(new HexEdge(0, 0, 1, 1)), msg); Assert.IsTrue(neighbors.Contains(new HexEdge(1, 0, 1, 1)), msg); }
public void TestSerialize() { var edges = new HexEdge[] { new HexEdge(0, 0, 1, 0), new HexEdge(-2, -2, -1, -1), new HexEdge(int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue - 1), new HexEdge(int.MinValue, int.MinValue, int.MinValue, int.MinValue + 1), }; foreach (var edge in edges) { var str = edge.ToString(); var actual = new HexEdge(); actual.FromString(str); Assert.AreEqual(edge, actual, "The FromString method must produce the exact object that called the ToString method."); } }
private PointF[] HexEdgeToAbsolutePoints(HexEdge hexEdge) { var h1 = HexagonToAbsolutePoints(hexEdge.Hex1); var h2 = HexagonToAbsolutePoints(hexEdge.Hex2); var linePoints = h1.Intersect(h2).ToArray(); if (linePoints.Length == 2) return linePoints; return null; }
private void DrawRoad(Graphics gfx, HexEdge edge, Road road) { var linePoints = HexEdgeToAbsolutePoints(edge); if (linePoints != null) { Pen p1 = new Pen(Color.Black, 5f); Pen p2 = new Pen(PlayerToColor(road.Player), 4f); gfx.DrawLine(p1, linePoints[0], linePoints[1]); gfx.DrawLine(p2, linePoints[0], linePoints[1]); p1.Dispose(); p2.Dispose(); } }
private void DrawPort(Graphics gfx, HexEdge edge, Port port) { var linePoints = HexEdgeToAbsolutePoints(edge); if (linePoints != null) { Color c = port.Resource == ResourceTypes.None ? Color.Black : ResourceColorMap[port.Resource]; Brush hb = new HatchBrush(HatchStyle.Wave, c, BoardColors.Water); Pen p = new Pen(c, 2f); Pen bp = new Pen(Color.Black, 1f); var box = linePoints.GetBoundingBox(); gfx.DrawEllipse(bp, box.OffsetSize(2, 2)); gfx.DrawEllipse(p, box); gfx.FillEllipse(hb, box); bp.Dispose(); hb.Dispose(); p.Dispose(); } }
/// <summary> /// Indicates if this edge is touching another edge. /// </summary> public bool IsTouching(HexEdge edge) { return GetNeighborEdges().Contains(edge); }
/// <summary> /// Places a road for the given player at the given location. /// If it's the initial placement phase of the game, the road is free. /// Otherwise, resources will be removed from the player. /// </summary> public ActionResult PlayerPlaceRoad(int playerId, HexEdge location) { var validation = ValidatePlayerAction(PlayerTurnState.PlacingRoad, playerId); if (validation.Failed) return validation; var pr = GetPlayerFromId(playerId); if (pr.Failed) return pr; var player = pr.Data; bool startOfGame = (_gameState == GameStates.InitialPlacement); // Make sure the player doesn't place too many roads in the intial placement phase if (startOfGame) { var buildingCount = _gameBoard.GetBuildingCountForPlayer(playerId); var roadCount = _gameBoard.GetRoadCountForPlayer(playerId); var maxRoads = buildingCount; if (roadCount >= maxRoads) return ActionResult.CreateFailed("Cannot place more than 1 road per settlement during the initial placement phase."); } var placementValidation = _gameBoard.ValidateRoadPlacement(playerId, location, startOfGame); if (placementValidation.Failed) return placementValidation; var purchaseResult = player.Purchase(PurchasableItems.Road, startOfGame); if (purchaseResult.Failed) return purchaseResult; // We'll assume this succeeds because we already validated it. var placement = _gameBoard.PlaceRoad(player.Id, location, startOfGame); System.Diagnostics.Debug.Assert(placement.Succeeded); // When we place a road, do a check to see if we deserve the longest road. CheckForLongestRoad(playerId); // Update game and player states. if (_gameState == GameStates.InitialPlacement) { var buildingCount = _gameBoard.GetBuildingCountForPlayer(playerId); if (LastPlayerIsActive && buildingCount == 1) { // The "last" player gets to place twice. _playerTurnState = PlayerTurnState.PlacingBuilding; } else { // Go to the next players turn. AdvanceToNextPlayerTurn(); } } else if (_gameState == GameStates.GameInProgress) { _playerTurnState = PlayerTurnState.TakeAction; } return ActionResult.CreateSuccess(); }
private bool IsPlayerBuildingHere(int player, HexEdge edge) { foreach (var point in edge.GetPoints()) { if (IsPlayerBuildingHere(player, point)) return true; } return false; }
private bool IsEdgeInBoard(HexEdge edge) { return _validBoardEdges.Contains(edge); }
private IEnumerable<HexEdge> GetRoadPermutations(int player, HexEdge road, IEnumerable<HexEdge> allPlayerRoads, IEnumerable<HexEdge> excludeRoads) { return GetRoadPermutations(player, road, allPlayerRoads) .Where(e => !excludeRoads.Contains(e)); }
private IEnumerable<HexEdge> GetRoadPermutations(int player, HexEdge road, IEnumerable<HexEdge> allPlayerRoads) { return road.GetNeighborEdges() .Where(e => allPlayerRoads.Contains(e) && !IsEnemyPlayerBuildingHere(player, road.GetNeighborPoint(e))); // An enemy building can cut off a road. }
/// <summary> /// Returns a success result if this is a valid placement for a road. /// </summary> public ActionResult ValidateRoadPlacement(int player, HexEdge edge, bool startOfGame) { if (!IsEdgeInBoard(edge)) { return new ActionResult(false, string.Format("The road location {0} is out of bounds.", edge)); } // Do not allow removing a road. if (_roads.ContainsKey(edge)) { return new ActionResult(false, string.Format("The road location {0} is already used.", edge)); } if (startOfGame) { // Make sure this is touching a settlement owned by this player. It's the start of the game. if (!IsPlayerBuildingHere(player, edge)) { return new ActionResult(false, String.Format("The road location {0} is not near a settlement.", edge)); } } else { // We must be near a settlement, city, or another road. if (!IsPlayerBuildingHere(player, edge)) { bool isTouchingRoad = false; foreach (var surroundingRoad in edge.GetNeighborEdges()) { if (IsPlayerRoadHere(player, surroundingRoad)) { isTouchingRoad = true; break; } } if (!isTouchingRoad) { return new ActionResult(false, string.Format("The road location {0} is not near a city, settlement, or road.", edge)); } } } return ActionResult.CreateSuccess(); }
/// <summary> /// Places a new road onto the board. /// </summary> public ActionResult PlaceRoad(int player, HexEdge edge, bool startOfGame) { var validationResult = ValidateRoadPlacement(player, edge, startOfGame); if (validationResult.Failed) return validationResult; _roads[edge] = new Road(player); return ActionResult.CreateSuccess(); }
/// <summary> /// Indicates if the hexagon contains the given edge. /// </summary> public bool ContainsEdge(HexEdge edge) { return GetEdges().Contains(edge); }
private bool IsPlayerRoadHere(int player, HexEdge edge) { if (_roads.ContainsKey(edge)) { return (_roads[edge].Player == player); } return false; }
public SearchRoad(HexEdge edge, SearchRoad parent = null) { Edge = edge; Parent = parent; }
/// <summary> /// Places a road for the given player at the given location after the RoadBuilding card has been played. /// Can only be called by the active player. /// </summary> public ActionResult PlayerPlaceRoadForRoadBuilding(int playerId, HexEdge location) { var validation = ValidatePlayerAction(PlayerTurnState.RoadBuildingSelectingRoads, playerId); if (validation.Failed) return validation; var pr = GetPlayerFromId(playerId); if (pr.Failed) return pr; var player = pr.Data; // Make sure the player doesn't place too many roads if (_roadBuildingRoadsRemaining <= 0) return ActionResult.CreateFailed("Cannot place more than 2 roads with the RoadBuilding card."); var placementValidation = _gameBoard.ValidateRoadPlacement(playerId, location, false); if (placementValidation.Failed) return placementValidation; var purchaseResult = player.Purchase(PurchasableItems.Road, true); if (purchaseResult.Failed) { // If this failed, it means that the player has no more roads available. This turn state has to end. _roadBuildingRoadsRemaining = 0; _playerTurnState = PlayerTurnState.TakeAction; return purchaseResult; } var rr = _gameBoard.PlaceRoad(player.Id, location, false); if (rr.Failed) return rr; // When we place a road, do a check to see if we deserve the longest road. CheckForLongestRoad(playerId); _roadBuildingRoadsRemaining--; if (_roadBuildingRoadsRemaining <= 0) { _playerTurnState = PlayerTurnState.TakeAction; } return ActionResult.CreateSuccess(); }
/// <summary> /// Gets the point which connects two edges. /// </summary> public HexPoint GetNeighborPoint(HexEdge neighborEdge) { var point = this.GetPoints().Intersect(neighborEdge.GetPoints()).ToList(); if (point.Count != 1) throw new ArgumentException("Invalid neighbor edge."); return point[0]; }