/// <summary> /// Player removes follower from tile. /// </summary> /// <param name="player">Color of player making the move.</param> /// <param name="coords">Coordinates of tile where follower is placed.</param> /// <exception cref="GameException">Exeption describing the error.</exception> public void RemoveFollower(PlayerColor player, Coords coords) { // Check if correct player is making the request if (CurrentGameState.Params.PlayerOrder[CurrentGameState.CurrentPlayerIndex] != player) { throw new NotOnMoveException(); } // Check if it is correct time to place a tile if (CurrentGameState.CurrentPhase != GamePhase.TILE_PLACED) { throw new WrongMovePhaseException(); } // Retrieve the follower placement var correctFollowers = CurrentGameState.PlacedFollowers.Where(f => f.Color == player && f.TileCoords == coords).ToList(); // Check if exactly one place is found if (correctFollowers.Count() != 1) { throw new IncorrectFollowerCoordsException(); } // Retrieve the score var score = GridExplorer.GetPointsForFollower(CurrentGameState.Grid, coords, correctFollowers[0].RegionId, forceOpen: false); // Remove the follower CurrentGameState.PlacedFollowers.Remove(correctFollowers[0]); CurrentGameState.Grid[coords].PlacedFollower = null; CurrentGameState.Scores[player] += score; FollowerRemovedEvent.Invoke(player, coords, score); // Also finish the move FinishMove(); }
/// <summary> /// Player places tile on a grid. /// </summary> /// <param name="player">Color of player making the move.</param> /// <param name="tile">Tile that is being placed.</param> /// <param name="coords">Coordinates of tile.</param> /// <param name="orientation">Orientation of the tile.</param> /// <exception cref="GameException">Exeption describing the error.</exception> public void PlaceTile(PlayerColor player, TileScheme tile, Coords coords, TileOrientation orientation) { // Check if the first tile is being placed if (player == PlayerColor.NONE && (CurrentGameState.CurrentPhase == GamePhase.BEFORE_START || _TileSetType != TileSetType.STANDARD)) { // Check the tile placement GridExplorer.CheckTilePlacement(CurrentGameState.Grid, tile, coords, orientation, first: true); if (_TileSetType == TileSetType.STANDARD_PASSIVE) { ((StandardPassiveTileSetSupplier)CurrentGameState.TileSupplier).DiscardTile(tile); } CurrentGameState.Grid.Add(coords, new TilePlacement() { Orientation = orientation, Scheme = tile }); TilePlacedEvent.Invoke(PlayerColor.NONE, tile, coords, orientation); return; } // Check if correct player is making the request if (CurrentGameState.Params.PlayerOrder[CurrentGameState.CurrentPlayerIndex] != player) { throw new NotOnMoveException(); } // Check if it is correct time to place a tile if (CurrentGameState.CurrentPhase != GamePhase.TILE_SELECTED) { throw new WrongMovePhaseException(); } // Check if tile is the same if ((_TileSetType == TileSetType.STANDARD) && !CurrentGameState.CurrentTile.IsSameAs(tile)) { throw new WrongTileException(); } // Check the tile placement GridExplorer.CheckTilePlacement(CurrentGameState.Grid, tile, coords, orientation, first: false); // Place the tile CurrentGameState.Grid.Add(coords, new TilePlacement() { Orientation = orientation, Scheme = tile }); CurrentGameState.CurrentCoords = coords; CurrentGameState.CurrentPhase = GamePhase.TILE_PLACED; TilePlacedEvent.Invoke(player, tile, coords, orientation); if (_TileSetType == TileSetType.STANDARD_PASSIVE) { ((StandardPassiveTileSetSupplier)CurrentGameState.TileSupplier).DiscardTile(tile); } }
/// <summary> /// Player places follower on a region. /// </summary> /// <param name="player">Color of player making the move.</param> /// <param name="coords">Coordinates of tile.</param> /// <param name="regionId">Region ID on tile.</param> /// <exception cref="GameException">Exeption describing the error.</exception> public void PlaceFollower(PlayerColor player, Coords coords, int regionId) { // Check if correct player is making the request if (CurrentGameState.Params.PlayerOrder[CurrentGameState.CurrentPlayerIndex] != player) { throw new NotOnMoveException(); } // Check if it is correct time to place a tile if (CurrentGameState.CurrentPhase != GamePhase.TILE_PLACED) { throw new WrongMovePhaseException(); } // Check if coordinates of tile follower corresponds to the current tile coordinates if (CurrentGameState.CurrentCoords != coords) { throw new IncorrectFollowerCoordsException(); } // Check if player has any unoccupied follower if (CurrentGameState.PlacedFollowers.Where(f => f.Color == player).Count() >= CurrentGameState.Params.FollowerAmount) { throw new NoFollowerAvailableException(); } // Check follower placement (whether region is occupied) if (GridExplorer.IsRegionOccupied(CurrentGameState.Grid, coords, regionId)) { throw new AlreadyOccupiedException(); } // Place the follower var tileInfo = CurrentGameState.Grid[coords]; tileInfo.PlacedFollower = new FollowerPlacement() { Color = player, RegionId = regionId, TileCoords = coords }; // Add follower placement info to the list CurrentGameState.PlacedFollowers.Add(tileInfo.PlacedFollower); // Invoke the event FollowerPlacedEvent.Invoke(player, coords, regionId); // Also finish the move FinishMove(); }
/// <summary> /// Finishes the game. /// </summary> private void FinishGame() { // Retrieve remaining followers FollowerPlacement[] remaining = new FollowerPlacement[CurrentGameState.PlacedFollowers.Count]; CurrentGameState.PlacedFollowers.CopyTo(remaining); // Remove remaining followers foreach (var fp in remaining) { // Retrieve the score var score = GridExplorer.GetPointsForFollower(CurrentGameState.Grid, fp.TileCoords, fp.RegionId, forceOpen: true); // Remove the follower CurrentGameState.Scores[fp.Color] += score; FollowerRemovedEvent.Invoke(fp.Color, fp.TileCoords, score); } // Notify about end of the game and change state type CurrentGameState.CurrentPhase = GamePhase.GAME_OVER; GameEndedEvent.Invoke(); }