changeset 152:0c0e14f03785

Re #180: Add multiple mutex groups * Add multiple mutex groups to UnitEquipmentItem * Add new attribute to Race schema * Make everywhere handle multiple groups instead of assuming one * Make factory load new attribute then fall back to old (deprecated) attribute * Add method to Unit to get the blocking items (useful for future UI work to say "replace X and Y with Z") * Add IsMutuallyExclusive method to UnitEquipmentItem to determine whether mutex groups overlap
author IBBoard <dev@ibboard.co.uk>
date Sat, 26 Sep 2009 19:51:11 +0000
parents 1d13820b3d96
children dd892567f054
files api/Factories/Xml/WarFoundryXmlRaceFactory.cs api/Objects/Unit.cs api/Objects/UnitEquipmentItem.cs api/Objects/UnitType.cs dtds/race.xsd
diffstat 5 files changed, 122 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/api/Factories/Xml/WarFoundryXmlRaceFactory.cs	Sat Sep 26 18:48:36 2009 +0000
+++ b/api/Factories/Xml/WarFoundryXmlRaceFactory.cs	Sat Sep 26 19:51:11 2009 +0000
@@ -154,8 +154,32 @@
 				
 				if (equipItem!=null)
 				{
-					string mutexGroup = equip.GetAttribute("exclusivityGroup");
-					UnitEquipmentItem unitEquipItem = new UnitEquipmentItem(equipItem, type, mutexGroup);
+					string mutexGroupString = equip.GetAttribute("exclusivityGroups");
+					string[] mutexGroups;
+
+					if (mutexGroupString == "")
+					{
+						mutexGroupString = equip.GetAttribute("exclusivityGroup");
+					}
+
+					if (mutexGroupString != "")
+					{
+						string[] groups = mutexGroupString.Split(',');
+						int groupCount = groups.Length;
+
+						for (int i = 0; i < groupCount; i++)
+						{
+							groups[i] = groups[i].Trim();
+						}
+
+						mutexGroups = groups;
+					}
+					else
+					{
+						mutexGroups = new string[0];
+					}
+
+					UnitEquipmentItem unitEquipItem = new UnitEquipmentItem(equipItem, type, mutexGroups);
 					unitEquipItem.RoundNumberUp = equip.GetAttribute("roundDirection").Equals("up");
 					
 					
--- a/api/Objects/Unit.cs	Sat Sep 26 18:48:36 2009 +0000
+++ b/api/Objects/Unit.cs	Sat Sep 26 19:51:11 2009 +0000
@@ -433,22 +433,39 @@
 		
 		public bool CanEquipWithItem(UnitEquipmentItem item)
 		{
-			string mutex = item.MutexGroup;
-
-			if (mutex == "")
-			{
-				return true;
+			string[] mutexes = item.MutexGroups;
+			bool canEquip = false;
+
+			if (mutexes.Length == 0)
+			{
+				canEquip = true;
+			}
+			else
+			{
+				canEquip = GetBlockingEquipmentItems(item).Count == 0;
 			}
 
-			foreach (UnitEquipmentItem unitItem in GetEquipment())
-			{
-				if (unitItem.MutexGroup == mutex)
-				{
-					return false;
-				}
-			}
-
-			return true;
+			return canEquip;
+		}
+
+		/// <summary>
+		/// Gets a list of all <see cref="UnitEquipmentItem"/>s that would stop the unit taking <code>item</code> because of mutex groups.
+		/// </summary>
+		/// <param name="item">The item to check blocking items for</param>
+		/// <returns>a list of all <see cref="UnitEquipmentItem"/>s that would stop the unit taking <code>item</code></returns>
+		public List<UnitEquipmentItem> GetBlockingEquipmentItems(UnitEquipmentItem item)
+		{
+			List<UnitEquipmentItem> items = new List<UnitEquipmentItem>();
+
+			foreach (UnitEquipmentItem unitItem in GetEquipment())
+			{
+				if (unitItem.IsMutuallyExclusive(item))
+				{
+					items.Add(unitItem);
+				}
+			}
+
+			return items;
 		}
 
 		public bool CanEquipWithItem(string equipID)
--- a/api/Objects/UnitEquipmentItem.cs	Sat Sep 26 18:48:36 2009 +0000
+++ b/api/Objects/UnitEquipmentItem.cs	Sat Sep 26 19:51:11 2009 +0000
@@ -3,7 +3,6 @@
 // The file and the library/program it is in are licensed and distributed, without warranty, under the GNU Affero GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license.
 
 using System;
-using System.Xml;
 using IBBoard.Lang;
 
 namespace IBBoard.WarFoundry.API.Objects
@@ -21,22 +20,22 @@
 		private double minPercentage;
 		private double maxPercentage;
 		private double costMultiplier;
-		private RoundType roundType;
-		private string mutexGroup;
+		private RoundType roundType;
+		private string[] mutexGroups;
 		private UnitType unitType;
 
-		public UnitEquipmentItem(EquipmentItem equipmentItem, UnitType equipmentFor) : this(equipmentItem, equipmentFor, "")
+		public UnitEquipmentItem(EquipmentItem equipmentItem, UnitType equipmentFor) : this(equipmentItem, equipmentFor, new string[0])
 		{
 			//Do nothing extra
 		}
 		
-		public UnitEquipmentItem(EquipmentItem equipmentItem, UnitType equipmentFor, string mutexGroup)
+		public UnitEquipmentItem(EquipmentItem equipmentItem, UnitType equipmentFor, params string[] mutexGroups)
 		{
 			item = equipmentItem;
 			unitType = equipmentFor;
-			this.mutexGroup = mutexGroup;
+			this.mutexGroups = mutexGroups;
 			unitType.AddEquipmentItem(this);
-		}
+		}
 		
 		public override string Name
 		{
@@ -105,9 +104,15 @@
 			set { roundUp = value; }
 		}
 
+		[Obsolete("Use MutexGroups instead for greater flexibility")]
 		public string MutexGroup
 		{
-			get { return mutexGroup; }
+			get { return (mutexGroups.Length == 0 ? "" : mutexGroups[0]); }
+		}
+
+		public String[] MutexGroups
+		{
+			get { return (string[]) mutexGroups.Clone(); }
 		}
 
 		public UnitType EquipmentForUnit
@@ -184,7 +189,7 @@
 
 		public bool HasAlternatives()
 		{
-			if (MutexGroup=="")
+			if (MutexGroups.Length == 0)
 			{
 				return false;
 			}
@@ -195,7 +200,7 @@
 			else
 			{
 				//If the number of items in the MutEx group is greater than one then it must be this item plus another
-				return EquipmentForUnit.GetEquipmentItemsByExclusionGroup(MutexGroup).Length > 1;
+				return EquipmentForUnit.GetEquipmentItemsByExclusionGroups(MutexGroups).Length > 1;
 			}
 		}
 
@@ -222,6 +227,31 @@
 		public bool CanBeUsedWithArmourType(ArmourType otherItemType)
 		{
 			return EquipmentItem.CanBeUsedWithArmourType(otherItemType);
-		}
+		}
+
+		/// <summary>
+		/// Checks the "mutex" (mutual exclusion) groups of the other item against its own and determines whether the two items are mutually exclusive (share at least one mutex group)
+		/// </summary>
+		/// <param name="item">the item to check against</param>
+		/// <returns><code>true</code> if the two items share at least one mutex group, else <code>false</code></returns>
+		public bool IsMutuallyExclusive(UnitEquipmentItem item)
+		{
+			bool areMutex = false;
+
+			foreach (string mutex in MutexGroups)
+			{
+				foreach (string otherMutex in item.MutexGroups)
+				{
+					if (mutex.Equals(otherMutex))
+					{
+						areMutex = true;
+						goto postLoop;
+					}
+				}
+			}
+			postLoop:
+
+			return areMutex;
+		}
 	}
 }
