void TryToRushAttack(IBot bot)
        {
            var allEnemyBaseBuilder = AIUtils.FindEnemiesByCommonName(Info.ConstructionYardTypes, Player);

            // TODO: This should use common names & ExcludeFromSquads instead of hardcoding TraitInfo checks
            var ownUnits = activeUnits
                           .Where(unit => unit.IsIdle && unit.Info.HasTraitInfo <AttackBaseInfo>() &&
                                  !unit.Info.HasTraitInfo <AircraftInfo>() && !unit.Info.HasTraitInfo <HarvesterInfo>()).ToList();

            if (!allEnemyBaseBuilder.Any() || ownUnits.Count < Info.SquadSize)
            {
                return;
            }

            foreach (var b in allEnemyBaseBuilder)
            {
                // Don't rush enemy aircraft!
                var enemies = World.FindActorsInCircle(b.CenterPosition, WDist.FromCells(Info.RushAttackScanRadius))
                              .Where(unit => IsEnemyUnit(unit) && unit.Info.HasTraitInfo <AttackBaseInfo>() && !unit.Info.HasTraitInfo <AircraftInfo>()).ToList();

                if (AttackOrFleeFuzzy.Rush.CanAttack(ownUnits, enemies))
                {
                    var target = enemies.Any() ? enemies.Random(World.LocalRandom) : b;
                    var rush   = GetSquadOfType(SquadType.Rush);
                    if (rush == null)
                    {
                        rush = RegisterNewSquad(bot, SquadType.Rush, target);
                    }

                    foreach (var a3 in ownUnits)
                    {
                        rush.Units.Add(a3);
                    }

                    return;
                }
            }
        }
Пример #2
0
        /// <summary>Detail scans an area, evaluating positions.</summary>
        CPos?FindFineAttackLocationToSupportPower(SupportPowerInstance readyPower, CPos checkPos, int extendedRange = 1)
        {
            CPos?bestLocation       = null;
            var  bestAttractiveness = 0;
            var  powerDecision      = powerDecisions[readyPower.Info.OrderName];

            if (powerDecision == null)
            {
                AIUtils.BotDebug("Bot Bug: FindAttackLocationToSupportPower, couldn't find powerDecision for {0}", readyPower.Info.OrderName);
                return(null);
            }

            var checkRadius = powerDecision.CoarseScanRadius;
            var fineCheck   = powerDecision.FineScanRadius;

            for (var i = 0 - extendedRange; i <= (checkRadius + extendedRange); i += fineCheck)
            {
                var x = checkPos.X + i;

                for (var j = 0 - extendedRange; j <= (checkRadius + extendedRange); j += fineCheck)
                {
                    var y   = checkPos.Y + j;
                    var pos = world.Map.CenterOfCell(new CPos(x, y));
                    var consideredAttractiveness = 0;
                    consideredAttractiveness += powerDecision.GetAttractiveness(pos, player);

                    if (consideredAttractiveness <= bestAttractiveness || consideredAttractiveness < powerDecision.MinimumAttractiveness)
                    {
                        continue;
                    }

                    bestAttractiveness = consideredAttractiveness;
                    bestLocation       = new CPos(x, y);
                }
            }

            return(bestLocation);
        }
Пример #3
0
        protected void OrderHarvesters(IBot bot)
        {
            var toRemove = harvesters.Keys.Where(unitCannotBeOrdered).ToList();

            foreach (var a in toRemove)
            {
                harvesters.Remove(a);
            }

            // Find new harvesters
            // TODO: Look for a more performance-friendly way to update this list
            var newHarvesters = world.ActorsHavingTrait <Harvester>().Where(a => a.Owner == player && !harvesters.ContainsKey(a));

            foreach (var a in newHarvesters)
            {
                harvesters[a] = new HarvesterTraitWrapper(a);
            }

            // Find idle harvesters and give them orders:
            foreach (var h in harvesters)
            {
                if (!h.Key.IsIdle)
                {
                    var act = h.Key.CurrentActivity as FindAndDeliverResources;

                    // Ignore this actor if FindAndDeliverResources is working fine or it is performing a different activity
                    if (act == null || !act.LastSearchFailed)
                    {
                        continue;
                    }
                }

                // Tell the idle harvester to quit slacking:
                var newSafeResourcePatch = FindNextResource(h.Key, h.Value);
                AIUtils.BotDebug("AI: Harvester {0} is idle. Ordering to {1} in search for new resources.".F(h.Key, newSafeResourcePatch));
                bot.QueueOrder(new Order("Harvest", h.Key, newSafeResourcePatch, false));
            }
        }
Пример #4
0
    public override void OnEnter()
    {
        controller.ClearVelocity();
        controller.ActiveGravity = false;
        intervalTimer            = Interval;
        currentCount             = 0;

        target = Owner.GetComponent <NodeCanvas.Framework.Blackboard> ().GetValue <Transform> ("Target");

        var hit = Physics2D.Raycast(target.position, Vector2.down, float.MaxValue, LayerMask.GetMask("Platform", "OneWayPlatform", "Wall"));

        if (hit.collider != null)
        {
            heightY    = hit.collider.bounds.max.y + height;
            rangeLeft  = target.position.x - range * 0.5f;
            rangeRight = target.position.x + range * 0.5f;
            AIUtils.ClampPlatformEdgePoint(hit.collider, ref rangeLeft, ref rangeRight);
        }
        else
        {
            Debug.LogError($"Action_Boss08_Atk3_Teleport没找到平台");
        }
    }
Пример #5
0
        void IBotTick.BotTick(IBot bot)
        {
            var colonies = AIUtils.GetActorsWithTrait <Colony>(world).Where(c => c.Owner == player).ToArray();

            foreach (var colony in colonies)
            {
                var health = colony.Trait <IHealth>();
                if (health.DamageState == Info.DamageState)
                {
                    var queue = colony.TraitOrDefault <ProductionQueue>();                    // Turrets don't produce
                    if (queue == null)
                    {
                        continue;
                    }

                    foreach (var current in queue.AllQueued())
                    {
                        bot.QueueOrder(Order.CancelProduction(queue.Actor, current.Item, 1));
                        AIUtils.BotDebug("{0}: Stopping production of {1} at {2} to heal.".F(player.PlayerName, current.Item, colony));
                    }
                }
            }
        }
Пример #6
0
        private void Crossover(List <double> mum, List <double> dad, ref List <double> baby1, ref List <double> baby2)
        {
            if ((AIUtils.Random(1.0) > _crossoverRate) || (mum == dad))
            {
                baby1 = mum;
                baby2 = dad;
                return;
            }

            int cp = AIUtils.RandomInt(0, _chromosomeLength - 1);

            for (int i = 0; i < cp; ++i)
            {
                baby1.Add(mum[i]);
                baby2.Add(dad[i]);
            }

            for (int i = cp; i < mum.Count; ++i)
            {
                baby1.Add(dad[i]);
                baby2.Add(mum[i]);
            }
        }
        Target FindNextResource(Actor actor, MinerTraitWrapper miner)
        {
            var towerInfo    = AIUtils.GetInfoByCommonName(Info.DeployedActorTypes, player);
            var buildingInfo = towerInfo.TraitInfo <BuildingInfo>();
            Func <CPos, bool> isValidResource = cell =>
                                                domainIndex.IsPassable(actor.Location, cell, miner.Locomotor.Info) &&
                                                Info.DeployableTerrainTypes.Contains(world.Map.GetTerrainInfo(cell).Type) &&
                                                miner.Locomotor.CanStayInCell(cell) &&
                                                world.CanPlaceBuilding(cell + miner.Transforms.Info.Offset, towerInfo, buildingInfo, actor);

            var path = pathfinder.FindPath(
                PathSearch.Search(world, miner.Locomotor, actor, BlockedByActor.Stationary, isValidResource)
                .WithCustomCost(loc => world.FindActorsInCircle(world.Map.CenterOfCell(loc), Info.EnemyAvoidanceRadius)
                                .Where(u => !u.IsDead && actor.Owner.Stances[u.Owner] == Stance.Enemy)
                                .Sum(u => Math.Max(WDist.Zero.Length, Info.EnemyAvoidanceRadius.Length - (world.Map.CenterOfCell(loc) - u.CenterPosition).Length)))
                .FromPoint(actor.Location));

            if (path.Count == 0)
            {
                return(Target.Invalid);
            }

            return(Target.FromCell(world, path[0]));
        }
