public void TestSerialize() { var points = new HexPoint[] { new HexPoint(0, 0, 1, 0, 1, 1), new HexPoint(-2, -2, -2, -1, -1, -1), new HexPoint(int.MaxValue - 1, int.MaxValue - 1, int.MaxValue, int.MaxValue - 1, int.MaxValue, int.MaxValue) }; foreach (var point in points) { var str = point.ToString(); var actual = new HexPoint(); actual.FromString(str); Assert.AreEqual(point, actual, "The FromString method must produce the exact object that called the ToString method."); } }
/// <summary> /// Places a building for the given player at the given location. /// If it's the start of the game, the building is free. /// Otherwise, resources will be removed from the player. /// </summary> public ActionResult PlayerPlaceBuilding(int playerId, BuildingTypes type, HexPoint location) { var validation = ValidatePlayerAction(PlayerTurnState.PlacingBuilding, 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 buildings in the intial placement phase if (startOfGame) { if (type != BuildingTypes.Settlement) return ActionResult.CreateFailed("Can only place settlements during the initial placement phase."); var buildingCount = _gameBoard.GetBuildingCountForPlayer(playerId); var maxBuildingCount = (LastPlayerHasPlaced) ? 2 : 1; if (buildingCount >= maxBuildingCount) return ActionResult.CreateFailed("Cannot place any more settlements during the initial placement phase."); } var placementValidation = _gameBoard.ValidateBuildingPlacement(playerId, type, location, startOfGame); if (placementValidation.Failed) return placementValidation; PurchasableItems itemToBuy = (type == BuildingTypes.City) ? PurchasableItems.City : PurchasableItems.Settlement; var purchaseResult = player.Purchase(itemToBuy, startOfGame); if (purchaseResult.Failed) return purchaseResult; // We'll assume this succeeds because we already validated it. var placement = _gameBoard.PlaceBuilding(player.Id, type, location, startOfGame); System.Diagnostics.Debug.Assert(placement.Succeeded); // Update game and player states. if (_gameState == GameStates.InitialPlacement) { var buildingCount = _gameBoard.GetBuildingCountForPlayer(playerId); if (buildingCount == 2) { // We've played the second building during the setup phase. Collect resources. var resources = _gameBoard.GetResourcesForBuilding(location, BuildingTypes.Settlement); player.ResourceCards.Add(resources); } _playerTurnState = PlayerTurnState.PlacingRoad; } else if (_gameState == GameStates.GameInProgress) { _playerTurnState = PlayerTurnState.TakeAction; } return ActionResult.CreateSuccess(); }
private PointF HexPointToAbsolutePoint(HexPoint hexPoint) { var h1 = HexagonToAbsolutePoints(hexPoint.Hex1); var h2 = HexagonToAbsolutePoints(hexPoint.Hex2); var h3 = HexagonToAbsolutePoints(hexPoint.Hex3); var centerPoint = h1.Intersect(h2).Intersect(h3).ToArray(); if (centerPoint.Length == 1) return centerPoint[0]; return PointF.Empty; }
private void DrawBuilding(Graphics gfx, HexPoint point, Building building) { var centerPoint = HexPointToAbsolutePoint(point); if (centerPoint != PointF.Empty) // Should never draw a building at (0,0)... { Brush b = new SolidBrush(PlayerToColor(building.Player)); Pen p = new Pen(Color.Black, 1f); var relativeSize = (building.Type == BuildingTypes.Settlement) ? (RelativeTileWidth)*(1/5f) : (RelativeTileWidth)*(2/5f); var width = this.Width*relativeSize/100f; var height = this.Height*relativeSize/100f; var rect = centerPoint.GetRect(width, height); gfx.FillRectangle(b, rect); gfx.DrawRectangle(p, rect.X, rect.Y, rect.Width, rect.Height); b.Dispose(); p.Dispose(); } }
private bool IsPointInBoard(HexPoint point) { return _validBoardPoints.Contains(point); }
private bool IsPlayerBuildingHere(int player, HexPoint point) { if (_buildings.ContainsKey(point)) { var b = _buildings[point]; return (b.Player == player); } return false; }
/// <summary> /// Returns a success result if this is a valid placement for a building. /// </summary> public ActionResult ValidateBuildingPlacement(int player, BuildingTypes buildingType, HexPoint point, bool startOfGame) { if (!IsPointInBoard(point)) { return new ActionResult(false, string.Format("The location {0} is out of bounds.", point)); } if (_buildings.ContainsKey(point)) { if (_buildings[point].Player != player) return new ActionResult(false, string.Format("The location {0} is already used by another player.", point)); // If this play has something here, make sure that it's not a city, which can't be upgraded. if (_buildings[point].Type == BuildingTypes.City) return new ActionResult(false, string.Format("The location {0} already contains a city.", point)); // If the existing building is a settlement, make sure the building being placed is not a settlement. if (buildingType == BuildingTypes.Settlement) return new ActionResult(false, string.Format("The location {0} already contains a settlement.", point)); } // Check that there isn't a neighboring building. var buildingNearby = point.GetNeighborPoints().Any(b => _buildings.ContainsKey(b)); if (buildingNearby) { return new ActionResult(false, string.Format("The location {0} is too close to another settlement or city.", point)); } if (!startOfGame) { // Make sure the player has a road nearby. bool roadNearby = point.GetNeighborEdges().Any(r => IsPlayerRoadHere(player, r)); if (!roadNearby) { return new ActionResult(false, string.Format("The location {0} is not touching a road.", point)); } } return ActionResult.CreateSuccess(); }
/// <summary> /// Places a new building onto the board. A player is allowed to upgrade a settlement to a city. /// </summary> public ActionResult PlaceBuilding(int player, BuildingTypes buildingType, HexPoint point, bool startOfGame) { var validationResult = ValidateBuildingPlacement(player, buildingType, point, startOfGame); if (validationResult.Failed) return validationResult; _buildings[point] = new Building(player, buildingType); return ActionResult.CreateSuccess(); }
/// <summary> /// Gets the resources generated by a building location. Ignores the robber. /// </summary> public ResourceCollection GetResourcesForBuilding(HexPoint location, BuildingTypes type) { var result = new ResourceCollection(); foreach (var hex in location.GetHexes()) { if (_resourceTiles.ContainsKey(hex)) { var tile = _resourceTiles[hex]; int count = (type == BuildingTypes.Settlement) ? 1 : 2; result[tile.Resource] += count; } } return result; }
/// <summary> /// Indicates if the hexagon contains the given point. /// </summary> public bool ContainsPoint(HexPoint point) { return GetPoints().Contains(point); }