changeset 487:248df19652f9

Re #410: Create "N units per M models in parent unit" requirement * Add null adding context * Add initial skeleton of "N units per M models in parent unit" requirement * Update use of context * Standardise some of "is applicable" testing
author IBBoard <dev@ibboard.co.uk>
date Fri, 27 Jul 2012 20:31:12 +0100
parents 6e5b39caeb4e
children c082a312a741
files API/Objects/Requirement/AbstractUnitRequirement.cs API/Objects/Requirement/Context/NullAddingContext.cs API/Objects/Requirement/IRequirement.cs API/Objects/Requirement/RequirementHandler.cs API/Objects/Requirement/RequiresAtLeastNUnitsRequirement.cs API/Objects/Requirement/RequiresNUnitsForMObjectsRequirement.cs API/Objects/Requirement/RequiresNoMoreThanNOfUnitTypeRequirement.cs API/Objects/Requirement/UnitRequiresAtLeastNUnitsRequirement.cs API/Objects/Requirement/UnitRequiresNParentModelsForMUnitsRequirement.cs API/Objects/Requirement/UnitRequiresNUnitsForMUnitsRequirement.cs API/Objects/Requirement/UnitRequiresNoMoreThanNOfUnitTypeRequirement.cs API/Objects/UnitType.cs IBBoard.WarFoundry.API.csproj
diffstat 13 files changed, 336 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/API/Objects/Requirement/AbstractUnitRequirement.cs	Sun Jul 15 21:01:47 2012 +0100
+++ b/API/Objects/Requirement/AbstractUnitRequirement.cs	Fri Jul 27 20:31:12 2012 +0100
@@ -74,21 +74,97 @@
 			return hash;
 		}
 
-		protected virtual bool IsApplicable(IWarFoundryObject toObjectAdded, Army toArmy, AddingContext context)
+		/// <summary>
+		/// A wrapper method that supplies a default "null context" to determines whether this requirement is applicable to the specified object and/or the specified army
+		/// </summary>
+		/// <returns>
+		/// <c>true</c> if this instance is applicable to the specified toObjectAdded or toArmy (or both); otherwise, <c>false</c>.
+		/// </returns>
+		/// <param name='toObjectAdded'>
+		/// The WarFoundry object being added
+		/// </param>
+		/// <param name='toArmy'>
+		/// The army the object is being added to
+		/// </param>
+		protected bool IsApplicable(IWarFoundryObject toObjectAdded, Army toArmy)
 		{
-			return IsApplicable(toArmy, context) || IsApplicable(toObjectAdded, context);
+			return IsApplicable(toObjectAdded, toArmy, new NullAddingContext());
 		}
 
+		/// <summary>
+		/// Determines whether this requirement is independantly applicable to the specified object or the specified army.
+		/// </summary>
+		/// <returns>
+		/// <c>true</c> if this instance is applicable to the specified toObjectAdded or toArmy (or both); otherwise, <c>false</c>.
+		/// </returns>
+		/// <param name='toObjectAdded'>
+		/// The WarFoundry object being added
+		/// </param>
+		/// <param name='toArmy'>
+		/// The army the object is being added to
+		/// </param>
+		/// <param name='context'>
+		/// The context for adding the object
+		/// </param>
+		protected bool IsApplicable(IWarFoundryObject toObjectAdded, Army toArmy, AddingContext context)
+		{
+			return IsApplicableToBoth(toObjectAdded, toArmy, context) || IsApplicable(toArmy, context) || IsApplicable(toObjectAdded, context);
+		}
+
+		/// <summary>
+		/// Determines whether this requirement is applicable the specified army in the given context
+		/// </summary>
+		/// <returns>
+		/// <c>true</c> if this requirement is applicable to the specified army in the given context; otherwise, <c>false</c>.
+		/// </returns>
+		/// <param name='toArmy'>
+		/// The army that an object is being added to
+		/// </param>
+		/// <param name='context'>
+		/// The context for adding the object
+		/// </param>
 		protected virtual bool IsApplicable(Army toArmy, AddingContext context)
 		{
 			return false;
 		}
 
+		/// <summary>
+		/// Determines whether this requirement is applicable the specified object in the given context.
+		/// </summary>
+		/// <returns>
+		/// <c>true</c> if this requirement is applicable the specified object in the context; otherwise, <c>false</c>.
+		/// </returns>
+		/// <param name='toObject'>
+		/// The object being added to an army
+		/// </param>
+		/// <param name='context'>
+		/// The context for adding the object
+		/// </param>
 		protected virtual bool IsApplicable(IWarFoundryObject toObject, AddingContext context)
 		{
 			return false;
 		}
 
