View Javadoc

1   /* 
2    *   Magic-Project is a turn based strategy simulator
3    *   Copyright (C) 2003-2007 Fabrice Daugan
4    *
5    *   This program is free software; you can redistribute it and/or modify it 
6    * under the terms of the GNU General Public License as published by the Free 
7    * Software Foundation; either version 2 of the License, or (at your option) any
8    * later version.
9    *
10   *   This program is distributed in the hope that it will be useful, but WITHOUT 
11   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12   * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
13   * details.
14   *
15   *   You should have received a copy of the GNU General Public License along  
16   * with this program; if not, write to the Free Software Foundation, Inc., 
17   * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   * 
19   */
20  package net.sf.magicproject.action;
21  
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.util.HashMap;
25  
26  import net.sf.magicproject.action.context.ActionContextWrapper;
27  import net.sf.magicproject.action.context.Int;
28  import net.sf.magicproject.action.handler.ChoosenAction;
29  import net.sf.magicproject.action.handler.InitAction;
30  import net.sf.magicproject.action.handler.RollBackAction;
31  import net.sf.magicproject.clickable.ability.Ability;
32  import net.sf.magicproject.clickable.targetable.Targetable;
33  import net.sf.magicproject.clickable.targetable.card.MCard;
34  import net.sf.magicproject.clickable.targetable.player.Player;
35  import net.sf.magicproject.event.ModifiedRegister;
36  import net.sf.magicproject.event.context.ContextEventListener;
37  import net.sf.magicproject.expression.Expression;
38  import net.sf.magicproject.expression.IntValue;
39  import net.sf.magicproject.operation.Any;
40  import net.sf.magicproject.operation.Operation;
41  import net.sf.magicproject.stack.StackManager;
42  import net.sf.magicproject.test.Test;
43  import net.sf.magicproject.test.TestOn;
44  import net.sf.magicproject.token.IdConst;
45  import net.sf.magicproject.token.IdTokens;
46  
47  /***
48   * This action is used to modifiy a register of a player or a card. <br>
49   * This action can use the target list when is played : the address
50   * (idToken=register name + register index) must be IdTokens#TARGET. So the
51   * target list must set before this action would be played.
52   * 
53   * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
54   * @since 0.71
55   * @since 0.85 useless operation are ignored and not genrated.
56   */
57  public class ModifyTargetableRegister extends ModifyRegister implements
58  		ChoosenAction, InitAction, RollBackAction {
59  
60  	/***
61  	 * Create an instance of ModifyRegister by reading a file Offset's file must
62  	 * pointing on the first byte of this action <br>
63  	 * <ul>
64  	 * Structure of InputStream : Data[size]
65  	 * <li>[super]</li>
66  	 * </ul>
67  	 * 
68  	 * @param inputFile
69  	 *          file containing this action
70  	 * @throws IOException
71  	 *           if error occured during the reading process from the specified
72  	 *           input stream
73  	 */
74  	ModifyTargetableRegister(InputStream inputFile) throws IOException {
75  		super(inputFile);
76  		register = TestOn.deserialize(inputFile);
77  	}
78  	
79  	@Override
80  	public final Actiontype getIdAction() {
81  		return Actiontype.MODIFY_TARGETABLE_REGISTER;
82  	}
83  
84  	public boolean init(ActionContextWrapper actionContext,
85  			ContextEventListener context, Ability ability) {
86  		actionContext.actionContext = new Int(getValue(ability, null, context));
87  		return true;
88  	}
89  
90  	public boolean choose(ActionContextWrapper actionContext,
91  			ContextEventListener context, Ability ability) {
92  		return true;
93  	}
94  
95  	public void disactivate(ActionContextWrapper actionContext,
96  			ContextEventListener context, Ability ability) {
97  		// Nothing to do
98  	}
99  
100 	public boolean replay(ActionContextWrapper actionContext,
101 			ContextEventListener context, Ability ability) {
102 		return modifyRegister(StackManager.getRealSource(ability.getCard()),
103 				register.getTargetable(ability, null), index.getValue(
104 						ability, null, context), ((Int) actionContext.actionContext)
105 						.getInt(), op);
106 	}
107 
108 	public void rollback(ActionContextWrapper actionContext,
109 			ContextEventListener context, Ability ability) {
110 		// TODO ModyRegister rollback --> not yet implemented
111 	}
112 
113 	public String toHtmlString(Ability ability, ContextEventListener context,
114 			ActionContextWrapper actionContext) {
115 		return toHtmlString(ability, context);
116 	}
117 
118 	@Override
119 	public boolean play(ContextEventListener context, Ability ability) {
120 		return modifyRegister(StackManager.getRealSource(ability.getCard()),
121 				register.getTargetable(ability, null), index.getValue(
122 						ability, null, context), getValue(ability, null, context), op);
123 	}
124 
125 	/***
126 	 * Generate event associated to this action. Only one or several events are
127 	 * generated and may be collected by event listeners. Then play this action
128 	 * 
129 	 * @param source
130 	 *          the source, and the concerned card to this modification
131 	 * @param targetable
132 	 *          the component to modify
133 	 * @param index
134 	 *          the register's index
135 	 * @param value
136 	 *          right value of operation
137 	 * @param op
138 	 *          identifiant of the operation applied to the specified card
139 	 *          @return true
140 	 */
141 	public static boolean modifyRegister(MCard source, Targetable targetable,
142 			int index, int value, Operation op) {
143 		if (targetable.isPlayer())
144 			return modifyRegister(source, (Player) targetable, index, op, value);
145 		return modifyRegister(source, (MCard) targetable, index, op, value);
146 	}
147 
148 	private static boolean modifyRegister(MCard source, Player player, int index,
149 			Operation op, int rightValue) {
150 		if (index == IdTokens.MANA_POOL) {
151 			// no care about operation, we empty the mana pool
152 			player.mana.setToZero();
153 			return true;
154 		}
155 
156 		// Generate event only if necessary
157 		if (!op.isUselessWith(index, rightValue)) {
158 			if (!ModifiedRegister.tryAction(player, source, IdTokens.PLAYER, index,
159 					op, rightValue)) {
160 				// this action has been replaced
161 				return false;
162 			}
163 			// we continue : dispatch event, and process to the register modification
164 			player.setValue(index, op, rightValue);
165 			ModifiedRegister.dispatchEvent(player, source, IdTokens.PLAYER, index,
166 					op, rightValue);
167 		}
168 		return true;
169 	}
170 
171 	private static boolean modifyRegister(MCard source, MCard card, int index,
172 			Operation op, int rightValue) {
173 		// Generate event only if necessary
174 		if (op.isUselessWith(card.getValue(index), rightValue)) {
175 			return true;
176 		}
177 		boolean replaced = false;
178 		if (index < IdTokens.FIRST_FREE_CARD_INDEX) {
179 			// notify this modification to the replacement abilities
180 			replaced = !ModifiedRegister.tryAction(card, source, IdTokens.CARD,
181 					index, op, rightValue);
182 		}
183 
184 		if (!replaced) {
185 			// also, we notify the modification of this register
186 			card.setValue(index, op, rightValue);
187 			if (index < IdTokens.FIRST_FREE_CARD_INDEX) {
188 				ModifiedRegister.dispatchEvent(card, source, IdTokens.CARD, index, op,
189 						rightValue);
190 			}
191 			return true;
192 		}
193 		return false;
194 	}
195 
196 	@Override
197 	public Test parseTest(Test test) {
198 		final HashMap<String, Expression> values = new HashMap<String, Expression>();
199 		values.put("%value", valueExpr);
200 		return test.getConstraintTest(values);
201 	}
202 
203 	@Override
204 	public boolean equal(MAction constraintAction) {
205 		if (!(constraintAction instanceof ModifyTargetableRegister)) {
206 			return false;
207 		}
208 		final ModifyTargetableRegister other = (ModifyTargetableRegister) constraintAction;
209 		return (other.op == op || other.op == Any.getInstance())
210 				&& register == other.register
211 				&& index instanceof IntValue
212 				&& ((IntValue) index).value == ((IntValue) index).value
213 				&& valueExpr instanceof IntValue
214 				&& (((IntValue) valueExpr).value == IdConst.ALL || ((IntValue) valueExpr).value == ((IntValue) other.valueExpr).value);
215 	}
216 
217 	@Override
218 	public String toString(Ability ability) {
219 		final int index = this.index.getValue(ability, null, null);
220 		String value = null;
221 		try {
222 			value = "" + valueExpr.getValue(ability, null, null);
223 		} catch (Exception e) {
224 			value = "?";
225 		}
226 		return op.getClass().getSimpleName() + " (L=" + index + ",R=" + value + ")";
227 	}
228 
229 	/***
230 	 * represents the token to modify
231 	 */
232 	protected final TestOn register;
233 }