Пример #8
0
        void IBotTick.BotTick(IBot bot)
        {
            foreach (var sp in supportPowerManager.Powers.Values)
            {
                if (sp.Disabled)
                {
                    continue;
                }

                // Add power to dictionary if not in delay dictionary yet
                if (!waitingPowers.ContainsKey(sp))
                {
                    waitingPowers.Add(sp, 0);
                }

                if (waitingPowers[sp] > 0)
                {
                    waitingPowers[sp]--;
                }

                // If we have recently tried and failed to find a use location for a power, then do not try again until later
                var isDelayed = waitingPowers[sp] > 0;
                if (sp.Ready && !isDelayed && powerDecisions.ContainsKey(sp.Info.OrderName))
                {
                    var powerDecision = powerDecisions[sp.Info.OrderName];
                    if (powerDecision == null)
                    {
                        AIUtils.BotDebug("Bot Bug: FindAttackLocationToSupportPower, couldn't find powerDecision for {0}", sp.Info.OrderName);
                        continue;
                    }

                    if (sp.Info.Cost != 0 && playerResource.Cash + playerResource.Resources < sp.Info.Cost)
                    {
                        AIUtils.BotDebug("AI: {1} can't afford the activation of support power {0}. Delaying rescan.", sp.Info.OrderName, player.PlayerName);
                        waitingPowers[sp] += powerDecision.GetNextScanTime(world);

                        continue;
                    }

                    var attackLocation = FindAttackLocationToSupportPower(sp);
                    if (attackLocation == null)
                    {
                        AIUtils.BotDebug("AI: {1} can't find suitable attack location for support power {0}. Delaying rescan.", sp.Info.OrderName, player.PlayerName);
                        waitingPowers[sp] += powerDecision.GetNextScanTime(world);

                        continue;
                    }

                    // Valid target found, delay by a few ticks to avoid rescanning before power fires via order
                    AIUtils.BotDebug("AI: {2} found new target location {0} for support power {1}.", attackLocation, sp.Info.OrderName, player.PlayerName);
                    waitingPowers[sp] += 10;
                    bot.QueueOrder(new Order(sp.Key, supportPowerManager.Self, Target.FromCell(world, attackLocation.Value), false)
                    {
                        SuppressVisualFeedback = true
                    });
                }
            }

            // Remove stale powers
            stalePowers.AddRange(waitingPowers.Keys.Where(wp => !supportPowerManager.Powers.ContainsKey(wp.Key)));
            foreach (var p in stalePowers)
            {
                waitingPowers.Remove(p);
            }

            stalePowers.Clear();
        }
Пример #9
0
        private bool IsAttackable(Character target)
        {
            bool targetTooFar = Vector2.Distance(target.iso.pos, character.iso.pos) > maxAgroDistance;

            return(!targetTooFar && AIUtils.IsAttackable(character, target));
        }
Пример #10
0
 protected override void OnTick()
 {
     //持球进攻
     if (m_player.m_bWithBall)
     {
         PlayerState.State state = m_player.m_StateMachine.m_curState.m_eState;
         if (m_match.m_ruler.m_bToCheckBall)                 //带出三分线
         {
             if (state == PlayerState.State.eStand ||
                 state == PlayerState.State.eRun ||
                 state == PlayerState.State.eRush ||
                 state == PlayerState.State.eHold)
             {
                 bool inTakeOver = false;
                 if (m_player.m_inputDispatcher != null)
                 {
                     inTakeOver = m_player.m_inputDispatcher.inTakeOver;
                 }
                 if (!inTakeOver)
                 {
                     Player passTarget = AIUtils.ChoosePassTargetCheckBall(m_player, m_match);
                     if (passTarget != null)
                     {
                         AI_Pass pass = m_system.GetState(Type.ePass) as AI_Pass;
                         pass.m_toPass = passTarget;
                         m_system.SetTransaction(pass);
                     }
                     else
                     {
                         m_system.SetTransaction(AIState.Type.eCheckBall);
                     }
                 }
                 else
                 {
                     m_system.SetTransaction(AIState.Type.eCheckBall);
                 }
             }
         }
         else
         {
             if (state == PlayerState.State.eStand ||
                 state == PlayerState.State.eRun ||
                 state == PlayerState.State.eRush)
             {
                 Offense();
             }
             else if (state == PlayerState.State.eHold)
             {
                 if ((m_match.mCurScene.mGround.GetArea(m_player) == Area.eNear ||
                      !m_player.IsDefended(m_system.AI.devAngleAttacker, m_system.AI.devDistAOD)) &&
                     arriveFirstTarget)
                 {
                     Offense();
                 }
                 else
                 {
                     m_system.SetTransaction(AIState.Type.eIdle);
                 }
             }
         }
     }
     else            //非持球进攻
     {
         //空切
         if (arriveFirstTarget && m_ball.m_owner != null && IM.Random.value < new IM.Number(0, 250) &&
             m_player.IsDefended(m_system.AI.devAngleAttacker, m_system.AI.devDistAOD))
         {
             //if( !(m_match is GameMatch_PVP) )
             m_system.SetTransaction(AIState.Type.eCutIn);
         }
         //要球
         else if (m_ball.m_owner != null && m_ball.m_owner.m_team == m_player.m_team && m_system.m_bNotDefended && !m_match.m_ruler.m_bToCheckBall)
         {
             //if( !(m_match is GameMatch_PVP) )
             m_system.SetTransaction(AIState.Type.eRequireBall);
         }
         //靠近球6米,追球
         else if (AIUtils.ShouldTraceBall(m_ball, m_player))
         {
             m_system.SetTransaction(AIState.Type.eIdle);
         }
         //挡拆
         else
         {
             int result = AIUtils.CanPickAndRoll(m_player);
             if (result == 1 && m_player.m_StateMachine.m_curState.IsCommandValid(Command.PickAndRoll))
             {
                 m_system.SetTransaction(AIState.Type.ePickAndRoll);
             }
             else if (result == 2)
             {
                 positionForPR = true;
                 m_system.SetTransaction(AIState.Type.ePositioning, new IM.Number(100), true);
             }
         }
     }
 }
Пример #11
0
 private Dictionary <EDirection, Vector2Int> GetNeighbours(
     Vector2Int position,
     bool onlyAccessible = false)
 {
     return(AIUtils.GetNeighbours(position, _map, onlyAccessible));
 }
Пример #12
0
        bool TickQueue(IBot bot, ProductionQueue queue)
        {
            var currentBuilding = queue.AllQueued().FirstOrDefault();

            // Waiting to build something
            if (currentBuilding == null && failCount < baseBuilder.Info.MaximumFailedPlacementAttempts)
            {
                var item = ChooseBuildingToBuild(queue);
                if (item == null)
                {
                    return(false);
                }

                bot.QueueOrder(Order.StartProduction(queue.Actor, item.Name, 1));
            }
            else if (currentBuilding != null && currentBuilding.Done)
            {
                // Production is complete
                // Choose the placement logic
                // HACK: HACK HACK HACK
                // TODO: Derive this from BuildingCommonNames instead
                var    type        = BuildingType.Building;
                CPos?  location    = null;
                string orderString = "PlaceBuilding";

                // Check if Building is a plug for other Building
                var actorInfo = world.Map.Rules.Actors[currentBuilding.Item];
                var plugInfo  = actorInfo.TraitInfoOrDefault <PlugInfo>();
                if (plugInfo != null)
                {
                    var possibleBuilding = world.ActorsWithTrait <Pluggable>().FirstOrDefault(a =>
                                                                                              a.Actor.Owner == player && a.Trait.AcceptsPlug(a.Actor, plugInfo.Type));

                    if (possibleBuilding.Actor != null)
                    {
                        orderString = "PlacePlug";
                        location    = possibleBuilding.Actor.Location + possibleBuilding.Trait.Info.Offset;
                    }
                }
                else
                {
                    // Check if Building is a defense and if we should place it towards the enemy or not.
                    if (actorInfo.HasTraitInfo <AttackBaseInfo>() && world.LocalRandom.Next(100) < baseBuilder.Info.PlaceDefenseTowardsEnemyChance)
                    {
                        type = BuildingType.Defense;
                    }
                    else if (baseBuilder.Info.RefineryTypes.Contains(actorInfo.Name))
                    {
                        type = BuildingType.Refinery;
                    }

                    location = ChooseBuildLocation(currentBuilding.Item, true, type);
                }

                if (location == null)
                {
                    AIUtils.BotDebug("{0} has nowhere to place {1}".F(player, currentBuilding.Item));
                    bot.QueueOrder(Order.CancelProduction(queue.Actor, currentBuilding.Item, 1));
                    failCount += failCount;

                    // If we just reached the maximum fail count, cache the number of current structures
                    if (failCount == baseBuilder.Info.MaximumFailedPlacementAttempts)
                    {
                        cachedBuildings = world.ActorsHavingTrait <Building>().Count(a => a.Owner == player);
                        cachedBases     = world.ActorsHavingTrait <BaseProvider>().Count(a => a.Owner == player);
                    }
                }
                else
                {
                    failCount = 0;

                    bot.QueueOrder(new Order(orderString, player.PlayerActor, Target.FromCell(world, location.Value), false)
                    {
                        // Building to place
                        TargetString = currentBuilding.Item,

                        // Actor ID to associate the placement with
                        ExtraData = queue.Actor.ActorID,
                        SuppressVisualFeedback = true
                    });

                    return(true);
                }
            }

            return(true);
        }
