1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package net.sf.magicproject.expression;
24
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.util.List;
28
29 import net.sf.magicproject.action.ModifyRegister;
30 import net.sf.magicproject.clickable.ability.Ability;
31 import net.sf.magicproject.clickable.targetable.Targetable;
32 import net.sf.magicproject.clickable.targetable.card.MCard;
33 import net.sf.magicproject.event.MEventListener;
34 import net.sf.magicproject.event.MovedCard;
35 import net.sf.magicproject.event.context.ContextEventListener;
36 import net.sf.magicproject.stack.StackManager;
37 import net.sf.magicproject.test.And;
38 import net.sf.magicproject.test.InZone;
39 import net.sf.magicproject.test.Test;
40 import net.sf.magicproject.test.TestFactory;
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.MToolKit;
45
46 /***
47 * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
48 * @since 0.82 restriction zone supported to optimize the target processing.
49 * @since 0.83 count-player option apply test on the players.
50 * @since 0.85 objects may be counted
51 */
52 public class Counter extends Expression {
53
54 /***
55 * The byte indicating the player are parsed during the counter process or
56 * not.
57 */
58 public static final int COUNT_PLAYER = 0x80;
59
60 /***
61 * Creates a new instance of Counter <br>
62 * <ul>
63 * Structure of InputStream : Data[size]
64 * <li>object's name + '\0' [...]
65 * <li>test used to fill counter [...]
66 * <li>idTestOn [1] (only if object's name specified)
67 * <li>restriction zone + enable count player [1] (only if object's name not
68 * specified)
69 * </ul>
70 *
71 * @param inputFile
72 * file containing this action
73 * @throws IOException
74 * if error occurred during the reading process from the specified
75 * input stream
76 */
77 public Counter(InputStream inputFile) throws IOException {
78 super();
79 objectName = MToolKit.readString(inputFile);
80 test = TestFactory.readNextTest(inputFile);
81 if (objectName.length() == 0) {
82
83 objectName = null;
84 restrictionZone = inputFile.read();
85 countPlayer = (restrictionZone & COUNT_PLAYER) == COUNT_PLAYER;
86 restrictionZone = (restrictionZone & ~COUNT_PLAYER) - 1;
87 } else {
88
89 objectName = objectName.intern();
90 on = TestOn.deserialize(inputFile);
91 }
92 }
93
94 @Override
95 public int getValue(Ability ability, Targetable tested,
96 ContextEventListener context) {
97 if (objectName != null) {
98
99 return on.getCard(ability, tested).getNbObjects(objectName, test);
100 }
101
102
103 Targetable previousTested = superTested;
104 superTested = tested;
105 int res = ModifyRegister.countAllCardsOf(test, ability, restrictionZone);
106 if (countPlayer) {
107
108 if (test.test(ability, StackManager.PLAYERS[0])) {
109 res++;
110 }
111 if (test.test(ability, StackManager.PLAYERS[1])) {
112 res++;
113 }
114 }
115
116
117 superTested = previousTested;
118 return res;
119 }
120
121 @Override
122 public void extractTriggeredEvents(List<MEventListener> res, MCard source,
123 Test globalTest) {
124 if (test != null) {
125 test.extractTriggeredEvents(res, source, globalTest);
126 if (restrictionZone != -1) {
127 res.add(new MovedCard(IdZones.PLAY, new InZone(restrictionZone,
128 TestOn.TESTED), globalTest, source));
129 res.add(new MovedCard(IdZones.PLAY, True.getInstance(), And.append(
130 new InZone(restrictionZone, TestOn.TESTED), globalTest), source));
131 }
132 }
133 }
134
135 /***
136 * The test to use for counters
137 */
138 private Test test;
139
140 /***
141 * The upper tested card. Since the tested card is overwritten by this
142 * counter, the tested card is saved before.
143 */
144 public static Targetable superTested = null;
145
146 /***
147 * The zone identifant where the scan is restricted. If is equal to -1, there
148 * would be no restriction zone.
149 *
150 * @see net.sf.magicproject.token.IdZones
151 */
152 private int restrictionZone;
153
154 /***
155 * Is this counter will counter players.
156 */
157 private boolean countPlayer;
158
159 /***
160 * Objet's name to count. Null if objects are not counted.
161 */
162 private String objectName;
163
164 /***
165 * Represents the component where the objects would be counted. Is null if
166 * objects are not counted.
167 */
168 private TestOn on;
169
170 }