public void White_FourCaptures_OnePush_Correct() { var gameState = FenHelpers.Parse("K6k/8/8/8/8/p1p2p1p/1P4P1/8 w - -"); var board = CreateBoard(gameState); var moves = new List <uint>(10); MoveGenerator.Generate(board, gameState.ToPlay, moves); var move1 = MoveBuilder.Create(Colour.White, PieceType.Pawn, SquareFlag.B2.ToSquare(), SquareFlag.B3.ToSquare(), PieceType.None, MoveType.Ordinary); var move2 = MoveBuilder.Create(Colour.White, PieceType.Pawn, SquareFlag.G2.ToSquare(), SquareFlag.G3.ToSquare(), PieceType.None, MoveType.Ordinary); var captures = moves.Where(x => x.GetCapturePieceType() != PieceType.None); var capture1 = MoveBuilder.Create(Colour.White, PieceType.Pawn, SquareFlag.B2.ToSquare(), SquareFlag.A3.ToSquare(), PieceType.Pawn, MoveType.Ordinary); var capture2 = MoveBuilder.Create(Colour.White, PieceType.Pawn, SquareFlag.B2.ToSquare(), SquareFlag.C3.ToSquare(), PieceType.Pawn, MoveType.Ordinary); var capture3 = MoveBuilder.Create(Colour.White, PieceType.Pawn, SquareFlag.G2.ToSquare(), SquareFlag.F3.ToSquare(), PieceType.Pawn, MoveType.Ordinary); var capture4 = MoveBuilder.Create(Colour.White, PieceType.Pawn, SquareFlag.G2.ToSquare(), SquareFlag.H3.ToSquare(), PieceType.Pawn, MoveType.Ordinary); Assert.Contains(move1, moves); Assert.Contains(move2, moves); Assert.Contains(capture1, moves); Assert.Contains(capture2, moves); Assert.Contains(capture3, moves); Assert.Contains(capture4, moves); }
public void KingCannotCastleIfRookAlreadyMoved() { var kingBoard = CreateBoardWithWhiteKingAt(new Position(File.E, Rank._1)); kingBoard.AddPiece(new PieceBuilder(PieceType.Rook) .As(PieceColor.White) .At(new Position(File.A, Rank._1)) .Create()); var rookStart = (from p in kingBoard.WhitePieces where p.Type == PieceType.Rook select p).First(); kingBoard = kingBoard.PerformMove(MoveBuilder.CreateNormalMove( rookStart, rookStart.Position.MoveVert(1), false)); var rookMoveBack = (from p in kingBoard.WhitePieces where p.Type == PieceType.Rook select p).First(); kingBoard = kingBoard.PerformMove(MoveBuilder.CreateNormalMove( rookMoveBack, rookMoveBack.Position.MoveVert(-1), false)); var rookBackWhereHeStarted = (from p in kingBoard.WhitePieces where p.Type == PieceType.Rook select p).First(); Assert.Equal(new Position(File.A, Rank._1), rookBackWhereHeStarted.Position); var moves = kingBoard.GetPossibleMoves(PieceColor.White); var castleMoves = (from m in moves where m.Type == MoveType.Castle select m).ToList(); Assert.Equal(castleMoves.Count, 0); }
public void Move_AreNotEqual() { var moveA = MoveBuilder.Create(Colour.White, 0, new Models.Square(), new Models.Square(), 0, MoveType.Ordinary); var moveB = MoveBuilder.Create(Colour.Black, 0, new Models.Square(), new Models.Square(), 0, MoveType.Ordinary); Assert.NotEqual(moveA, moveB); }
public void AppendMoves(BoardSquare originSquare, Position.Position position, List <Move> moves) { var board = position.Board; var playerToMove = position.PlayerToMove; var moveDeltas = GetMoveDeltas(); var moveBuilder = new MoveBuilder(GetPiece(), originSquare); for (int i = 0; i < moveDeltas.Length; ++i) { if (!moveDeltas[i].IsCanApplyTo(originSquare)) { continue; } var destSquare = moveDeltas[i].GetDestSquare(originSquare); if (board.IsEmpty(destSquare)) { moves.Add(moveBuilder.SetDestSquare(destSquare).Build()); } else { var pieceAtDestSquare = board.GetPieceAt(destSquare); if (pieceAtDestSquare.player != playerToMove) { moves.Add(moveBuilder .SetDestSquare(destSquare) .SetCapture(pieceAtDestSquare.piece) .Build()); } } } }
private List <Move> GetAdvancingMoves(Board board) { var moves = new List <Move>(); bool canMoveTwo = false; if ((Color == PieceColor.White && Position.Rank == Rank._2) || (Color == PieceColor.Black && Position.Rank == Rank._7)) { canMoveTwo = true; } var singleMovePos = Position.MoveVert(IncrementDirection); if (board[singleMovePos] == null) { moves.Add(MoveBuilder.CreateNormalMove(this, singleMovePos, false)); } else { // Can't move two if you can't move one canMoveTwo = false; } if (canMoveTwo) { var moveTwoPos = Position.MoveVert(IncrementDirection * 2); if (board[moveTwoPos] == null) { moves.Add(MoveBuilder.CreateNormalMove(this, moveTwoPos, false)); } } return(moves); }
private List <Move> GetCapturingMoves(Board board) { var capturingMoves = new List <Move>(); if (Position.File != File.A) { var leftDiagPosition = Position .MoveVert(IncrementDirection) .MoveHoriz(-1); if (IsPositionEnemyOccupied(board, leftDiagPosition)) { capturingMoves.Add(MoveBuilder.CreateNormalMove(this, leftDiagPosition, true)); } } if (Position.File != File.H) { var rightDiagPosition = Position .MoveVert(IncrementDirection) .MoveHoriz(1); if (IsPositionEnemyOccupied(board, rightDiagPosition)) { capturingMoves.Add(MoveBuilder.CreateNormalMove(this, rightDiagPosition, true)); } } return(capturingMoves); }
public override List <Move> FindMoves(Board board) { var advancingMoves = GetAdvancingMoves(board); var capturingMoves = GetCapturingMoves(board); var advancingAndCapturingMoves = GetAdvancingMoves(board) .Concat(GetCapturingMoves(board)) .ToList(); // We need to go through and swap out capturing moves for // promotion moves if the pawn gets to the last rank var movesWithPromotions = new List <Move>(); foreach (var m in advancingAndCapturingMoves) { var newPos = m.NormalPieceMove.NewPosition; if (newPos.Rank == Rank._8 || newPos.Rank == Rank._1) { // Promotion move! movesWithPromotions.AddRange(MoveBuilder.CreatePromotionMoves(this, newPos, true)); } else { movesWithPromotions.Add(m); } } return(movesWithPromotions.Concat(GetEnPassantMoves(board)).ToList()); }
private List <Move> GetMovesWithDirection(Board board, int vertIncrement, int horizIncrement) { var moves = new List <Move>(); int r = (int)Position.Rank; int f = (int)Position.File; while (true) { r = r + vertIncrement; f = f + horizIncrement; bool validPosition = (f <= 8 && f >= 1) && (r <= 8 && r >= 1); if (!validPosition) { break; } var newPos = new Position((File)f, (Rank)r); var currentPiece = board[newPos]; if (currentPiece != null) { if (currentPiece.Color != this.Color) { // We can't go any further, but we can take! moves.Add(MoveBuilder.CreateNormalMove(this, newPos, true)); } break; } moves.Add(MoveBuilder.CreateNormalMove(this, newPos, false)); } return(moves); }
private static void AppendMoveWithPromotions(MoveBuilder moveBuilder, List <Move> moves) { moves.Add(moveBuilder.SetPromotion(Piece.Queen).Build()); moves.Add(moveBuilder.SetPromotion(Piece.Rook).Build()); moves.Add(moveBuilder.SetPromotion(Piece.Bishop).Build()); moves.Add(moveBuilder.SetPromotion(Piece.Knight).Build()); }
public void E4_16Moves_8Captures_Correct() { var gameState = FenHelpers.Parse("K7/8/2p1p1p1/8/2p1Q1p1/8/2p1p1p1/k7 w - -"); var board = CreateBoard(gameState); var moves = new List <uint>(10); MoveGenerator.Generate(board, gameState.ToPlay, moves); var moveCount = moves.Count; var captureViews = GetCaptureMoveViews(moves); var capture1 = MoveBuilder.Create(Colour.White, PieceType.Queen, SquareFlag.E4.ToSquare(), SquareFlag.C6.ToSquare(), PieceType.Pawn, MoveType.Ordinary); var capture2 = MoveBuilder.Create(Colour.White, PieceType.Queen, SquareFlag.E4.ToSquare(), SquareFlag.E6.ToSquare(), PieceType.Pawn, MoveType.Ordinary); var capture3 = MoveBuilder.Create(Colour.White, PieceType.Queen, SquareFlag.E4.ToSquare(), SquareFlag.G6.ToSquare(), PieceType.Pawn, MoveType.Ordinary); var capture4 = MoveBuilder.Create(Colour.White, PieceType.Queen, SquareFlag.E4.ToSquare(), SquareFlag.C4.ToSquare(), PieceType.Pawn, MoveType.Ordinary); var capture5 = MoveBuilder.Create(Colour.White, PieceType.Queen, SquareFlag.E4.ToSquare(), SquareFlag.G4.ToSquare(), PieceType.Pawn, MoveType.Ordinary); var capture6 = MoveBuilder.Create(Colour.White, PieceType.Queen, SquareFlag.E4.ToSquare(), SquareFlag.C2.ToSquare(), PieceType.Pawn, MoveType.Ordinary); var capture7 = MoveBuilder.Create(Colour.White, PieceType.Queen, SquareFlag.E4.ToSquare(), SquareFlag.E2.ToSquare(), PieceType.Pawn, MoveType.Ordinary); var capture8 = MoveBuilder.Create(Colour.White, PieceType.Queen, SquareFlag.E4.ToSquare(), SquareFlag.G2.ToSquare(), PieceType.Pawn, MoveType.Ordinary); var captures = captureViews.Select(x => x.Value); Assert.Contains(capture1, captures); Assert.Contains(capture2, captures); Assert.Contains(capture3, captures); Assert.Contains(capture4, captures); Assert.Contains(capture5, captures); Assert.Contains(capture6, captures); Assert.Contains(capture7, captures); Assert.Contains(capture8, captures); }
public void Board_MakeUnMake_WhiteEnPassantCapture() { var board = CreateBitBoard("K6k/8/8/3Pp3/8/8/8/8 w - e6"); var rootKey = KeyGenerator.Hash(board, Colour.White); var enPassantCapture = MoveBuilder.Create(Colour.White, PieceType.Pawn, SquareFlag.D5.ToSquare(), SquareFlag.E6.ToSquare(), PieceType.Pawn, MoveType.EnPassant); var beforeKey = board.Key; board.MakeMove(enPassantCapture); var hashKey = KeyGenerator.Hash(board, Colour.Black); var updateKey = KeyGenerator.UpdateHash(rootKey, enPassantCapture); Assert.Equal(hashKey, board.Key); Assert.Equal(updateKey, board.Key); var afterKey = board.Key; board.UnMakeMove(enPassantCapture); var hashKey2 = KeyGenerator.Hash(board, Colour.White); var updateKey2 = KeyGenerator.UpdateHash(updateKey, enPassantCapture); Assert.Equal(hashKey2, board.Key); Assert.Equal(updateKey2, board.Key); Assert.NotEqual(beforeKey, afterKey); Assert.Equal(beforeKey, board.Key); }
private void AppendRayMoves( BoardSquare originSquare, Position.Position position, MoveDelta rayDelta, List <Move> moves) { var board = position.Board; var moveBuilder = new MoveBuilder(piece, originSquare); var currentSquare = originSquare; while (rayDelta.IsCanApplyTo(currentSquare)) { currentSquare = rayDelta.GetDestSquare(currentSquare); if (board.IsEmpty(currentSquare)) { moves.Add(moveBuilder.SetDestSquare(currentSquare).Build()); } else { var obstacle = board.GetPieceAt(currentSquare); if (obstacle.player != position.PlayerToMove) { moves.Add(moveBuilder .SetDestSquare(currentSquare) .SetCapture(obstacle.piece) .Build()); } break; } } }
public override List <Move> FindMoves(Board board) { var moves = new List <Move>(); int[] indices = new int[] { -2, -1, 1, 2 }; foreach (int x in indices) { foreach (int y in indices) { if (Math.Abs(x) == Math.Abs(y)) { continue; } if (!Position.IsOnBoard((int)Position.Rank + y, (int)Position.File + x)) { continue; } var newPos = Position.MoveHoriz(x).MoveVert(y); bool enemyOccupied = (board[newPos]?.Color.Opposite() == this.Color); moves.Add(MoveBuilder.CreateNormalMove(this, newPos, enemyOccupied)); } } return(moves); }
private List <Move> GetMovesInDirection(Board board, int vert, int horiz) { var moves = new List <Move>(); int currentRank = (int)Position.Rank; int currentFile = (int)Position.File; int magnitude = 1; while (true) { int newRank = currentRank + magnitude * vert; int newFile = currentFile + magnitude * horiz; var newPos = new Position((File)newFile, (Rank)newRank); if (!Position.IsOnBoard(newPos)) { break; } var currentPiece = board[newPos]; if (currentPiece != null) { if (currentPiece.Color != this.Color) { // We can take! moves.Add(MoveBuilder.CreateNormalMove(this, newPos, true)); } break; } moves.Add(MoveBuilder.CreateNormalMove(this, newPos, false)); magnitude++; } return(moves); }
private static Move DetermineMove(Board board, UCIChessMove uciMove) { string from = uciMove.From; string to = uciMove.To; var fromPos = Position.Parse(from); var toPos = Position.Parse(to); var fromPiece = board[fromPos]; int fileDiff = Math.Abs((int)fromPiece.Position.File - (int)toPos.File); if (fromPiece.Type == PieceType.King && (fileDiff == 3 || fileDiff == 4)) { King king = (King)fromPiece; Rook rook; if (fileDiff == 4) { rook = (Rook)board[File.A, fromPiece.Position.Rank]; } else { rook = (Rook)board[File.H, fromPiece.Position.Rank]; } return(MoveBuilder.CreateCastleMove(king, rook)); } if (uciMove.PromotionChar != null) { string promotionChar = uciMove.PromotionChar.ToUpper(); var promotionType = (from p in (PieceType[])Enum.GetValues(typeof(PieceType)) where p.ToNotationLetter().ToUpper() == promotionChar.ToUpper() select p).First(); var promotionMoves = MoveBuilder.CreatePromotionMoves((Pawn)fromPiece, toPos, board[toPos] != null); return((from m in promotionMoves where m.Promotion.NewPieceType.Type == promotionType select m).First()); } // Check for en passant var existingPieceRank = fromPiece.Position.Rank; var isCorrectRank = fromPiece.Color == PieceColor.Black ? existingPieceRank == Rank._4 : existingPieceRank == Rank._5; try { int vertDir = fromPiece.Color == PieceColor.White ? -1 : 1; var existingPieceTo = board[toPos]; var capturedPiecePos = toPos.MoveVert(vertDir); var capturedPiece = board[capturedPiecePos]; if (capturedPiece.Color == fromPiece.Color.Opposite() && capturedPiece.MoveHistory.Count == 1) { // This is an en passant return(MoveBuilder.CreateEnPassantMove((Pawn)fromPiece, toPos, capturedPiecePos)); } } catch { } // Only other option is that this is a normal move. return(MoveBuilder.CreateNormalMove(fromPiece, toPos, board[toPos] != null)); }
/// <summary> /// Returns a move with the given actions. /// </summary> public static Move CreateMove( string name = "yeti", string description = "amon", int maxUses = 5, MoveSuccessCalculatorFactory successCalculatorFactory = null, params IAction[] moveActions) { if (successCalculatorFactory is null) { successCalculatorFactory = () => new AlwaysMoveSuccessCalculator(); } var builder = new MoveBuilder() .Name(name) .Describe(description) .WithMaxUses(maxUses) .WithSuccessCalculatorFactory(successCalculatorFactory); foreach (var action in moveActions) { builder = builder.WithAction(action); } return(builder.Build()); }
public void Move_AreEqual() { var moveA = MoveBuilder.Create(Colour.White, PieceType.Rook, SquareFlag.G5.ToSquare(), new Models.Square(), 0, MoveType.Ordinary); var moveB = MoveBuilder.Create(Colour.White, PieceType.Rook, SquareFlag.G5.ToSquare(), new Models.Square(), 0, MoveType.Ordinary); Assert.Equal(moveA, moveB); }
public void White_Empty_OnePush_Promotion() { var board = CreateBitBoard("K6k/3P4/8/8/8/8/8/8 w - -"); var rootKey = KeyGenerator.Hash(board, Colour.White); var promotion1 = MoveBuilder.Create(Colour.White, PieceType.Pawn, SquareFlag.D7.ToSquare(), SquareFlag.D8.ToSquare(), PieceType.None, MoveType.PromotionQueen); var promotion2 = MoveBuilder.Create(Colour.White, PieceType.Pawn, SquareFlag.D7.ToSquare(), SquareFlag.D8.ToSquare(), PieceType.None, MoveType.PromotionRook); var promotion3 = MoveBuilder.Create(Colour.White, PieceType.Pawn, SquareFlag.D7.ToSquare(), SquareFlag.D8.ToSquare(), PieceType.None, MoveType.PromotionBishop); var promotion4 = MoveBuilder.Create(Colour.White, PieceType.Pawn, SquareFlag.D7.ToSquare(), SquareFlag.D8.ToSquare(), PieceType.None, MoveType.PromotionKnight); var beforeKey = board.Key; board.MakeMove(promotion1); var hashKey = KeyGenerator.Hash(board, Colour.Black); var updateKey = KeyGenerator.UpdateHash(rootKey, promotion1); Assert.Equal(hashKey, board.Key); Assert.Equal(updateKey, board.Key); var afterKey = board.Key; board.UnMakeMove(promotion1); var hashKey2 = KeyGenerator.Hash(board, Colour.White); var updateKey2 = KeyGenerator.UpdateHash(updateKey, promotion1); Assert.Equal(hashKey2, board.Key); Assert.Equal(updateKey2, board.Key); Assert.NotEqual(beforeKey, afterKey); Assert.Equal(beforeKey, board.Key); }
public void Name_BadArgument_Throws(string name) { // Arrange var builder = new MoveBuilder(); // Act and Assert Assert.Throws <ArgumentException>(() => _ = builder.Name(name)); }
public void WithSuccessCalculatorFactory_NullArgument_Throws() { // Arrange var builder = new MoveBuilder(); // Act and Assert Assert.Throws <ArgumentNullException>(() => _ = builder.WithSuccessCalculatorFactory(null)); }
public void Describe_BadArgument_Throws(string description) { // Arrange var builder = new MoveBuilder(); // Act and Assert Assert.Throws <ArgumentException>(() => _ = builder.Describe(description)); }
public void AppendMoves(BoardSquare originSquare, Position.Position position, List <Move> moves) { var board = position.Board; var moveBuilder = new MoveBuilder(Piece.Pawn, originSquare); var moveAppender = GetMoveAppender(originSquare); var moveForwardSquare = new BoardSquare(originSquare.Row + deltaRow, originSquare.Column); if (board.IsEmpty(moveForwardSquare)) { moveAppender(moveBuilder.SetDestSquare(moveForwardSquare), moves); if (originSquare.Row == initialRow) { var moveDoubleForwardSquare = GetDoubleForwardMoveSquare(originSquare); if (board.IsEmpty(moveDoubleForwardSquare)) { moves.Add(moveBuilder .SetDestSquare(moveDoubleForwardSquare) .SetPawnDoubleMove() .Build()); } } } if (originSquare.Column > 0) { AppendIfCanCapture( new BoardSquare(originSquare.Row + deltaRow, originSquare.Column - 1), moveBuilder, board, moves, moveAppender); } if (originSquare.Column + 1 < Board.Board.ColumnCount) { AppendIfCanCapture( new BoardSquare(originSquare.Row + deltaRow, originSquare.Column + 1), moveBuilder, board, moves, moveAppender); } if (originSquare.Row == enPassantCaptureRow && position.EnPassantCaptureColumn.Exists(x => Abs(originSquare.Column - x) == 1)) { var enPassantDstSquare = new BoardSquare( originSquare.Row + deltaRow, position.EnPassantCaptureColumn.ValueOr(0)); moves.Add(moveBuilder .SetDestSquare(enPassantDstSquare) .SetEnPassantCapture() .Build()); } }
public void Build_MissingMaxUses_Throws() { // Arrange var builder = new MoveBuilder() .Name("caribou") .Describe("andorra") .AlwaysSucceeds(); // Act and Assert Assert.Throws <InvalidOperationException>(() => _ = builder.Build()); }
public void Build_MissingSuccessCalculator_Throws() { // Arrange var builder = new MoveBuilder() .Name("caribou") .Describe("andorra") .WithMaxUses(9); // Act and Assert Assert.Throws <InvalidOperationException>(() => _ = builder.Build()); }
public static void Main(string[] args) { MoveBuilder mbuilder = new MoveBuilder("res/Moves/"); CharacterBuilder cbuilder = new CharacterBuilder("res/Characters/"); cbuilder.MoveBuilder = mbuilder; Character[] pside = new Character[] { cbuilder.buildFromXml("milly.xml", new PlayerMoveProvider()) }; Character[] eside = new Character[] { cbuilder.buildFromXml("gerard.xml", new PlayerMoveProvider()) }; TurnProvider turnProvider = new TraditionalTurnProvider(); Battle b = new Battle(pside, eside, turnProvider); b.start(); }
public void Make_EnPassantOnlySetIfCapturePossible(string partialFen, SquareFlag enPassant) { var board = Create($"rnbqkbnr/pppp1ppp/8/{partialFen}/1P6/2PPPPPP/RNBQKBNR b KQkq -"); var fromSquare = SquareFlag.D2; var toSquare = SquareFlag.D4; var move = MoveBuilder.Create(Colour.White, PieceType.Pawn, fromSquare.ToSquare(), toSquare.ToSquare(), PieceType.None, MoveType.Ordinary); board.MakeMove(move); Assert.Equal(enPassant, board.EnPassant); }
public void White_EnPassant_Capture_DiscoveredCheck() { var gameState = FenHelpers.Parse("8/8/8/q1rPp2K/8/7p/8/8 w - e6"); var board = CreateBoard(gameState); var moves = new List <uint>(10); MoveGenerator.Generate(board, gameState.ToPlay, moves); var enPassantCapture = MoveBuilder.Create(Colour.White, PieceType.Pawn, SquareFlag.D6.ToSquare(), SquareFlag.E7.ToSquare(), PieceType.Pawn, MoveType.EnPassant); var movesView = moves.Select(x => new MoveViewer(x)); Assert.DoesNotContain(enPassantCapture, moves); }
public void DiscoverCheck(string fenString, SquareFlag fromSquare, SquareFlag toSquare) { var gameState = FenHelpers.Parse(fenString); var board = CreateBoard(gameState); var moves = new List <uint>(20); MoveGenerator.Generate(board, gameState.ToPlay, moves); var moveCount = moves.Count; var illegalMove = MoveBuilder.Create(Colour.White, PieceType.Pawn, fromSquare.ToSquare(), toSquare.ToSquare(), PieceType.None, MoveType.Ordinary); Assert.DoesNotContain(illegalMove, moves); }
public void White_DiscoveredCheck() { var gameState = FenHelpers.Parse("8/2b5/3P4/4K3/8/8/8/7k w - -"); var board = CreateBoard(gameState); var moves = new List <uint>(10); MoveGenerator.Generate(board, gameState.ToPlay, moves); var illegalMove = MoveBuilder.Create(Colour.White, PieceType.Pawn, SquareFlag.D6.ToSquare(), SquareFlag.D7.ToSquare(), PieceType.None, MoveType.Ordinary); var movesView = moves.Select(x => new MoveViewer(x)); Assert.DoesNotContain(illegalMove, moves); }
public void Build_CallsPresent_Succeeds() { // Arrange var builder = new MoveBuilder() .Name("caribou") .Describe("andorra") .WithMaxUses(9) .WithPriority(1) .WithAccuracy(100, Mock.Of <Random>()); // Act var move = builder.Build(); // Assert Assert.That(move, Is.Not.Null); }
public Monster(string name, string type, int hp, int atk, int def, int spAtk, int spDef, int speed, string location) { level = 10; this.name = name; this.type = type; this.hp = hp; this.atk = atk; this.def = def; this.spAtk = spAtk; this.spDef = spDef; this.speed = speed; sprite = Game1.gameContent.Load<Texture2D>(location); moveBuilder = new MoveBuilder("Index/Moves.csv"); moves = new Move[4]; moves[0] = moveBuilder.moveList["Sing"]; moves[1] = moveBuilder.moveList["Defense Curl"]; moves[2] = moveBuilder.moveList["Pound"]; moves[3] = moveBuilder.moveList["Double Slap"]; CalculateMaxes(); }