Пример #13
0
        private bool Checkproximity(float distanceFromStart)
        {
            bool detonate = false;

            if (distanceFromStart < blastRadius)
            {
                return(detonate = false);
            }

            using (var hitsEnu = Physics.OverlapSphere(transform.position, detonationRange, 557057).AsEnumerable().GetEnumerator())
            {
                while (hitsEnu.MoveNext())
                {
                    if (hitsEnu.Current == null)
                    {
                        continue;
                    }

                    Part partHit = hitsEnu.Current.GetComponentInParent <Part>();
                    if (partHit == null || partHit.vessel == null)
                    {
                        continue;
                    }
                    if (partHit.vessel == vessel || partHit.vessel == sourcevessel)
                    {
                        continue;
                    }
                    if (partHit.vessel.vesselType == VesselType.Debris)
                    {
                        continue;
                    }
                    if (sourcevessel != null && partHit.vessel.vesselName.Contains(sourcevessel.vesselName))
                    {
                        continue;
                    }
                    var weaponManager = partHit.vessel.FindPartModuleImplementing <MissileFire>();
                    if (IFF_On && (weaponManager == null || weaponManager.teamString == IFFID))
                    {
                        continue;
                    }
                    if (detonateAtMinimumDistance)
                    {
                        var distance          = Vector3.Distance(partHit.transform.position + partHit.CoMOffset, transform.position);
                        var predictedDistance = Vector3.Distance(AIUtils.PredictPosition(partHit.transform.position + partHit.CoMOffset, partHit.vessel.Velocity(), partHit.vessel.acceleration, Time.fixedDeltaTime), AIUtils.PredictPosition(transform.position, vessel.Velocity(), vessel.acceleration, Time.fixedDeltaTime));
                        if (distance > predictedDistance && distance > Time.fixedDeltaTime * (float)vessel.srfSpeed) // If we're closing and not going to hit within the next update, then wait.
                        {
                            return(detonate = false);
                        }
                    }
                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        Debug.Log("[BDArmory.BDExplosivePart]: Proxifuze triggered by " + partHit.partName + " from " + partHit.vessel.vesselName);
                    }
                    return(detonate = true);
                }
            }
            return(detonate);
        }
Пример #14
0
        void IBotTick.BotTick(IBot bot)
        {
            if (--scanForBitsTicks > 0)
            {
                return;
            }

            scanForBitsTicks = Info.ScanInterval;

            var bits = world.ActorsHavingTrait <ColonyBit>().ToList();

            if (!bits.Any())
            {
                return;
            }

            if (Info.CheckTargetsForVisibility)
            {
                bits.RemoveAll(c => !c.CanBeViewedByPlayer(player));
            }

            var units = world.ActorsHavingTrait <Mobile>().Where(a => a.Owner == player && a.IsIdle &&
                                                                 (Info.IncludedUnitTypes.Contains(a.Info.Name) || (!Info.IncludedUnitTypes.Any() && !Info.ExcludedUnitTypes.Contains(a.Info.Name)))).ToList();

            if (!units.Any())
            {
                return;
            }

            foreach (var bit in bits)
            {
                var bitCollector = units.ClosestTo(bit);
                if (bitCollector == null)
                {
                    continue;
                }

                if ((bit.Location - bitCollector.Location).Length > maxProximity)
                {
                    continue;
                }

                units.Remove(bitCollector);

                if (squadManagerBotModule == null)
                {
                    squadManagerBotModule = bot.Player.PlayerActor.TraitsImplementing <SquadManagerBotModule>().FirstEnabledTraitOrDefault();
                }

                if (squadManagerBotModule != null)
                {
                    // You got ONE job!
                    var squad = squadManagerBotModule.Squads.FirstOrDefault(s => s.Units.Contains(bitCollector));
                    if (squad != null)
                    {
                        squad.Units.Remove(bitCollector);
                    }
                }

                var target = Target.FromCell(world, bit.Location);
                AIUtils.BotDebug("AI: Ordering unit {0} to {1} for colony bit pick up.".F(bitCollector, target));
                bot.QueueOrder(new Order("Stop", bitCollector, false));
                bot.QueueOrder(new Order("Move", bitCollector, target, false));
            }
        }
Пример #15
0
        void QueueCaptureOrders(IBot bot)
        {
            if (player.WinState != WinState.Undefined)
            {
                return;
            }

            var newUnits = world.ActorsHavingTrait <Captures>()
                           .Where(a => a.Owner == player && !a.IsDead && a.IsInWorld);

            if (!newUnits.Any())
            {
                return;
            }

            var capturers = newUnits
                            .Where(a => a.IsIdle && Info.CapturingActorTypes.Contains(a.Info.Name))
                            .Select(a => new TraitPair <CaptureManager>(a, a.TraitOrDefault <CaptureManager>()))
                            .Where(tp => tp.Trait != null);

            if (!capturers.Any())
            {
                return;
            }

            var baseCenter = world.Map.CenterOfCell(initialBaseCenter);

            if (world.LocalRandom.Next(100) < Info.PriorityCaptureChance)
            {
                var priorityTargets = world.Actors.Where(a =>
                                                         !a.IsDead && a.IsInWorld && Info.CapturableStances.HasRelationship(player.RelationshipWith(a.Owner)) &&
                                                         Info.PriorityCapturableActorTypes.Contains(a.Info.Name.ToLowerInvariant()));

                if (Info.CheckCaptureTargetsForVisibility)
                {
                    priorityTargets = priorityTargets.Where(a => a.CanBeViewedByPlayer(player));
                }

                if (priorityTargets.Any())
                {
                    priorityTargets = priorityTargets.OrderBy(a => (a.CenterPosition - baseCenter).LengthSquared);

                    var priorityCaptures = Math.Min(capturers.Count(), priorityTargets.Count());

                    for (int i = 0; i < priorityCaptures; i++)
                    {
                        var capturer = capturers.First();

                        var priorityTarget = priorityTargets.First();

                        var captureManager = priorityTarget.TraitOrDefault <CaptureManager>();
                        if (captureManager != null && captureManager.CanBeTargetedBy(priorityTarget, capturer.Actor, capturer.Trait))
                        {
                            var safeTarget = SafePath(capturer.Actor, priorityTarget);
                            if (safeTarget.Type == TargetType.Invalid)
                            {
                                priorityTargets = priorityTargets.Skip(1);
                                capturers       = capturers.Skip(1);
                                continue;
                            }

                            bot.QueueOrder(new Order("CaptureActor", capturer.Actor, safeTarget, true));
                            AIUtils.BotDebug("AI ({0}): Ordered {1} {2} to capture {3} {4} in priority mode.",
                                             player.ClientIndex, capturer.Actor, capturer.Actor.ActorID, priorityTarget, priorityTarget.ActorID);
                        }

                        priorityTargets = priorityTargets.Skip(1);
                        capturers       = capturers.Skip(1);
                    }

                    if (!capturers.Any())
                    {
                        return;
                    }
                }
            }

            var randomPlayer = world.Players.Where(p => !p.Spectating &&
                                                   Info.CapturableStances.HasRelationship(player.RelationshipWith(p))).Random(world.LocalRandom);

            var targetOptions = Info.CheckCaptureTargetsForVisibility
                                ? GetVisibleActorsBelongingToPlayer(randomPlayer)
                                : GetActorsThatCanBeOrderedByPlayer(randomPlayer);

            var capturableTargetOptions = targetOptions
                                          .Where(target =>
            {
                var captureManager = target.TraitOrDefault <CaptureManager>();
                if (captureManager == null)
                {
                    return(false);
                }

                return(capturers.Any(tp => captureManager.CanBeTargetedBy(target, tp.Actor, tp.Trait)));
            })
                                          .OrderBy(target => (target.CenterPosition - baseCenter).LengthSquared)
                                          .Take(maximumCaptureTargetOptions);

            if (Info.CapturableActorTypes.Any())
            {
                capturableTargetOptions = capturableTargetOptions.Where(target => Info.CapturableActorTypes.Contains(target.Info.Name.ToLowerInvariant()));
            }

            if (!capturableTargetOptions.Any())
            {
                return;
            }

            foreach (var capturer in capturers)
            {
                var nearestTargetActors = capturableTargetOptions.OrderBy(target => (target.CenterPosition - capturer.Actor.CenterPosition).LengthSquared);
                foreach (var nearestTargetActor in nearestTargetActors)
                {
                    var safeTarget = SafePath(capturer.Actor, nearestTargetActor);
                    if (safeTarget.Type == TargetType.Invalid)
                    {
                        continue;
                    }

                    bot.QueueOrder(new Order("CaptureActor", capturer.Actor, safeTarget, true));
                    AIUtils.BotDebug("AI: Ordered {0} to capture {1}", capturer.Actor, nearestTargetActor);
                    break;
                }
            }
        }