+		/// <summary>
+		/// Determines whether this instance is applicable to both the specified object and army in the given context.
+		/// </summary>
+		/// <returns>
+		/// <c>true</c> if this instance is applicable to both the specified object and army in the given context; otherwise, <c>false</c>.
+		/// </returns>
+		/// <param name='toObject'>
+		/// The object being added to an army
+		/// </param>
+		/// <param name='toArmy'>
+		/// The army that an object is being added to
+		/// </param>
+		/// <param name='context'>
+		/// The context for adding the object
+		/// </param>
+		protected virtual bool IsApplicableToBoth(IWarFoundryObject toObjectAdded, Army toArmy, AddingContext context)
+		{
+			return false;
+		}
+
 		public string GetValidationMessage(Army army)
 		{
 			string message = "";
@@ -113,12 +189,17 @@
 
 		public string GetAllowsAddingMessage(IWarFoundryObject toAdd, Army toArmy)
 		{
+			return GetAllowsAddingMessage(toAdd, toArmy, new NullAddingContext());
+		}
+
+		public string GetAllowsAddingMessage(IWarFoundryObject toAdd, Army toArmy, AddingContext context)
+		{
 			string message = "";
 
-			Validation result = AllowsAdding(toAdd, toArmy);
+			Validation result = AllowsAdding(toAdd, toArmy, context);
 			if (!Validates.AsOkay(result))
 			{
-				message = GetAllowsAddingFailedMessage(toAdd, toArmy);
+				message = GetAllowsAddingFailedMessage(toAdd, toArmy, context);
 			}
 
 			return message;
@@ -126,12 +207,12 @@
 
 		protected virtual string AllowsAddingFailedMessage { get { return ValidationFailedMessage; } }
 
-		protected string GetAllowsAddingFailedMessage(IWarFoundryObject toAdd, Army toArmy)
+		protected string GetAllowsAddingFailedMessage(IWarFoundryObject toAdd, Army toArmy, AddingContext context)
 		{
-			return String.Format(AllowsAddingFailedMessage, GetFailedAddingRequirementsString(toAdd, toArmy));
+			return String.Format(AllowsAddingFailedMessage, GetFailedAddingRequirementsString(toAdd, toArmy, context));
 		}
 
-		protected abstract string GetFailedAddingRequirementsString(IWarFoundryObject toAdd, Army toArmy);
+		protected abstract string GetFailedAddingRequirementsString(IWarFoundryObject toAdd, Army toArmy, AddingContext context);
 
 		/// <summary>
 		/// Checks whether the supplied WarFoundryObject can be added to the supplied army.
@@ -147,7 +228,7 @@
 		/// </param>
 		public Validation AllowsAdding(IWarFoundryObject wfObject, Army toArmy)
 		{
-			return AllowsAdding(wfObject, toArmy, null);
+			return AllowsAdding(wfObject, toArmy, new NullAddingContext());
 		}
 
 		/// <summary>
@@ -243,6 +324,19 @@
 			string[] names = namesList.ToArray();
 			return String.Join(" or ", names);
 		}
+
+		protected bool IsUnitTypeLimited(UnitType unitType)
+		{
+			foreach (UnitCountRequirementData requirement in requiredTypes)
+			{
+				if (Arrays.Contains(requirement.UnitTypes, unitType))
+				{
+					return true;
+				}
+			}
+
+			return false;
+		}
 	}
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/API/Objects/Requirement/Context/NullAddingContext.cs	Fri Jul 27 20:31:12 2012 +0100
@@ -0,0 +1,13 @@
+// This file (NullAddingContext.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2012 IBBoard
+//
+// 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;
+
+namespace IBBoard.WarFoundry.API.Objects.Requirement.Context
+{
+	public class NullAddingContext : AddingContext
+	{
+		//Do nothing special
+	}
+}
+
--- a/API/Objects/Requirement/IRequirement.cs	Sun Jul 15 21:01:47 2012 +0100
+++ b/API/Objects/Requirement/IRequirement.cs	Fri Jul 27 20:31:12 2012 +0100
@@ -2,6 +2,7 @@
 // 
 // 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 IBBoard.WarFoundry.API.Objects.Requirement.Context;
 
 namespace IBBoard.WarFoundry.API.Objects.Requirement
 {
@@ -67,7 +68,10 @@
 		/// <param name='toArmy'>
 		/// The army the object will be added to
 		/// </param>
-		string GetAllowsAddingMessage(IWarFoundryObject toAdd, Army toArmy);
+		/// <param name="context">
+		/// The context of the addition
+		/// </para>			
+		string GetAllowsAddingMessage(IWarFoundryObject toAdd, Army toArmy, AddingContext context);
 	}
 }
 
