예제 #1
0
파일: AIUtils.cs 프로젝트: MoyTW/7DRL2021
        private static List <EncounterAction> ActionsUnitAdvanceRotateOut(EncounterState state, Entity parent, Unit unit, bool backSecure)
        {
            var actions = new List <EncounterAction>();

            var unitComponent     = parent.GetComponent <UnitComponent>();
            var parentPos         = parent.GetComponent <PositionComponent>().EncounterPosition;
            var parentFaction     = parent.GetComponent <FactionComponent>().Faction;
            var rotationComponent = parent.GetComponent <AIRotationComponent>();

            var positionBack = AIUtils.RotateAndProject(parentPos, 0, 1, unit.UnitFacing);

            var  friendliesParent = AIUtils.FriendliesInPosition(state, parent, parentFaction, parentPos.X, parentPos.Y);
            bool parentPosSecure  = false;

            foreach (var friendly in friendliesParent)
            {
                if (!friendly.IsRotating())
                {
                    parentPosSecure = true;
                    break;
                }
            }

            // If nobody is in your square or behind you, hold position
            // Issue: if you have 2 units that are retreating, they'll form a self-reinforcing rout, which...I mean. lol.
            if (backSecure || parentPosSecure)
            {
                actions.Add(new MoveAction(parent.EntityId, positionBack));
            }
            else
            {
                rotationComponent.NotifyRotationCompleted();
                actions.Add(new WaitAction(parent.EntityId));
            }

            return(actions);
        }
예제 #2
0
        public static List <TriggeredOrder> ExecutePREPARE_SWEEP_NEXT_LANE(EncounterState state, Unit unit)
        {
            // Find your current lane
            Lane   closestLane     = null;
            double closestDistance = 9999.0;

            foreach (var lane in state.DeploymentInfo.Lanes)
            {
                var d = lane.LaneCenter.DistanceTo(unit.AveragePosition);
                if (d < closestDistance)
                {
                    closestDistance = d;
                    closestLane     = lane;
                }
            }

            // Find a target lane
            int targetLane = -1;

            for (int i = closestLane.LaneIdx - 1; i >= 0; i--)
            {
                GD.Print("PREPPING CHECKING: ", i);
                var clear = state.DeploymentInfo.Lanes[i].UnitsForFaction(unit.UnitFaction.Opposite())
                            .Select((unitAtLanePosition) => state.GetUnit(unitAtLanePosition.UnitId).StandingOrder)
                            .All((order) => order == UnitOrder.ROUT);
                if (!clear)
                {
                    targetLane = i;
                    break;
                }
            }
            for (int i = closestLane.LaneIdx + 1; i < state.DeploymentInfo.Lanes.Count; i++)
            {
                GD.Print("PREPPING CHECKING: ", i);
                var clear = state.DeploymentInfo.Lanes[i].UnitsForFaction(unit.UnitFaction.Opposite())
                            .Select((unitAtLanePosition) => state.GetUnit(unitAtLanePosition.UnitId).StandingOrder)
                            .All((order) => order == UnitOrder.ROUT);
                if (!clear)
                {
                    targetLane = i;
                    break;
                }
            }
            GD.Print("CHOSEN LANE: ", targetLane);
            if (targetLane == -1)
            {
                return(null);
            }

            // Given a target lane, get the closest unit, and advance to its center
            var closestUnroutedEnemy = state.DeploymentInfo.Lanes[targetLane]
                                       .UnitsForFaction(unit.UnitFaction.Opposite())
                                       .Last((u) => state.GetUnit((u.UnitId)).StandingOrder != UnitOrder.ROUT);
            var enemyUnit     = state.GetUnit(closestUnroutedEnemy.UnitId);
            var enemyPos      = enemyUnit.AveragePosition;
            var vectorToEnemy = AIUtils.VectorFromCenterRotated(unit.AveragePosition, enemyPos.X, enemyPos.Y, unit.UnitFacing);
            var stepsBehind   = vectorToEnemy.Item2;

            GD.Print("UNIT IS BEHIND THE ENEMY UNIT BY: ", stepsBehind, " unit pos: ", unit.AveragePosition, " enemy pos: ", enemyPos, "facing: ", unit.UnitFacing);

            // Order unit to march steps + 5
            // unit.StandingOrder = UnitOrder.ADVANCE;

            // Order unit to reform perpendicular to the enemy line
            // var triggerStepsPlusFive = new OrderTrigger(OrderTriggerType.ACTIVATE_ON_OR_AFTER_TURN, false, activateOnTurn: state.CurrentTurn + stepsBehind + 5);
            var oldFacing = unit.UnitFacing;
            var newFacing = vectorToEnemy.Item1 < 0 ? unit.UnitFacing.LeftOf() : unit.UnitFacing.RightOf();

            unit.RallyPoint    = AIUtils.RotateAndProject(unit.AveragePosition, 0, -1 * stepsBehind - 25, unit.UnitFacing);;
            unit.UnitFacing    = newFacing;
            unit.StandingOrder = UnitOrder.REFORM;

            var behindEnemyUnit = AIUtils.RotateAndProject(enemyUnit.AveragePosition, 0, 15, enemyUnit.UnitFacing);

            // Order unit to advance after wheeling
            var triggerStepsPlus40 = new OrderTrigger(OrderTriggerType.ACTIVATE_ON_OR_AFTER_TURN, false, activateOnTurn: state.CurrentTurn + Math.Max(0, stepsBehind) + 15);
            var sweepOrder         = new TriggeredOrder(triggerStepsPlus40, new Order(unit.UnitId, OrderType.ROTATE_AND_REFORM_AT, newPosition: behindEnemyUnit, newFacing: oldFacing.Opposite()));

            // Order unit to finally advance
            var triggerStepsPlus60 = new OrderTrigger(OrderTriggerType.ACTIVATE_ON_OR_AFTER_TURN, false, activateOnTurn: state.CurrentTurn + Math.Max(0, stepsBehind) + 50);
            var advance            = new TriggeredOrder(triggerStepsPlus60, new Order(unit.UnitId, OrderType.ADVANCE));

            return(new List <TriggeredOrder>()
            {
                sweepOrder, advance
            });
        }
