Split HackyAI.BaseBuilder into its own file; Move hackyAI components into OpenRA.Mods.RA.AI namespace and dir

This commit is contained in:
Chris Forbes
2011-10-24 19:10:07 +13:00
parent bfddbeeb02
commit 3a5cce1f1f
3 changed files with 114 additions and 89 deletions

View File

@@ -0,0 +1,102 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Traits;
using OpenRA.Mods.RA.Activities;
using XRandom = OpenRA.Thirdparty.Random;
namespace OpenRA.Mods.RA.AI
{
class BaseBuilder
{
enum BuildState { ChooseItem, WaitForProduction, WaitForFeedback }
BuildState state = BuildState.WaitForFeedback;
string category;
HackyAI ai;
int lastThinkTick;
Func<ProductionQueue, ActorInfo> chooseItem;
public BaseBuilder(HackyAI ai, string category, Func<ProductionQueue, ActorInfo> chooseItem)
{
this.ai = ai;
this.category = category;
this.chooseItem = chooseItem;
}
public void Tick()
{
// Pick a free queue
var queue = ai.FindQueues( category ).FirstOrDefault();
if (queue == null)
return;
var currentBuilding = queue.CurrentItem();
switch (state)
{
case BuildState.ChooseItem:
{
var item = chooseItem(queue);
if (item == null)
{
state = BuildState.WaitForFeedback;
lastThinkTick = ai.ticks;
}
else
{
HackyAI.BotDebug("AI: Starting production of {0}".F(item.Name));
state = BuildState.WaitForProduction;
ai.world.IssueOrder(Order.StartProduction(queue.self, item.Name, 1));
}
}
break;
case BuildState.WaitForProduction:
if (currentBuilding == null) return; /* let it happen.. */
else if (currentBuilding.Paused)
ai.world.IssueOrder(Order.PauseProduction(queue.self, currentBuilding.Item, false));
else if (currentBuilding.Done)
{
state = BuildState.WaitForFeedback;
lastThinkTick = ai.ticks;
/* place the building */
var location = ai.ChooseBuildLocation(currentBuilding);
if (location == null)
{
HackyAI.BotDebug("AI: Nowhere to place {0}".F(currentBuilding.Item));
ai.world.IssueOrder(Order.CancelProduction(queue.self, currentBuilding.Item, 1));
}
else
{
ai.world.IssueOrder(new Order("PlaceBuilding", ai.p.PlayerActor, false)
{
TargetLocation = location.Value,
TargetString = currentBuilding.Item
});
}
}
break;
case BuildState.WaitForFeedback:
if (ai.ticks - lastThinkTick > HackyAI.feedbackTime)
state = BuildState.ChooseItem;
break;
}
}
}
}

View File