--- a/API/Objects/Requirement/RequirementHandler.cs	Sun Jul 15 21:01:47 2012 +0100
+++ b/API/Objects/Requirement/RequirementHandler.cs	Fri Jul 27 20:31:12 2012 +0100
@@ -3,6 +3,7 @@
 // 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.Collections.Generic;
+using IBBoard.WarFoundry.API.Objects.Requirement.Context;
 
 namespace IBBoard.WarFoundry.API.Objects.Requirement
 {
@@ -41,12 +42,22 @@
 
 		public static Validation AllowsAdding(UnitType unitType, Army army)
 		{
-			ICollection<string> ignored;
-			return AllowsAdding(unitType, army, out ignored);
+			return AllowsAdding(unitType, army, new NullAddingContext());
 		}
 
+		public static Validation AllowsAdding(UnitType unitType, Army army, AddingContext context)
+		{
+			ICollection<string> ignored;
+			return AllowsAdding(unitType, army, context, out ignored);
+		}
+		
 		public static Validation AllowsAdding(UnitType unitType, Army army, out ICollection<string> failureMessages)
 		{
+			return AllowsAdding(unitType, army, new NullAddingContext(), out failureMessages);
+		}
+
+		public static Validation AllowsAdding(UnitType unitType, Army army, AddingContext context, out ICollection<string> failureMessages)
+		{
 			Validation result = Validation.Passed;
 			failureMessages = new List<string>();
 			
@@ -55,7 +66,7 @@
 				if (!Validates.AsOkay(requirement.AllowsAdding(unitType, army)))
 				{
 					result = Validation.Failed;
-					failureMessages.Add(requirement.GetAllowsAddingMessage(unitType, army));
+					failureMessages.Add(requirement.GetAllowsAddingMessage(unitType, army, context));
 				}
 			}
 
--- a/API/Objects/Requirement/RequiresAtLeastNUnitsRequirement.cs	Sun Jul 15 21:01:47 2012 +0100
+++ b/API/Objects/Requirement/RequiresAtLeastNUnitsRequirement.cs	Fri Jul 27 20:31:12 2012 +0100
@@ -189,7 +189,7 @@
 			return failures;
 		}
 
-		protected override string GetFailedAddingRequirementsString(IWarFoundryObject toAdd, Army toArmy)
+		protected override string GetFailedAddingRequirementsString(IWarFoundryObject toAdd, Army toArmy, AddingContext context)
 		{
 			return String.Join("; ", GetFailedAddingRequirements(toAdd, toArmy).ToArray());
 		}
--- a/API/Objects/Requirement/RequiresNUnitsForMObjectsRequirement.cs	Sun Jul 15 21:01:47 2012 +0100
+++ b/API/Objects/Requirement/RequiresNUnitsForMObjectsRequirement.cs	Fri Jul 27 20:31:12 2012 +0100
@@ -27,7 +27,7 @@
 			return hash;
 		}
 
-		protected override string GetFailedAddingRequirementsString(IWarFoundryObject toAdd, Army toArmy)
+		protected override string GetFailedAddingRequirementsString(IWarFoundryObject toAdd, Army toArmy, AddingContext context)
 		{
 			return String.Join("; ", GetFailedAddingRequirements(toAdd, toArmy).ToArray());
 		}
