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  package net.sf.magicproject.action;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  
24  import net.sf.magicproject.action.context.ActionContextWrapper;
25  import net.sf.magicproject.action.context.MovePlayerCardContext;
26  import net.sf.magicproject.action.handler.FollowAction;
27  import net.sf.magicproject.clickable.ability.Ability;
28  import net.sf.magicproject.clickable.targetable.Targetable;
29  import net.sf.magicproject.clickable.targetable.card.MCard;
30  import net.sf.magicproject.clickable.targetable.player.Player;
31  import net.sf.magicproject.event.UncaughtException;
32  import net.sf.magicproject.event.context.ContextEventListener;
33  import net.sf.magicproject.stack.StackManager;
34  import net.sf.magicproject.test.TestOn;
35  import net.sf.magicproject.token.IdPositions;
36  import net.sf.magicproject.token.IdZones;
37  import net.sf.magicproject.tools.Log;
38  import net.sf.magicproject.tools.MToolKit;
39  import net.sf.magicproject.zone.MZone;
40  import net.sf.magicproject.zone.ZoneManager;
41  
42  /***
43   * To move any number of cards or the targeted player from their place to
44   * another. New position within the new zone, and the new controller have to be
45   * specified. <br>
46   * 
47   * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
48   * @since 0.54
49   */
50  class MovePlayerCard extends UserAction implements LoopAction, FollowAction {
51  
52  	/***
53  	 * Create an instance of MovePlayerCard by reading a file Offset's file must
54  	 * pointing on the first byte of this action <br>
55  	 * <ul>
56  	 * Structure of InputStream : Data[size]
57  	 * <li>new controller [TestOn]</li>
58  	 * <li>from zone [IdZone]</li>
59  	 * <li>destination zone [IdZone]</li>
60  	 * <li>idPosition [int16]</li>
61  	 * </ul>
62  	 * 
63  	 * @param inputFile
64  	 *          file containing this action
65  	 * @throws IOException
66  	 *           if error occurred during the reading process from the specified
67  	 *           input stream
68  	 */
69  	MovePlayerCard(InputStream inputFile) throws IOException {
70  		super(inputFile);
71  		controller = TestOn.deserialize(inputFile);
72  		from = inputFile.read();
73  		to = inputFile.read();
74  		idPosition = MToolKit.readInt16(inputFile);
75  	}
76  
77  	@Override
78  	public final Actiontype getIdAction() {
79  		return Actiontype.MOVE_PLAYER_CARD;
80  	}
81  
82  	public boolean continueLoop(ContextEventListener context, int loopingIndex,
83  			Ability ability) {
84  		final Targetable targetable = StackManager.getInstance().getTargetedList()
85  				.get(loopingIndex);
86  		if (!targetable.isPlayer()) {
87  			Log.fatal("The move-player-card action use "
88  					+ "the players placed in the target-list, "
89  					+ "nevertheless a non-player element has been found (" + targetable
90  					+ ") : \n" + debugData);
91  		}
92  		final MZone panel = ((Player) targetable).zoneManager.getContainer(from);
93  		if (panel.getComponentCount() == 0) {
94  			UncaughtException.dispatchEvent((Player) StackManager.getInstance()
95  					.getTargetedList().get(loopingIndex), "NoSuchElement");
96  			return true;
97  		} else if (MoveCard.moveCard(panel.getTop(), controller, to, context,
98  				idPosition, ability, false)) {
99  			return true;
100 		}
101 		return false;
102 	}
103 
104 	public void rollback(ActionContextWrapper actionContext,
105 			ContextEventListener context, Ability ability) {
106 		final MovePlayerCardContext bContext = (MovePlayerCardContext) actionContext.actionContext;
107 
108 		for (int loopingIndex = bContext.srcZones.length; loopingIndex-- > 0;) {
109 			final MZone zoneSrc = bContext.srcZones[loopingIndex];
110 			final MCard card = bContext.cards[loopingIndex];
111 			if (zoneSrc == null)
112 				break;
113 			zoneSrc.remove(card);
114 			card.setIdZone(zoneSrc.getZoneId());
115 			card.controller = bContext.controllers[loopingIndex];
116 
117 			// update positions and controller
118 			card.isHighLighted = false;
119 			card.reversed = card.needReverse();
120 			card.getMUI().updateLayout();
121 
122 			// move to the destination this card
123 			switch (zoneSrc.getZoneId()) {
124 			case IdZones.PLAY:
125 				// update card UI
126 				card.tap(bContext.tapPosition[loopingIndex]);
127 				card.controller.zoneManager.play.addTop(card);
128 				break;
129 			case IdZones.NOWHERE:
130 				// the specified card will never be seen again
131 				break;
132 			default:
133 				zoneSrc.addTop(card);
134 			}
135 		}
136 	}
137 
138 	public void simulate(ActionContextWrapper actionContext,
139 			ContextEventListener context, Ability ability) {
140 		final MovePlayerCardContext bContext = new MovePlayerCardContext(
141 				StackManager.getInstance().getTargetedList().size());
142 		actionContext.actionContext = bContext;
143 		for (int loopingIndex = bContext.srcZones.length; loopingIndex-- > 0;) {
144 			final MZone zoneSrc = ((Player) StackManager.getInstance()
145 					.getTargetedList().get(loopingIndex)).zoneManager.getContainer(from);
146 			if (zoneSrc.getComponentCount() > 0) {
147 				final MCard card = zoneSrc.getTop();
148 				final Player newController = (Player) controller.getTargetable(ability,
149 						card, context, null);
150 				final int destinationZone = MCard.getIdZone(to, context);
151 				final boolean newIsTapped = (to & IdZones.PLAY_TAPPED) == IdZones.PLAY_TAPPED;
152 
153 				bContext.tapPosition[loopingIndex] = card.tapped;
154 				bContext.controllers[loopingIndex] = card.controller;
155 				bContext.srcZones[loopingIndex] = zoneSrc;
156 
157 				// remove card from it's previous zone
158 				zoneSrc.remove(card);
159 
160 				// update positions and controller
161 				card.controller = newController;
162 				card.setIdZone(destinationZone);
163 				card.isHighLighted = false;
164 				card.reversed = card.needReverse();
165 				card.tap(false);
166 
167 				// move to the destination this card
168 				switch (destinationZone) {
169 				case IdZones.PLAY:
170 					// update card UI
171 					card.tap(newIsTapped);
172 					newController.zoneManager.play.addBottom(card);
173 					break;
174 				case IdZones.NOWHERE:
175 					// the specified card will never be seen again
176 					break;
177 				default:
178 					switch (idPosition) {
179 					case IdPositions.ON_THE_TOP:
180 						newController.zoneManager.getContainer(destinationZone)
181 								.addTop(card);
182 						break;
183 					case IdPositions.ON_THE_BOTTOM:
184 					default:
185 						newController.zoneManager.getContainer(destinationZone).addBottom(
186 								card);
187 					}
188 				}
189 			}
190 		}
191 	}
192 
193 	/***
194 	 * Return the first index of this loop.
195 	 * 
196 	 * @return the first index of this loop.
197 	 */
198 	public int getStartIndex() {
199 		return StackManager.getInstance().getTargetedList().size() - 1;
200 	}
201 
202 	@Override
203 	public String toString(Ability ability) {
204 		if (MCard.getIdZone(to, null) == IdZones.PLAY) {
205 			return "Put in play" + (MCard.isTapped(to) ? " tapped" : "");
206 		}
207 		if (to == IdZones.HAND) {
208 			return "Return to graveyard";
209 		}
210 		return "move from " + ZoneManager.getZoneName(from) + " to "
211 				+ ZoneManager.getZoneName(MCard.getIdZone(to, null));
212 	}
213 
214 	/***
215 	 * the destination place
216 	 */
217 	private final int to;
218 
219 	/***
220 	 * the source place
221 	 */
222 	private final int from;
223 
224 	/***
225 	 * The new controller
226 	 */
227 	private final TestOn controller;
228 
229 	/***
230 	 * The position where card would be placed
231 	 */
232 	private final int idPosition;
233 
234 }