Пример #16
0
    public static Player ChoosePassTargetCheckBall(Player player, GameMatch match)
    {
        List <Player> teammates = new List <Player>(player.m_team.members);

        teammates.Remove(player);
        if (teammates.Count == 0)
        {
            return(null);
        }

        // Teammates in far area.
        List <Player> matesFar = new List <Player>();

        foreach (Player mate in teammates)
        {
            if (match.mCurScene.mGround.GetArea(mate) == Area.eFar)
            {
                matesFar.Add(mate);
            }
        }
        if (matesFar.Count > 0)         // There are teammates in far area, pass to most prior mate.
        {
            return(AIUtils.GetMostPriorPassTarget(matesFar, player));
        }
        else            // No teammates in far area.
        {
            // Teammates in PG or SG's favor area.
            List <Player> matesOutSide        = new List <Player>();
            RoadPathManager.SectorArea areaPG = Player.positionFavorSectors[PositionType.PT_PG];
            RoadPathManager.SectorArea areaSG = Player.positionFavorSectors[PositionType.PT_SG];
            foreach (Player mate in player.m_team.members)
            {
                if (RoadPathManager.Instance.InSectors(areaPG, mate.position) ||
                    RoadPathManager.Instance.InSectors(areaSG, mate.position))
                {
                    matesOutSide.Add(mate);
                }
            }
            if (matesOutSide.Count > 0)                 // There are teammates in PG or SG's favor area, pass to most prior mate if its not myself.
            {
                Player passTarget = AIUtils.GetMostPriorPassTarget(matesOutSide, player);
                return(passTarget == player ? null : passTarget);
            }
            else                // No teammates in PG or SG's favor area.
            {
                List <Player> teammatesPGSG = new List <Player>();
                foreach (Player mate in teammates)
                {
                    if (mate.m_matchPosition == PositionType.PT_PG || mate.m_matchPosition == PositionType.PT_SG)
                    {
                        teammatesPGSG.Add(mate);
                    }
                }
                if (player.m_matchPosition == PositionType.PT_C)
                {
                    if (teammatesPGSG.Count > 0)                        // Pass to most prior PG or SG.
                    {
                        return(AIUtils.GetMostPriorPassTarget(teammatesPGSG, player));
                    }
                    else                        // Pass to nearest non-C teammate.
                    {
                        Player    nearestNonC = null;
                        IM.Number minDist     = IM.Number.max;
                        foreach (Player mate in teammates)
                        {
                            if (mate.m_matchPosition != PositionType.PT_C)
                            {
                                IM.Number curDist = GameUtils.HorizonalDistance(mate.position, player.position);
                                if (curDist < minDist)
                                {
                                    minDist     = curDist;
                                    nearestNonC = mate;
                                }
                            }
                        }
                        return(nearestNonC);
                    }
                }
                else if (player.m_matchPosition == PositionType.PT_PF)
                {
                    if (teammatesPGSG.Count > 0)                        // Pass to most prior PG or SG.
                    {
                        return(AIUtils.GetMostPriorPassTarget(teammatesPGSG, player));
                    }
                    else                        // Pass to nearest non-PF teammate.
                    {
                        Player    nearestNonPF = null;
                        IM.Number minDist      = IM.Number.max;
                        foreach (Player mate in teammates)
                        {
                            if (mate.m_matchPosition != PositionType.PT_PF)
                            {
                                IM.Number curDist = GameUtils.HorizonalDistance(mate.position, player.position);
                                if (curDist < minDist)
                                {
                                    minDist      = curDist;
                                    nearestNonPF = mate;
                                }
                            }
                        }
                        return(nearestNonPF);
                    }
                }
                else
                {
                    return(null);
                }
            }
        }
    }
        void IBotTick.BotTick(IBot bot)
        {
            if (resourceLayer == null || resourceLayer.IsResourceLayerEmpty)
            {
                return;
            }

            if (--scanForIdleMinersTicks > 0)
            {
                return;
            }

            scanForIdleMinersTicks = Info.MinimumScanDelay;

            var toRemove = miners.Keys.Where(unitCannotBeOrdered).ToList();

            foreach (var a in toRemove)
            {
                miners.Remove(a);
            }

            // TODO: Look for a more performance friendly way to update this list
            var newMiners = world.Actors.Where(a => Info.DeployableActorTypes.Contains(a.Info.Name) && a.Owner == player && !miners.ContainsKey(a));

            foreach (var a in newMiners)
            {
                miners[a] = new MinerTraitWrapper(a);
            }

            foreach (var miner in miners)
            {
                if (!miner.Key.IsIdle)
                {
                    continue;
                }

                if (Info.DeployableTerrainTypes.Contains(world.Map.GetTerrainInfo(miner.Key.Location).Type))
                {
                    bot.QueueOrder(new Order("DeployTransform", miner.Key, true));
                    continue;
                }

                // Tell the idle miner to quit slacking:
                var newSafeResourcePatch = FindNextResource(miner.Key, miner.Value);
                if (newSafeResourcePatch.Type == TargetType.Invalid)
                {
                    scanForIdleMinersTicks = Info.LastSearchFailedDelay;
                    return;
                }

                AIUtils.BotDebug("AI: Miner {0} is idle. Ordering to {1} in search for new resources.".F(miner.Key, newSafeResourcePatch));
                bot.QueueOrder(new Order("Move", miner.Key, newSafeResourcePatch, true));
            }

            // Keep the economy running before starving out.
            var unitBuilder = requestUnitProduction.FirstOrDefault(Exts.IsTraitEnabled);

            if (unitBuilder != null)
            {
                var minerInfo    = AIUtils.GetInfoByCommonName(Info.DeployableActorTypes, player);
                var miningTowers = AIUtils.CountBuildingByCommonName(Info.DeployedActorTypes, player);
                if (miningTowers < Info.MinimumDeployedActors && unitBuilder.RequestedProductionCount(bot, minerInfo.Name) == 0)
                {
                    unitBuilder.RequestUnitProduction(bot, minerInfo.Name);
                }
            }
        }
Пример #18
0
 // Line indices are "lower towards enemy" - 0th = skirmishers, first = hastatus, third = triarius, highest = reserves
 public EncounterPosition PositionFor(FormationFacing facing, int line, int interval = 15)
 {
     // The facing has to be swapped in order for the position to work - an army FACING north should be DEPLOYED south
     return(AIUtils.RotateAndProject(LaneCenter, 0, -interval * line - interval / 5, facing.Opposite()));
 }