예제 #3
0
파일: AIUtils.cs 프로젝트: MoyTW/7DRL2021
        private static List <EncounterAction> ActionsUnitAdvanceFight(EncounterState state, Entity parent, Unit unit)
        {
            var actions = new List <EncounterAction>();

            var unitComponent = parent.GetComponent <UnitComponent>();
            var parentPos     = parent.GetComponent <PositionComponent>().EncounterPosition;
            var parentFaction = parent.GetComponent <FactionComponent>().Faction;

            var  targetEndPos = parentPos;
            bool tryAdvance   = true;

            if (tryAdvance)
            {
                if (IsNextRowTooFarAhead(parentPos, unit))
                {
                    tryAdvance = false;
                }
            }

            // Override for if you're too far back
            if (IsPositionTooFarBehind(AIUtils.RotateAndProject(parentPos, 0, -1, unit.UnitFacing), unit))
            {
                var aheadPos = AIUtils.RotateAndProject(parentPos, 0, -1, unit.UnitFacing);
                actions.Add(new MoveAction(parent.EntityId, aheadPos));
                TryAddAttackAdjacent(state, parent, actions, parentFaction, aheadPos);
                return(actions);
            }

            // Morale check for advancing directly into an enemy
            if (tryAdvance)
            {
                var twoStepsAhead = AIUtils.RotateAndProject(parentPos, 0, -2, unit.UnitFacing);
                if (AIUtils.HostilesInPosition(state, parentFaction, twoStepsAhead.X, twoStepsAhead.Y).Count > 0)
                {
                    var moraleState = parent.GetComponent <AIMoraleComponent>().CurrentMoraleState;
                    if (moraleState == MoraleState.WAVERING)
                    {
                        if (state.EncounterRand.Next(2) == 0)
                        {
                            tryAdvance = false;
                        }
                    }
                    else if (moraleState < MoraleState.WAVERING)
                    {
                        tryAdvance = false;
                    }
                }
            }

            if (tryAdvance)
            {
                // We're gonna have some serious Phalanx Drift goin' on I guess?
                var forwardPositions = new List <EncounterPosition>()
                {
                    AIUtils.RotateAndProject(parentPos, 0, -1, unit.UnitFacing)
                };
                if (!(unit.RightFlank && AIUtils.IsOnFlank(parentPos.X, parentPos.Y, unit, Flank.RIGHT)))
                {
                    forwardPositions.Add(AIUtils.RotateAndProject(parentPos, 1, -1, unit.UnitFacing));
                }
                if (!(unit.LeftFlank && AIUtils.IsOnFlank(parentPos.X, parentPos.Y, unit, Flank.LEFT)))
                {
                    forwardPositions.Add(AIUtils.RotateAndProject(parentPos, -1, -1, unit.UnitFacing));
                }

                foreach (var forwardPos in forwardPositions)
                {
                    if (state.EntitiesAtPosition(forwardPos.X, forwardPos.Y).Count == 0)
                    {
                        // Never go into a square unless it's flanked by an existing friendly
                        bool supported = false;
                        for (int y = -1; y < 2; y++)
                        {
                            var leftPos = AIUtils.RotateAndProject(forwardPos, -1, y, unit.UnitFacing);
                            if (AIUtils.FriendliesInPosition(state, parent, parentFaction, leftPos.X, leftPos.Y).Count > 0)
                            {
                                supported = true;
                                break;
                            }
                            var rightPos = AIUtils.RotateAndProject(forwardPos, 1, y, unit.UnitFacing);
                            if (AIUtils.FriendliesInPosition(state, parent, parentFaction, rightPos.X, rightPos.Y).Count > 0)
                            {
                                supported = true;
                                break;
                            }
                        }
                        if (supported)
                        {
                            targetEndPos = forwardPos;
                            break;
                        }
                    }
                }
                if (targetEndPos != parentPos)
                {
                    actions.Add(new MoveAction(parent.EntityId, targetEndPos));
                }
            }
            TryAddAttackAdjacent(state, parent, actions, parentFaction, targetEndPos);
            if (actions.Count == 0)
            {
                actions.Add(new WaitAction(parent.EntityId));
            }

            return(actions);
        }
