private BoardSquarePathInfo ResolveMovement(ActorData actor)
        {
            ActorTeamSensitiveData atsd          = actor.TeamSensitiveData_authority;
            ActorMovement          actorMovement = actor.GetActorMovement();
            BoardSquare            start         = actor.InitialMoveStartSquare;
            BoardSquare            end           = actor.MoveFromBoardSquare;

            BoardSquarePathInfo path;

            if (atsd.MovementLine != null)
            {
                path = BuildPathAlongMovementLine(actor);
            }
            else
            {
                path = actorMovement.BuildPathTo(start, end);
            }

            if (path == null)
            {
                path = actorMovement.BuildPathTo(start, start);
            }

            for (var pathNode = path; pathNode.next != null; pathNode = pathNode.next)
            {
                pathNode.m_unskippable = true;  // so that aestetic path is not optimized (see CreateRunAndVaultAesteticPath)
            }

            var path2 = path;

            while (path2.next != null)
            {
                Log.Info($"FINAL PATH {path2.square.GetGridPosition()}");
                path2 = path2.next;
            }
            Log.Info($"FINAL PATH {path2.square.GetGridPosition()}");

            return(path);
        }
        private static BoardSquarePathInfo BuildPathAlongMovementLine(ActorData actor)
        {
            ActorTeamSensitiveData atsd          = actor.TeamSensitiveData_authority;
            ActorMovement          actorMovement = actor.GetActorMovement();
            BoardSquare            start         = actor.InitialMoveStartSquare;
            BoardSquare            end           = actor.MoveFromBoardSquare;
            // TODO refactor this atrocity
            BoardSquarePathInfo path = actorMovement.BuildPathTo(start, start);
            BoardSquarePathInfo node = path;

            foreach (var curPos in atsd.MovementLine.m_positions)
            {
                node.next = actorMovement.BuildPathTo(node.square, Board.Get().GetSquare(curPos)).next;
                if (node.next == null)
                {
                    continue;
                }
                node.next.moveCost += node.moveCost;
                node.next.prev      = node;
                node = node.next;
            }

            return(path);
        }
        private float GetActorMovementCost(ActorData actor, out float lastStepCost)
        {
            float movementCost = 0;

            lastStepCost = 0;
            ActorMovement actorMovement = actor.GetActorMovement();

            LineData.LineInstance movementLine = actor.TeamSensitiveData_authority.MovementLine;
            if (movementLine != null)
            {
                GridPos prevPos = actor.InitialMoveStartSquare.GetGridPosition();
                foreach (var curPos in movementLine.m_positions)
                {
                    lastStepCost  = actorMovement.BuildPathTo(Board.Get().GetSquare(prevPos), Board.Get().GetSquare(curPos)).next?.moveCost ?? 0f; // TODO optimize this atrocity
                    movementCost += lastStepCost;
                    prevPos       = curPos;
                }
            }
            return(movementCost);
        }
        public void CmdSetSquare(ActorTurnSM actorTurnSM, int x, int y, bool setWaypoint)
        {
            ActorData actor = actorTurnSM.gameObject.GetComponent <ActorData>();

            if (!GameFlowData.Get().IsInDecisionState())
            {
                Log.Info($"Recieved CmdSetSquare not in desicion state! {actor.DisplayName} [{x}, {y}] (setWaypoint = {setWaypoint})");
                actorTurnSM.CallRpcTurnMessage((int)TurnMessage.MOVEMENT_REJECTED, 0);
                return;
            }

            Log.Info($"CmdSetSquare {actor.DisplayName} [{x}, {y}] (setWaypoint = {setWaypoint})");

            BoardSquare   boardSquare   = Board.Get().GetSquare(x, y);
            ActorMovement actorMovement = actor.GetActorMovement();

            if (!setWaypoint)
            {
                ClearMovementRequest(actor, false);
            }

            actorMovement.UpdateSquaresCanMoveTo();

            if (!actor.CanMoveToBoardSquare(boardSquare))
            {
                boardSquare = actorMovement.GetClosestMoveableSquareTo(boardSquare, false);
            }
            if (actor.TeamSensitiveData_authority.MovementLine == null)
            {
                actor.TeamSensitiveData_authority.MovementLine = new LineData.LineInstance();
            }
            if (actor.TeamSensitiveData_authority.MovementLine.m_positions.Count == 0)
            {
                actor.TeamSensitiveData_authority.MovementLine.m_positions.Add(actor.InitialMoveStartSquare.GetGridPosition());
            }

            BoardSquarePathInfo path = actorMovement.BuildPathTo(actor.TeamSensitiveData_authority.MoveFromBoardSquare, boardSquare);

            if (path == null)  // TODO check cost
            {
                Log.Info($"CmdSetSquare: Movement rejected");
                UpdatePlayerRemainingMovement(actor); // TODO updating because we cancelled movement - perhaps we should not cancel in this case
                actorTurnSM.CallRpcTurnMessage((int)TurnMessage.MOVEMENT_REJECTED, 0);
                return;
            }

            //List<GridPos> posList = path.ToGridPosPath();
            List <GridPos> posList = new List <GridPos>();

            for (var pathNode = path; pathNode.next != null; pathNode = pathNode.next)
            {
                posList.Add(pathNode.next.square.GetGridPosition()); // TODO why doesnt path.ToGridPosPath() work?
            }

            actor.TeamSensitiveData_authority.MovementLine.m_positions.AddRange(posList);
            actor.TeamSensitiveData_authority.MoveFromBoardSquare = boardSquare;
            actor.MoveFromBoardSquare = boardSquare;

            UpdatePlayerRemainingMovement(actor);
            actorTurnSM.CallRpcTurnMessage((int)TurnMessage.MOVEMENT_ACCEPTED, 0);
        }