--- a/api/Objects/UnitType.cs	Sat Sep 26 18:48:36 2009 +0000
+++ b/api/Objects/UnitType.cs	Sat Sep 26 19:51:11 2009 +0000
@@ -233,15 +233,15 @@
 			{
 				equipment.Add(item.ID, item);
 				equipmentKeyOrder.Add(item.ID);
-				AddToMutexGroup(item);
+				AddToMutexGroups(item);
 			}
 		}
 		
-		private void AddToMutexGroup(UnitEquipmentItem item)
+		private void AddToMutexGroups(UnitEquipmentItem item)
 		{
-			string mutexGroup = item.MutexGroup;
+			string[] mutexGroups = item.MutexGroups;
 			
-			if (mutexGroup!="" && mutexGroup!=null)
+			foreach (string mutexGroup in mutexGroups)
 			{
 				List<UnitEquipmentItem> items = DictionaryUtils.GetValue(equipmentExclusionGroups, mutexGroup);
 				
@@ -295,17 +295,25 @@
 		}
 
 		public UnitEquipmentItem[] GetEquipmentItemsByExclusionGroup(string group)
-		{
-			List<UnitEquipmentItem> list = DictionaryUtils.GetValue(equipmentExclusionGroups, group);
+		{
+			return GetEquipmentItemsByExclusionGroups(new string[] { group });
+		}
 
-			if (list == null)
-			{
-				return new UnitEquipmentItem[0];
-			}
-			else
-			{
-				return list.ToArray();
-			}
+		public UnitEquipmentItem[] GetEquipmentItemsByExclusionGroups(string[] groups)
+		{
+			List<UnitEquipmentItem> list = new List<UnitEquipmentItem>();
+
+			foreach (string group in groups)
+			{
+				List<UnitEquipmentItem> groupList = DictionaryUtils.GetValue(equipmentExclusionGroups, group);
+
+				if (groupList != null)
+				{
+					list.AddRange(groupList);
+				}
+			}
+
+			return list.ToArray();
 		}
 		
 		public bool IsRatioLimitedEquipmentItem(EquipmentItem item)
--- a/dtds/race.xsd	Sat Sep 26 18:48:36 2009 +0000
+++ b/dtds/race.xsd	Sat Sep 26 19:51:11 2009 +0000
@@ -35,7 +35,9 @@
 													<xs:complexType>
 														<xs:attribute name="id" type="xs:IDREF" />
 														<xs:attribute name="required" type="xs:boolean" default="false"/>
+														<!-- exclusivityGroup is deprecated in favour of the comma-separated exclusivityGroups -->
 														<xs:attribute name="exclusivityGroup" type="xs:string" default=""/>
+														<xs:attribute name="exclusivityGroups" type="xs:string" default=""/>
 														<xs:attribute name="minNum" type="core:nonNegativeOrInfiniteInteger" default="-1"/>
 														<xs:attribute name="maxNum" type="core:nonNegativeOrInfiniteInteger" default="-1"/>
 														<xs:attribute name="minPercentage" type="core:percentage" default="100"/>