--- a/API/Objects/Requirement/RequiresNoMoreThanNOfUnitTypeRequirement.cs	Sun Jul 15 21:01:47 2012 +0100
+++ b/API/Objects/Requirement/RequiresNoMoreThanNOfUnitTypeRequirement.cs	Fri Jul 27 20:31:12 2012 +0100
@@ -67,7 +67,7 @@
 			
 			foreach (UnitCountRequirementData limit in ConstraintTypes)
 			{
-				if (GetUnitTypeCount(toArmy, limit.UnitType, wfObject) > limit.Count)
+				if (GetUnitTypeCount(toArmy, limit.UnitType, wfObject, context) > limit.Count)
 				{
 					canAdd = Validation.Failed;
 					break;
@@ -77,16 +77,21 @@
 			return canAdd;
 		}
 
-		private int GetUnitTypeCount(Army toArmy, UnitType unitType, WarFoundryObject wfObject)
+		private int GetUnitTypeCount(Army toArmy, UnitType unitType, IWarFoundryObject wfObject, AddingContext context)
 		{
-			return toArmy.GetUnitTypeCount(unitType) + GetCountFromObject(wfObject, unitType);
+			return toArmy.GetUnitTypeCount(unitType) + GetCountFromObject(wfObject, unitType) + GetCountFromContext(context);
 		}
 
-		private int GetCountFromObject(WarFoundryObject wfObject, UnitType limitedType)
+		private int GetCountFromObject(IWarFoundryObject wfObject, UnitType limitedType, AddingContext context)
 		{
 			return (limitedType.Equals(wfObject) || (wfObject is Unit && ((Unit)wfObject).UnitType.Equals(limitedType))) ? 1 : 0;
 		}
 
+		protected virtual int GetCountFromContext(AddingContext context)
+		{
+			return 0;
+		}
+
 		/// <summary>
 		/// Adds a requirement for there to be no more than maxCount of a given UnitType
 		/// </summary>
@@ -177,7 +182,7 @@
 			return failures;
 		}
 
-		protected override string GetFailedAddingRequirementsString(IWarFoundryObject toAdd, Army toArmy)
+		protected override string GetFailedAddingRequirementsString(IWarFoundryObject toAdd, Army toArmy, AddingContext context)
 		{
 			return String.Join("; ", GetFailedAddingRequirements(toAdd, toArmy).ToArray());
 		}
--- a/API/Objects/Requirement/UnitRequiresAtLeastNUnitsRequirement.cs	Sun Jul 15 21:01:47 2012 +0100
+++ b/API/Objects/Requirement/UnitRequiresAtLeastNUnitsRequirement.cs	Fri Jul 27 20:31:12 2012 +0100
@@ -17,17 +17,12 @@
 		{
 		}
 
-		protected override bool IsApplicable(IWarFoundryObject toObject, Army toArmy, AddingContext context)
-		{
-			return IsApplicable(toObject, context) || IsApplicableForRequiredType(toObject, toArmy);
-		}
-
 		protected override bool IsApplicable(IWarFoundryObject toObject, AddingContext context)
 		{
 			return AllowedObject.Equals(toObject) || (toObject is Unit && AllowedObject.Equals(((Unit)toObject).UnitType));
 		}
 
