diff --git a/OpenRa.TechTreeTest/Building.cs b/OpenRa.TechTreeTest/Building.cs index d7178bc1db..1c2d13b9f8 100644 --- a/OpenRa.TechTreeTest/Building.cs +++ b/OpenRa.TechTreeTest/Building.cs @@ -8,14 +8,14 @@ using System.IO; namespace OpenRa.TechTreeTest { [Flags] - public enum BuildingRace + public enum Race { None = 0, Allies = 1, Soviet = 2 } - class Building + class Building : IRAUnit { readonly string friendlyName; readonly string tag; @@ -46,9 +46,9 @@ namespace OpenRa.TechTreeTest set { techLevel = value; } } - BuildingRace owner; + Race owner; - public BuildingRace Owner + public Race Owner { get { return owner; } set { owner = value; } @@ -90,7 +90,7 @@ namespace OpenRa.TechTreeTest bool buildable = false; public bool Buildable { get { return buildable; } } - public void CheckPrerequisites(IEnumerable buildings, BuildingRace currentRace) + public void CheckPrerequisites(IEnumerable buildings, Race currentRace) { if ((buildable && ShouldMakeUnbuildable(buildings)) || !((owner & currentRace) == currentRace)) buildable = false; diff --git a/OpenRa.TechTreeTest/Form1.cs b/OpenRa.TechTreeTest/Form1.cs index be074b44bc..b6bb4b7686 100644 --- a/OpenRa.TechTreeTest/Form1.cs +++ b/OpenRa.TechTreeTest/Form1.cs @@ -10,7 +10,7 @@ namespace OpenRa.TechTreeTest { public partial class Form1 : Form { - TechTree techTree = new TechTree(BuildingRace.Soviet); + TechTree techTree = new TechTree(Race.Allies); public Form1() { @@ -22,7 +22,7 @@ namespace OpenRa.TechTreeTest { buildableItems.Controls.Clear(); - foreach (Building b in techTree.BuildableItems) + foreach (IRAUnit b in techTree.BuildableItems) { PictureBox box = new PictureBox(); box.SizeMode = PictureBoxSizeMode.AutoSize; @@ -32,13 +32,13 @@ namespace OpenRa.TechTreeTest buildableItems.Controls.Add(box); - Building k = b; + IRAUnit k = b; box.Click += delegate { Build(k); }; } } - void Build(Building b) + void Build(IRAUnit b) { techTree.Build(b.Tag); RefreshList(); diff --git a/OpenRa.TechTreeTest/IRAUnit.cs b/OpenRa.TechTreeTest/IRAUnit.cs new file mode 100644 index 0000000000..f0f35db98d --- /dev/null +++ b/OpenRa.TechTreeTest/IRAUnit.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +namespace OpenRa.TechTreeTest +{ + interface IRAUnit + { + bool Buildable { get; } + void CheckPrerequisites(IEnumerable units, Race currentRace); + string FriendlyName { get; } + Bitmap Icon { get; } + Race Owner { get; set; } + string[] Prerequisites { get; set; } + bool ShouldMakeBuildable(IEnumerable units); + bool ShouldMakeUnbuildable(IEnumerable units); + string Tag { get; } + int TechLevel { get; set; } + } +} diff --git a/OpenRa.TechTreeTest/OpenRa.TechTreeTest.csproj b/OpenRa.TechTreeTest/OpenRa.TechTreeTest.csproj index 61bf9dbf72..904c370ee4 100644 --- a/OpenRa.TechTreeTest/OpenRa.TechTreeTest.csproj +++ b/OpenRa.TechTreeTest/OpenRa.TechTreeTest.csproj @@ -43,6 +43,7 @@ Form1.cs + @@ -68,6 +69,7 @@ True + diff --git a/OpenRa.TechTreeTest/TechTree.cs b/OpenRa.TechTreeTest/TechTree.cs index f1d783c4a0..013666c62e 100644 --- a/OpenRa.TechTreeTest/TechTree.cs +++ b/OpenRa.TechTreeTest/TechTree.cs @@ -9,14 +9,15 @@ namespace OpenRa.TechTreeTest { class TechTree { - Dictionary buildings = new Dictionary(); + Dictionary units = new Dictionary(); public ICollection built = new List(); - readonly BuildingRace currentRace; + readonly Race currentRace; - public TechTree(BuildingRace race) + public TechTree(Race race) { this.currentRace = race; LoadBuildings(); + LoadUnits(); LoadRules(); built.Add("FACT"); @@ -27,10 +28,10 @@ namespace OpenRa.TechTreeTest { IniFile rulesFile; rulesFile = new IniFile(File.OpenRead("../../../rules.ini")); - foreach (string key in buildings.Keys) + foreach (string key in units.Keys) { IniSection section = rulesFile.GetSection(key); - Building b = buildings[key]; + IRAUnit b = units[key]; string s = section.GetValue("Prerequisite", "").ToUpper(); b.Prerequisites = s.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); b.TechLevel = int.Parse(section.GetValue("TechLevel", "-1")); @@ -38,21 +39,25 @@ namespace OpenRa.TechTreeTest if (string.IsNullOrEmpty(s)) { - b.Owner = BuildingRace.None; + s = section.GetValue("DoubleOwned", "No"); + if (s.Equals("Yes", StringComparison.InvariantCultureIgnoreCase)) + b.Owner = Race.Allies | Race.Soviet; + else + b.Owner = Race.None; continue; } if (s.Equals("Both", StringComparison.InvariantCultureIgnoreCase)) { - b.Owner = BuildingRace.Allies | BuildingRace.Soviet; + b.Owner = Race.Allies | Race.Soviet; continue; } string[] frags = s.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (frags.Length > 1) - b.Owner = BuildingRace.Allies | BuildingRace.Soviet; + b.Owner = Race.Allies | Race.Soviet; else - b.Owner = (BuildingRace)Enum.Parse(typeof(BuildingRace), frags[0], true); + b.Owner = (Race)Enum.Parse(typeof(Race), frags[0], true); } } @@ -63,13 +68,24 @@ namespace OpenRa.TechTreeTest Regex pattern = new Regex(@"^(\w+),([\w ]+)$"); Match m = pattern.Match(line); if (!m.Success) continue; - buildings.Add(m.Groups[1].Value, new Building(m.Groups[1].Value, m.Groups[2].Value)); + units.Add(m.Groups[1].Value, new Building(m.Groups[1].Value, m.Groups[2].Value)); + } + } + + void LoadUnits() + { + foreach (string line in File.ReadAllLines("../../../units.txt")) + { + Regex pattern = new Regex(@"^(\w+),([\w ]+)$"); + Match m = pattern.Match(line); + if (!m.Success) continue; + units.Add(m.Groups[1].Value, new Unit(m.Groups[1].Value, m.Groups[2].Value)); } } public bool Build(string key) { - Building b = buildings[key]; + IRAUnit b = units[key]; if (!b.Buildable) return false; built.Add(key); CheckAll(); @@ -78,7 +94,7 @@ namespace OpenRa.TechTreeTest public bool Unbuild(string key) { - Building b = buildings[key]; + IRAUnit b = units[key]; if (!built.Contains(key)) return false; built.Remove(key); CheckAll(); @@ -87,15 +103,15 @@ namespace OpenRa.TechTreeTest void CheckAll() { - foreach (Building building in buildings.Values) - building.CheckPrerequisites(built, currentRace); + foreach (IRAUnit unit in units.Values) + unit.CheckPrerequisites(built, currentRace); } - public IEnumerable BuildableItems + public IEnumerable BuildableItems { get { - foreach (Building b in buildings.Values) + foreach (IRAUnit b in units.Values) if (b.Buildable) yield return b; } diff --git a/OpenRa.TechTreeTest/Unit.cs b/OpenRa.TechTreeTest/Unit.cs new file mode 100644 index 0000000000..2fe00b74fa --- /dev/null +++ b/OpenRa.TechTreeTest/Unit.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using OpenRa.FileFormats; +using System.IO; + +namespace OpenRa.TechTreeTest +{ + class Unit : IRAUnit + { + bool buildable; + public bool Buildable { get { return buildable; } } + + public void CheckPrerequisites(IEnumerable units, Race currentRace) + { + if ((buildable && ShouldMakeUnbuildable(units)) || !((owner & currentRace) == currentRace)) + buildable = false; + else if (!buildable && ShouldMakeBuildable(units)) + buildable = true; ; + } + + readonly string friendlyName; + public string FriendlyName { get { return friendlyName; } } + + Bitmap icon; + public Bitmap Icon + { + get { return icon ?? (icon = LoadIcon(tag)); } + } + + static Package package = new Package("../../../hires.mix"); + static Palette palette = new Palette(File.OpenRead("../../../temperat.pal")); + + static Bitmap LoadIcon(string tag) + { + string filename = tag + "icon.shp"; + + try + { + Stream s = package.GetContent(filename); + ShpReader reader = new ShpReader(s); + foreach (ImageHeader h in reader) + return BitmapBuilder.FromBytes(h.Image, reader.Width, reader.Height, palette); + + return null; + } + catch (FileNotFoundException) { return LoadIcon("dog"); } + } + + Race owner; + public Race Owner + { + get { return owner; } + set { owner = value; } + } + + string[] prerequisites; + public string[] Prerequisites + { + get { return prerequisites; } + set { prerequisites = value; } + } + + public bool ShouldMakeBuildable(IEnumerable units) + { + if (techLevel > 10 || techLevel < 0) + return false; + + if (prerequisites.Length == 0) + return true; + + List p = new List(prerequisites); + foreach (string b in units) + p.Remove(b); + + return p.Count == 0; + } + + public bool ShouldMakeUnbuildable(IEnumerable units) + { + if (prerequisites.Length == 0) + return false; + + List p = new List(prerequisites); + foreach (string b in units) + p.Remove(b); + + return p.Count == prerequisites.Length; + } + + readonly string tag; + public string Tag + { + get { return tag; } + } + + int techLevel; + public int TechLevel + { + get { return techLevel; } + set { techLevel = value; } + } + + public Unit(string tag, string friendlyName) + { + this.friendlyName = friendlyName; + this.tag = tag; + } + } +}