private void GetValidSlides(PieceName target, Position currentPosition, HashSet <Position> visitedPositions, int currentRange, int?maxRange, MoveSet validMoves) { if (!maxRange.HasValue || currentRange < maxRange.Value) { for (int slideDirection = 0; slideDirection < EnumUtils.NumDirections; slideDirection++) { Position slidePosition = currentPosition.NeighborAt(slideDirection); if (!visitedPositions.Contains(slidePosition) && !HasPieceAt(slidePosition)) { // Slide position is open int right = EnumUtils.RightOf(slideDirection); int left = EnumUtils.LeftOf(slideDirection); if (HasPieceAt(currentPosition.NeighborAt(right)) != HasPieceAt(currentPosition.NeighborAt(left))) { // Can slide into slide position Move move = new Move(target, slidePosition); if (validMoves.Add(move)) { // Sliding from this position has not been tested yet visitedPositions.Add(move.Position); GetValidSlides(target, slidePosition, visitedPositions, currentRange + 1, maxRange, validMoves); } } } } } }
private MoveSet GetValidGrasshopperMovements(Piece targetPiece) { MoveSet validMoves = new MoveSet(); Position startingPosition = targetPiece.Position; for (int direction = 0; direction < EnumUtils.NumDirections; direction++) { Position landingPosition = startingPosition.NeighborAt(direction); int distance = 0; while (HasPieceAt(landingPosition)) { // Jump one more in the same direction landingPosition = landingPosition.NeighborAt(direction); distance++; } if (distance > 0) { // Can only move if there's at least one piece in the way Move move = new Move(targetPiece.PieceName, landingPosition); validMoves.Add(move); } } return(validMoves); }
private MoveSet GetValidPillbugSpecialAbilityMovements(Piece targetPiece) { MoveSet validMoves = new MoveSet(); Position positionAboveTargetPiece = targetPiece.Position.GetAbove(); for (int dir = 0; dir < EnumUtils.NumDirections; dir++) { Position neighbor = targetPiece.Position.NeighborAt(dir); Piece piece = GetPieceInternal(neighbor); if (null != piece && piece.PieceName != LastPieceMoved && null == piece.PieceAbove && CanMoveWithoutBreakingHive(piece)) { // Piece can be moved Move firstMove = new Move(piece.PieceName, positionAboveTargetPiece); if (GetValidBeetleMovements(piece).Contains(firstMove)) { // Piece can be moved on top Position pieceStartingPosition = piece.Position; MovePiece(piece, positionAboveTargetPiece, false); foreach (Move secondMove in GetValidBeetleMovements(piece)) { if (secondMove.Position.Stack == 0 && secondMove.Position != pieceStartingPosition) { validMoves.Add(secondMove); } } MovePiece(piece, pieceStartingPosition, false); } } } return(validMoves); }
private MoveSet GetValidSpiderMovements(Piece targetPiece) { MoveSet validMoves = new MoveSet(); // Get all slides up to 2 spots away MoveSet upToTwo = GetValidSlides(targetPiece, 2); if (upToTwo.Count > 0) { // Get all slides up to 3 spots away MoveSet upToThree = GetValidSlides(targetPiece, 3); if (upToThree.Count > 0) { // Get all slides ONLY 3 spots away upToThree.Remove(upToTwo); if (upToThree.Count > 0) { validMoves.Add(upToThree); } } } return(validMoves); }
public MoveSet GetValidMoves() { MoveSet moves = new MoveSet(); if (GameInProgress) { foreach (PieceName pieceName in CurrentTurnPieces) { moves.Add(GetValidMoves(pieceName)); } if (moves.Count == 0) { moves.Add(Move.Pass); } } return(moves); }
private MoveSet GetValidBeetleMovements(Piece targetPiece) { MoveSet validMoves = new MoveSet(); // Look in all directions for (int direction = 0; direction < EnumUtils.NumDirections; direction++) { Position newPosition = targetPiece.Position.NeighborAt(direction); Piece topNeighbor = GetPieceOnTopInternal(newPosition); // Get positions to left and right or direction we're heading int leftOfTarget = EnumUtils.LeftOf(direction); int rightOfTarget = EnumUtils.RightOf(direction); Position leftNeighborPosition = targetPiece.Position.NeighborAt(leftOfTarget); Position rightNeighborPosition = targetPiece.Position.NeighborAt(rightOfTarget); Piece topLeftNeighbor = GetPieceOnTopInternal(leftNeighborPosition); Piece topRightNeighbor = GetPieceOnTopInternal(rightNeighborPosition); // At least one neighbor is present uint currentHeight = targetPiece.Position.Stack + 1; uint destinationHeight = null != topNeighbor ? topNeighbor.Position.Stack + 1 : 0; uint topLeftNeighborHeight = null != topLeftNeighbor ? topLeftNeighbor.Position.Stack + 1 : 0; uint topRightNeighborHeight = null != topRightNeighbor ? topRightNeighbor.Position.Stack + 1 : 0; // "Take-off" beetle currentHeight--; if (!(currentHeight == 0 && destinationHeight == 0 && topLeftNeighborHeight == 0 && topRightNeighborHeight == 0)) { // Logic from http://boardgamegeek.com/wiki/page/Hive_FAQ#toc9 if (!(destinationHeight < topLeftNeighborHeight && destinationHeight < topRightNeighborHeight && currentHeight < topLeftNeighborHeight && currentHeight < topRightNeighborHeight)) { Position targetPosition = (newPosition.Stack == destinationHeight) ? newPosition : topNeighbor.Position.GetAbove(); Move targetMove = new Move(targetPiece.PieceName, targetPosition); validMoves.Add(targetMove); } } } return(validMoves); }
public static MoveSet ParseMoveStringList(Board board, string moveStringList) { if (null == board) { throw new ArgumentNullException(nameof(board)); } if (string.IsNullOrWhiteSpace(moveStringList)) { throw new ArgumentNullException(nameof(moveStringList)); } string[] split = moveStringList.Split(new char[] { MoveSet.MoveStringSeparator }, StringSplitOptions.RemoveEmptyEntries); MoveSet moves = new MoveSet(); for (int i = 0; i < split.Length; i++) { Move parseMove = ParseMoveString(board, split[i]); moves.Add(parseMove); } return(moves); }
private MoveSet GetValidLadybugMovements(Piece targetPiece) { MoveSet validMoves = new MoveSet(); Position startingPosition = targetPiece.Position; foreach (Move firstMove in GetValidBeetleMovements(targetPiece)) { if (firstMove.Position.Stack > 0) { MovePiece(targetPiece, firstMove.Position, false); foreach (Move secondMove in GetValidBeetleMovements(targetPiece)) { if (secondMove.Position.Stack > 0) { MovePiece(targetPiece, secondMove.Position, false); foreach (Move thirdMove in GetValidBeetleMovements(targetPiece)) { if (thirdMove.Position.Stack == 0 && thirdMove.Position != startingPosition) { validMoves.Add(thirdMove); } } MovePiece(targetPiece, firstMove.Position, false); } } MovePiece(targetPiece, startingPosition, false); } } return(validMoves); }
private MoveSet GetValidPlacements(Piece targetPiece) { PlayerColor targetColor = CurrentTurnColor; if (targetPiece.Color != targetColor) { return(MoveSet.EmptySet); } if (null == _cachedValidPlacementPositions) { _cachedValidPlacementPositions = new HashSet <Position>(); _visitedPlacements = new HashSet <Position>(); for (int i = 0; i < EnumUtils.NumPieceNames; i++) { Piece piece = _pieces[i]; if (null != piece && piece.InPlay && PieceIsOnTop(piece) && piece.Color == targetColor) { // Piece is in play, on the top and is the right color, look through neighbors Position bottomPosition = GetPieceOnBottom(piece).Position; _visitedPlacements.Add(bottomPosition); for (int j = 0; j < EnumUtils.NumDirections; j++) { Position neighbor = bottomPosition.NeighborAt(j); if (_visitedPlacements.Add(neighbor) && !HasPieceAt(neighbor)) { // Neighboring position is a potential, verify its neighbors are empty or same color bool validPlacement = true; for (int k = 0; k < EnumUtils.NumDirections; k++) { Position surroundingPosition = neighbor.NeighborAt(k); Piece surroundingPiece = GetPieceOnTopInternal(surroundingPosition); if (null != surroundingPiece && surroundingPiece.Color != targetColor) { validPlacement = false; break; } } if (validPlacement) { _cachedValidPlacementPositions.Add(neighbor); } } } } } #if DEBUG ValidMoveCacheMetricsSet["ValidPlacements"].Miss(); #endif } #if DEBUG else { ValidMoveCacheMetricsSet["ValidPlacements"].Hit(); } #endif MoveSet validMoves = new MoveSet(); foreach (Position validPlacement in _cachedValidPlacementPositions) { validMoves.Add(new Move(targetPiece.PieceName, validPlacement)); } return(validMoves); }
private MoveSet GetValidMovesInternal(Piece targetPiece) { if (null != targetPiece && GameInProgress) { if (targetPiece.Color == CurrentTurnColor && PlacingPieceInOrder(targetPiece)) { if (CurrentTurn == 0 && targetPiece.Color == PlayerColor.White && targetPiece.InHand) { // First move must be at the origin and not the White Queen Bee if (targetPiece.PieceName == PieceName.WhiteQueenBee) { return(MoveSet.EmptySet); } return(new MoveSet() { new Move(targetPiece.PieceName, Position.Origin) }); } else if (CurrentTurn == 1 && targetPiece.Color == PlayerColor.Black && targetPiece.InHand) { // Second move must be around the origin and not the Black Queen Bee if (targetPiece.PieceName == PieceName.BlackQueenBee) { return(MoveSet.EmptySet); } MoveSet validMoves = new MoveSet(); for (int i = 0; i < EnumUtils.NumDirections; i++) { Position neighbor = Position.Origin.NeighborAt(i); validMoves.Add(new Move(targetPiece.PieceName, neighbor)); } return(validMoves); } else if (targetPiece.InHand && (CurrentPlayerTurn != 4 || // Normal turn OR (CurrentPlayerTurn == 4 && // Turn 4 and AND (CurrentTurnQueenInPlay || (!CurrentTurnQueenInPlay && targetPiece.BugType == BugType.QueenBee))))) // Queen is in play or you're trying to play it { // Look for valid new placements return(GetValidPlacements(targetPiece)); } else if (targetPiece.PieceName != LastPieceMoved && targetPiece.InPlay && CurrentTurnQueenInPlay && PieceIsOnTop(targetPiece)) { MoveSet validMoves = new MoveSet(); if (CanMoveWithoutBreakingHive(targetPiece)) { // Look for basic valid moves of played pieces who can move switch (targetPiece.BugType) { case BugType.QueenBee: validMoves.Add(GetValidQueenBeeMovements(targetPiece)); break; case BugType.Spider: validMoves.Add(GetValidSpiderMovements(targetPiece)); break; case BugType.Beetle: validMoves.Add(GetValidBeetleMovements(targetPiece)); break; case BugType.Grasshopper: validMoves.Add(GetValidGrasshopperMovements(targetPiece)); break; case BugType.SoldierAnt: validMoves.Add(GetValidSoldierAntMovements(targetPiece)); break; case BugType.Mosquito: validMoves.Add(GetValidMosquitoMovements(targetPiece, false)); break; case BugType.Ladybug: validMoves.Add(GetValidLadybugMovements(targetPiece)); break; case BugType.Pillbug: validMoves.Add(GetValidPillbugBasicMovements(targetPiece)); validMoves.Add(GetValidPillbugSpecialAbilityMovements(targetPiece)); break; } } else { // Check for special ability moves switch (targetPiece.BugType) { case BugType.Mosquito: validMoves.Add(GetValidMosquitoMovements(targetPiece, true)); break; case BugType.Pillbug: validMoves.Add(GetValidPillbugSpecialAbilityMovements(targetPiece)); break; } } return(validMoves); } } } return(MoveSet.EmptySet); }
private MoveSet GetValidMosquitoMovements(Piece targetPiece, bool specialAbilityOnly) { if (targetPiece.Position.Stack > 0 && !specialAbilityOnly) { // Mosquito on top acts like a beetle return(GetValidBeetleMovements(targetPiece)); } MoveSet validMoves = new MoveSet(); bool[] bugTypesEvaluated = new bool[EnumUtils.NumBugTypes]; for (int dir = 0; dir < EnumUtils.NumDirections; dir++) { Position neighbor = targetPiece.Position.NeighborAt(dir); Piece piece = GetPieceOnTopInternal(neighbor); if (null != piece && !bugTypesEvaluated[(int)(piece.BugType)]) { if (specialAbilityOnly) { if (piece.BugType == BugType.Pillbug) { validMoves.Add(GetValidPillbugSpecialAbilityMovements(targetPiece)); } } else { switch (piece.BugType) { case BugType.QueenBee: validMoves.Add(GetValidQueenBeeMovements(targetPiece)); break; case BugType.Spider: validMoves.Add(GetValidSpiderMovements(targetPiece)); break; case BugType.Beetle: validMoves.Add(GetValidBeetleMovements(targetPiece)); break; case BugType.Grasshopper: validMoves.Add(GetValidGrasshopperMovements(targetPiece)); break; case BugType.SoldierAnt: validMoves.Add(GetValidSoldierAntMovements(targetPiece)); break; case BugType.Ladybug: validMoves.Add(GetValidLadybugMovements(targetPiece)); break; case BugType.Pillbug: validMoves.Add(GetValidPillbugBasicMovements(targetPiece)); validMoves.Add(GetValidPillbugSpecialAbilityMovements(targetPiece)); break; } } bugTypesEvaluated[(int)(piece.BugType)] = true; } } return(validMoves); }