-		private bool IsApplicableForRequiredType(IWarFoundryObject toObject, Army toArmy)
+		protected override bool IsApplicableToBoth(IWarFoundryObject toObject, Army toArmy, AddingContext context)
 		{
 			bool isApplicable = false;
 			UnitType addedType = toObject as UnitType;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/API/Objects/Requirement/UnitRequiresNParentModelsForMUnitsRequirement.cs	Fri Jul 27 20:31:12 2012 +0100
@@ -0,0 +1,183 @@
+// This file (UnitRequiresNoMoreThanNUnitsPerMModelsInParentUnitRequirement.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2012 IBBoard
+//
+// 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 IBBoard.WarFoundry.API.Objects.Requirement.Context;
+
+namespace IBBoard.WarFoundry.API.Objects.Requirement
+{
+	public class UnitRequiresNParentModelsForMUnitsRequirement : AbstractUnitRequirement<UnitType>
+	{
+		public static readonly string N_PER_M_IN_PARENT_REQUIREMENT_ID = "RequiresNoMoreThanNUnitsPerMModelsInParent";
+
+		public UnitRequiresNParentModelsForMUnitsRequirement(UnitType allowedObject, params UnitType[] limitedUnitTypes) : base(allowedObject, limitedUnitTypes)
+		{
+			//Do nothing special
+		}
+
+		public override string RequirementID
+		{
+			get
+			{
+				return N_PER_M_IN_PARENT_REQUIREMENT_ID;
+			}
+		}
+
+		protected override bool IsApplicable(IWarFoundryObject toObject, AddingContext context)
+		{
+			return GetCountFromContext(context) > 0 && IsApplicable(toObject);
+		}
+		
+		private bool IsApplicable(IWarFoundryObject toObject)
+		{
+			bool isApplicable = false;
+			UnitType unitType = GetUnitTypeFromObject(toObject);
+			
+			if (unitType != null)
+			{
+				isApplicable = this.AllowedObject.Equals(unitType) || IsApplicable(unitType);
+			}
+			
+			return isApplicable;
+		}
+		
+		private bool IsApplicable(UnitType unitType)
+		{
+			bool isApplicable = false;
+			foreach (UnitCountRequirementData requirement in ConstraintTypes)
+			{
+				if (requirement.UnitType.Equals(unitType))
+				{
+					isApplicable = true;
+					break;
+				}
+			}
+			return isApplicable;
+		}
+
+		protected override int GetObjectCountFromArmy(Army toArmy, UnitType obj)
+		{
+			return 0;
+		}
+
+		protected override int GetObjectCountFromObject(IWarFoundryObject wfObject)
+		{
+			return base.GetObjectCountFromObject(wfObject);
+		}
+
+		private int GetCountFromContext(AddingContext context)
+		{
+			AddingToParentContext parentContext = context as AddingToParentContext;
+
+			if (parentContext == null || !IsUnitTypeLimited(parentContext.ParentUnit.UnitType))
+			{
+				return 0;
+			}
+			else
+			{
+				return parentContext.ParentUnit.Size;
+			}
+		}
+
+		public override void AddUnitTypeRequirement(UnitType unitType)
+		{
+			this.ConstraintTypes.Add(new UnitCountRequirementData(unitType, 1, 1));
+		}
+
+		protected override string GetFailedRequirementsString(Army army)
+		{
+			return "";
+		}
+
+		protected override string GetFailedAddingRequirementsString(IWarFoundryObject toAdd, Army toArmy, AddingContext context)
+		{
+			UnitType unitType = GetUnitTypeFromObject(toAdd);
+			AddingToParentContext parentContext = context as AddingToParentContext;
+
+			if (unitType != null && parentContext != null)
+			{			
+				return GetFailedAddingRequirementsString(unitType, parentContext.ParentUnit, toArmy);
+			}
+			else
+			{
+				return "";
+			}
+		}
+
+		private string GetFailedAddingRequirementsString(UnitType unitType, Unit parentUnit, Army toArmy)
+		{
+			int allowedTypeCount = GetChildCountFromUnit(parentUnit);
+			
+			return String.Format("Army can only contain {0} × {1} as a sub-unit of each {2}, would have {3}", allowedTypeCount, unitType.Name, parentUnit.UnitType.Name, (allowedTypeCount + 1));
+		}
+
+		protected override string AllowsAddingFailedMessage
+		{
+			get
+			{
+				return "{0}";
+			}
+		}
+
+		protected override Validation CheckAllowsAdding(IWarFoundryObject wfObject, Army toArmy, AddingContext context)
+		{
+			AddingToParentContext parentContext = context as AddingToParentContext;
+			return parentContext == null ? Validation.Passed : CheckAllowsAdding(wfObject, toArmy, parentContext);
+		}
+
+		private Validation CheckAllowsAdding(IWarFoundryObject obj, Army toArmy, AddingToParentContext context)
+		{
+			Validation canAdd = Validation.Passed;
+			Unit parentUnit = context.ParentUnit;
+			//Get count and add one because we're checking if this unit can be added, so it hasn't been added yet
+			int allowedTypeCount = GetChildCountFromUnit(parentUnit) + 1; 
+			
+			foreach (UnitCountRequirementData limit in ConstraintTypes)
+			{
+				int limitedTypeCount = parentUnit.Size;
+
+				if (!IsValidByRequirement(limit, allowedTypeCount, limitedTypeCount))
+				{
+					canAdd = Validation.Failed;
+					break;
+				}
+			}
+
+			return canAdd;
+		}
+
+		private int GetChildCountFromUnit(Unit parentUnit)
+		{
+			int count = 0;
+
+			foreach (Unit unit in parentUnit.ContainedUnits)
+			{
+				if (unit.UnitType.Equals(AllowedObject))
+				{
+					count++;
+				}
+			}
+
+			return count;
+		}
+		
+		private bool IsValidByRequirement(UnitCountRequirementData limit, int allowedTypeCount, int limitedTypeCount)
+		{
+			//Round down limited units to get only whole amounts
+			double normalisedLimited = Math.Floor(limitedTypeCount / (limit.Count * 1.0));
+			double normalisedAllowed = allowedTypeCount / (limit.AllowsCount * 1.0);
+			return normalisedLimited >= 1 && normalisedAllowed <= normalisedLimited;
+		}
+
+		public override Validation ValidatesArmy(Army army)
+		{
+			throw new System.NotImplementedException();
+		}
+
+		protected override int GetObjectCountFromArmy(Army toArmy)
+		{
+			return 0;
+		}
+	}
+}
+
--- a/API/Objects/Requirement/UnitRequiresNUnitsForMUnitsRequirement.cs	Sun Jul 15 21:01:47 2012 +0100
+++ b/API/Objects/Requirement/UnitRequiresNUnitsForMUnitsRequirement.cs	Fri Jul 27 20:31:12 2012 +0100
@@ -21,17 +21,12 @@
 			//Do nothing
 		}
 