예제 #4
0
        public List <EncounterAction> DecideNextActionForInput(EncounterState state, Entity parent, string actionMapping)
        {
            var unit          = state.GetUnit(parent.GetComponent <UnitComponent>().UnitId);
            var unitComponent = parent.GetComponent <UnitComponent>();

            if (actionMapping == InputHandler.ActionMapping.LEAVE_FORMATION)
            {
                parent.GetComponent <PlayerComponent>().LeaveFormation(state, parent);
                return(null);
            }

            if (unit.StandingOrder == UnitOrder.REFORM)
            {
                if (actionMapping == AUTOPILOT)
                {
                    return(AIUtils.ActionsForUnitReform(state, parent, unitComponent.FormationNumber, unit));
                }
                else
                {
                    return(null);
                }
            }
            else if (unit.StandingOrder == UnitOrder.ADVANCE)
            {
                if (this.AllowedActions(state, parent, unit.StandingOrder).Contains(actionMapping))
                {
                    if (actionMapping == InputHandler.ActionMapping.ROTATE)
                    {
                        parent.GetComponent <AIRotationComponent>().PlayerSetRotation(true);
                        parent.GetComponent <PlayerComponent>().AddPrestige(-2, state,
                                                                            "You cry out [b]'Rotation!'[/b]' and pull back through your lines. [b]You lose 2 prestige.[/b]", PrestigeSource.ROTATING);
                        return(null);
                    }
                    else if (actionMapping == InputHandler.ActionMapping.WAIT)
                    {
                        return(new List <EncounterAction>()
                        {
                            new WaitAction(parent.EntityId)
                        });
                    }
                    else
                    {
                        return(HandleMoveCommand(state, actionMapping));
                    }
                }
                else if (actionMapping == AUTOPILOT)
                {
                    var playerComponent = state.Player.GetComponent <PlayerComponent>();

                    var actions = AIUtils.ActionsForUnitAdvanceInLine(state, parent, unit);

                    // Termination for startoflevel
                    if (playerComponent.StartOfLevel)
                    {
                        var anyHostilesAdjacent = AIUtils.AdjacentHostiles(state, FactionName.PLAYER, parent.GetComponent <PositionComponent>().EncounterPosition).Count > 0;
                        if (anyHostilesAdjacent)
                        {
                            state.Player.GetComponent <PlayerComponent>().StartOfLevel = false;
                            return(null);
                        }
                        foreach (var action in actions)
                        {
                            if (action.ActionType == ActionType.MOVE)
                            {
                                if (AIUtils.AdjacentHostiles(state, FactionName.PLAYER, ((MoveAction)action).TargetPosition).Count > 0)
                                {
                                    state.Player.GetComponent <PlayerComponent>().StartOfLevel = false;
                                    return(null);
                                }
                            }
                        }
                    }

                    return(actions);
                }
                else
                {
                    return(null);
                }
            }
            else if (unit.StandingOrder == UnitOrder.ROUT)
            {
                return(null);
            }
            else
            {
                throw new NotImplementedException();
            }
        }