/// <summary> /// Build a settlement on the board /// If you try to build too close to another building a IllegalBuildPosition is thrown /// Must be called before BuildRoad, otherwise an IllegalActionException is thrown /// </summary> /// <param name="firstTile">The intersection</param> public void BuildSettlement(Intersection intersection) { if (settlementBuilt) throw new IllegalActionException("Only one settlement may be built in a turn during the startup"); settlementPosition = intersection; controller.BuildFirstSettlement(player, intersection); settlementBuilt = true; }
private Board(Tile[][] terrain, Dictionary<Edge, int> roads, Dictionary<Intersection, Piece> settlements, int robber, Harbor[] harbors, Intersection[] inter, Edge[] edges) : this() { this.allEdges = edges; this.allIntersections = inter; this.terrain = terrain; this.roads = roads; this.settlements = settlements; this.robberLocation = robber; this.harbors = harbors; }
/// <summary> /// Let a player upgrade a settlement to a city /// If the player doesn't have enough resources to build a city a InsufficientResourcesException is thrown /// If the player tries to build at a position where he doesn't have a settlement a IllegalBuildPosition is thrown /// If the player doesn't have any more city pieces left to place a IllegalActionException is thrown /// The required resources are taken from the player and placed back at the resource bank /// The settlement previously on the location is given back to the player /// </summary> /// <param name="player">The player upgrading to a city</param> /// <param name="intersection">The intersection to upgrade to a city on</param> /// <returns></returns> public GameState BuildCity(Player player, Intersection intersection) { var r = player.Resources; if (!(r.Count(c => c == Resource.Ore) >= 3 && r.Count(c => c == Resource.Grain) >= 2)) throw new InsufficientResourcesException("Not enough resources to buy a city"); if (player.CitiesLeft == 0) throw new IllegalActionException("No more city pieces left of your color"); Piece piece = board.GetPiece(intersection); if (piece == null || piece.Player != player.Id || piece.Token != Token.Settlement) throw new IllegalBuildPositionException("The chosen position does not contain one of your settlements"); PayResource(player, Resource.Ore, 3); PayResource(player, Resource.Grain, 2); Log(new BuildPieceLogEvent(player.Id, Token.City, intersection)); player.CitiesLeft--; player.SettlementsLeft++; board = board.PlacePiece(intersection, new Piece(Token.City, player.Id)); return CurrentGamestate(); }
private IEnumerable<Intersection> GetEnds(Intersection inter, IBoard board) { return board.GetAdjacentEdges(inter).SelectMany(e => board.GetAdjacentIntersections(e)).Where(i => !i.Equals(inter)); }
private Edge GetEdgeBetween(Intersection first, Intersection second) { int[] result = first.ToArray().Where(i => second.ToArray().Contains(i)).ToArray(); if (result.Length < 2) return null; return new Edge(result[0], result[1]); }
private Edge FindBestRoad(Intersection from, IBoard board) { // find the best neighbor intersection and takes the edge to that return GetEdgeBetween(FindBestIntersection(GetEnds(from, board),board),from); }
private int DifferentTypes(Intersection inter, IBoard board) { return inter.ToArray().Select(i => board.GetTile(i).Terrain).Where(t => t != Terrain.Water && t != Terrain.Desert).Distinct().Count(); }
public Intersection[] GetAllIntersections() { if(allIntersections == null){ List<Intersection> result = new List<Intersection>(22); for (int r = 0; r < 7; r++) { for (int c = 0; c < Board.GetRowLength(r); c++) { Intersection south = null; Intersection southeast = null; if (r % 2 == 0) { if(r + 1 < 7 && c + 1 < Board.GetRowLength(r + 1)) south = new Intersection(GetTerrainIndex(r, c), GetTerrainIndex(r + 1, c), GetTerrainIndex(r + 1, c + 1)); if (r + 1 < 7 && c + 1 < Board.GetRowLength(r)) southeast = new Intersection(GetTerrainIndex(r, c), GetTerrainIndex(r, c + 1), GetTerrainIndex(r + 1, c + 1)); } else { if (r + 1 < 7 && c - 1 >= 0 && c < 6) south = new Intersection(GetTerrainIndex(r, c), GetTerrainIndex(r + 1, c - 1), GetTerrainIndex(r + 1, c)); if (r + 1 < 7 && c < 6) southeast = new Intersection(GetTerrainIndex(r, c), GetTerrainIndex(r, c + 1), GetTerrainIndex(r + 1, c)); } if (south != null && (GetTile(south.FirstTile).Terrain != Terrain.Water || GetTile(south.SecondTile).Terrain != Terrain.Water)) result.Add(south); if (southeast != null && (GetTile(southeast.FirstTile).Terrain != Terrain.Water || GetTile(southeast.SecondTile).Terrain != Terrain.Water)) result.Add(southeast); } } allIntersections = result.ToArray(); } return allIntersections.ToArray(); }
public bool CanBuildPiece(Intersection intersection) { if (GetTile(intersection.FirstTile).Terrain == Terrain.Water && GetTile(intersection.SecondTile).Terrain == Terrain.Water && GetTile(intersection.ThirdTile).Terrain == Terrain.Water) return false; return !settlements.ContainsKey(intersection); }
private void AddPiece(List<Piece> list, Intersection intersection) { Piece hit = this.GetPiece(intersection); if(hit != null) list.Add(hit); }
private int CountRoadLengthFromIntersection(int playerID, Intersection curInt, HashSet<Edge> visited, HashSet<Edge> globalVisited) { // check for break Piece curPiece = GetPiece(curInt); if(curPiece != null && curPiece.Player != playerID) return 0; // no more edges this direction // find connections var edgesOut = GetAdjacentEdges(curInt).Where(e => !visited.Contains(e) && GetRoad(e) == playerID).ToArray(); // temp array int highest = 0; foreach (var edge in edgesOut) { // add edges to visited visited.Add(edge); globalVisited.Add(edge); Intersection otherEnd = GetAdjacentIntersections(edge).First(i => !i.Equals(curInt)); int depthSearch = CountRoadLengthFromIntersection(playerID, otherEnd, visited, globalVisited); if (1 + depthSearch > highest) highest = 1 + depthSearch; visited.Remove(edge); } return highest; }
public IBoard PlacePiece(Intersection intersection, Piece p) { var newSettlements = new Dictionary<Intersection, Piece>(settlements); newSettlements[intersection] = p; return new Board(terrain, new Dictionary<Edge, int>(roads), newSettlements, robberLocation, harbors, allIntersections, allEdges); }
public bool HasNoNeighbors(Intersection intersection) { return GetAdjacentEdges(intersection). SelectMany(edge => GetAdjacentIntersections(edge)). All(inter => inter.Equals(intersection) || GetPiece(inter) == null); }
public Piece GetPiece(Intersection intersection) { return settlements.ContainsKey(intersection) ? settlements[intersection] : null; }
private int GetScore(Intersection inter, IBoard board) { return Chances(board.GetTile(inter.FirstTile).Value) + Chances(board.GetTile(inter.SecondTile).Value) + Chances(board.GetTile(inter.ThirdTile).Value); }
/// <summary> /// Let a player build a settlement without a requirement for connectivity and free of charge /// The settlement still has to follow the distance rule and cannot be placed on top of another building /// </summary> /// <param name="player">The player placing the settlement</param> /// <param name="intersection">The intersection to build a settlement on</param> public GameState BuildFirstSettlement(Player player, Intersection intersection) { if (board.GetPiece(intersection) != null) throw new IllegalBuildPositionException("The chosen position is occupied by another building"); if (!board.HasNoNeighbors(intersection)) throw new IllegalBuildPositionException("The chosen position violates the distance rule"); if (!board.CanBuildPiece(intersection)) throw new IllegalBuildPositionException("The chosen position is not valid"); player.SettlementsLeft--; board = board.PlacePiece(intersection, new Piece(Token.Settlement, player.Id)); return CurrentGamestate(); }
//Building public GameState BuildSettlement(Intersection intersection) { if (!valid) throw new IllegalActionException("Tried to perform an action on an invalid GameAction"); if (!isAfterDieRoll) throw new IllegalActionException("Tried to build before the die roll"); return controller.BuildSettlement(player, intersection); }
/// <summary> /// Let a player build a settlement /// If the player doesn't have enough resources to build a settlement a InsufficientResourcesException is thrown /// If the player tries to build too close to another building, or not connected to a road a IllegalBuildPosition is thrown /// If the player doesn't have any more settlement pieces left to place a IllegalActionException is thrown /// The required resources are taken from the player and placed back at the resource bank /// If the settlement is placed at a harbor, the harbor can be used immediately (rules p. 7 - footnote 12) /// </summary> /// <param name="player">The player building a settlement</param> /// <param name="inter">The intersection to build a settlement on</param> /// <returns></returns> public GameState BuildSettlement(Player player, Intersection inter) { var r = player.Resources; if (!(r.Contains(Resource.Grain) && r.Contains(Resource.Wool) && r.Contains(Resource.Brick) && r.Contains(Resource.Lumber))) throw new InsufficientResourcesException("Not enough resources to buy a settlement"); if (player.SettlementsLeft == 0) throw new IllegalActionException("No more settlement pieces left of your color"); if (board.GetPiece(inter) != null) throw new IllegalBuildPositionException("The chosen position is occupied by another building"); if (!board.HasNoNeighbors(inter)) throw new IllegalBuildPositionException("The chosen position violates the distance rule"); if (board.GetRoad(new Edge(inter.FirstTile,inter.SecondTile)) != player.Id && board.GetRoad(new Edge(inter.FirstTile,inter.ThirdTile)) != player.Id && board.GetRoad(new Edge(inter.SecondTile, inter.ThirdTile)) != player.Id) throw new IllegalBuildPositionException("The chosen position has no road leading to it"); if (!board.CanBuildPiece(inter)) throw new IllegalBuildPositionException("The chosen position is not valid"); PayResource(player, Resource.Grain); PayResource(player, Resource.Wool); PayResource(player, Resource.Brick); PayResource(player, Resource.Lumber); Log(new BuildPieceLogEvent(player.Id, Token.Settlement, inter)); player.SettlementsLeft--; board = board.PlacePiece(inter, new Piece(Token.Settlement, player.Id)); UpdateLongestRoad(); return CurrentGamestate(); }
public BuildPieceLogEvent(int player, Token piece, Intersection position) { Player = player; Piece = piece; this.Position = position; }
public Edge[] GetAdjacentEdges(Intersection intersection) { List<Edge> result = new List<Edge>(3); if (IsLegalEdge(new Edge(intersection.FirstTile, intersection.SecondTile))) result.Add(new Edge(intersection.FirstTile,intersection.SecondTile)); if (IsLegalEdge(new Edge(intersection.SecondTile, intersection.ThirdTile))) result.Add(new Edge(intersection.SecondTile, intersection.ThirdTile)); if (IsLegalEdge(new Edge(intersection.FirstTile, intersection.ThirdTile))) result.Add(new Edge(intersection.FirstTile, intersection.ThirdTile)); return result.ToArray(); }