internal StateController(IDataCollector sender, Labyrinth GameState, Player[] Players)
 {
     this.Phase = sender;
     this.Current = GameState;
     this.Players = Players;
     this.Chest = new Vector2((int)GameState.Board.GetLength(1) / 2, (int)GameState.Board.GetLength(0) / 2);
 }
 /// <summary
 /// Check whether rotating a target players block is a good counter.
 /// </summary>
 /// <param name="target"></param>
 /// <param name="dir"></param>
 /// <returns>Returns true </returns>
 private bool AttemptRotate(Player target, Direction dir)
 {
     Current.Rotate((int)target.Position.X, (int)target.Position.Y, Rotate.Left);
     if (!Current.PlayerCanMove(target, dir))
         return true;
     Current.Rotate((int)target.Position.X, (int)target.Position.Y, Rotate.Right, 2);
     if (!Current.PlayerCanMove(target, dir))
         return true;
     Current.Rotate((int)target.Position.X, (int)target.Position.Y, Rotate.Left, 1, true);
     return false;
 }
        /// <summary>
        /// Moves a Player object on the board according to specific AI Rules.
        /// If the player won the game a true value is returned.
        /// </summary>
        /// <returns>Returns true if the player calling the method has won.</returns>
        internal bool ExecuteNextMove(Player sender, int Chance)
        {
            bool Answer = AnswerQuestion(Chance);
            Phase.IncrementAnswer(Answer);

            CalculateMove(sender, Answer);

            if (sender.Position == Chest)
                return true;
            return false;
            // Check for win state.
            // Call next player.
        }
        /// <summary>
        /// Creates a Labyrinth board with given dimensions.
        /// </summary>
        /// <param name="BoardSize">An integer defining the board dimensions. This number should be uneven! and greater than 4.</param>
        /// <param name="StraightBlocks">An integer defining the amount of Straight type blocks on both the board and reserves combined.</param>
        /// <param name="CornerBlocks">An integer defining the amount of Corner type blocks on both the board and reserves combined.</param>
        /// <param name="TSplitBlocks">An integer defining the amount of T-Split type blocks on both the board and reserves combined.</param>
        /// <param name="ReserveBlocks">An integer defining the amount of reserve blocks available. This value has a default of 5 and should be greater than 0.</param>
        internal Labyrinth(IDataCollector sender, Player[] Players, int BoardSize, int StraightBlocks, int CornerBlocks, int TSplitBlocks, int ReserveBlocks)
        {
            this.Players = Players;
            this.Phase = sender;

            Board = new LabyrinthBlock[BoardSize, BoardSize];
            Reserves = new LabyrinthBlock[ReserveBlocks];

            int TotalBlocks = BoardSize * BoardSize + ReserveBlocks - 5; // 5 = Corners + chest

            List<int> Blocks = new List<int>(){ StraightBlocks, CornerBlocks, TSplitBlocks };

            // Start randomizer
            RandomizeBoard(Blocks);
        }
        public static void Animate(Tuple<string,string,string> AnimationData, LabyrinthBlock[,] CurrentBoard, LabyrinthBlock[] CurrentReserves, Player[] CurrentPlayers, float scale, float offset)
        {
            if (IsAnimating)
                return;
            CurrentOperation = AnimationData;

            GameBoard = CurrentBoard;
            GameReserves = CurrentReserves;
            GamePlayers = CurrentPlayers;
            Scale = scale;
            Offset = offset;

            DataSetter set;
            if(CurrentOperation == null) {
                Game1.CurrentTurn++;
                Game1.CurrentPlayerIndex++;
                AnimationDone();
                return;
            }
            switch (CurrentOperation.Item1) {
                case "PawnMoved":
                    set = SetPlayerMovementData;
                    break;
                case "HallShifted":
                    set = SetShiftingData;
                    break;
                case "BlockRotated":
                    set = SetRotationData;
                    break;
                default:
                    AnimationDone();
                    return;
            }
            set.Invoke();
            IsAnimating = true;
        }
        /// <summary>
        /// Executes a counter move without obstructing player movement.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="dir">Direction in which the player is required to be able to move after the counter move.</param>
        private bool ExecuteCounter(Player sender, Direction dir)
        {
            var EnemyData = new List<Tuple<Player, int>>();
            for (int i = 0; i < Players.Length; i++)
                if (Players[i] != sender)
                    EnemyData.Add(Tuple.Create(Players[i], GetTotalDistance(Players[i])));
            EnemyData = EnemyData.OrderBy(x => x.Item2).ToList();

            for (int i = 0; i < EnemyData.Count; i++) {
                if (TryShiftRowCounter(sender, EnemyData[i].Item1, EnemyData, true, dir))
                    return true;
                else if (TryRotateCounter(EnemyData[i].Item1))
                    return true;
            }
            return false;
        }
 /// <summary>
 /// If possible moves a row and then the player in a direction.
 /// </summary>
 /// <returns>Returns true if player was able to move.</returns>
 private bool TryShiftRowAndMove(Player sender, Direction dir)
 {
     if (dir == Direction.Left || dir == Direction.Right) {
         if (Current.CanShift((int)sender.Position.Y) && Current.PlayerCanMove(sender, dir)) {
             Current.ShiftRow((int)sender.Position.Y, dir);
             sender.MovePlayer(dir);
             return true;
         }
     }
     else {
         if (Current.CanShift((int)sender.Position.X) && Current.PlayerCanMove(sender, dir)) {
             Current.ShiftRow((int)sender.Position.X, dir);
             sender.MovePlayer(dir);
             return true;
         }
     }
     return false;
 }
 private bool TryShiftRowCounter(Player sender, Player target, List<Tuple<Player,int>> EnemyData, bool AvoidObstruction, Direction dir = Direction.Down)
 {
     int Distance = GetTotalDistance(target);
     try {
         if (Current.CanShift((int)target.Position.Y)) {    // Can shift target along it's X axis.
             if(GoodCounter(target, EnemyData, new Vector2(1,0))) {   // Distance of target is increased. Good counter. (Shift Right)
                 if (!AvoidObstruction) {
                     Current.ShiftRow((int)target.Position.Y, Direction.Right);
                     return true;
                 }
                 if (sender.Position.X != target.Position.X && // If player is not moved.
                     (ExpectedPlayerLocation(sender, dir).Y != target.Position.Y ||     // If the row the player has to move to has not been moved.
                     Current.PlayerCanMoveOut(ExpectedPlayerLocation(sender, dir) + new Vector2(-1, 0), GetOpposite(dir)))) { // If the row has been moved but the player can move anyway.
                     Current.ShiftRow((int)target.Position.Y, Direction.Right);
                     return true;
                 }
             }
             else if (GoodCounter(target, EnemyData, new Vector2(-1, 0))) {
                 if (!AvoidObstruction) {
                     Current.ShiftRow((int)target.Position.Y, Direction.Left);
                     return true;
                 }
                 if (sender.Position.X != target.Position.X &&
                     (ExpectedPlayerLocation(sender, dir).Y != target.Position.Y ||
                     Current.PlayerCanMoveOut(ExpectedPlayerLocation(sender, dir) + new Vector2(1, 0), GetOpposite(dir)))) {
                     Current.ShiftRow((int)target.Position.Y, Direction.Left);
                     return true;
                 }
             }
         }
         if (Current.CanShift((int)target.Position.X)) {
             if (GoodCounter(target, EnemyData, new Vector2(0, 1))) {
                 if (!AvoidObstruction) {
                     Current.ShiftRow((int)target.Position.X, Direction.Down);
                     return true;
                 }
                 if (sender.Position.Y != target.Position.Y &&
                     (ExpectedPlayerLocation(sender, dir).X != target.Position.X ||
                     Current.PlayerCanMoveOut(ExpectedPlayerLocation(sender, dir) + new Vector2(0, -1), GetOpposite(dir)))) {
                     Current.ShiftRow((int)target.Position.X, Direction.Down);
                     return true;
                 }
             }
             else if (GoodCounter(target, EnemyData, new Vector2(0, -1))) {
                 if (!AvoidObstruction) {
                     Current.ShiftRow((int)target.Position.X, Direction.Up);
                     return true;
                 }
                 if (sender.Position.Y != target.Position.Y &&
                     (ExpectedPlayerLocation(sender, dir).X != target.Position.X ||
                     Current.PlayerCanMoveOut(ExpectedPlayerLocation(sender, dir) + new Vector2(0, 1), GetOpposite(dir)))) {
                     Current.ShiftRow((int)target.Position.X, Direction.Up);
                     return true;
                 }
             }
         }
         return false;
     }
     catch {
         return false;
     }
 }
 private Vector2 ExpectedPlayerLocation(Player sender, Direction dir)
 {
     switch (dir) {
         case Direction.Left:
             return new Vector2(sender.Position.X - 1, sender.Position.Y);
         case Direction.Right:
             return new Vector2(sender.Position.X + 1, sender.Position.Y);
         case Direction.Up:
             return new Vector2(sender.Position.X, sender.Position.Y - 1);
         default:
             return new Vector2(sender.Position.X, sender.Position.Y + 1);
     }
 }
 private bool TryRotateSelf(Player sender, Direction dir)
 {
     Current.Rotate((int)sender.Position.X, (int)sender.Position.Y, Rotate.Left);
     if (Current.PlayerCanMove(sender, dir))
         return true;
     Current.Rotate((int)sender.Position.X, (int)sender.Position.Y, Rotate.Right, 2);
     if (Current.PlayerCanMove(sender, dir))
         return true;
     Current.Rotate((int)sender.Position.X, (int)sender.Position.Y, Rotate.Left, 1, true);
     return false;
 }
        /// <summary>
        /// Executes a counter move disregarding player movement after the counter.
        /// Should be used when the player can't move and will only counter others.
        /// </summary>
        private bool ExecuteCounter(Player sender)
        {
            var EnemyData = new List<Tuple<Player, int>>(); // List containing all enemies with their respective distance to chest.
            for (int i = 0; i < Players.Length; i++)
                if (Players[i] != sender)
                    EnemyData.Add(Tuple.Create(Players[i], GetTotalDistance(Players[i])));
            EnemyData = EnemyData.OrderBy(x => x.Item2).ToList();  // Sort array to get the closest player to the chest at the lowest index.

            for (int i = 0; i < EnemyData.Count; i++) {
                if (TryShiftRowCounter(sender, EnemyData[i].Item1, EnemyData, false))
                    return true;
                else if (TryRotateCounter(EnemyData[i].Item1))
                    return true;
            }
            return false;
        }
 internal bool PlayerCanMoveOut(Player player, Direction dir)
 {
     if (Board[(int)player.Position.Y, (int)player.Position.X].CanMove(dir))
         return true;
     return false;
 }
        private bool OnlyMovePlayer(Player sender, Vector2 Distance)
        {
            if (Distance.X == 0) {
                if (Distance.Y > 0) {
                    if (Current.PlayerCanMove(sender, Direction.Down)) {
                        sender.MovePlayer(Direction.Down);
                        return true;
                    }
                }
                else {
                    if (Current.PlayerCanMove(sender, Direction.Up)) {
                        sender.MovePlayer(Direction.Up);
                        return true;
                    }
                }
                return false;
            }
            else if (Distance.Y == 0) {
                if (Distance.X > 0) {
                    if (Current.PlayerCanMove(sender, Direction.Right)) {
                        sender.MovePlayer(Direction.Right);
                        return true;
                    }
                }
                else {
                    if (Current.PlayerCanMove(sender, Direction.Left)) {
                        sender.MovePlayer(Direction.Left);
                        return true;
                    }
                }
                return false;
            }

            if (Distance.X > 0) {
                if (Current.PlayerCanMove(sender, Direction.Right)) {
                    sender.MovePlayer(Direction.Right);
                    return true;
                }
            }
            else if (Distance.X < 0) {
                if (Current.PlayerCanMove(sender, Direction.Left)) {
                    sender.MovePlayer(Direction.Left);
                    return true;
                }
            }
            if (Distance.Y > 0) {
                if (Current.PlayerCanMove(sender, Direction.Down)) {
                    sender.MovePlayer(Direction.Down);
                    return true;
                }
            }
            else if (Distance.Y < 0) {
                if (Current.PlayerCanMove(sender, Direction.Up)) {
                    sender.MovePlayer(Direction.Up);
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// Executes a counter move to block a target player.
        /// </summary>
        /// <returns>Returns true if a counter move was found and executed.</returns>
        private bool ExecuteCounter(Player sender, Player target)
        {
            var EnemyData = new List<Tuple<Player, int>>();
            for (int i = 0; i < Players.Length; i++)
                if (Players[i] != sender)
                    EnemyData.Add(Tuple.Create(Players[i], GetTotalDistance(Players[i])));
            EnemyData = EnemyData.OrderBy(x => x.Item2).ToList();

            if (TryShiftRowCounter(sender, target, EnemyData, false))
                return true;
            else if (TryRotateCounter(target))
                return true;
            return false;
        }
        /// <summary>
        /// Execute when players X or Y location is alligned with the Chest.
        /// </summary>
        private void HandleZeroDistance(Player sender, Vector2 Distance, Direction dir)
        {
            if (Current.PlayerCanMove(sender, dir)) {   // Player can move, try to block another player.
                ExecuteCounter(sender, dir); // Execute counter move.
                sender.MovePlayer(dir); // Move self in direction.
                return;
            }
            // Try rotating self to see if you can move after.
            Current.Rotate((int)sender.Position.X, (int)sender.Position.Y, Rotate.Right);
            if (Current.PlayerCanMove(sender, dir)) {
                sender.MovePlayer(dir);
                return;
            }
            Current.Rotate((int)sender.Position.X, (int)sender.Position.Y, Rotate.Left, 2);
            if (Current.PlayerCanMove(sender, dir)) {
                sender.MovePlayer(dir);
                return;
            }
            Current.Rotate((int)sender.Position.X, (int)sender.Position.Y, Rotate.Right, 1, true);   // Rotating self not usefull, reset rotation.

            // Move not possible. Rotate adjacent and check again.
            RotateAdjacent(sender, Distance);
            // If player can move after rotating , move player.
            if (Current.PlayerCanMove(sender, dir))
                sender.MovePlayer(dir);
        }
 private bool LastMove(Player sender, Direction dir)
 {
     if (Current.PlayerCanMove(sender, dir)) {
         sender.MovePlayer(dir);
         return true;
     }
     else if (TryRotateSelf(sender, dir)) {
         sender.MovePlayer(dir);
         return true;
     }
     else {
         Current.Rotate((int)sender.Position.X, (int)sender.Position.Y, Rotate.Right);
         return true;
     }
 }
 private bool HandleSameBlock(Player sender, Vector2 Distance)
 {
     if (OnlyMovePlayer(sender, Distance))
         return true;
     if (Distance.X > 0) {
         if (TryRotateSelf(sender, Direction.Right) || TryRotate(sender, Direction.Right)) {
             sender.MovePlayer(Direction.Right);
             return true;
         }
     }
     else if (Distance.X < 0) {
         if (TryRotateSelf(sender, Direction.Left) || TryRotate(sender, Direction.Left)) {
             sender.MovePlayer(Direction.Left);
             return true;
         }
     }
     if (Distance.Y > 0) {
         if (TryRotateSelf(sender, Direction.Down) || TryRotate(sender, Direction.Down)) {
             sender.MovePlayer(Direction.Down);
             return true;
         }
     }
     else if (Distance.Y < 0) {
         if (TryRotateSelf(sender, Direction.Up) || TryRotate(sender, Direction.Up)) {
             sender.MovePlayer(Direction.Up);
             return true;
         }
     }
     return false;
 }
        /// <summary>
        /// Execute when player is within a 1 block radius of chest.
        /// </summary>
        private void HandleLastMove(Player sender, Vector2 Distance)
        {
            // State where player is in proximity of chest
            if (Distance.X == 0) {
                if (Distance.Y > 0)
                    LastMove(sender, Direction.Down);
                else
                    LastMove(sender, Direction.Up);
                return;
            }
            else if (Distance.Y == 0) {
                if (Distance.X > 0)
                    LastMove(sender, Direction.Right);
                else
                    LastMove(sender, Direction.Left);
                return;
            }

            if (Distance.X == 1 && Distance.Y == 1) {    // Player is Left and above of chest.
                if (Current.PlayerCanMoveOut(sender, Direction.Right)) {
                    Current.ShiftRow((int)sender.Position.X, Direction.Down);
                    sender.MovePlayer(Direction.Right);
                }
                else if (Current.PlayerCanMoveOut(sender, Direction.Down)) {
                    Current.ShiftRow((int)sender.Position.Y, Direction.Right);
                    sender.MovePlayer(Direction.Down);
                }
                else
                    Current.ShiftRow((int)sender.Position.X, Direction.Down);
            }
            else if (Distance.X == -1 && Distance.Y == 1) {  // Player is right and above chest.
                if (Current.PlayerCanMoveOut(sender, Direction.Left)) {
                    Current.ShiftRow((int)sender.Position.X, Direction.Down);
                    sender.MovePlayer(Direction.Left);
                }
                else if (Current.PlayerCanMoveOut(sender, Direction.Down)) {
                    Current.ShiftRow((int)sender.Position.Y, Direction.Left);
                    sender.MovePlayer(Direction.Down);
                }
                else
                    Current.ShiftRow((int)sender.Position.X, Direction.Down);
            }
            else if (Distance.X == 1 && Distance.Y == -1) {  // Player is left and below the chest.
                if (Current.PlayerCanMoveOut(sender, Direction.Right)) {
                    Current.ShiftRow((int)sender.Position.X, Direction.Up);
                    sender.MovePlayer(Direction.Right);
                }
                else if (Current.PlayerCanMoveOut(sender, Direction.Up)) {
                    Current.ShiftRow((int)sender.Position.Y, Direction.Right);
                    sender.MovePlayer(Direction.Up);
                }
                else
                    Current.ShiftRow((int)sender.Position.X, Direction.Up);
            }
            else if (Distance.X == -1 && Distance.Y == -1) { // Player is right and below the chest.
                if (Current.PlayerCanMoveOut(sender, Direction.Left)) {
                    Current.ShiftRow((int)sender.Position.X, Direction.Up);
                    sender.MovePlayer(Direction.Left);
                }
                else if (Current.PlayerCanMoveOut(sender, Direction.Up)) {
                    Current.ShiftRow((int)sender.Position.Y, Direction.Left);
                    sender.MovePlayer(Direction.Up);
                }
                else
                    Current.ShiftRow((int)sender.Position.X, Direction.Up);
            }
        }
 private bool GoodCounter(Player target, List<Tuple<Player, int>> EnemyData, Vector2 Movement)
 {
     bool GoodMove = true;
     for (int i = 0; i < EnemyData.Count; i++)
         if (EnemyData[i].Item1 == target) {
             if (GetTotalDistance(EnemyData[i].Item1.Position + Movement) > EnemyData[i].Item2)
                 GoodMove = true;
             else
                 return false;
         }
         else if (GetTotalDistance(EnemyData[i].Item1.Position + Movement) < EnemyData[i].Item2)
             return false;
     return GoodMove;
 }
 private void CalculateMove(Player sender, bool Correct)
 {
     var Distance = new Vector2(Chest.X - sender.Position.X, Chest.Y - sender.Position.Y);
     if (!Correct) { // Incorrect answer. Only rotate an adjacent block.
         RotateAdjacent(sender, Distance);
         return;
     }
     for (int i = 0; i < Players.Length; i++) {
         if (Players[i] != sender && GetTotalDistance(Players[i]) <= 2) { // Player is in proximity of chest.
             if (Players[i].Position != sender.Position && ExecuteCounter(sender, Players[i])) {
                 OnlyMovePlayer(sender, Distance);
                 return;
             }
         }
         else if (Players[i] != sender && Players[i].Position == sender.Position) {   // Player shares a block with another player.
             if (HandleSameBlock(sender, Distance))
                 return;
             else
                 ExecuteBestMove(sender, Distance);
         }
     }
     ExecuteBestMove(sender, Distance);
 }
        /// <summary>
        /// Rotates and Adjacent block to the player.
        /// </summary>
        private bool RotateAdjacent(Player sender, Vector2 Distance, bool SecondBest = false)
        {
            if (Distance.X == 0) {   // X-axis is alligned.
                if (Distance.Y > 0) {   // Needs to move down.
                    if (TryRotate(sender, Direction.Down))
                        return true;
                    else if (!Current.PlayerCanMoveOut(sender.Position + new Vector2(0, 1), Direction.Up))
                        Current.Rotate((int)sender.Position.X, (int)sender.Position.Y + 1, Rotate.Right);
                }
                else {  // Needs to move up.
                    if (TryRotate(sender, Direction.Up))
                        return true;
                    else if(!Current.PlayerCanMoveOut(sender.Position + new Vector2(0, -1), Direction.Down))
                        Current.Rotate((int)sender.Position.X, (int)sender.Position.Y - 1, Rotate.Right);
                }
                return false;   // Rotated adjacent but still can't move.
            }
            else if (Distance.Y == 0) {  // Y-axis is alligned.
                if (Distance.X > 0) {    // Needs to move right.
                    if (TryRotate(sender, Direction.Right))
                        return true;
                    else if (!Current.PlayerCanMoveOut(sender.Position + new Vector2(1, 0), Direction.Left))
                        Current.Rotate((int)sender.Position.X + 1, (int)sender.Position.Y, Rotate.Right);
                }
                else {  // Needs to move left.
                    if (TryRotate(sender, Direction.Left))
                        return true;
                    else if (!Current.PlayerCanMoveOut(sender.Position + new Vector2(-1, 0), Direction.Right))
                        Current.Rotate((int)sender.Position.X - 1, (int)sender.Position.Y, Rotate.Right);
                }
                return false;   // rotated adjacent but still can't move.
            }

            if (Distance.X > 0) {    // Rotate right adjacent.
                if (TryRotate(sender, Direction.Right))
                    return true;
                if (SecondBest && !Current.PlayerCanMoveOut(sender.Position + new Vector2(1,0), Direction.Left)) {
                    Current.Rotate((int)sender.Position.X + 1, (int)sender.Position.Y, Rotate.Right);
                    return true;
                }
            }
            else if (Distance.X < 0) {   // Rotate left adjacent.
                if (TryRotate(sender, Direction.Left))
                    return true;
                if (SecondBest && !Current.PlayerCanMoveOut(sender.Position + new Vector2(-1, 0), Direction.Right)) {
                    Current.Rotate((int)sender.Position.X - 1, (int)sender.Position.Y, Rotate.Right);
                    return true;
                }
            }
            if (Distance.Y > 0) {  // Rotate down adjacent.
                if (TryRotate(sender, Direction.Down))
                    return true;
                if (SecondBest && !Current.PlayerCanMoveOut(sender.Position + new Vector2(0, 1), Direction.Up)) {
                    Current.Rotate((int)sender.Position.X, (int)sender.Position.Y + 1, Rotate.Right);
                    return true;
                }
            }
            else if (Distance.Y < 0) {   // Rotate up adjacent.
                if (TryRotate(sender, Direction.Up))
                    return true;
                if (SecondBest && !Current.PlayerCanMoveOut(sender.Position + new Vector2(0, -1), Direction.Down)) {
                    Current.Rotate((int)sender.Position.X, (int)sender.Position.Y - 1, Rotate.Right);
                    return true;
                }
            }

            // No adjacent rotation improves the player's position. Recursive call to rotate an adjacent block anyway.
            if (SecondBest)
                return false;
            return RotateAdjacent(sender, Distance, true);
        }
Esempio n. 22
0
 private Player[] GetPlayers()
 {
     var toReturn = new Player[PlayerHistory.Length];
     for(int i = 0; i < toReturn.Length; i++) {
         Vector2 Position;
         switch (i) {
             case 0:
                 Position = Vector2.Zero;
                 break;
             case 1:
                 Position = new Vector2(CurrentBoard.GetLength(0) - 1, 0);
                 break;
             case 2:
                 Position = new Vector2(CurrentBoard.GetLength(0) - 1);
                 break;
             case 3:
                 Position = new Vector2(0, CurrentBoard.GetLength(0) - 1);
                 break;
             default: throw new IndexOutOfRangeException("Not more than 4 players can exist.");
         }
         toReturn[i] = new Player(ConvertColor(PlayerHistory[i]), Position);
     }
     return toReturn;
 }
        /// <summary>
        /// Checks whether or not rotating an adjacent block is beneficial to the player.
        /// </summary>
        /// <returns>Returns true when the move is beneficial.</returns>
        private bool TryRotate(Player sender, Direction dir)
        {
            int OffsetX = 0;
            int OffsetY = 0;
            if (dir == Direction.Right)
                OffsetX = 1;
            else if (dir == Direction.Left)
                OffsetX = -1;
            else if (dir == Direction.Up)
                OffsetY = -1;
            else
                OffsetY = 1;

            Current.Rotate((int)sender.Position.X + OffsetX, (int)sender.Position.Y + OffsetY, Rotate.Right);
            if (Current.PlayerCanMove(sender, dir))
                return true;
            Current.Rotate((int)sender.Position.X + OffsetX, (int)sender.Position.Y + OffsetY, Rotate.Left, 2);
            if (Current.PlayerCanMove(sender, dir))
                return true;
            Current.Rotate((int)sender.Position.X + OffsetX, (int)sender.Position.Y + OffsetY, Rotate.Right, 1, true);
            return false;
        }
 internal bool PlayerCanMove(Player player, Direction dir)
 {
     return PlayerCanMove(player.Position, dir);
 }
 private bool TryRotateCounter(Player target)
 {
     Vector2 Distance = new Vector2(Chest.X - target.Position.X, Chest.Y - target.Position.Y);
     if(Distance.X == 0) {
         if (Distance.Y > 0) {
             if (!Current.PlayerCanMove(target, Direction.Down))  // Player can't move in the first place.
                 return false;
             if (AttemptRotate(target, Direction.Down))
                 return true;
         }
         else {
             if (!Current.PlayerCanMove(target, Direction.Up))
                 return false;
             if (AttemptRotate(target, Direction.Up))
                 return true;
         }
     }
     else if(Distance.Y == 0) {
         if(Distance.X > 0) {
             if (!Current.PlayerCanMove(target, Direction.Right))
                 return false;
             if (AttemptRotate(target, Direction.Right))
                 return true;
         }
         else {
             if (!Current.PlayerCanMove(target, Direction.Left))
                 return false;
             if (AttemptRotate(target, Direction.Left))
                 return true;
         }
     }
     return false;
 }
        private void ExecuteBestMove(Player sender, Vector2 Distance, bool SecondBest = false)
        {
            // Handle player being inline with the Chest.
            #region New Method : HandleZeroDistance     // <<<<<
            if (SecondBest)
                if (HandleSameBlock(sender, Distance))
                    return;

            if (Distance.X == 0) {
                if (Distance.Y > 0)    // Player has to move Down.
                    HandleZeroDistance(sender, Distance, Direction.Down);
                else                   // Player has to move Up.
                    HandleZeroDistance(sender, Distance, Direction.Up);
                return;
            }
            else if (Distance.Y == 0) {
                if (Distance.X > 0)    // Player has to move Right.
                    HandleZeroDistance(sender, Distance, Direction.Right);
                else                   // Player has to move Left.
                    HandleZeroDistance(sender, Distance, Direction.Left);
                return;
            }
            if (Distance.X == 1 && Distance.Y == 1) {
                HandleLastMove(sender, Distance);
                return;
            }
            #endregion

            if (Distance.X > 0) {
                if (Distance.X != 1) {
                    if (TryShiftRowAndMove(sender, Direction.Right))
                        return;
                    if (SecondBest) {
                        if (Current.PlayerCanMove(sender, Direction.Right)) {
                            ExecuteCounter(sender, Direction.Right);
                            sender.MovePlayer(Direction.Right);
                            return;
                        }
                        else if (Current.CanShift((int)sender.Position.Y)) {  // If second best, only move a row. Player can't move.
                            Current.ShiftRow((int)sender.Position.Y, Direction.Right);
                            return;
                        }
                    }
                }
            }
            else if (Distance.X < 0) {
                if (Distance.X != -1) {
                    if (TryShiftRowAndMove(sender, Direction.Left))
                        return;
                    if (SecondBest) {
                        if (Current.PlayerCanMove(sender, Direction.Left)) {
                            ExecuteCounter(sender, Direction.Left);
                            sender.MovePlayer(Direction.Left);
                            return;
                        }
                        else if (Current.CanShift((int)sender.Position.Y)) {
                            Current.ShiftRow((int)sender.Position.Y, Direction.Left);
                            return;
                        }

                    }

                }
            }
            if (Distance.Y > 0) {
                if (Distance.Y != 1) {
                    if (TryShiftRowAndMove(sender, Direction.Down))
                        return;
                    if (SecondBest)
                        if (Current.PlayerCanMove(sender, Direction.Down)) {
                            ExecuteCounter(sender, Direction.Down);
                            sender.MovePlayer(Direction.Down);
                            return;
                        }
                        else if (Current.CanShift((int)sender.Position.X)) {
                            Current.ShiftRow((int)sender.Position.X, Direction.Down);
                            return;
                        }
                }
            }
            else if (Distance.Y < 0) {
                if (Distance.Y != 1) {
                    if (TryShiftRowAndMove(sender, Direction.Up))
                        return;
                    if (SecondBest)
                        if (Current.PlayerCanMove(sender, Direction.Up)) {
                            ExecuteCounter(sender, Direction.Up);
                            sender.MovePlayer(Direction.Up);
                            return;
                        }
                        else if (Current.CanShift((int)sender.Position.X)) {
                            Current.ShiftRow((int)sender.Position.X, Direction.Up);
                            return;
                        }
                }
            }

            if (SecondBest) {
                // Worst possible move. Only obstruct other player.
                if (!RotateAdjacent(sender, Distance))
                    ExecuteCounter(sender);
                return;
                // Later implementation ? :
                // Annoy other player if you can move.
                // else rotate nearby and move.
                // else only rotate.
            }
            ExecuteBestMove(sender, Distance, true);
        }
 private int GetTotalDistance(Player target)
 {
     return (int)(Math.Abs(Chest.X - target.Position.X) + Math.Abs(Chest.Y - target.Position.Y));
 }