Пример #19
0
        void IBotTick.BotTick(IBot bot)
        {
            if (cubeSpawner == null || !cubeSpawner.IsTraitEnabled() || !cubeSpawner.Enabled)
            {
                return;
            }

            if (--scanForcubesTicks > 0)
            {
                return;
            }

            scanForcubesTicks = Info.ScanForCubesInterval;

            var cubes = world.ActorsHavingTrait <Crate>().ToList();

            if (!cubes.Any())
            {
                return;
            }

            if (Info.CheckTargetsForVisibility)
            {
                cubes.RemoveAll(c => !c.CanBeViewedByPlayer(player));
            }

            var idleUnits = world.ActorsHavingTrait <Mobile>().Where(a => a.Owner == player && a.IsIdle &&
                                                                     (Info.IncludedUnitTypes.Contains(a.Info.Name) || (!Info.IncludedUnitTypes.Any() && !Info.ExcludedUnitTypes.Contains(a.Info.Name)))).ToList();

            if (!idleUnits.Any())
            {
                return;
            }

            foreach (var cube in cubes)
            {
                if (alreadyPursuitcubes.Contains(cube))
                {
                    continue;
                }

                if (!cube.IsAtGroundLevel())
                {
                    continue;
                }

                var cubeCollector = idleUnits.ClosestTo(cube);
                if (cubeCollector == null)
                {
                    continue;
                }

                if ((cube.Location - cubeCollector.Location).Length > maxProximity)
                {
                    continue;
                }

                idleUnits.Remove(cubeCollector);

                var target = PathToNextcube(cubeCollector, cube);
                if (target.Type == TargetType.Invalid)
                {
                    continue;
                }

                var cell = world.Map.CellContaining(target.CenterPosition);
                AIUtils.BotDebug("AI: Ordering {0} to {1} for cube pick up.".F(cubeCollector, cell));
                bot.QueueOrder(new Order("Move", cubeCollector, target, true));
                alreadyPursuitcubes.Add(cube);
            }
        }
Пример #20
0
        void AttitudeControl(FlightCtrlState s)
        {
            const float terrainOffset = 5;

            Vector3 yawTarget = Vector3.ProjectOnPlane(targetDirection, vesselTransform.forward);

            // limit "aoa" if we're moving
            float driftMult = 1;

            if (vessel.horizontalSrfSpeed * 10 > CruiseSpeed)
            {
                driftMult = Mathf.Max(Vector3.Angle(vessel.srf_velocity, yawTarget) / MaxDrift, 1);
                yawTarget = Vector3.RotateTowards(vessel.srf_velocity, yawTarget, MaxDrift * Mathf.Deg2Rad, 0);
            }

            float yawError = VectorUtils.SignedAngle(vesselTransform.up, yawTarget, vesselTransform.right) + (aimingMode ? 0 : weaveAdjustment);

            DebugLine($"yaw target: {yawTarget}, yaw error: {yawError}");
            DebugLine($"drift multiplier: {driftMult}");

            Vector3 baseForward = vessel.transform.up * terrainOffset;
            float   basePitch   = Mathf.Atan2(
                AIUtils.GetTerrainAltitude(vessel.CoM + baseForward, vessel.mainBody, false)
                - AIUtils.GetTerrainAltitude(vessel.CoM - baseForward, vessel.mainBody, false),
                terrainOffset * 2) * Mathf.Rad2Deg;
            float pitchAngle = basePitch + TargetPitch * Mathf.Clamp01((float)vessel.horizontalSrfSpeed / CruiseSpeed);

            if (aimingMode)
            {
                pitchAngle = VectorUtils.SignedAngle(vesselTransform.up, Vector3.ProjectOnPlane(targetDirection, vesselTransform.right), -vesselTransform.forward);
            }
            DebugLine($"terrain fw slope: {basePitch}, target pitch: {pitchAngle}");


            float pitch      = 90 - Vector3.Angle(vesselTransform.up, upDir);
            float pitchError = pitchAngle - pitch;

            Vector3 baseLateral = vessel.transform.right * terrainOffset;
            float   baseRoll    = Mathf.Atan2(
                AIUtils.GetTerrainAltitude(vessel.CoM + baseLateral, vessel.mainBody, false)
                - AIUtils.GetTerrainAltitude(vessel.CoM - baseLateral, vessel.mainBody, false),
                terrainOffset * 2) * Mathf.Rad2Deg;
            float drift      = VectorUtils.SignedAngle(vesselTransform.up, Vector3.ProjectOnPlane(vessel.GetSrfVelocity(), upDir), vesselTransform.right);
            float bank       = VectorUtils.SignedAngle(-vesselTransform.forward, upDir, -vesselTransform.right);
            float targetRoll = baseRoll + BankAngle * Mathf.Clamp01(drift / MaxDrift) * Mathf.Clamp01((float)vessel.srfSpeed / CruiseSpeed);
            float rollError  = targetRoll - bank;

            DebugLine($"terrain sideways slope: {baseRoll}, target roll: {targetRoll}");

            Vector3 localAngVel = vessel.angularVelocity;

            s.roll       = steerMult * 0.006f * rollError - 0.4f * steerDamping * -localAngVel.y;
            s.pitch      = ((aimingMode ? 0.02f : 0.015f) * steerMult * pitchError) - (steerDamping * -localAngVel.x);
            s.yaw        = (((aimingMode ? 0.007f : 0.005f) * steerMult * yawError) - (steerDamping * 0.2f * -localAngVel.z)) * driftMult;
            s.wheelSteer = -(((aimingMode? 0.005f : 0.003f) * steerMult * yawError) - (steerDamping * 0.1f * -localAngVel.z));

            if (ManeuverRCS && (Mathf.Abs(s.roll) >= 1 || Mathf.Abs(s.pitch) >= 1 || Mathf.Abs(s.yaw) >= 1))
            {
                vessel.ActionGroups.SetGroup(KSPActionGroup.RCS, true);
            }
        }
Пример #21
0
        bool TickQueue(IBot bot, ProductionQueue queue)
        {
            var currentBuilding = queue.AllQueued().FirstOrDefault();

            // Waiting to build something
            if (currentBuilding == null && failCount < baseBuilder.Info.MaximumFailedPlacementAttempts)
            {
                var item = ChooseBuildingToBuild(queue);
                if (item == null)
                {
                    return(false);
                }

                bot.QueueOrder(Order.StartProduction(queue.Actor, item.Name, 1));
            }
            else if (currentBuilding != null && currentBuilding.Done)
            {
                // Production is complete
                // Choose the placement logic
                // HACK: HACK HACK HACK
                // TODO: Derive this from BuildingCommonNames instead
                var type = BuildingType.Building;
                if (world.Map.Rules.Actors[currentBuilding.Item].HasTraitInfo <AttackBaseInfo>())
                {
                    type = BuildingType.Defense;
                }
                else if (baseBuilder.Info.RefineryTypes.Contains(world.Map.Rules.Actors[currentBuilding.Item].Name))
                {
                    type = BuildingType.Refinery;
                }

                var location = ChooseBuildLocation(currentBuilding.Item, true, type);
                if (location == null)
                {
                    AIUtils.BotDebug("AI: {0} has nowhere to place {1}".F(player, currentBuilding.Item));
                    bot.QueueOrder(Order.CancelProduction(queue.Actor, currentBuilding.Item, 1));
                    failCount += failCount;

                    // If we just reached the maximum fail count, cache the number of current structures
                    if (failCount == baseBuilder.Info.MaximumFailedPlacementAttempts)
                    {
                        cachedBuildings = world.ActorsHavingTrait <Building>().Count(a => a.Owner == player);
                        cachedBases     = world.ActorsHavingTrait <BaseProvider>().Count(a => a.Owner == player);
                    }
                }
                else
                {
                    failCount = 0;
                    bot.QueueOrder(new Order("PlaceBuilding", player.PlayerActor, Target.FromCell(world, location.Value), false)
                    {
                        // Building to place
                        TargetString = currentBuilding.Item,

                        // Actor ID to associate the placement with
                        ExtraData = queue.Actor.ActorID,
                        SuppressVisualFeedback = true
                    });

                    return(true);
                }
            }

            return(true);
        }
