view API/Objects/Requirement/RequiresNUnitsForMUnitsRequirement.cs @ 437:0922851f6125

Re #350: Add requirement to allow N of unit for specific other units * Extend unit count requirement data to handle fixed numbers of units allowed per unit required * Add initial stub of requirement using some copy-and-paste, but starting to avoid ticket:379
author IBBoard <dev@ibboard.co.uk>
date Tue, 29 Nov 2011 20:55:21 +0000
parents
children 410f3d85c9c5
line wrap: on
line source

// This file(RequiresNUnitsForMUnitsRequirement.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2011 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 System.Collections.Generic;

namespace IBBoard.WarFoundry.API.Objects.Requirement
{
	public class RequiresNUnitsForMUnitsRequirement : AbstractRequirement
	{
		public static readonly string REQUIREMENT_ID = "RequiresNUnitsForMUnits";
		private List<UnitCountRequirementData> requiredTypes;
		private UnitType allowedType;

		public RequiresNUnitsForMUnitsRequirement(UnitType allowedType, params UnitType[] requiredUnitTypes)
		{
			this.allowedType = allowedType;
			FailureStringPrefix = "Army must contain: ";
			requiredTypes = new List<UnitCountRequirementData>();

			foreach (UnitType unitType in requiredUnitTypes)
			{
				AddUnitTypeRequirement(unitType);
			}
		}

		public override int GetHashCode()
		{
			int hash = 0;

			foreach (UnitCountRequirementData req in requiredTypes)
			{
				hash += req.UnitType.GetHashCode();
			}

			return hash;
		}

		protected override bool TypeEquals(object obj)
		{
			RequiresNUnitsForMUnitsRequirement otherReq = (RequiresNUnitsForMUnitsRequirement)obj;
			if (!Collections.Collections.AreEqual(requiredTypes, otherReq.requiredTypes))
			{
				return false;
			}
			else
			{
				return true;
			}
		}

		protected string FailureStringPrefix { get; set; }

		protected override string GetValidationFailedMessage(Army army)
		{
			return "";
		}

		protected override string GetAllowsAddingFailedMessage(UnitType toAdd, Army toArmy)
		{
			return "";
		}

		public override Validation AllowsAdding(WarFoundryObject wfObject, Army toArmy)
		{
			Validation canAdd = Validation.NotApplicable;
			UnitType addedUnitType = (wfObject is Unit) ? ((Unit)wfObject).UnitType : wfObject as UnitType;
			bool typeFound = (addedUnitType == allowedType);
			int allowedTypeCount = GetUnitTypeCount(toArmy, allowedType, wfObject);

			foreach (UnitCountRequirementData limit in requiredTypes)
			{
				typeFound |= (addedUnitType == limit.UnitType);
				int limitedTypeCount = GetUnitTypeCount(toArmy, limit.UnitType, wfObject);
				double limitedTypeMultiplier = limitedTypeCount / (limit.Count * 1.0);
				double allowedTypeMultiplier = allowedTypeCount / (limit.AllowsCount * 1.0);

				if (allowedTypeMultiplier > limitedTypeMultiplier)
				{
					canAdd = Validation.Failed;
					break;
				}
			}

			if (typeFound && canAdd == Validation.NotApplicable)
			{
				canAdd = Validation.Passed;
			}

			return canAdd;
		}

		private int GetUnitTypeCount(Army toArmy, UnitType unitType, WarFoundryObject wfObject)
		{
			return toArmy.GetUnitTypeCount(unitType) + GetCountFromObject(wfObject, unitType);
		}

		private int GetCountFromObject(WarFoundryObject wfObject, UnitType limitedType)
		{
			return (limitedType.Equals(wfObject) || (wfObject is Unit && ((Unit)wfObject).UnitType.Equals(limitedType))) ? 1 : 0;
		}

		public override Validation ValidatesArmy(Army army)
		{
			return Validation.NotApplicable;
		}

		public override string RequirementID
		{
			get
			{
				return REQUIREMENT_ID;
			}
		}

		/// <summary>
		/// Adds a requirement for there to be at least minCount of a given UnitType, allowing allowedCount of this UnitType
		/// </summary>
		/// <param name='unitType'>
		/// The unit type to require.
		/// </param>
		/// <param name='minCount'>
		/// The minimum number of that type that must exist.
		/// </param>
		public void AddUnitTypeRequirement(UnitType unitType, int minCount, int allowedCount)
		{
			requiredTypes.Add(new UnitCountRequirementData(unitType, minCount, allowedCount));
		}

		/// <summary>
		/// Adds a requirement for there to be one or more of a given UnitType, allowing one of this UnitType
		/// </summary>
		/// <param name='unitType'>
		/// The unit type to require.
		/// </param>
		public void AddUnitTypeRequirement(UnitType unitType)
		{
			AddUnitTypeRequirement(unitType, 1, 1);
		}
	}
}