comparison API/Objects/Requirement/UnitRequiresNParentModelsForMUnitsRequirement.cs @ 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
children c082a312a741
comparison
equal deleted inserted replaced
486:6e5b39caeb4e 487:248df19652f9
1 // This file (UnitRequiresNoMoreThanNUnitsPerMModelsInParentUnitRequirement.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2012 IBBoard
2 //
3 // 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.
4 using System;
5 using IBBoard.WarFoundry.API.Objects.Requirement.Context;
6
7 namespace IBBoard.WarFoundry.API.Objects.Requirement
8 {
9 public class UnitRequiresNParentModelsForMUnitsRequirement : AbstractUnitRequirement<UnitType>
10 {
11 public static readonly string N_PER_M_IN_PARENT_REQUIREMENT_ID = "RequiresNoMoreThanNUnitsPerMModelsInParent";
12
13 public UnitRequiresNParentModelsForMUnitsRequirement(UnitType allowedObject, params UnitType[] limitedUnitTypes) : base(allowedObject, limitedUnitTypes)
14 {
15 //Do nothing special
16 }
17
18 public override string RequirementID
19 {
20 get
21 {
22 return N_PER_M_IN_PARENT_REQUIREMENT_ID;
23 }
24 }
25
26 protected override bool IsApplicable(IWarFoundryObject toObject, AddingContext context)
27 {
28 return GetCountFromContext(context) > 0 && IsApplicable(toObject);
29 }
30
31 private bool IsApplicable(IWarFoundryObject toObject)
32 {
33 bool isApplicable = false;
34 UnitType unitType = GetUnitTypeFromObject(toObject);
35
36 if (unitType != null)
37 {
38 isApplicable = this.AllowedObject.Equals(unitType) || IsApplicable(unitType);
39 }
40
41 return isApplicable;
42 }
43
44 private bool IsApplicable(UnitType unitType)
45 {
46 bool isApplicable = false;
47 foreach (UnitCountRequirementData requirement in ConstraintTypes)
48 {
49 if (requirement.UnitType.Equals(unitType))
50 {
51 isApplicable = true;
52 break;
53 }
54 }
55 return isApplicable;
56 }
57
58 protected override int GetObjectCountFromArmy(Army toArmy, UnitType obj)
59 {
60 return 0;
61 }
62
63 protected override int GetObjectCountFromObject(IWarFoundryObject wfObject)
64 {
65 return base.GetObjectCountFromObject(wfObject);
66 }
67
68 private int GetCountFromContext(AddingContext context)
69 {
70 AddingToParentContext parentContext = context as AddingToParentContext;
71
72 if (parentContext == null || !IsUnitTypeLimited(parentContext.ParentUnit.UnitType))
73 {
74 return 0;
75 }
76 else
77 {
78 return parentContext.ParentUnit.Size;
79 }
80 }
81
82 public override void AddUnitTypeRequirement(UnitType unitType)
83 {
84 this.ConstraintTypes.Add(new UnitCountRequirementData(unitType, 1, 1));
85 }
86
87 protected override string GetFailedRequirementsString(Army army)
88 {
89 return "";
90 }
91
92 protected override string GetFailedAddingRequirementsString(IWarFoundryObject toAdd, Army toArmy, AddingContext context)
93 {
94 UnitType unitType = GetUnitTypeFromObject(toAdd);
95 AddingToParentContext parentContext = context as AddingToParentContext;
96
97 if (unitType != null && parentContext != null)
98 {
99 return GetFailedAddingRequirementsString(unitType, parentContext.ParentUnit, toArmy);
100 }
101 else
102 {
103 return "";
104 }
105 }
106
107 private string GetFailedAddingRequirementsString(UnitType unitType, Unit parentUnit, Army toArmy)
108 {
109 int allowedTypeCount = GetChildCountFromUnit(parentUnit);
110
111 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));
112 }
113
114 protected override string AllowsAddingFailedMessage
115 {
116 get
117 {
118 return "{0}";
119 }
120 }
121
122 protected override Validation CheckAllowsAdding(IWarFoundryObject wfObject, Army toArmy, AddingContext context)
123 {
124 AddingToParentContext parentContext = context as AddingToParentContext;
125 return parentContext == null ? Validation.Passed : CheckAllowsAdding(wfObject, toArmy, parentContext);
126 }
127
128 private Validation CheckAllowsAdding(IWarFoundryObject obj, Army toArmy, AddingToParentContext context)
129 {
130 Validation canAdd = Validation.Passed;
131 Unit parentUnit = context.ParentUnit;
132 //Get count and add one because we're checking if this unit can be added, so it hasn't been added yet
133 int allowedTypeCount = GetChildCountFromUnit(parentUnit) + 1;
134
135 foreach (UnitCountRequirementData limit in ConstraintTypes)
136 {
137 int limitedTypeCount = parentUnit.Size;
138
139 if (!IsValidByRequirement(limit, allowedTypeCount, limitedTypeCount))
140 {
141 canAdd = Validation.Failed;
142 break;
143 }
144 }
145
146 return canAdd;
147 }
148
149 private int GetChildCountFromUnit(Unit parentUnit)
150 {
151 int count = 0;
152
153 foreach (Unit unit in parentUnit.ContainedUnits)
154 {
155 if (unit.UnitType.Equals(AllowedObject))
156 {
157 count++;
158 }
159 }
160
161 return count;
162 }
163
164 private bool IsValidByRequirement(UnitCountRequirementData limit, int allowedTypeCount, int limitedTypeCount)
165 {
166 //Round down limited units to get only whole amounts
167 double normalisedLimited = Math.Floor(limitedTypeCount / (limit.Count * 1.0));
168 double normalisedAllowed = allowedTypeCount / (limit.AllowsCount * 1.0);
169 return normalisedLimited >= 1 && normalisedAllowed <= normalisedLimited;
170 }
171
172 public override Validation ValidatesArmy(Army army)
173 {
174 throw new System.NotImplementedException();
175 }
176
177 protected override int GetObjectCountFromArmy(Army toArmy)
178 {
179 return 0;
180 }
181 }
182 }
183