From 8e56bdc1971169aaca3df1ffe1974f2ac774b9e2 Mon Sep 17 00:00:00 2001 From: Erasmus Schroder Date: Tue, 29 Mar 2011 22:20:50 +0200 Subject: [PATCH] Made HackyAI attackers scan for enemy units --- OpenRA.Mods.RA/HackyAI.cs | 143 ++++++++++++++++++++++++++++---------- 1 file changed, 107 insertions(+), 36 deletions(-) diff --git a/OpenRA.Mods.RA/HackyAI.cs b/OpenRA.Mods.RA/HackyAI.cs index 9f7df28775..ee8b5e9d13 100644 --- a/OpenRA.Mods.RA/HackyAI.cs +++ b/OpenRA.Mods.RA/HackyAI.cs @@ -110,7 +110,7 @@ namespace OpenRA.Mods.RA { this.p = p; enabled = true; - playerPower = p.PlayerActor.Trait(); + playerPower = p.PlayerActor.Trait(); builders = new BaseBuilder[] { new BaseBuilder( this, "Building", q => ChooseBuildingToBuild(q, true) ), new BaseBuilder( this, "Defense", q => ChooseBuildingToBuild(q, false) ) }; @@ -142,17 +142,17 @@ namespace OpenRA.Mods.RA var buildableThings = queue.BuildableItems(); if (!HasAdequatePower()) /* try to maintain 20% excess power */ - { + { if (!buildPower) return null; /* find the best thing we can build which produces power */ return buildableThings.Where(a => GetPowerProvidedBy(a) > 0) .OrderByDescending(a => GetPowerProvidedBy(a)).FirstOrDefault(); - } - - var myBuildings = p.World - .ActorsWithTrait() - .Where( a => a.Actor.Owner == p ) + } + + var myBuildings = p.World + .ActorsWithTrait() + .Where( a => a.Actor.Owner == p ) .Select(a => a.Actor.Info.Name).ToArray(); foreach (var frac in Info.BuildingFractions) @@ -222,6 +222,7 @@ namespace OpenRA.Mods.RA //e.g. ClearAreaAroundSpawnPoints(); //e.g. start repairing damaged buildings. BuildRandom("Vehicle"); + BuildRandom("Vehicle"); BuildRandom("Infantry"); BuildRandom("Plane"); } @@ -237,6 +238,8 @@ namespace OpenRA.Mods.RA //A bunch of hardcoded lists to keep track of which units are doing what. List unitsHangingAroundTheBase = new List(); List attackForce = new List(); + bool attackForceMoving = false; + int2? attackTarget; //Units that the ai already knows about. Any unit not on this list needs to be given a role. List activeUnits = new List(); @@ -255,6 +258,8 @@ namespace OpenRA.Mods.RA // 2. human. // 3. not dead. + + var possibleTargets = world.WorldActor.Trait().Start .Where(kv => kv.Key != p && (!HasHumanPlayers() || IsHumanPlayer(kv.Key)) && p.WinState == WinState.Undefined) @@ -270,10 +275,10 @@ namespace OpenRA.Mods.RA activeUnits.RemoveAll(a => a.Destroyed); unitsHangingAroundTheBase.RemoveAll(a => a.Destroyed); attackForce.RemoveAll(a => a.Destroyed); - + // don't select harvesters. var newUnits = self.World.ActorsWithTrait() - .Where(a => a.Actor.Owner == p && a.Actor.Info != Rules.Info["harv"] + .Where(a => a.Actor.Owner == p && a.Actor.Info != Rules.Info["harv"] && a.Actor.Info != Rules.Info["mcv"] && !activeUnits.Contains(a.Actor)) .Select(a => a.Actor).ToArray(); @@ -286,35 +291,101 @@ namespace OpenRA.Mods.RA /* Create an attack force when we have enough units around our base. */ // (don't bother leaving any behind for defense.) - if (unitsHangingAroundTheBase.Count >= Info.SquadSize) + if (unitsHangingAroundTheBase.Count >= 1) { BotDebug("Launch an attack."); - var attackTarget = ChooseEnemyTarget(); - if (attackTarget == null) - return; + if (attackForce.Count == 0) + { + attackTarget = ChooseEnemyTarget(); + if (attackTarget == null) + return; + } foreach (var a in unitsHangingAroundTheBase) if (TryToAttackMove(a, attackTarget.Value)) attackForce.Add(a); + attackForceMoving = true; unitsHangingAroundTheBase.Clear(); } - } - - bool IsRallyPointValid(int2 x) - { - return world.IsCellBuildable(x, false); + + // If we have any attackers, let them scan for enemy units and stop and regroup if they spot any + if (attackForce.Count > 0 ) + { + bool foundEnemy = false; + foreach (var a1 in attackForce) + { + List enemyUnits = world.FindUnitsInCircle(a1.CenterLocation, Game.CellSize * 10).Where(unit => IsHumanPlayer(unit.Owner) ).ToList(); + if (enemyUnits.Count > 0) + { + //BotDebug("Found enemy "+enemyUnits.First().Info.Name); + // Found enemy units nearby. + foundEnemy = true; + Actor enemy = enemyUnits.First(); + + // Which of the attackers is nearest? + foreach (var e in enemyUnits) + { + int x, y; + int oldx, oldy; + x = e.Location.X - a1.Location.X; + y = e.Location.Y - a1.Location.Y; + + oldx = enemy.Location.X - a1.Location.X; + oldy = enemy.Location.Y - a1.Location.Y; + + if (Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2)) < Math.Sqrt(Math.Pow(oldx, 2) + Math.Pow(oldy, 2))) + enemy = e; + } + + // Check how many own units we have gathered nearby... + List ownUnits = world.FindUnitsInCircle(a1.CenterLocation, Game.CellSize * 2).Where(unit => unit.Owner == p).ToList(); + if (ownUnits.Count < Info.SquadSize) + { + // Not enough to attack. Send more units. + world.IssueOrder(new Order("Stop", a1, false) { }); + foreach (var a2 in attackForce) + { + if (a2 != a1) + world.IssueOrder(new Order("AttackMove", a2, false) { TargetLocation = a1.Location }); + } + } + else + { + // We have gathered sufficient units. Attack the nearest enemy unit. + foreach (var a2 in attackForce) + { + world.IssueOrder(new Order("Attack", a2, false) { TargetActor = enemy }); + + } + } + return; + } + } + /* + if (foundEnemy == false) + { + attackTarget = ChooseEnemyTarget(); + foreach (var a in attackForce) + TryToAttackMove(a, attackTarget.Value); + }*/ + } + } + + bool IsRallyPointValid(int2 x) + { + return world.IsCellBuildable(x, false); } void SetRallyPointsForNewProductionBuildings(Actor self) - { - var buildings = self.World.ActorsWithTrait() - .Where(rp => rp.Actor.Owner == p && - !IsRallyPointValid(rp.Trait.rallyPoint)).ToArray(); - - if (buildings.Length > 0) - BotDebug("Bot {0} needs to find rallypoints for {1} buildings.", + { + var buildings = self.World.ActorsWithTrait() + .Where(rp => rp.Actor.Owner == p && + !IsRallyPointValid(rp.Trait.rallyPoint)).ToArray(); + + if (buildings.Length > 0) + BotDebug("Bot {0} needs to find rallypoints for {1} buildings.", p.PlayerName, buildings.Length); @@ -327,14 +398,14 @@ namespace OpenRA.Mods.RA //won't work for shipyards... int2 ChooseRallyLocationNear(int2 startPos) - { - var possibleRallyPoints = world.FindTilesInCircle(startPos, 8).Where(x => world.IsCellBuildable(x, false)).ToArray(); - if (possibleRallyPoints.Length == 0) - { - Game.Debug("Bot Bug: No possible rallypoint near {0}", startPos); - return startPos; - } - + { + var possibleRallyPoints = world.FindTilesInCircle(startPos, 8).Where(x => world.IsCellBuildable(x, false)).ToArray(); + if (possibleRallyPoints.Length == 0) + { + Game.Debug("Bot Bug: No possible rallypoint near {0}", startPos); + return startPos; + } + return possibleRallyPoints.Random(random); } @@ -382,9 +453,9 @@ namespace OpenRA.Mods.RA void DeployMcv(Actor self) { - /* find our mcv and deploy it */ - var mcv = self.World.Actors - .FirstOrDefault(a => a.Owner == p && a.Info == Rules.Info["mcv"]); + /* find our mcv and deploy it */ + var mcv = self.World.Actors + .FirstOrDefault(a => a.Owner == p && a.Info == Rules.Info["mcv"]); if (mcv != null) {