Пример #22
0
        public void Tick(IBot bot)
        {
            // If failed to place something N consecutive times, wait M ticks until resuming building production
            if (failCount >= baseBuilder.Info.MaximumFailedPlacementAttempts && --failRetryTicks <= 0)
            {
                var currentBuildings = world.ActorsHavingTrait <Building>().Count(a => a.Owner == player);
                var baseProviders    = world.ActorsHavingTrait <BaseProvider>().Count(a => a.Owner == player);

                // Only bother resetting failCount if either a) the number of buildings has decreased since last failure M ticks ago,
                // or b) number of BaseProviders (construction yard or similar) has increased since then.
                // Otherwise reset failRetryTicks instead to wait again.
                if (currentBuildings < cachedBuildings || baseProviders > cachedBases)
                {
                    failCount = 0;
                }
                else
                {
                    failRetryTicks = baseBuilder.Info.StructureProductionResumeDelay;
                }
            }

            if (waterState == WaterCheck.NotChecked)
            {
                if (AIUtils.IsAreaAvailable <BaseProvider>(world, player, world.Map, baseBuilder.Info.MaxBaseRadius, baseBuilder.Info.WaterTerrainTypes))
                {
                    waterState = WaterCheck.EnoughWater;
                }
                else
                {
                    waterState         = WaterCheck.NotEnoughWater;
                    checkForBasesTicks = baseBuilder.Info.CheckForNewBasesDelay;
                }
            }

            if (waterState == WaterCheck.NotEnoughWater && --checkForBasesTicks <= 0)
            {
                var currentBases = world.ActorsHavingTrait <BaseProvider>().Count(a => a.Owner == player);

                if (currentBases > cachedBases)
                {
                    cachedBases = currentBases;
                    waterState  = WaterCheck.NotChecked;
                }
            }

            // Only update once per second or so
            if (--waitTicks > 0)
            {
                return;
            }

            playerBuildings = world.ActorsHavingTrait <Building>().Where(a => a.Owner == player).ToArray();
            var excessPowerBonus = baseBuilder.Info.ExcessPowerIncrement * (playerBuildings.Count() / baseBuilder.Info.ExcessPowerIncreaseThreshold.Clamp(1, int.MaxValue));

            minimumExcessPower = (baseBuilder.Info.MinimumExcessPower + excessPowerBonus).Clamp(baseBuilder.Info.MinimumExcessPower, baseBuilder.Info.MaximumExcessPower);

            var active = false;

            foreach (var queue in AIUtils.FindQueues(player, category))
            {
                if (TickQueue(bot, queue))
                {
                    active = true;
                }
            }

            // Add a random factor so not every AI produces at the same tick early in the game.
            // Minimum should not be negative as delays in HackyAI could be zero.
            var randomFactor = world.LocalRandom.Next(0, baseBuilder.Info.StructureProductionRandomBonusDelay);

            // Needs to be at least 4 * OrderLatency because otherwise the AI frequently duplicates build orders (i.e. makes the same build decision twice)
            waitTicks = active ? 4 * world.OrderLatency + baseBuilder.Info.StructureProductionActiveDelay + randomFactor
                                : baseBuilder.Info.StructureProductionInactiveDelay + randomFactor;
        }
Пример #23
0
        private bool IsAttackable(Unit target)
        {
            bool targetTooFar = Vector2.Distance(target.iso.pos, _unit.iso.pos) > maxAgroDistance;

            return(!targetTooFar && AIUtils.IsAttackable(_unit, target));
        }
Пример #24
0
        void IBotTick.BotTick(IBot bot)
        {
            if (resourceLayer == null || resourceLayer.IsEmpty)
            {
                return;
            }

            if (--scanForIdleHarvestersTicks > 0)
            {
                return;
            }

            var toRemove = harvesters.Keys.Where(unitCannotBeOrdered).ToList();

            foreach (var a in toRemove)
            {
                harvesters.Remove(a);
            }

            scanForIdleHarvestersTicks = Info.ScanForIdleHarvestersInterval;

            // Find new harvesters
            // TODO: Look for a more performance-friendly way to update this list
            var newHarvesters = world.ActorsHavingTrait <Harvester>().Where(a => a.Owner == player && !harvesters.ContainsKey(a));

            foreach (var a in newHarvesters)
            {
                harvesters[a] = new HarvesterTraitWrapper(a);
            }

            // Find idle harvesters and give them orders:
            foreach (var h in harvesters)
            {
                if (!h.Key.IsIdle)
                {
                    // Ignore this actor if FindAndDeliverResources is working fine or it is performing a different activity
                    if (!(h.Key.CurrentActivity is FindAndDeliverResources act) || !act.LastSearchFailed)
                    {
                        continue;
                    }
                }

                if (h.Value.Parachutable != null && h.Value.Parachutable.IsInAir)
                {
                    continue;
                }

                // Tell the idle harvester to quit slacking:
                var newSafeResourcePatch = FindNextResource(h.Key, h.Value);
                AIUtils.BotDebug("AI: Harvester {0} is idle. Ordering to {1} in search for new resources.".F(h.Key, newSafeResourcePatch));
                bot.QueueOrder(new Order("Harvest", h.Key, newSafeResourcePatch, false));
            }

            // Less harvesters than refineries - build a new harvester
            var unitBuilder = requestUnitProduction.FirstOrDefault(Exts.IsTraitEnabled);

            if (unitBuilder != null && Info.HarvesterTypes.Any())
            {
                var harvInfo        = AIUtils.GetInfoByCommonName(Info.HarvesterTypes, player);
                var harvCountTooLow = AIUtils.CountActorByCommonName(Info.HarvesterTypes, player) < AIUtils.CountBuildingByCommonName(Info.RefineryTypes, player);
                if (harvCountTooLow && unitBuilder.RequestedProductionCount(bot, harvInfo.Name) == 0)
                {
                    unitBuilder.RequestUnitProduction(bot, harvInfo.Name);
                }
            }
        }
