View Javadoc

1   /*
2    * Created on Nov 8, 2004 
3    * Original filename was Counter.java
4    * 
5    *   Magic-Project is a turn based strategy simulator
6    *   Copyright (C) 2003-2007 Fabrice Daugan
7    *
8    *   This program is free software; you can redistribute it and/or modify it 
9    * under the terms of the GNU General Public License as published by the Free 
10   * Software Foundation; either version 2 of the License, or (at your option) any
11   * later version.
12   *
13   *   This program is distributed in the hope that it will be useful, but WITHOUT 
14   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15   * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
16   * details.
17   *
18   *   You should have received a copy of the GNU General Public License along  
19   * with this program; if not, write to the Free Software Foundation, Inc., 
20   * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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  			// object counter will be disabled
83  			objectName = null;
84  			restrictionZone = inputFile.read();
85  			countPlayer = (restrictionZone & COUNT_PLAYER) == COUNT_PLAYER;
86  			restrictionZone = (restrictionZone & ~COUNT_PLAYER) - 1;
87  		} else {
88  			// only objects will be counted on the specified card
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  			// we count objects on the given component. The test is applied on creator
99  			return on.getCard(ability, tested).getNbObjects(objectName, test);
100 		}
101 
102 		// we count cards, we save the upper counter test.
103 		Targetable previousTested = superTested;
104 		superTested = tested;
105 		int res = ModifyRegister.countAllCardsOf(test, ability, restrictionZone);
106 		if (countPlayer) {
107 			// we count players
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 		// restore the previous upper counter test.
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 }