@@ -17,7 +17,6 @@ using OpenRA.Traits;
using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Activities;
using XRandom = OpenRA.Thirdparty.Random; using XRandom = OpenRA.Thirdparty.Random;
//TODO: //TODO:
// effectively clear the area around the production buildings' spawn points. // effectively clear the area around the production buildings' spawn points.
// don't spam the build unit button, only queue one unit then wait for the backoff period. // don't spam the build unit button, only queue one unit then wait for the backoff period.
@@ -28,7 +27,7 @@ using XRandom = OpenRA.Thirdparty.Random;
// explore spawn points methodically // explore spawn points methodically
// once you find a player, attack the player instead of spawn points. // once you find a player, attack the player instead of spawn points.
namespace OpenRA.Mods.RA namespace OpenRA.Mods.RA.AI
{ {
class HackyAIInfo : IBotInfo, ITraitInfo class HackyAIInfo : IBotInfo, ITraitInfo
{ {
@@ -63,8 +62,8 @@ namespace OpenRA.Mods.RA
class HackyAI : ITick, IBot, INotifyDamage class HackyAI : ITick, IBot, INotifyDamage
{ {
bool enabled; bool enabled;
int ticks; public int ticks;
Player p; public Player p;
PowerManager playerPower; PowerManager playerPower;
readonly BuildingInfo rallypointTestBuilding; // temporary hack readonly BuildingInfo rallypointTestBuilding; // temporary hack
@@ -72,7 +71,9 @@ namespace OpenRA.Mods.RA
XRandom random = new XRandom(); //we do not use the synced random number generator. XRandom random = new XRandom(); //we do not use the synced random number generator.
BaseBuilder[] builders; BaseBuilder[] builders;
World world { get { return p.PlayerActor.World; } } public const int feedbackTime = 30; // ticks; = a bit over 1s. must be >= netlag.
public World world { get { return p.PlayerActor.World; } }
IBotInfo IBot.Info { get { return this.Info; } } IBotInfo IBot.Info { get { return this.Info; } }
readonly HackyAIInfo Info; readonly HackyAIInfo Info;
@@ -156,7 +157,7 @@ namespace OpenRA.Mods.RA
return cells.All(c => bi.GetBuildingAt(c) == null); return cells.All(c => bi.GetBuildingAt(c) == null);
} }
int2? ChooseBuildLocation(ProductionItem item) public int2? ChooseBuildLocation(ProductionItem item)
{ {
var bi = Rules.Info[item.Item].Traits.Get<BuildingInfo>(); var bi = Rules.Info[item.Item].Traits.Get<BuildingInfo>();
@@ -171,8 +172,6 @@ namespace OpenRA.Mods.RA
return null; // i don't know where to put it. return null; // i don't know where to put it.
} }
const int feedbackTime = 30; // ticks; = a bit over 1s. must be >= netlag.
public void Tick(Actor self) public void Tick(Actor self)
{ {
if (!enabled) if (!enabled)
@@ -428,86 +427,6 @@ namespace OpenRA.Mods.RA
world.IssueOrder(Order.StartProduction(queue.self, unit.Name, 1)); world.IssueOrder(Order.StartProduction(queue.self, unit.Name, 1));
} }
class BaseBuilder
{
enum BuildState { ChooseItem, WaitForProduction, WaitForFeedback }
BuildState state = BuildState.WaitForFeedback;
string category;
HackyAI ai;
int lastThinkTick;
Func<ProductionQueue, ActorInfo> chooseItem;
public BaseBuilder(HackyAI ai, string category, Func<ProductionQueue, ActorInfo> chooseItem)
{
this.ai = ai;
this.category = category;
this.chooseItem = chooseItem;
}
public void Tick()
{
// Pick a free queue
var queue = ai.FindQueues( category ).FirstOrDefault();
if (queue == null)
return;
var currentBuilding = queue.CurrentItem();
switch (state)
{
case BuildState.ChooseItem:
{
var item = chooseItem(queue);
if (item == null)
{
state = BuildState.WaitForFeedback;
lastThinkTick = ai.ticks;
}
else
{
BotDebug("AI: Starting production of {0}".F(item.Name));
state = BuildState.WaitForProduction;
ai.world.IssueOrder(Order.StartProduction(queue.self, item.Name, 1));
}
}
break;
case BuildState.WaitForProduction:
if (currentBuilding == null) return; /* let it happen.. */
else if (currentBuilding.Paused)
ai.world.IssueOrder(Order.PauseProduction(queue.self, currentBuilding.Item, false));
else if (currentBuilding.Done)
{
state = BuildState.WaitForFeedback;
lastThinkTick = ai.ticks;
/* place the building */
var location = ai.ChooseBuildLocation(currentBuilding);
if (location == null)
{
BotDebug("AI: Nowhere to place {0}".F(currentBuilding.Item));
ai.world.IssueOrder(Order.CancelProduction(queue.self, currentBuilding.Item, 1));
}
else
{
ai.world.IssueOrder(new Order("PlaceBuilding", ai.p.PlayerActor, false)
{
TargetLocation = location.Value,
TargetString = currentBuilding.Item
});
}
}
break;
case BuildState.WaitForFeedback:
if (ai.ticks - lastThinkTick > feedbackTime)
state = BuildState.ChooseItem;
break;
}
}
}
public void Damaged(Actor self, AttackInfo e) public void Damaged(Actor self, AttackInfo e)
{ {
if (!enabled) return; if (!enabled) return;

View File

@@ -200,7 +200,6 @@
<Compile Include="GainsExperience.cs" /> <Compile Include="GainsExperience.cs" />
<Compile Include="GivesBounty.cs" /> <Compile Include="GivesBounty.cs" />
<Compile Include="GivesExperience.cs" /> <Compile Include="GivesExperience.cs" />
<Compile Include="HackyAI.cs" />
<Compile Include="Harvester.cs" /> <Compile Include="Harvester.cs" />
<Compile Include="HarvesterHuskModifier.cs" /> <Compile Include="HarvesterHuskModifier.cs" />
<Compile Include="Husk.cs" /> <Compile Include="Husk.cs" />
@@ -362,6 +361,8 @@
<Compile Include="World\SmudgeLayer.cs" /> <Compile Include="World\SmudgeLayer.cs" />
<Compile Include="Widgets\Logic\LobbyUtils.cs" /> <Compile Include="Widgets\Logic\LobbyUtils.cs" />
<Compile Include="Widgets\Logic\DownloadPackagesLogic.cs" /> <Compile Include="Widgets\Logic\DownloadPackagesLogic.cs" />
<Compile Include="AI\BaseBuilder.cs" />
<Compile Include="AI\HackyAI.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj"> <ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
@@ -388,4 +389,7 @@
copy "$(TargetPath)" "$(SolutionDir)mods/ra/" copy "$(TargetPath)" "$(SolutionDir)mods/ra/"
cd "$(SolutionDir)"</PostBuildEvent> cd "$(SolutionDir)"</PostBuildEvent>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Folder Include="AI\" />
</ItemGroup>
</Project> </Project>