Пример #25
0
        ActorInfo ChooseBuildingToBuild(ProductionQueue queue)
        {
            var buildableThings = queue.BuildableItems();

            // This gets used quite a bit, so let's cache it here
            var power = GetProducibleBuilding(baseBuilder.Info.PowerTypes, buildableThings,
                                              a => a.TraitInfos <PowerInfo>().Where(i => i.EnabledByDefault).Sum(p => p.Amount));

            // First priority is to get out of a low power situation
            if (powerManager != null && powerManager.ExcessPower < minimumExcessPower)
            {
                if (power != null && power.TraitInfos <PowerInfo>().Where(i => i.EnabledByDefault).Sum(p => p.Amount) > 0)
                {
                    AIUtils.BotDebug("{0} decided to build {1}: Priority override (low power)", queue.Actor.Owner, power.Name);
                    return(power);
                }
            }

            // Next is to build up a strong economy
            if (!baseBuilder.HasAdequateRefineryCount)
            {
                var refinery = GetProducibleBuilding(baseBuilder.Info.RefineryTypes, buildableThings);
                if (refinery != null && HasSufficientPowerForActor(refinery))
                {
                    AIUtils.BotDebug("{0} decided to build {1}: Priority override (refinery)", queue.Actor.Owner, refinery.Name);
                    return(refinery);
                }

                if (power != null && refinery != null && !HasSufficientPowerForActor(refinery))
                {
                    AIUtils.BotDebug("{0} decided to build {1}: Priority override (would be low power)", queue.Actor.Owner, power.Name);
                    return(power);
                }
            }

            // Make sure that we can spend as fast as we are earning
            if (baseBuilder.Info.NewProductionCashThreshold > 0 && playerResources.Resources > baseBuilder.Info.NewProductionCashThreshold)
            {
                var production = GetProducibleBuilding(baseBuilder.Info.ProductionTypes, buildableThings);
                if (production != null && HasSufficientPowerForActor(production))
                {
                    AIUtils.BotDebug("{0} decided to build {1}: Priority override (production)", queue.Actor.Owner, production.Name);
                    return(production);
                }

                if (power != null && production != null && !HasSufficientPowerForActor(production))
                {
                    AIUtils.BotDebug("{0} decided to build {1}: Priority override (would be low power)", queue.Actor.Owner, power.Name);
                    return(power);
                }
            }

            // Only consider building this if there is enough water inside the base perimeter and there are close enough adjacent buildings
            if (waterState == WaterCheck.EnoughWater && baseBuilder.Info.NewProductionCashThreshold > 0 &&
                playerResources.Resources > baseBuilder.Info.NewProductionCashThreshold &&
                AIUtils.IsAreaAvailable <GivesBuildableArea>(world, player, world.Map, baseBuilder.Info.CheckForWaterRadius, baseBuilder.Info.WaterTerrainTypes))
            {
                var navalproduction = GetProducibleBuilding(baseBuilder.Info.NavalProductionTypes, buildableThings);
                if (navalproduction != null && HasSufficientPowerForActor(navalproduction))
                {
                    AIUtils.BotDebug("{0} decided to build {1}: Priority override (navalproduction)", queue.Actor.Owner, navalproduction.Name);
                    return(navalproduction);
                }

                if (power != null && navalproduction != null && !HasSufficientPowerForActor(navalproduction))
                {
                    AIUtils.BotDebug("{0} decided to build {1}: Priority override (would be low power)", queue.Actor.Owner, power.Name);
                    return(power);
                }
            }

            // Create some head room for resource storage if we really need it
            if (playerResources.Resources > 0.8 * playerResources.ResourceCapacity)
            {
                var silo = GetProducibleBuilding(baseBuilder.Info.SiloTypes, buildableThings);
                if (silo != null && HasSufficientPowerForActor(silo))
                {
                    AIUtils.BotDebug("{0} decided to build {1}: Priority override (silo)", queue.Actor.Owner, silo.Name);
                    return(silo);
                }

                if (power != null && silo != null && !HasSufficientPowerForActor(silo))
                {
                    AIUtils.BotDebug("{0} decided to build {1}: Priority override (would be low power)", queue.Actor.Owner, power.Name);
                    return(power);
                }
            }

            // Build everything else
            foreach (var frac in baseBuilder.Info.BuildingFractions.Shuffle(world.LocalRandom))
            {
                var name = frac.Key;

                // Does this building have initial delay, if so have we passed it?
                if (baseBuilder.Info.BuildingDelays != null &&
                    baseBuilder.Info.BuildingDelays.ContainsKey(name) &&
                    baseBuilder.Info.BuildingDelays[name] > world.WorldTick)
                {
                    continue;
                }

                // Can we build this structure?
                if (!buildableThings.Any(b => b.Name == name))
                {
                    continue;
                }

                // Do we want to build this structure?
                var count = playerBuildings.Count(a => a.Info.Name == name);
                if (count * 100 > frac.Value * playerBuildings.Length)
                {
                    continue;
                }

                if (baseBuilder.Info.BuildingLimits.ContainsKey(name) && baseBuilder.Info.BuildingLimits[name] <= count)
                {
                    continue;
                }

                // If we're considering to build a naval structure, check whether there is enough water inside the base perimeter
                // and any structure providing buildable area close enough to that water.
                // TODO: Extend this check to cover any naval structure, not just production.
                if (baseBuilder.Info.NavalProductionTypes.Contains(name) &&
                    (waterState == WaterCheck.NotEnoughWater ||
                     !AIUtils.IsAreaAvailable <GivesBuildableArea>(world, player, world.Map, baseBuilder.Info.CheckForWaterRadius, baseBuilder.Info.WaterTerrainTypes)))
                {
                    continue;
                }

                // Will this put us into low power?
                var actor = world.Map.Rules.Actors[name];
                if (powerManager != null && (powerManager.ExcessPower < minimumExcessPower || !HasSufficientPowerForActor(actor)))
                {
                    // Try building a power plant instead
                    if (power != null && power.TraitInfos <PowerInfo>().Where(i => i.EnabledByDefault).Sum(pi => pi.Amount) > 0)
                    {
                        if (powerManager.PowerOutageRemainingTicks > 0)
                        {
                            AIUtils.BotDebug("{0} decided to build {1}: Priority override (is low power)", queue.Actor.Owner, power.Name);
                        }
                        else
                        {
                            AIUtils.BotDebug("{0} decided to build {1}: Priority override (would be low power)", queue.Actor.Owner, power.Name);
                        }

                        return(power);
                    }
                }

                // Lets build this
                AIUtils.BotDebug("{0} decided to build {1}: Desired is {2} ({3} / {4}); current is {5} / {4}",
                                 queue.Actor.Owner, name, frac.Value, frac.Value * playerBuildings.Length, playerBuildings.Length, count);
                return(actor);
            }

            // Too spammy to keep enabled all the time, but very useful when debugging specific issues.
            // AIUtils.BotDebug("{0} couldn't decide what to build for queue {1}.", queue.Actor.Owner, queue.Info.Group);
            return(null);
        }
Пример #26
0
    public override void CollectDiscreteActionMasks(DiscreteActionMasker actionMasker)
    {
        List <AgentAction> disableActions = new List <AgentAction>()
        {
            AgentAction.Up,
            AgentAction.Right,
            AgentAction.Down,
            AgentAction.Left,
            AgentAction.Bomb
        };

        if (!_player.IsDead)
        {
            if (_isMoving)
            {
                // We only allow the same action (so direction) than the previous one
                disableActions.Remove(_previousAction);
                disableActions.Add(AgentAction.Nothing);
            }
            else if (_canTakeDecision)
            {
                // Check accessible cells around
                var cellPosition = _map.CellPosition(transform.position);
                var neighbours   = AIUtils.GetNeighbours(cellPosition, _map, true, true, false);

                foreach (var neighbourDirection in neighbours.Keys)
                {
                    switch (neighbourDirection)
                    {
                    case EDirection.None:
                        break;

                    case EDirection.Up:
                        disableActions.Remove(AgentAction.Up);
                        break;

                    case EDirection.Right:
                        disableActions.Remove(AgentAction.Right);
                        break;

                    case EDirection.Down:
                        disableActions.Remove(AgentAction.Down);
                        break;

                    case EDirection.Left:
                        disableActions.Remove(AgentAction.Left);
                        break;
                    }
                }

                // Only allow the agent to plant a bomb if he can
                if (_player.BombCount > 0)
                {
                    disableActions.Remove(AgentAction.Bomb);
                }
            }
        }

        int[] actionsMask = new int[disableActions.Count];

        for (int i = 0; i < disableActions.Count; i++)
        {
            actionsMask[i] = (int)disableActions[i];
        }

        actionMasker.SetMask(0, actionsMask);
    }
Пример #27
0
        void QueueCaptureOrders(IBot bot)
        {
            if (!Info.CapturingActorTypes.Any() || player.WinState != WinState.Undefined)
            {
                return;
            }

            activeCapturers.RemoveAll(unitCannotBeOrderedOrIsIdle);

            var newUnits = world.ActorsHavingTrait <IPositionable>()
                           .Where(a => a.Owner == player && !activeCapturers.Contains(a));

            var capturers = newUnits
                            .Where(a => a.IsIdle && Info.CapturingActorTypes.Contains(a.Info.Name) && a.Info.HasTraitInfo <CapturesInfo>())
                            .Select(a => new TraitPair <CaptureManager>(a, a.TraitOrDefault <CaptureManager>()))
                            .Where(tp => tp.Trait != null)
                            .ToArray();

            if (capturers.Length == 0)
            {
                return;
            }

            var randPlayer = world.Players.Where(p => !p.Spectating &&
                                                 Info.CapturableStances.HasStance(player.Stances[p])).Random(world.LocalRandom);

            var targetOptions = Info.CheckCaptureTargetsForVisibility
                                ? GetVisibleActorsBelongingToPlayer(randPlayer)
                                : GetActorsThatCanBeOrderedByPlayer(randPlayer);

            var capturableTargetOptions = targetOptions
                                          .Where(target =>
            {
                var captureManager = target.TraitOrDefault <CaptureManager>();
                if (captureManager == null)
                {
                    return(false);
                }

                return(capturers.Any(tp => captureManager.CanBeTargetedBy(target, tp.Actor, tp.Trait)));
            })
                                          .OrderByDescending(target => target.GetSellValue())
                                          .Take(maximumCaptureTargetOptions);

            if (Info.CapturableActorTypes.Any())
            {
                capturableTargetOptions = capturableTargetOptions.Where(target => Info.CapturableActorTypes.Contains(target.Info.Name.ToLowerInvariant()));
            }

            if (!capturableTargetOptions.Any())
            {
                return;
            }

            var failedAttempts = captureHistory.Where(a => a.Key.IsDead).Select(a => a.Value);

            foreach (var capturer in capturers)
            {
                var targetActor = capturableTargetOptions.MinByOrDefault(t => (t.CenterPosition - capturer.Actor.CenterPosition).LengthSquared);
                if (targetActor == null)
                {
                    continue;
                }

                if (failedAttempts.Any(f => f.Actor == targetActor))
                {
                    AIUtils.BotDebug("AI ({0}): skipping capture of {1} as there was a previously failed attempt.", player.ClientIndex, targetActor);
                    continue;
                }

                var target = Target.FromActor(targetActor);
                bot.QueueOrder(new Order("CaptureActor", capturer.Actor, target, true));
                AIUtils.BotDebug("AI ({0}): Ordered {1} to capture {2}", player.ClientIndex, capturer.Actor, targetActor);
                activeCapturers.Add(capturer.Actor);

                if (!captureHistory.ContainsKey(capturer.Actor))
                {
                    captureHistory.Add(capturer.Actor, target);
                }
            }
        }
