1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package net.sf.magicproject.event;
22
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.util.ArrayList;
26 import java.util.List;
27 import java.util.Map;
28
29 import net.sf.magicproject.clickable.ability.Ability;
30 import net.sf.magicproject.clickable.ability.AbstractAbility;
31 import net.sf.magicproject.clickable.ability.DetachmentAbility;
32 import net.sf.magicproject.clickable.ability.Priority;
33 import net.sf.magicproject.clickable.ability.ReplacementAbility;
34 import net.sf.magicproject.clickable.targetable.card.AbstractCard;
35 import net.sf.magicproject.clickable.targetable.card.MCard;
36 import net.sf.magicproject.clickable.targetable.player.Player;
37 import net.sf.magicproject.event.context.ContextEventListener;
38 import net.sf.magicproject.event.context.MContextCardCardIntInt;
39 import net.sf.magicproject.test.Test;
40 import net.sf.magicproject.test.TestFactory;
41
42 /***
43 * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
44 * @since 0.54
45 * @since 0.80 support replacement
46 */
47 public class MovedCard extends TriggeredEvent {
48
49 /***
50 * Create an instance of MEventListener by reading a file Offset's file must
51 * pointing on the first byte of this event <br>
52 * <ul>
53 * Structure of InputStream : Data[size]
54 * <li>idZone [1]</li>
55 * <li>test to apply on source [...]</li>
56 * <li>test to apply on destination [...]</li>
57 * </ul>
58 *
59 * @param inputFile
60 * is the file containing this event
61 * @param card
62 * is the card owning this event
63 * @throws IOException
64 * if error occurred during the reading process from the specified
65 * input stream
66 */
67 public MovedCard(InputStream inputFile, MCard card) throws IOException {
68 super(inputFile, card);
69 testDestination = TestFactory.readNextTest(inputFile);
70 }
71
72 /***
73 * Creates a new instance of CanICast specifying all attributes of this class.
74 * All parameters are copied, not cloned. So this new object shares the card
75 * and the specified codes
76 *
77 * @param idPlace
78 * the place constraint to activate this event
79 * @param testSource
80 * the test of this event, this one is applied on source
81 * @param testDestination
82 * test to apply on destination
83 * @param card
84 * is the card owning this card
85 */
86 public MovedCard(int idPlace, Test testSource, Test testDestination,
87 MCard card) {
88 super(idPlace, testSource, card);
89 this.testDestination = testDestination;
90 }
91
92 @Override
93 public MEventListener clone(MCard card) {
94 return new MovedCard(idZone, test, testDestination, card);
95 }
96
97 /***
98 * Tell if the current event matches with this event. If there is an
99 * additional code to check, it'would be checked if the main event matches
100 * with the main event
101 *
102 * @param movingCard
103 * the moving card
104 * @param ability
105 * is the ability owning this test. The card component of this
106 * ability should correspond to the card owning this test too.
107 * @return true if the current event match with this event
108 */
109 public boolean isMatching(Ability ability, MCard movingCard) {
110 return test(ability, movingCard);
111 }
112
113 @Override
114 public boolean reCheck(ContextEventListener previousContext, Ability ability) {
115 return super.reCheck(previousContext, ability)
116 && testDestination.test(ability,
117 ((MContextCardCardIntInt) previousContext).getCard());
118 }
119
120 /***
121 * Dispatch this event to all active event listeners able to understand this
122 * event. The listening events able to understand this event are <code>this
123 * </code>
124 * and other multiple event listeners. For each event listeners having
125 * responded they have been activated, the corresponding ability is added to
126 * the triggered buffer zone of player owning this ability
127 *
128 * @param movingCard
129 * the moving card
130 * @param idPlaceDest
131 * destination zone of this move
132 * @param newController
133 * the new controller.
134 * @param silentMode
135 * Is the silent mode is enabled for this move.
136 * @return true if this action cannot be played, or has been replaced by
137 * another one(s)
138 */
139 public static boolean tryAction(MCard movingCard, int idPlaceDest,
140 Player newController, boolean silentMode) {
141 if (silentMode) {
142 return true;
143 }
144 final Map<Priority, List<ReplacementAbility>> map = getReplacementAbilities(EVENT);
145 for (Priority priority : Priority.values()) {
146 List<AbstractCard> result = null;
147 final int previousPlace = movingCard.getIdZone();
148 final Player previousController = movingCard.controller;
149 movingCard.controller = newController;
150 for (ReplacementAbility ability : map.get(priority)) {
151
152 if (((MovedCard) ability.eventComing()).isMatching(ability, movingCard)
153 && ability.isMatching()) {
154
155
156
157
158 movingCard.setIdZone(idPlaceDest);
159 if (((MovedCard) ability.eventComing()).testDestination.test(ability,
160 movingCard)) {
161
162 if (result == null) {
163 result = new ArrayList<AbstractCard>();
164 }
165 result.add(ability.getTriggeredClone(new MContextCardCardIntInt(
166 movingCard, null, idPlaceDest, newController.idPlayer)));
167 }
168 movingCard.setIdZone(previousPlace);
169 }
170 }
171 if (result != null) {
172
173 movingCard.unregisterAbilities();
174 manageReplacement(movingCard, result, "moved card");
175 return false;
176 }
177 movingCard.controller = previousController;
178 }
179 return true;
180 }
181
182 /***
183 * Dispatch this event to all active event listeners able to understand this
184 * event. The listening events able to understand this event are <code>this
185 * </code>
186 * and other multiple event listeners. For each event listeners having
187 * responded they have been activated, the corresponding ability is added to
188 * the triggered buffer zone of player owning this ability
189 *
190 * @param movingCard
191 * the moving card
192 * @param idPlaceDest
193 * destination zone of this move
194 * @param newController
195 * the new controller.
196 * @param silentMode
197 * Is the silent mode is enabled for this move.
198 */
199 public static void dispatchEvent(MCard movingCard, int idPlaceDest,
200 Player newController, boolean silentMode) {
201 for (Ability ability : TRIGGRED_ABILITIES.get(EVENT)) {
202 if ((!silentMode || (ability instanceof AbstractAbility && !(ability instanceof DetachmentAbility)))
203 && ((MovedCard) ability.eventComing())
204 .isMatching(ability, movingCard) && ability.isMatching()) {
205 ability.triggerIt(new MContextCardCardIntInt(movingCard, null,
206 idPlaceDest, newController.idPlayer, movingCard.getTimestamp() + 1,
207 -1));
208 }
209 }
210 }
211
212 @Override
213 public final Event getIdEvent() {
214 return EVENT;
215 }
216
217 @Override
218 public boolean equals(Object other) {
219 return other instanceof MovedCard && ((MovedCard) other).test == test
220 && ((MovedCard) other).testDestination == testDestination;
221 }
222
223 /***
224 * The event type.
225 */
226 public static final Event EVENT = Event.MOVING_CARD;
227
228 /***
229 * test of card destination
230 */
231 private final Test testDestination;
232
233 }