Merge pull request #2736 from Mailaender/better-bots

Better AI Bots
This commit is contained in:
Chris Forbes
2013-03-09 21:11:29 -08:00
19 changed files with 1972 additions and 177 deletions

View File

@@ -44,6 +44,7 @@ Also thanks to:
* Riderr3
* Tim Mylemans (gecko)
* Tirili
* Vladimir Komarov (VrKomarov)
Past developers included:
* Paul Chote (pchote)

View File

@@ -1,8 +1,8 @@
CSC = gmcs
CSFLAGS = -nologo -warn:4 -debug:full -optimize- -codepage:utf8 -unsafe
DEFINE = DEBUG;TRACE
COMMON_LIBS = System.dll System.Core.dll System.Drawing.dll System.Xml.dll thirdparty/ICSharpCode.SharpZipLib.dll
PHONY = core tools package all mods clean distclean
COMMON_LIBS = System.dll System.Core.dll System.Drawing.dll System.Xml.dll thirdparty/ICSharpCode.SharpZipLib.dll thirdparty/FuzzyLogicLibrary.dll
PHONY = core tools package all mods clean distclean
.SUFFIXES:
core: game renderers mods utility tsbuild
@@ -132,6 +132,7 @@ ralint_TARGET = RALint.exe
ralint_KIND = exe
ralint_DEPS = $(fileformats_TARGET) $(game_TARGET)
ralint_LIBS = $(COMMON_LIBS) $(ralint_DEPS)
ralint_EXTRA_CMDS = cp thirdparty/FuzzyLogicLibrary.dll .
PROGRAMS += ralint
ralint: $(ralint_TARGET)
@@ -245,6 +246,7 @@ install: all
@cp *.ttf $(INSTALL_DIR)
@cp thirdparty/Tao/* $(INSTALL_DIR)
@$(INSTALL_PROGRAM) thirdparty/ICSharpCode.SharpZipLib.dll $(INSTALL_DIR)
@$(INSTALL_PROGRAM) thirdparty/FuzzyLogicLibrary.dll $(INSTALL_DIR)
@echo "#!/bin/sh" > openra
@echo "cd "$(datadir)"/openra" >> openra

View File

@@ -82,6 +82,7 @@ namespace OpenRA.Traits
public int DisplayCash;
public int DisplayOre;
public bool AlertSilo;
public int Earned;
public int Spent;
@@ -155,8 +156,13 @@ namespace OpenRA.Traits
if (--nextSiloAdviceTime <= 0)
{
if (Ore > 0.8*OreCapacity)
if (Ore > 0.8 * OreCapacity)
{
Sound.PlayNotification(Owner, "Speech", "SilosNeeded", Owner.Country.Race);
AlertSilo = true;
}
else
AlertSilo = false;
nextSiloAdviceTime = AdviceInterval;
}

View File

@@ -0,0 +1,250 @@
#region Copyright & License Information
/*
* Copyright 2007-2012 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 System.Text;
using OpenRA.Mods.RA.Move;
using OpenRA.Traits;
using AI.Fuzzy.Library;
namespace OpenRA.Mods.RA.AI
{
class AttackOrFleeFuzzy
{
protected MamdaniFuzzySystem fuzzyEngine;
protected Dictionary<FuzzyVariable, double> result;
public bool CanAttack
{
get
{
//not sure that this will happen (NaN), it's for the safety of
if (result[fuzzyEngine.OutputByName("AttackOrFlee")].ToString() != "NaN")
return result[fuzzyEngine.OutputByName("AttackOrFlee")] < 30.0;
return false;
}
}
public AttackOrFleeFuzzy()
{
InitializateFuzzyVariables();
}
protected void InitializateFuzzyVariables()
{
fuzzyEngine = new MamdaniFuzzySystem();
FuzzyVariable playerHealthFuzzy = new FuzzyVariable("OwnHealth", 0.0, 100.0);
playerHealthFuzzy.Terms.Add(new FuzzyTerm("NearDead", new TrapezoidMembershipFunction(0, 0, 20, 40)));
playerHealthFuzzy.Terms.Add(new FuzzyTerm("Injured", new TrapezoidMembershipFunction(30, 50, 50, 70)));
playerHealthFuzzy.Terms.Add(new FuzzyTerm("Normal", new TrapezoidMembershipFunction(50, 80, 100, 100)));
fuzzyEngine.Input.Add(playerHealthFuzzy);
FuzzyVariable enemyHealthFuzzy = new FuzzyVariable("EnemyHealth", 0.0, 100.0);
enemyHealthFuzzy.Terms.Add(new FuzzyTerm("NearDead", new TrapezoidMembershipFunction(0, 0, 20, 40)));
enemyHealthFuzzy.Terms.Add(new FuzzyTerm("Injured", new TrapezoidMembershipFunction(30, 50, 50, 70)));
enemyHealthFuzzy.Terms.Add(new FuzzyTerm("Normal", new TrapezoidMembershipFunction(50, 80, 100, 100)));
fuzzyEngine.Input.Add(enemyHealthFuzzy);
FuzzyVariable relativeAttackPowerFuzzy = new FuzzyVariable("RelativeAttackPower", 0.0, 1000.0);
relativeAttackPowerFuzzy.Terms.Add(new FuzzyTerm("Weak", new TrapezoidMembershipFunction(0, 0, 70, 90)));
relativeAttackPowerFuzzy.Terms.Add(new FuzzyTerm("Equal", new TrapezoidMembershipFunction(85, 100, 100, 115)));
relativeAttackPowerFuzzy.Terms.Add(new FuzzyTerm("Strong", new TrapezoidMembershipFunction(110, 150, 150, 1000)));
fuzzyEngine.Input.Add(relativeAttackPowerFuzzy);
FuzzyVariable relativeSpeedFuzzy = new FuzzyVariable("RelativeSpeed", 0.0, 1000.0);
relativeSpeedFuzzy.Terms.Add(new FuzzyTerm("Slow", new TrapezoidMembershipFunction(0, 0, 70, 90)));
relativeSpeedFuzzy.Terms.Add(new FuzzyTerm("Equal", new TrapezoidMembershipFunction(85, 100, 100, 115)));
relativeSpeedFuzzy.Terms.Add(new FuzzyTerm("Fast", new TrapezoidMembershipFunction(110, 150, 150, 1000)));
fuzzyEngine.Input.Add(relativeSpeedFuzzy);
FuzzyVariable attackOrFleeFuzzy = new FuzzyVariable("AttackOrFlee", 0.0, 50.0);
attackOrFleeFuzzy.Terms.Add(new FuzzyTerm("Attack", new TrapezoidMembershipFunction(0, 15, 15, 30)));
attackOrFleeFuzzy.Terms.Add(new FuzzyTerm("Flee", new TrapezoidMembershipFunction(25, 35, 35, 50)));
fuzzyEngine.Output.Add(attackOrFleeFuzzy);
AddingRulesForNormalOwnHealth();
AddingRulesForInjuredOwnHealth();
AddingRulesForNearDeadOwnHealth();
}
protected virtual void AddingRulesForNormalOwnHealth()
{
//1 OwnHealth is Normal
fuzzyEngine.Rules.Add(fuzzyEngine.ParseRule("if ((OwnHealth is Normal) " +
"and ((EnemyHealth is NearDead) or (EnemyHealth is Injured) or (EnemyHealth is Normal)) " +
"and ((RelativeAttackPower is Weak) or (RelativeAttackPower is Equal) or (RelativeAttackPower is Strong)) " +
"and ((RelativeSpeed is Slow) or (RelativeSpeed is Equal) or (RelativeSpeed is Fast))) " +
"then AttackOrFlee is Attack"));
}
protected virtual void AddingRulesForInjuredOwnHealth()
{
//OwnHealth is Injured
fuzzyEngine.Rules.Add(fuzzyEngine.ParseRule("if ((OwnHealth is Injured) " +
"and (EnemyHealth is NearDead) " +
"and ((RelativeAttackPower is Weak) or (RelativeAttackPower is Equal) or (RelativeAttackPower is Strong)) " +
"and ((RelativeSpeed is Slow) or (RelativeSpeed is Equal) or (RelativeSpeed is Fast))) " +
"then AttackOrFlee is Attack"));
fuzzyEngine.Rules.Add(fuzzyEngine.ParseRule("if ((OwnHealth is Injured) " +
"and ((EnemyHealth is Injured) or (EnemyHealth is Normal)) " +
"and ((RelativeAttackPower is Equal) or (RelativeAttackPower is Strong)) " +
"and ((RelativeSpeed is Slow) or (RelativeSpeed is Equal) or (RelativeSpeed is Fast))) " +
"then AttackOrFlee is Attack"));
fuzzyEngine.Rules.Add(fuzzyEngine.ParseRule("if ((OwnHealth is Injured) " +
"and ((EnemyHealth is Injured) or (EnemyHealth is Normal)) " +
"and (RelativeAttackPower is Weak) " +
"and (RelativeSpeed is Slow)) " +
"then AttackOrFlee is Attack"));
fuzzyEngine.Rules.Add(fuzzyEngine.ParseRule("if ((OwnHealth is Injured) " +
"and ((EnemyHealth is Injured) or (EnemyHealth is Normal)) " +
"and (RelativeAttackPower is Weak) " +
"and ((RelativeSpeed is Equal) or (RelativeSpeed is Fast))) " +
"then AttackOrFlee is Flee"));
//2
fuzzyEngine.Rules.Add(fuzzyEngine.ParseRule("if ((OwnHealth is Injured) " +
"and ((EnemyHealth is NearDead) or (EnemyHealth is Injured) or (EnemyHealth is Normal)) " +
"and ((RelativeAttackPower is Weak) or (RelativeAttackPower is Equal) or (RelativeAttackPower is Strong)) " +
"and (RelativeSpeed is Slow)) " +
"then AttackOrFlee is Attack"));
}
protected virtual void AddingRulesForNearDeadOwnHealth()
{
//3 OwnHealth is NearDead
fuzzyEngine.Rules.Add(fuzzyEngine.ParseRule("if ((OwnHealth is NearDead) " +
"and (EnemyHealth is Injured) " +
"and (RelativeAttackPower is Equal) " +
"and ((RelativeSpeed is Slow) or (RelativeSpeed is Equal))) " +
"then AttackOrFlee is Attack"));
//4
fuzzyEngine.Rules.Add(fuzzyEngine.ParseRule("if ((OwnHealth is NearDead) " +
"and (EnemyHealth is NearDead) " +
"and (RelativeAttackPower is Weak) " +
"and ((RelativeSpeed is Equal) or (RelativeSpeed is Fast))) " +
"then AttackOrFlee is Flee"));
//5
fuzzyEngine.Rules.Add(fuzzyEngine.ParseRule("if ((OwnHealth is NearDead) " +
"and (EnemyHealth is Injured) " +
"and (RelativeAttackPower is Weak) " +
"and ((RelativeSpeed is Equal) or (RelativeSpeed is Fast))) " +
"then AttackOrFlee is Flee"));
//6
fuzzyEngine.Rules.Add(fuzzyEngine.ParseRule("if ((OwnHealth is NearDead) " +
"and (EnemyHealth is Normal) " +
"and (RelativeAttackPower is Weak) " +
"and ((RelativeSpeed is Equal) or (RelativeSpeed is Fast))) " +
"then AttackOrFlee is Flee"));
//7
fuzzyEngine.Rules.Add(fuzzyEngine.ParseRule("if (OwnHealth is NearDead) " +
"and (EnemyHealth is Normal) " +
"and (RelativeAttackPower is Equal) " +
"and (RelativeSpeed is Fast) " +
"then AttackOrFlee is Flee"));
//8
fuzzyEngine.Rules.Add(fuzzyEngine.ParseRule("if (OwnHealth is NearDead) " +
"and (EnemyHealth is Normal) " +
"and (RelativeAttackPower is Strong) " +
"and (RelativeSpeed is Fast) " +
"then AttackOrFlee is Flee"));
//9
fuzzyEngine.Rules.Add(fuzzyEngine.ParseRule("if (OwnHealth is NearDead) " +
"and (EnemyHealth is Injured) " +
"and (RelativeAttackPower is Equal) " +
"and (RelativeSpeed is Fast) " +
"then AttackOrFlee is Flee"));
}
public void CalculateFuzzy(List<Actor> ownUnits, List<Actor> enemyUnits)
{
Dictionary<FuzzyVariable, double> inputValues = new Dictionary<FuzzyVariable, double>();
inputValues.Add(fuzzyEngine.InputByName("OwnHealth"), (double)NormalizedHealth(ownUnits, 100));
inputValues.Add(fuzzyEngine.InputByName("EnemyHealth"), (double)NormalizedHealth(enemyUnits, 100));
inputValues.Add(fuzzyEngine.InputByName("RelativeAttackPower"), (double)RelativePower(ownUnits, enemyUnits));
inputValues.Add(fuzzyEngine.InputByName("RelativeSpeed"), (double)RelativeSpeed(ownUnits, enemyUnits));
result = fuzzyEngine.Calculate(inputValues);
}
protected float NormalizedHealth(List<Actor> actors, float normalizeByValue)
{
int sumOfMaxHp = 0;
int sumOfHp = 0;
foreach (var a in actors)
if (a.HasTrait<Health>())
{
sumOfMaxHp += a.Trait<Health>().MaxHP;
sumOfHp += a.Trait<Health>().HP;
}
if (sumOfMaxHp == 0) return 0.0f;
return (sumOfHp * normalizeByValue) / sumOfMaxHp;
}
protected float RelativePower(List<Actor> own, List<Actor> enemy)
{
return RelativeValue(own, enemy, 100, SumOfValues<AttackBase>, (Actor a) =>
{
int sumOfDamage = 0;
foreach (var weap in a.Trait<AttackBase>().Weapons)
if (weap.Info.Warheads[0] != null)
sumOfDamage += weap.Info.Warheads[0].Damage;
return sumOfDamage;
});
}
protected float RelativeSpeed(List<Actor> own, List<Actor> enemy)
{
return RelativeValue(own, enemy, 100, Average<Mobile>, (Actor a) => a.Trait<Mobile>().Info.Speed);
}
protected float RelativeValue(List<Actor> own, List<Actor> enemy, float normalizeByValue,
Func<List<Actor>, Func<Actor, int>, float> relativeFunc, Func<Actor, int> getValue)
{
if (enemy.Count == 0)
return 999.0f;
if (own.Count == 0)
return 0.0f;
float relative = (relativeFunc(own, getValue) / relativeFunc(enemy, getValue)) * normalizeByValue;
return relative.Clamp(0.0f, 999.0f);
}
protected float SumOfValues<Trait>(List<Actor> actors, Func<Actor, int> getValue)
{
int sum = 0;
foreach (var a in actors)
if (a.HasTrait<Trait>())
sum += getValue(a);
return sum;
}
protected float Average<Trait>(List<Actor> actors, Func<Actor, int> getValue)
{
int sum = 0;
int countActors = 0;
foreach (var a in actors)
if (a.HasTrait<Trait>())
{
sum += getValue(a);
countActors++;
}
if (countActors == 0) return 0.0f;
return sum / countActors;
}
}
}

View File

@@ -74,7 +74,13 @@ namespace OpenRA.Mods.RA.AI
lastThinkTick = ai.ticks;
/* place the building */
var location = ai.ChooseBuildLocation(currentBuilding.Item);
BuildingType type = BuildingType.Building;
if(Rules.Info[currentBuilding.Item].Traits.Contains<AttackBaseInfo>())
type = BuildingType.Defense;
else if(Rules.Info[currentBuilding.Item].Traits.Contains<OreRefineryInfo>())
type = BuildingType.Refinery;
var location = ai.ChooseBuildLocation(currentBuilding.Item, type);
if (location == null)
{
HackyAI.BotDebug("AI: Nowhere to place {0}".F(currentBuilding.Item));

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
#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 System.Text;
using AI.Fuzzy.Library;
namespace OpenRA.Mods.RA.AI
{
class RushFuzzy : AttackOrFleeFuzzy
{
public RushFuzzy() : base() { }
protected override void AddingRulesForNormalOwnHealth()
{
//1 OwnHealth is Normal
fuzzyEngine.Rules.Add(fuzzyEngine.ParseRule("if ((OwnHealth is Normal) " +
"and ((EnemyHealth is NearDead) or (EnemyHealth is Injured) or (EnemyHealth is Normal)) " +
"and (RelativeAttackPower is Strong) " +
"and ((RelativeSpeed is Slow) or (RelativeSpeed is Equal) or (RelativeSpeed is Fast))) " +
"then AttackOrFlee is Attack"));
fuzzyEngine.Rules.Add(fuzzyEngine.ParseRule("if ((OwnHealth is Normal) " +
"and ((EnemyHealth is NearDead) or (EnemyHealth is Injured) or (EnemyHealth is Normal)) " +
"and ((RelativeAttackPower is Weak) or (RelativeAttackPower is Equal)) " +
"and ((RelativeSpeed is Slow) or (RelativeSpeed is Equal) or (RelativeSpeed is Fast))) " +
"then AttackOrFlee is Flee"));
}
}
}

View File

@@ -0,0 +1,79 @@
#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
namespace OpenRA.Mods.RA.AI
{
class StateMachine
{
//a pointer to the agent that owns this instance
private Squad owner;
private IState currentState;
//a record of the last state the agent was in
private IState previousState;
public StateMachine(Squad owner)
{
this.owner = owner;
}
public IState CurrentState
{
get { return currentState; }
set { currentState = value; }
}
public IState PreviousState
{
get { return previousState; }
set { previousState = value; }
}
//call this to update the FSM
public void UpdateFsm()
{
currentState.Execute(owner);
}
//change to a new state
//boolean variable isSaveCurrentState respons on save or not current state
public void ChangeState(IState newState, bool saveCurrentState)
{
if (saveCurrentState)
//keep a record of the previous state
previousState = currentState;
//call the exit method of the existing state
if(currentState != null)
currentState.Exit(owner);
//change state to the new state
if (newState != null)
currentState = newState;
//call the entry method of the new state
currentState.Enter(owner);
}
//change state back to the previous state
public void RevertToPreviousState(bool saveCurrentState)
{
ChangeState(previousState, saveCurrentState);
}
}
interface IState
{
void Enter(Squad bot);
void Execute(Squad bot);
void Exit(Squad bot);
}
}

View File

@@ -229,7 +229,22 @@ namespace OpenRA.Mods.RA.Move
public CPos NearestMoveableCell(CPos target, int minRange, int maxRange)
{
return NearestCell(target, CanEnterCell, minRange, maxRange);
if (CanEnterCell(target))
return target;
var searched = new List<CPos>();
// Limit search to a radius of 10 tiles
for (int r = minRange; r < maxRange; r++)
foreach (var tile in self.World.FindTilesInCircle(target, r).Except(searched))
{
if (CanEnterCell(tile))
return tile;
searched.Add(tile);
}
// Couldn't find a cell
return target;
}
public CPos NearestCell(CPos target, Func<CPos, bool> check, int minRange, int maxRange)
@@ -237,9 +252,15 @@ namespace OpenRA.Mods.RA.Move
if (check(target))
return target;
foreach (var tile in self.World.FindTilesInCircle(target, maxRange))
if (check(tile))
return tile;
var searched = new List<CPos>();
for (int r = minRange; r < maxRange; r++)
foreach (var tile in self.World.FindTilesInCircle(target, r).Except(searched))
{
if (check(tile))
return tile;
searched.Add(tile);
}
// Couldn't find a cell
return target;

View File

@@ -42,6 +42,7 @@
<WarningLevel>4</WarningLevel>
<CustomCommands>
<CustomCommands>
<Command type="AfterBuild" command="cp ../thirdparty/FuzzyLogicLibrary.dll ../" workingdir="${ProjectDir}" />
<Command type="AfterBuild" command="cp ${TargetFile} ../mods/ra" workingdir="${ProjectDir}" />
<Command type="AfterBuild" command="mono RALint.exe ra" workingdir="${ProjectDir}/../" />
</CustomCommands>
@@ -58,6 +59,9 @@
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="FuzzyLogicLibrary">
<HintPath>..\thirdparty\FuzzyLogicLibrary.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
@@ -69,6 +73,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AI\AttackOrFleeFuzzy.cs" />
<Compile Include="AI\BaseBuilder.cs" />
<Compile Include="AI\HackyAI.cs" />
<Compile Include="AcceptsSupplies.cs" />
@@ -120,6 +125,8 @@
<Compile Include="Air\ReturnOnIdle.cs" />
<Compile Include="Air\ReturnToBase.cs" />
<Compile Include="Air\TargetableAircraft.cs" />
<Compile Include="AI\RushFuzzy.cs" />
<Compile Include="AI\StateMachine.cs" />
<Compile Include="AnnounceOnBuild.cs" />
<Compile Include="AnnounceOnKill.cs" />
<Compile Include="AppearsOnRadar.cs" />
@@ -451,6 +458,7 @@
<PropertyGroup>
<PostBuildEvent>mkdir "$(SolutionDir)mods/ra/"
copy "$(TargetPath)" "$(SolutionDir)mods/ra/"
copy "thirdparty/FuzzyLogicLibrary.dll" "$(SolutionDir)"
cd "$(SolutionDir)"</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,57 @@
#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.Collections.Generic;
using System.Drawing;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Orders
{
class SetChronoTankDestination : IOrderGenerator
{
public readonly Actor self;
public SetChronoTankDestination(Actor self)
{
this.self = self;
}
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
{
if (mi.Button == MouseButton.Left)
{
world.CancelInputMode();
yield break;
}
var queued = mi.Modifiers.HasModifier(Modifiers.Shift);
if (world.LocalPlayer.Shroud.IsExplored(xy))
yield return new Order("ChronoshiftSelf", self, queued) { TargetLocation = xy };
}
public void Tick( World world ) { }
public void RenderAfterWorld( WorldRenderer wr, World world )
{
wr.DrawSelectionBox(self, Color.White);
}
public void RenderBeforeWorld( WorldRenderer wr, World world ) { }
public string GetCursor(World world, CPos xy, MouseInput mi)
{
if (!world.LocalPlayer.Shroud.IsExplored(xy))
return "move-blocked";
var movement = self.TraitOrDefault<IMove>();
return (movement.CanEnterCell(xy)) ? "chrono-target" : "move-blocked";
}
}
}

View File

@@ -1,4 +1,4 @@
#region Copyright & License Information
#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
@@ -9,7 +9,6 @@
#endregion
using System.Collections.Generic;
using OpenRA.Mods.RA.Effects;
using OpenRA.Traits;
namespace OpenRA.Mods.RA

View File

@@ -14,6 +14,7 @@ TRAN:
Selectable:
Bounds: 41,41
Helicopter:
RearmBuildings: hpad
LandWhenIdle: true
ROT: 5
Speed: 15
@@ -54,6 +55,7 @@ HELI:
Selectable:
Bounds: 30,24
Helicopter:
RearmBuildings: hpad
ROT: 4
Speed: 20
Health:
@@ -100,6 +102,7 @@ ORCA:
Selectable:
Bounds: 30,24
Helicopter:
RearmBuildings: hpad
ROT: 4
Speed: 20
Health:

View File

@@ -11,6 +11,26 @@ Player:
DeveloperMode:
HackyAI@Default:
Name:Easy AI
BuildingCommonNames:
ConstructionYard: fact
Refinery: proc
Power: nuke,nuk2
Barracks: pyle,hand
VehiclesFactory: weap,afld
Silo: silo
UnitsCommonNames:
Mcv: mcv
BuildingLimits:
proc: 4
pyle: 2
hand: 2
hq: 1
weap: 2
afld: 2
hpad: 1
eye: 1
tmpl: 1
fix: 1
BuildingFractions:
proc: 20%
nuke: 9%
@@ -49,6 +69,68 @@ Player:
htnk: 50%
heli: 5%
orca: 5%
SquadSize: 15
HackyAI@Normal:
Name:Normal AI
BuildingCommonNames:
ConstructionYard: fact
Refinery: proc
Power: nuke,nuk2
Barracks: pyle,hand
VehiclesFactory: weap,afld
Silo: silo
UnitsCommonNames:
Mcv: mcv
BuildingLimits:
proc: 4
pyle: 2
hand: 2
hq: 1
weap: 2
afld: 2
hpad: 1
eye: 1
tmpl: 1
fix: 1
BuildingFractions:
proc: 17%
nuke: 1%
pyle: 2%
hand: 2%
hq: 1%
nuk2: 18%
weap: 5%
afld: 5%
hpad: 4%
gtwr: 5%
gun: 5%
atwr: 9%
obli: 7%
eye: 1%
tmpl: 1%
sam: 7%
silo: 7%
fix: 1%
UnitsToBuild:
e1: 30%
e2: 30%
e3: 30%
e4: 30%
e5: 30%
harv: 1%
bggy: 10%
ftnk: 10%
arty: 40%
bike: 10%
heli: 10%
ltnk: 40%
stnk: 40%
orca: 10%
msam: 50%
htnk: 50%
jeep: 20%
mtnk: 50%
SquadSize: 15
PlayerColorPalette:
BasePalette: terrain
RemapIndex: 176, 178, 180, 182, 184, 186, 189, 191, 177, 179, 181, 183, 185, 187, 188, 190

View File

@@ -52,6 +52,42 @@ Player:
Name:Omnius
UnitQueues: Infantry, Vehicle, Armor, Starport
RallypointTestBuilding: conyarda
BuildingCommonNames:
ConstructionYard: conyarda,conyardh,conyardo
Refinery: refa,refh,refo
Power: pwra,pwrh,pwro
VehiclesFactory: lighta,lighth,lighto,heavya,heavyh,heavyo
Silo: siloa, siloh, siloo
UnitsCommonNames:
Mcv: mcva,mcvh,mcvo
BuildingLimits:
refa: 4
refh: 4
refo: 4
barra: 1
barrh: 1
barro: 1
lighta: 1
lighth: 1
lighto: 1
heavya: 1
heavyh: 1
heavyo: 1
researcha: 1
researchh: 1
researcho: 1
repaira: 1
repairh: 1
repairo: 1
radara: 1
radaro: 1
radarh: 1
hightecha: 1
hightechh: 1
hightecho: 1
palacea: 1
palaceh: 1
palaceo: 1
BuildingFractions:
refa: 20.1%
refh: 20.1%

View File

@@ -39,6 +39,28 @@ Player:
DeveloperMode:
HackyAI@EasyAI:
Name:Easy AI
BuildingCommonNames:
ConstructionYard: fact
Refinery: proc
Power: powr,apwr
Barracks: barr,tent
VehiclesFactory: weap
Silo: silo
UnitsCommonNames:
Mcv: mcv
BuildingLimits:
proc: 4
barr: 2
tent: 2
dome: 1
weap: 2
spen: 1
syrd: 1
hpad: 4
afld: 4
atek: 1
stek: 1
fix: 1
BuildingFractions:
proc: 30%
powr: 35%
@@ -67,24 +89,52 @@ Player:
2tnk: 25%
3tnk: 50%
SquadSize: 20
HackyAI@HardAI:
Name:Hard AI
HackyAI@NormalAI:
Name:Normal AI
BuildingCommonNames:
ConstructionYard: fact
Refinery: proc
Power: powr,apwr
Barracks: barr,tent
VehiclesFactory: weap
Silo: silo
UnitsCommonNames:
Mcv: mcv
BuildingLimits:
proc: 4
barr: 2
tent: 2
dome: 1
weap: 2
spen: 1
syrd: 1
hpad: 4
afld: 4
atek: 1
stek: 1
fix: 1
BuildingFractions:
proc: 30%
powr: 35%
proc: 10%
powr: 1%
apwr: 30%
tent: 1%
barr: 1%
weap: 1%
dome: 1%
weap: 6%
hpad: 4%
spen: 1%
syrd: 1%
afld: 4%
pbox.e1: 7%
gun: 7%
ftur: 10%
tsla: 5%
fix: 0.1%
dome: 10%
fix: 1%
agun: 5%
sam: 1%
atek: 1%
stek: 1%
mslo: 1%
UnitsToBuild:
e1: 50%
e3: 10%
@@ -95,9 +145,178 @@ Player:
1tnk: 70%
2tnk: 25%
3tnk: 50%
heli: 30%
hind: 30%
mig: 30%
yak: 30%
ss: 10%
msub: 10%
dd: 10%
ca: 10%
pt: 10%
SquadSize: 40
HackyAI@HardAI:
Name:Hard AI
BuildingCommonNames:
ConstructionYard: fact
Refinery: proc
Power: powr,apwr
Barracks: barr,tent
VehiclesFactory: weap
Silo: silo
UnitsCommonNames:
Mcv: mcv
BuildingLimits:
proc: 4
barr: 2
tent: 2
dome: 1
weap: 2
spen: 1
syrd: 1
hpad: 4
afld: 4
atek: 1
stek: 1
fix: 1
BuildingFractions:
proc: 30%
powr: 1%
apwr: 30%
tent: 1%
barr: 1%
weap: 3%
hpad: 2%
spen: 1%
syrd: 1%
pbox.e1: 7%
gun: 7%
ftur: 10%
tsla: 5%
fix: 0.1%
dome: 10%
agun: 5%
sam: 1%
atek: 1%
stek: 1%
mslo: 1%
UnitsToBuild:
e1: 50%
e3: 10%
harv: 10%
apc: 30%
jeep: 40%
ftrk: 50%
1tnk: 70%
2tnk: 25%
3tnk: 50%
heli: 30%
hind: 30%
mig: 30%
yak: 30%
ss: 10%
msub: 10%
dd: 10%
ca: 10%
pt: 10%
SquadSize: 10
HackyAI@TestAI:
Name:Test AI
BuildingCommonNames:
ConstructionYard: fact
Refinery: proc
Power: powr,apwr
Barracks: barr,tent
VehiclesFactory: weap
Silo: silo
UnitsCommonNames:
Mcv: mcv
BuildingLimits:
proc: 4
barr: 2
tent: 2
dome: 1
weap: 2
spen: 1
syrd: 1
hpad: 4
afld: 4
atek: 1
stek: 1
fix: 1
BuildingFractions:
proc: 29%
powr: 1%
apwr: 24%
tent: 3%
barr: 3%
dome: 1%
weap: 5%
hpad: 5%
afld: 5%
fix: 1%
atek: 1%
stek: 1%
spen: 1%
syrd: 1%
pbox.e1: 12%
gun: 12%
ftur: 12%
tsla: 12%
agun: 5%
sam: 5%
mslo: 1%
UnitsToBuild:
e1: 4%
e2: 4%
e3: 8%
e4: 4%
shok: 3%
harv: 1%
apc: 3%
jeep: 5%
ftrk: 8%
1tnk: 9%
2tnk: 20%
3tnk: 10%
4tnk: 14%
ttnk: 8%
arty: 15%
v2rl: 10%
heli: 7%
hind: 7%
mig: 10%
yak: 1%
ss: 7%
msub: 5%
dd: 8%
ca: 8%
pt: 8%
SquadSize: 10
HackyAI@OptiAI:
Name:Eisenhower AI
BuildingCommonNames:
ConstructionYard: fact
Refinery: proc
Power: powr,apwr
Barracks: barr,tent
VehiclesFactory: weap
Silo: silo
UnitsCommonNames:
Mcv: mcv
BuildingLimits:
proc: 4
barr: 2
tent: 2
dome: 1
weap: 2
spen: 1
syrd: 1
hpad: 4
afld: 4
atek: 1
stek: 1
fix: 1
BuildingFractions:
proc: 25.1%
powr: 35%
@@ -126,6 +345,28 @@ Player:
SquadSize: 10
HackyAI@ZhukovAI:
Name:Zhukov AI
BuildingCommonNames:
ConstructionYard: fact
Refinery: proc
Power: powr,apwr
Barracks: barr,tent
VehiclesFactory: weap
Silo: silo
UnitsCommonNames:
Mcv: mcv
BuildingLimits:
proc: 4
barr: 2
tent: 2
dome: 1
weap: 2
spen: 1
syrd: 1
hpad: 4
afld: 4
atek: 1
stek: 1
fix: 1
BuildingFractions:
proc: 20%
powr: 35%
@@ -156,6 +397,28 @@ Player:
SquadSize: 25
HackyAI@RommelAI:
Name:Rommel AI
BuildingCommonNames:
ConstructionYard: fact
Refinery: proc
Power: powr,apwr
Barracks: barr,tent
VehiclesFactory: weap
Silo: silo
UnitsCommonNames:
Mcv: mcv
BuildingLimits:
proc: 4
barr: 2
tent: 2
dome: 1
weap: 2
spen: 1
syrd: 1
hpad: 4
afld: 4
atek: 1
stek: 1
fix: 1
BuildingFractions:
proc: 30%
powr: 35%

View File

@@ -39,6 +39,9 @@ cp thirdparty/Tao/* packaging/built
# SharpZipLib for zip file support
cp thirdparty/ICSharpCode.SharpZipLib.dll packaging/built
# FuzzyLogicLibrary for improved AI
cp thirdparty/FuzzyLogicLibrary.dll packaging/built
# Copy game icon for windows package
cp OpenRA.Game/OpenRA.ico packaging/built

View File

@@ -83,6 +83,7 @@ Section "Client" Client
File "${SRCDIR}\OpenRA.Renderer.Cg.dll"
File "${SRCDIR}\OpenRA.Renderer.Null.dll"
File "${SRCDIR}\ICSharpCode.SharpZipLib.dll"
File "${SRCDIR}\FuzzyLogicLibrary.dll"
File "${SRCDIR}\COPYING"
File "${SRCDIR}\HACKING"
File "${SRCDIR}\INSTALL"
@@ -260,6 +261,7 @@ Function ${UN}Clean
Delete $INSTDIR\OpenRA.Renderer.Null.dll
Delete $INSTDIR\OpenRA.Renderer.SdlCommon.dll
Delete $INSTDIR\ICSharpCode.SharpZipLib.dll
Delete $INSTDIR\FuzzyLogicLibrary.dll
Delete $INSTDIR\Tao.*.dll
Delete $INSTDIR\COPYING
Delete $INSTDIR\HACKING

BIN
thirdparty/FuzzyLogicLibrary.dll vendored Normal file

Binary file not shown.