Пример #28
0
        void QueueCaptureOrders(IBot bot)
        {
            if (!Info.CapturingActorTypes.Any() || player.WinState != WinState.Undefined)
            {
                return;
            }

            activeCapturers.RemoveAll(unitCannotBeOrderedOrIsIdle);

            var newUnits = world.ActorsHavingTrait <IPositionable>()
                           .Where(a => a.Owner == player && !activeCapturers.Contains(a));

            var capturers = newUnits
                            .Where(a => a.IsIdle && Info.CapturingActorTypes.Contains(a.Info.Name) && a.Info.HasTraitInfo <CapturesInfo>())
                            .Select(a => new TraitPair <CaptureManager>(a, a.TraitOrDefault <CaptureManager>()))
                            .Where(tp => tp.Trait != null)
                            .ToArray();

            if (capturers.Length == 0)
            {
                return;
            }

            var randomPlayer = world.Players.Where(p => !p.Spectating &&
                                                   Info.CapturableStances.HasStance(player.RelationshipWith(p))).Random(world.LocalRandom);

            var targetOptions = Info.CheckCaptureTargetsForVisibility
                                ? GetVisibleActorsBelongingToPlayer(randomPlayer)
                                : GetActorsThatCanBeOrderedByPlayer(randomPlayer);

            var capturableTargetOptions = targetOptions
                                          .Where(target =>
            {
                var captureManager = target.TraitOrDefault <CaptureManager>();
                if (captureManager == null)
                {
                    return(false);
                }

                return(capturers.Any(tp => captureManager.CanBeTargetedBy(target, tp.Actor, tp.Trait)));
            })
                                          .OrderByDescending(target => target.GetSellValue())
                                          .Take(maximumCaptureTargetOptions);

            if (Info.CapturableActorTypes.Any())
            {
                capturableTargetOptions = capturableTargetOptions.Where(target => Info.CapturableActorTypes.Contains(target.Info.Name.ToLowerInvariant()));
            }

            if (!capturableTargetOptions.Any())
            {
                return;
            }

            foreach (var capturer in capturers)
            {
                var nearestTargetActors = capturableTargetOptions.OrderBy(target => (target.CenterPosition - capturer.Actor.CenterPosition).LengthSquared);
                foreach (var nearestTargetActor in nearestTargetActors)
                {
                    if (activeCapturers.Contains(capturer.Actor))
                    {
                        continue;
                    }

                    var safeTarget = SafePath(capturer.Actor, nearestTargetActor);
                    if (safeTarget.Type == TargetType.Invalid)
                    {
                        continue;
                    }

                    bot.QueueOrder(new Order("CaptureActor", capturer.Actor, safeTarget, true));
                    AIUtils.BotDebug("AI ({0}): Ordered {1} to capture {2}", player.ClientIndex, capturer.Actor, nearestTargetActor);
                    activeCapturers.Add(capturer.Actor);
                }
            }
        }
Пример #29
0
        void IBotTick.BotTick(IBot bot)
        {
            foreach (var sp in supportPowerManager.Powers.Values)
            {
                if (sp.Disabled)
                {
                    continue;
                }

                // Add power to dictionary if not in delay dictionary yet
                if (!waitingPowers.ContainsKey(sp))
                {
                    waitingPowers.Add(sp, 0);
                }

                if (waitingPowers[sp] > 0)
                {
                    waitingPowers[sp]--;
                }

                // If we have recently tried and failed to find a use location for a power, then do not try again until later
                var isDelayed = waitingPowers[sp] > 0;
                if (sp.Ready && !isDelayed && powerDecisions.ContainsKey(sp.Info.OrderName))
                {
                    var powerDecision = powerDecisions[sp.Info.OrderName];
                    if (powerDecision == null)
                    {
                        AIUtils.BotDebug("{0} couldn't find powerDecision for {1}", player.PlayerName, sp.Info.OrderName);
                        continue;
                    }

                    var attackLocation = FindCoarseAttackLocationToSupportPower(sp);
                    if (attackLocation == null)
                    {
                        AIUtils.BotDebug("{0} can't find suitable coarse attack location for support power {1}. Delaying rescan.", player.PlayerName, sp.Info.OrderName);
                        waitingPowers[sp] += powerDecision.GetNextScanTime(world);

                        continue;
                    }

                    // Found a target location, check for precise target
                    attackLocation = FindFineAttackLocationToSupportPower(sp, (CPos)attackLocation);
                    if (attackLocation == null)
                    {
                        AIUtils.BotDebug("{0} can't find suitable final attack location for support power {1}. Delaying rescan.", player.PlayerName, sp.Info.OrderName);
                        waitingPowers[sp] += powerDecision.GetNextScanTime(world);

                        continue;
                    }

                    // Valid target found, delay by a few ticks to avoid rescanning before power fires via order
                    AIUtils.BotDebug("{0} found new target location {1} for support power {2}.", player.PlayerName, attackLocation, sp.Info.OrderName);
                    waitingPowers[sp] += 10;

                    // Note: SelectDirectionalTarget uses uint.MaxValue in ExtraData to indicate that the player did not pick a direction.
                    bot.QueueOrder(new Order(sp.Key, supportPowerManager.Self, Target.FromCell(world, attackLocation.Value), false)
                    {
                        SuppressVisualFeedback = true, ExtraData = uint.MaxValue
                    });
                }
            }

            // Remove stale powers
            stalePowers.AddRange(waitingPowers.Keys.Where(wp => !supportPowerManager.Powers.ContainsKey(wp.Key)));
            foreach (var p in stalePowers)
            {
                waitingPowers.Remove(p);
            }

            stalePowers.Clear();
        }
Пример #30
0
    void Offense()
    {
        if (unreasonable)
        {
            if (m_player.CanLayup())
            {
                m_system.SetTransaction(AIState.Type.eLayup);
                Debug.LogError("Unreasonable layup.");
                return;
            }
        }

        if (!arriveFirstTarget)
        {
            return;
        }

        bool inTakeOver = false;

        if (m_player.m_inputDispatcher != null)
        {
            inTakeOver = m_player.m_inputDispatcher.inTakeOver;
        }

        bool isPvp = m_system.IsPvp;

        if (!inTakeOver)
        {
            if (!isPvp)
            {
                //进攻时间快结束了,投球
                if (m_match.IsFinalTime(new IM.Number(3) - m_system.AI.devTime))
                {
                    AIUtils.AttackByPosition(m_player, new IM.Number(100));
                    return;
                }
                //玩家要球,传给他
                Player mainRole = m_match.GetMainRole(m_player.m_roleInfo.acc_id);
                if (mainRole != null && mainRole.m_team == m_player.m_team && mainRole != m_player &&
                    mainRole.m_StateMachine.m_curState.m_eState == PlayerState.State.eRequireBall)
                {
                    AI_Pass pass = m_system.GetState(Type.ePass) as AI_Pass;
                    pass.m_toPass = mainRole;
                    m_system.SetTransaction(pass, new IM.Number(100));
                    return;
                }

                //进攻篮筐
                _Attack();
            }

            //传球
            Pass();

            if (!isPvp)
            {
                Area area = m_match.mCurScene.mGround.GetArea(m_player);
                if (area != Area.eNear) //非篮下区
                {
                    if (!inTakeOver)
                    {
                        //突破
                        CrossOver();
                        if (!AIUtils.InAttackableDistance(m_match, m_player))
                        {
                            m_system.SetTransaction(Type.ePositioning, new IM.Number(50), true);
                        }
                    }
                }
            }
        }
        else
        {
            m_system.SetTransaction(Type.ePositioning, new IM.Number(100), true);
        }
    }