-		protected override bool IsApplicable(IWarFoundryObject toObject, Army toArmy, AddingContext context)
-		{
-			return IsApplicable(toObject, context) || IsApplicableForRequiredType(toObject, toArmy);
-		}
-
 		protected override bool IsApplicable(IWarFoundryObject toObject, AddingContext context)
 		{
 			return AllowedObject.Equals(toObject) || (toObject is Unit && AllowedObject.Equals(((Unit)toObject).UnitType));
 		}
 
-		private bool IsApplicableForRequiredType(IWarFoundryObject toObject, Army toArmy)
+		protected override bool IsApplicableToBoth(IWarFoundryObject toObject, Army toArmy, AddingContext context)
 		{
 			bool isApplicable = false;
 			UnitType addedType = toObject as UnitType;
--- a/API/Objects/Requirement/UnitRequiresNoMoreThanNOfUnitTypeRequirement.cs	Sun Jul 15 21:01:47 2012 +0100
+++ b/API/Objects/Requirement/UnitRequiresNoMoreThanNOfUnitTypeRequirement.cs	Fri Jul 27 20:31:12 2012 +0100
@@ -18,17 +18,12 @@
 			//Do nothing special
 		}
 
-		protected override bool IsApplicable(IWarFoundryObject toObject, Army toArmy, AddingContext context)
-		{
-			return base.IsApplicable(toObject, toArmy, context) || IsApplicableForRequiredType(toObject, toArmy);
-		}
-
 		protected override bool IsApplicable(IWarFoundryObject toObject, AddingContext context)
 		{
 			return AllowedObject.Equals(toObject) || (toObject is Unit && AllowedObject.Equals(((Unit)toObject).UnitType));
 		}
 
-		private bool IsApplicableForRequiredType(IWarFoundryObject toObject, Army toArmy)
+		protected override bool IsApplicableToBoth(IWarFoundryObject toObject, Army toArmy, AddingContext context)
 		{
 			bool isApplicable = false;
 			UnitType addedType = toObject as UnitType;
--- a/API/Objects/UnitType.cs	Sun Jul 15 21:01:47 2012 +0100
+++ b/API/Objects/UnitType.cs	Fri Jul 27 20:31:12 2012 +0100
@@ -19,7 +19,8 @@
 		private int min = 0;
 		private int max = WarFoundryCore.INFINITY;
 		private int baseSize = 0;
-		private int minSize, maxSize;
+		private int minSize = 1;
+		private int maxSize = WarFoundryCore.INFINITY;
 		private double baseUnitCost;
 		private double costPerTrooper;
 		private Stats stats;
--- a/IBBoard.WarFoundry.API.csproj	Sun Jul 15 21:01:47 2012 +0100
+++ b/IBBoard.WarFoundry.API.csproj	Fri Jul 27 20:31:12 2012 +0100
@@ -162,6 +162,8 @@
     <Compile Include="API\Loading\ILoadableObjectSource.cs" />
     <Compile Include="API\Loading\LoadableObjectSourceDirectory.cs" />
     <Compile Include="API\Loading\LoadableObjectSourceResourceSet.cs" />
+    <Compile Include="API\Objects\Requirement\Context\NullAddingContext.cs" />
+    <Compile Include="API\Objects\Requirement\UnitRequiresNParentModelsForMUnitsRequirement.cs" />
   </ItemGroup>
   <ItemGroup>
     <Reference Include="System.Xml" />