1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package net.sf.magicproject.modifier;
23
24 import java.awt.Graphics;
25 import java.util.ArrayList;
26 import java.util.List;
27
28 import net.sf.magicproject.action.RefreshModifier;
29 import net.sf.magicproject.clickable.ability.Ability;
30 import net.sf.magicproject.clickable.ability.RefreshAbility;
31 import net.sf.magicproject.clickable.ability.RemoveModifier;
32 import net.sf.magicproject.clickable.targetable.card.MCard;
33 import net.sf.magicproject.clickable.targetable.card.SystemCard;
34 import net.sf.magicproject.event.MEventListener;
35 import net.sf.magicproject.event.MovedCard;
36 import net.sf.magicproject.event.TriggeredEvent;
37 import net.sf.magicproject.test.And;
38 import net.sf.magicproject.test.InZone;
39 import net.sf.magicproject.test.IsTested;
40 import net.sf.magicproject.test.Test;
41 import net.sf.magicproject.test.True;
42 import net.sf.magicproject.test.TestOn;
43 import net.sf.magicproject.token.IdZones;
44 import net.sf.magicproject.tools.Log;
45
46 /***
47 * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
48 */
49 public abstract class Modifier implements Unregisterable, ObjectModifier {
50
51 /***
52 * Creates a new instance of Modifier <br>
53 *
54 * @param name
55 * The modifier name.
56 * @param to
57 * Targetable attached to.
58 * @param creatorAbility
59 * is the ability owning this test. The card component of this
60 * ability should correspond to the card owning this test too.
61 * @param whileCondition
62 * When this test is true, this modifier is activated. Otherwise this
63 * modifier does nothing.
64 * @param linkedEvents
65 * the linked events used to build dynamically the corresponding
66 * abilities.
67 * @param until
68 * the until events stopping this modifier.
69 * @param linked
70 * is this modifier is linked to the creator.
71 * @param layer
72 * the layer of this modifier.
73 */
74 protected Modifier(String name, MCard to, Ability creatorAbility,
75 Test whileCondition, List<MEventListener> linkedEvents,
76 List<MEventListener> until, boolean linked, int layer) {
77 this.name = name;
78 this.to = to;
79 this.layer = layer;
80 abilities = new ArrayList<Ability>();
81 this.ability = creatorAbility;
82 final MCard creator = creatorAbility.getCard();
83
84
85
86
87
88
89 if (linkedEvents != null) {
90 final RefreshModifier refreshAction = new RefreshModifier(this);
91 for (MEventListener event : linkedEvents) {
92 final Ability refreshAbility = new RefreshAbility(
93 (TriggeredEvent) event.clone(to), refreshAction,
94 creator == null ? to : creator);
95 refreshAbility.registerToManager();
96 abilities.add(refreshAbility);
97 }
98 }
99
100
101 if (linked && creator != null && creator != SystemCard.instance) {
102
103 final Ability linkAbility = new RemoveModifier(new MovedCard(
104 IdZones.PLAY, And.append(IsTested.TESTED_IS_ME, new InZone(
105 IdZones.PLAY, TestOn.THIS)), True.getInstance(), creator),
106 this);
107 linkAbility.registerToManager();
108 abilities.add(linkAbility);
109 }
110
111
112 for (MEventListener event : until) {
113 final Ability untilAbility = new RemoveModifier((TriggeredEvent) event
114 .clone(to), this);
115 untilAbility.registerToManager();
116 abilities.add(untilAbility);
117 }
118
119 this.whileCondition = whileCondition;
120 }
121
122 public int paintObject(Graphics g, int startX, int startY) {
123 if (next != null) {
124 return next.paintObject(g, startX, startY);
125 }
126 return startX;
127 }
128
129 /***
130 * Add a modifier to the end of the modifier chain. The current modifier stays
131 * the first modifier of this chain.
132 *
133 * @param modifier
134 * the property modifier to add.
135 * @return the new chain.
136 */
137 public final Modifier addModifier(Modifier modifier) {
138 assert modifier.next != null;
139 if (modifier.next != null) {
140 throw new InternalError("'next' modifier should not be specified");
141 }
142
143
144 if (modifier.layer < layer) {
145
146 modifier.next = this;
147 return modifier;
148 }
149
150
151 if (this.next == null) {
152
153 this.next = modifier;
154 return this;
155 }
156
157
158 this.next = next.addModifier(modifier);
159 return this;
160 }
161
162 /***
163 * remove from the manager a modifier
164 *
165 * @param modifier
166 * the modifier to remove
167 * @return the new chain
168 */
169 protected Modifier removeModifier(Modifier modifier) {
170 if (next != null) {
171 next = next.removeModifier(modifier);
172 } else {
173 Log.warn("Cannot remove the modifier " + modifier.getClass() + ", name="
174 + modifier.name);
175 }
176 return this;
177 }
178
179 /***
180 * Refresh this modifier following the whileCondition.
181 */
182 public abstract void refresh();
183
184 public int getNbObjects(String objectName, Test objectTest) {
185 if (next == null) {
186 return 0;
187 }
188 return next.getNbObjects(objectName, objectTest);
189 }
190
191 public Modifier removeObject(String objectName, Test objectTest) {
192
193 if (next != null) {
194 next = next.removeObject(objectName, objectTest);
195 }
196 return this;
197 }
198
199 public void removeFromManager() {
200 if (unregisteringModifier) {
201
202 return;
203 }
204 unregisteringModifier = true;
205 for (int i = abilities.size(); i-- > 0;) {
206 abilities.get(i).removeFromManager();
207 }
208 unregisteringModifier = false;
209 }
210
211 /***
212 * Tag indicating we are currently unregistering this modifier
213 */
214 protected boolean unregisteringModifier;
215
216 /***
217 * Tag indicating this modifier is completely unregistered and can be released
218 */
219 protected boolean unregisteredModifier;
220
221 @Override
222 public String toString() {
223 return name;
224 }
225
226 public MCard getCard() {
227 return ability.getCard();
228 }
229
230 /***
231 * The next modifier
232 */
233 public Modifier next;
234
235 /***
236 * The modifier name
237 */
238 protected final String name;
239
240 /***
241 * When this test is true, this modifier is activated. Otherwise this modifier
242 * does nothing.
243 */
244 protected final Test whileCondition;
245
246 /***
247 * Is this modifier is activated
248 */
249 protected boolean activated;
250
251 /***
252 * Targetable attached to.
253 */
254 protected final MCard to;
255
256 /***
257 * The ability having created this modifier.
258 */
259 protected Ability ability;
260
261 /***
262 * Abilities linked to this modifier
263 */
264 protected final List<Ability> abilities;
265
266 /***
267 * is the strategy used to add this modifier within the existing chain.
268 */
269 public int layer;
270 }