/// <summary> /// Creates a new hexagon edge /// </summary> public HexEdge(Hexagon hex1, Hexagon hex2) { Hex1 = hex1; Hex2 = hex2; if (!hex1.IsTouching(hex2)) throw new ArgumentException(string.Format("Invalid hexagon edge: {0}.", this)); }
/// <summary> /// Creates a new hexagon point /// </summary> public HexPoint(Hexagon hex1, Hexagon hex2, Hexagon hex3) { Hex1 = hex1; Hex2 = hex2; Hex3 = hex3; if (!hex1.IsTouching(hex2) || !hex2.IsTouching(hex3) || !hex1.IsTouching(hex3)) throw new ArgumentException(string.Format("Invalid hexagon point: {0}.", this)); }
public void TestGetNeighbors() { var hex = new Hexagon(0, 0); var neighbors = hex.GetNeighbors(); Assert.AreEqual(6, neighbors.Count, "A hexagon must have 6 neighbors."); var msg = "Hexagon is missing a neighbor."; Assert.IsTrue(neighbors.Contains(new Hexagon(1, 1)), msg); Assert.IsTrue(neighbors.Contains(new Hexagon(1, 0)), msg); Assert.IsTrue(neighbors.Contains(new Hexagon(0, -1)), msg); Assert.IsTrue(neighbors.Contains(new Hexagon(-1, -1)), msg); Assert.IsTrue(neighbors.Contains(new Hexagon(-1, 0)), msg); Assert.IsTrue(neighbors.Contains(new Hexagon(0, 1)), msg); }
public void TestGetEdges() { var hex = new Hexagon(0, 0); var edges = hex.GetEdges(); Assert.AreEqual(6, edges.Count, "A hexagon must have 6 edges."); string msg = "Hexagon is missing an edge."; Assert.IsTrue(edges.Contains(new HexEdge(0, 0, 1, 1)), msg); Assert.IsTrue(edges.Contains(new HexEdge(0, 0, 1, 0)), msg); Assert.IsTrue(edges.Contains(new HexEdge(0, 0, 0, -1)), msg); Assert.IsTrue(edges.Contains(new HexEdge(0, 0, -1, -1)), msg); Assert.IsTrue(edges.Contains(new HexEdge(0, 0, -1, 0)), msg); Assert.IsTrue(edges.Contains(new HexEdge(0, 0, 0, 1)), msg); }
public void TestGetPoint() { var hex = new Hexagon(0, 0); var msg = "Point is not correct."; var point = hex.GetPoint(PointDir.Top); Assert.AreEqual(new HexPoint(0, 0, 0, 1, 1, 1), point, msg); point = hex.GetPoint(PointDir.TopRight); Assert.AreEqual(new HexPoint(0, 0, 1, 1, 1, 0), point, msg); point = hex.GetPoint(PointDir.BottomRight); Assert.AreEqual(new HexPoint(0, 0, 1, 0, 0,-1), point, msg); point = hex.GetPoint(PointDir.Bottom); Assert.AreEqual(new HexPoint(0, 0, 0,-1,-1,-1), point, msg); point = hex.GetPoint(PointDir.BottomLeft); Assert.AreEqual(new HexPoint(0, 0,-1,-1,-1, 0), point, msg); point = hex.GetPoint(PointDir.TopLeft); Assert.AreEqual(new HexPoint(0, 0,-1, 0, 0, 1), point, msg); }
public void TestGetEdge() { var hex = new Hexagon(0, 0); var msg = "Edge is not correct."; var edge = hex.GetEdge(EdgeDir.TopRight); Assert.AreEqual(new HexEdge(0, 0, 1, 1), edge, msg); edge = hex.GetEdge(EdgeDir.Right); Assert.AreEqual(new HexEdge(0, 0, 1, 0), edge, msg); edge = hex.GetEdge(EdgeDir.BottomRight); Assert.AreEqual(new HexEdge(0, 0, 0,-1), edge, msg); edge = hex.GetEdge(EdgeDir.BottomLeft); Assert.AreEqual(new HexEdge(0, 0,-1,-1), edge, msg); edge = hex.GetEdge(EdgeDir.Left); Assert.AreEqual(new HexEdge(0, 0,-1, 0), edge, msg); edge = hex.GetEdge(EdgeDir.TopLeft); Assert.AreEqual(new HexEdge(0, 0, 0, 1), edge, msg); }
private void DrawResourceTile(Graphics gfx, Hexagon hex, ResourceTile resource) { Brush b = new SolidBrush(ResourceColorMap[resource.Resource]); Brush b2 = new SolidBrush(this.ForeColor); Pen p = new Pen(Color.Black, 1f); var hexPointsAbsolute = HexagonToAbsolutePoints(hex); gfx.FillPolygon(b, hexPointsAbsolute); gfx.DrawPolygon(p, hexPointsAbsolute); // Draw the dice number needed to collect var boundingBox = hexPointsAbsolute.GetBoundingBox(); var centerOfBox = boundingBox.GetCenter(); var size = RelativeToAbsolute(RelativeTileWidth / 2f, RelativeTileWidth / 2f); var wordsBox = centerOfBox.GetRect(size.X, size.Y); var textToDraw = string.Format("{0}\r\n({1},{2})", resource.RetrieveNumber, hex.X, hex.Y); gfx.DrawString(textToDraw, DefaultFont, b2, wordsBox); p.Dispose(); b.Dispose(); b2.Dispose(); }
private GameManager DoInitialPlacements(bool allowSevenRoll) { // This setup method will create a 3-player game with the center and far-right hexagons fully surrounded. var manager = new GameManager(); manager.AddPlayer("Billy"); // PLAYER_0 manager.AddPlayer("John"); // PLAYER_1 manager.AddPlayer("Greg"); // PLAYER_2 if (!allowSevenRoll) { var diceFieldInfo = typeof(GameManager).GetField("_dice", BindingFlags.NonPublic | BindingFlags.Instance); var dice = (diceFieldInfo != null) ? diceFieldInfo.GetValue(manager) as Dice : null; if (dice != null) { dice.ExcludeSet.Add(7); } } manager.StartNewGame(); // player 0 manager.PlayerPlaceBuilding(PLAYER_0, BuildingTypes.Settlement, Hexagon.Zero.GetPoint(PointDir.Top)); manager.PlayerPlaceRoad(PLAYER_0, Hexagon.Zero.GetEdge(EdgeDir.TopRight)); // player 1 manager.PlayerPlaceBuilding(PLAYER_1, BuildingTypes.Settlement, Hexagon.Zero.GetPoint(PointDir.BottomRight)); manager.PlayerPlaceRoad(PLAYER_1, Hexagon.Zero.GetEdge(EdgeDir.Right)); // player 2 manager.PlayerPlaceBuilding(PLAYER_2, BuildingTypes.Settlement, Hexagon.Zero.GetPoint(PointDir.BottomLeft)); manager.PlayerPlaceRoad(PLAYER_2, Hexagon.Zero.GetEdge(EdgeDir.Left)); // Create around a different hexagon since the middle is filled up. Hexagon otherHex = new Hexagon(2, 0); manager.PlayerPlaceBuilding(PLAYER_2, BuildingTypes.Settlement, otherHex.GetPoint(PointDir.BottomLeft)); manager.PlayerPlaceRoad(PLAYER_2, otherHex.GetEdge(EdgeDir.Left)); // player 1 manager.PlayerPlaceBuilding(PLAYER_1, BuildingTypes.Settlement, otherHex.GetPoint(PointDir.BottomRight)); manager.PlayerPlaceRoad(PLAYER_1, otherHex.GetEdge(EdgeDir.Right)); // player 0 manager.PlayerPlaceBuilding(PLAYER_0, BuildingTypes.Settlement, otherHex.GetPoint(PointDir.Top)); manager.PlayerPlaceRoad(PLAYER_0, otherHex.GetEdge(EdgeDir.TopRight)); Assert.AreEqual(PLAYER_0, manager.ActivePlayer.Id, "It should be player 0's turn."); Assert.AreEqual(GameStates.GameInProgress, manager.GameState, "The game state should be in the main game phase."); Assert.AreEqual(PlayerTurnState.NeedToRoll, manager.PlayerTurnState, "The player state should 'NeedToRoll'."); return manager; }
/// <summary> /// Returns true if this hexagon is touching the given hexagon. /// </summary> public bool IsTouching(Hexagon hex2) { if (this.X == hex2.X) return Math.Abs(hex2.Y - this.Y) == 1; if (this.Y == hex2.Y) return Math.Abs(hex2.X - this.X) == 1; return ((hex2.X == this.X + 1 && hex2.Y == this.Y + 1) || (hex2.X == this.X - 1 && hex2.Y == this.Y - 1)); }
private PointF[] HexagonToAbsolutePoints(Hexagon hex) { if (_hexPointMap.ContainsKey(hex)) return _hexPointMap[hex]; var hexPointsRelative = GetRelativeHexegonPoints(hex); var hexPointsAbsolute = ConvertRelativePointsToAbsolute(hexPointsRelative); _hexPointMap[hex] = hexPointsAbsolute; return hexPointsAbsolute; }
public void TestSerialize() { var hexes = new Hexagon[] { new Hexagon(0, 0), new Hexagon(1, 1), new Hexagon(134234, 3465465), new Hexagon(-134234, -3465465), new Hexagon(int.MaxValue, int.MinValue), }; foreach (var hex in hexes) { var str = hex.ToString(); var actual = new Hexagon(); actual.FromString(str); Assert.AreEqual(hex, actual, "The FromString method must produce the exact object that called the ToString method."); } }
private PointF GetIdentityHexOffset(Hexagon hex) { var newX = hex.X - (hex.Y * 0.5f); return new PointF(newX, -hex.Y); }
private PointF[] GetRelativeHexegonPoints(Hexagon hex) { PointF[] points = GetIdentityHexagonPoints(); var identityOffset = GetIdentityHexOffset(hex); for (int i = 0; i < points.Length; i++) { points[i].X = (points[i].X + identityOffset.X) * RelativeTileWidth; points[i].Y = (points[i].Y + identityOffset.Y) * RelativeTileWidth; } return points; }
public void TestGetPoints() { var hex = new Hexagon(0, 0); var points = hex.GetPoints(); Assert.AreEqual(6, points.Count, "A hexagon must have 6 points."); var msg = "Hexagon is missing a point."; Assert.IsTrue(points.Contains(new HexPoint(0, 0, 1, 1, 1, 0)), msg); Assert.IsTrue(points.Contains(new HexPoint(0, 0, 1, 0, 0, -1)), msg); Assert.IsTrue(points.Contains(new HexPoint(0, 0, 0, -1, -1, -1)), msg); Assert.IsTrue(points.Contains(new HexPoint(0, 0, -1, -1, -1, 0)), msg); Assert.IsTrue(points.Contains(new HexPoint(0, 0, -1, 0, 0, 1)), msg); Assert.IsTrue(points.Contains(new HexPoint(0, 0, 0, 1, 1, 1)), msg); }
public void TestInitialPlacementPhase() { var manager = new GameManager(); manager.AddPlayer("Billy"); // PLAYER_0 manager.AddPlayer("John"); // PLAYER_1 manager.AddPlayer("Greg"); // PLAYER_2 manager.StartNewGame(); Assert.AreEqual(GameStates.InitialPlacement, manager.GameState, "The game state should be in the initial placement phase."); Assert.AreEqual(PlayerTurnState.PlacingBuilding, manager.PlayerTurnState, "The player state should be in building placement mode."); // First, player 0 must place 1 settlement Assert.AreEqual(PLAYER_0, manager.ActivePlayer.Id, "It should be player 0's turn."); ActionResult ar; ar = manager.PlayerPlaceRoad(PLAYER_0, Hexagon.Zero.GetEdge(EdgeDir.Right)); Assert.IsTrue(ar.Failed, "The player can't build a road yet."); ar = manager.PlayerPlaceBuilding(PLAYER_0, BuildingTypes.City, Hexagon.Zero.GetPoint(PointDir.Top)); Assert.IsTrue(ar.Failed, "The player can't build a city during the initial placement phase."); ar = manager.PlayerPlaceBuilding(PLAYER_1, BuildingTypes.Settlement, Hexagon.Zero.GetPoint(PointDir.Top)); Assert.IsTrue(ar.Failed, "It is not this player's turn."); ar = manager.PlayerPlaceBuilding(PLAYER_0, BuildingTypes.Settlement, Hexagon.Zero.GetPoint(PointDir.Top)); Assert.IsTrue(ar.Succeeded, "The player should be able to place a settlement."); Assert.AreEqual(GameStates.InitialPlacement, manager.GameState, "The game state should be in the initial placement phase."); Assert.AreEqual(PlayerTurnState.PlacingRoad, manager.PlayerTurnState, "The player state should be in road placement mode."); // Now, player 0 is expected to place a road. ar = manager.PlayerPlaceBuilding(PLAYER_0, BuildingTypes.Settlement, Hexagon.Zero.GetPoint(PointDir.Bottom)); Assert.IsTrue(ar.Failed, "The player can't build a settlement during the road placement phase."); ar = manager.PlayerPlaceRoad(PLAYER_0, Hexagon.Zero.GetEdge(EdgeDir.TopRight)); Assert.IsTrue(ar.Succeeded, "The player should be able to place a road."); // Now, player 1 must place a settlement. Assert.AreEqual(PLAYER_1, manager.ActivePlayer.Id, "It should be player 1's turn."); ar = manager.PlayerPlaceBuilding(PLAYER_1, BuildingTypes.Settlement, Hexagon.Zero.GetPoint(PointDir.BottomRight)); Assert.IsTrue(ar.Succeeded, "The player should be able to place a settlement."); Assert.AreEqual(GameStates.InitialPlacement, manager.GameState, "The game state should be in the initial placement phase."); Assert.AreEqual(PlayerTurnState.PlacingRoad, manager.PlayerTurnState, "The player state should be in road placement mode."); // Now, player 1 is expected to place a road. ar = manager.PlayerPlaceRoad(PLAYER_1, Hexagon.Zero.GetEdge(EdgeDir.Right)); Assert.IsTrue(ar.Succeeded, "The player should be able to place a road."); // Player 2's turn to place a building, a road, another buliding, then another road. Assert.AreEqual(PLAYER_2, manager.ActivePlayer.Id, "It should be player 2's turn."); ar = manager.PlayerPlaceBuilding(PLAYER_2, BuildingTypes.Settlement, Hexagon.Zero.GetPoint(PointDir.BottomLeft)); Assert.IsTrue(ar.Succeeded, "The player should be able to place a settlement."); Assert.AreEqual(GameStates.InitialPlacement, manager.GameState, "The game state should be in the initial placement phase."); Assert.AreEqual(PlayerTurnState.PlacingRoad, manager.PlayerTurnState, "The player state should be in road placement mode."); ar = manager.PlayerPlaceRoad(PLAYER_2, Hexagon.Zero.GetEdge(EdgeDir.Left)); Assert.IsTrue(ar.Succeeded, "The player should be able to place a road."); Assert.AreEqual(PLAYER_2, manager.ActivePlayer.Id, "It should still be player 2's turn."); Assert.AreEqual(PlayerTurnState.PlacingBuilding, manager.PlayerTurnState, "The player state should be in road placement mode."); // Create around a different hexagon since the middle is filled up. Hexagon otherHex = new Hexagon(2, 0); ar = manager.PlayerPlaceBuilding(PLAYER_2, BuildingTypes.Settlement, otherHex.GetPoint(PointDir.BottomLeft)); Assert.IsTrue(ar.Succeeded, "The player should be able to place a settlement."); Assert.AreEqual(GameStates.InitialPlacement, manager.GameState, "The game state should be in the initial placement phase."); Assert.AreEqual(PlayerTurnState.PlacingRoad, manager.PlayerTurnState, "The player state should be in road placement mode."); ar = manager.PlayerPlaceRoad(PLAYER_2, otherHex.GetEdge(EdgeDir.Left)); Assert.IsTrue(ar.Succeeded, "The player should be able to place a road."); // Now we are counting down to player 0. It should be player 1's turn now. Assert.AreEqual(PLAYER_1, manager.ActivePlayer.Id, "It should be player 1's turn."); ar = manager.PlayerPlaceBuilding(PLAYER_1, BuildingTypes.Settlement, otherHex.GetPoint(PointDir.BottomRight)); Assert.IsTrue(ar.Succeeded, "The player should be able to place a settlement."); Assert.AreEqual(GameStates.InitialPlacement, manager.GameState, "The game state should be in the initial placement phase."); Assert.AreEqual(PlayerTurnState.PlacingRoad, manager.PlayerTurnState, "The player state should be in road placement mode."); ar = manager.PlayerPlaceRoad(PLAYER_1, otherHex.GetEdge(EdgeDir.Right)); Assert.IsTrue(ar.Succeeded, "The player should be able to place a road."); // It should be player 0's turn now. After this turn, the game should begin. Assert.AreEqual(PLAYER_0, manager.ActivePlayer.Id, "It should be player 0's turn."); ar = manager.PlayerPlaceBuilding(PLAYER_0, BuildingTypes.Settlement, otherHex.GetPoint(PointDir.Top)); Assert.IsTrue(ar.Succeeded, "The player should be able to place a settlement."); Assert.AreEqual(GameStates.InitialPlacement, manager.GameState, "The game state should be in the initial placement phase."); Assert.AreEqual(PlayerTurnState.PlacingRoad, manager.PlayerTurnState, "The player state should be in road placement mode."); ar = manager.PlayerPlaceRoad(PLAYER_0, otherHex.GetEdge(EdgeDir.TopRight)); Assert.IsTrue(ar.Succeeded, "The player should be able to place a road."); // // All done. The game should be started now. // Assert.AreEqual(PLAYER_0, manager.ActivePlayer.Id, "It should be player 0's turn."); Assert.AreEqual(GameStates.GameInProgress, manager.GameState, "The game state should be in the main game phase."); Assert.AreEqual(PlayerTurnState.NeedToRoll, manager.PlayerTurnState, "The player state should 'NeedToRoll'."); }
/// <summary> /// Creates a new game board. /// </summary> public GameBoard() { _resourceTiles = new Dictionary<Hexagon, ResourceTile>(); _roads = new Dictionary<HexEdge, Road>(); _buildings = new Dictionary<HexPoint, Building>(); _ports = new Dictionary<HexEdge, Port>(); _robberLocation = Hexagon.Zero; _robberMode = RobberMode.Normal; // Create lists of valid hexagons and points _validBoardHexagons = new List<Hexagon>(); _validBoardHexagons.AddRange(OuterHexagons); _validBoardHexagons.AddRange(InnerHexagons); _validBoardHexagons.Add(Hexagon.Zero); var tmpEdges = new List<HexEdge>(); foreach (var hex in _validBoardHexagons) tmpEdges.AddRange(hex.GetEdges()); _validBoardEdges = tmpEdges.Distinct().ToList(); var tmpPoints = new List<HexPoint>(); foreach (var hex in _validBoardHexagons) tmpPoints.AddRange(hex.GetPoints()); _validBoardPoints = tmpPoints.Distinct().ToList(); // Gets the list of border water tiles _waterHexagons = new List<Hexagon>(); foreach (var outerHexNeighbor in OuterHexagons) { // Get the out-of-bounds neighbors of all the outer ring tiles. var outerBorderTiles = outerHexNeighbor.GetNeighbors().Where(h => !_validBoardHexagons.Contains(h)); _waterHexagons.AddRange(outerBorderTiles); } _waterHexagons = _waterHexagons.Distinct().ToList(); // Get the edges that border the board. _borderEdges = _validBoardEdges.Where(e => _waterHexagons.Contains(e.Hex1) || _waterHexagons.Contains(e.Hex2)).Distinct().ToList(); }
private void SetupRobber() { foreach (var tuple in _resourceTiles) { if (tuple.Value.Resource == ResourceTypes.None) { _robberLocation = tuple.Key; return; } } _robberLocation = Hexagon.Zero; }
private bool IsHexagonInBoard(Hexagon hex) { return _validBoardHexagons.Contains(hex); }
/// <summary> /// Restores a specific board layout. /// </summary> public void RestoreBoard(IDictionary<Hexagon, ResourceTile> resourceTiles, IDictionary<HexEdge, Road> roads, IDictionary<HexPoint, Building> buildings, IDictionary<HexEdge, Port> ports, Hexagon robberLocation) { _resourceTiles = new Dictionary<Hexagon, ResourceTile>(resourceTiles); _roads = new Dictionary<HexEdge, Road>(roads); _buildings = new Dictionary<HexPoint, Building>(buildings); _ports = new Dictionary<HexEdge, Port>(ports); _robberLocation = robberLocation; }
/// <summary> /// Moves the robber to the given hex location and returns a list of players touching that hex (excluding the player moving it.) /// </summary> public ActionResult<IList<int>> MoveRobber(int player, Hexagon location) { if (!IsHexagonInBoard(location)) { return new ActionResult<IList<int>>(null, false, string.Format("The hex location {0} is out of bounds.", location)); } if (_robberLocation == location) { return new ActionResult<IList<int>>(null, false, string.Format("The hex location {0} already contains the robber.", location)); } _robberLocation = location; var points = location.GetPoints(); var buildingsTouching = _buildings.Where(b => points.Contains(b.Key)); var players = buildingsTouching.Select(b => b.Value.Player).Distinct().ToList(); players.Sort(); return new ActionResult<IList<int>>(players, true); }
/// <summary> /// Moves the robber to a new location. Can only be called by the active player. /// </summary> public ActionResult PlayerMoveRobber(int playerId, Hexagon newLocation) { var validation = ValidatePlayerAction(PlayerTurnState.PlacingRobber, playerId); if (validation.Failed) return validation; var apr = GetPlayerFromId(playerId); if (apr.Failed) return apr; var activePlayer = apr.Data; var moveResult = _gameBoard.MoveRobber(playerId, newLocation); if (moveResult.Failed) return moveResult; // Success. Check for nearby players which can be robbed. var touchingPlayers = moveResult.Data; if (touchingPlayers != null && touchingPlayers.Any()) { var playersWithCards = FilterOutPlayersWithNoCards(touchingPlayers.Where(pid => pid != playerId)); if (playersWithCards.Any()) { _playersToStealFrom.Clear(); _playersToStealFrom.AddRange(playersWithCards); _playerTurnState = PlayerTurnState.SelectingPlayerToStealFrom; } else { // No one to steal from. _playerTurnState = PlayerTurnState.TakeAction; } } else { _playerTurnState = PlayerTurnState.TakeAction; } return ActionResult.CreateSuccess(); }
private void DrawRobber(Graphics gfx, Hexagon hex) { var hexPointsAbsolute = HexagonToAbsolutePoints(hex); var boundingBox = hexPointsAbsolute.GetBoundingBox(); var centerOfBox = boundingBox.GetCenter(); var rect = centerOfBox.GetRect(8, 8); rect.Offset(RelativeToAbsolute(0, -RelativeTileWidth / 4)); Brush b = new SolidBrush(Color.Black); gfx.FillEllipse(b, rect); //gfx.FillPie(b, rect.ToRectangle(), (4.712f - .25f), (.5f)); b.Dispose(); }