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.ArrayList;
25  import java.util.Arrays;
26  import java.util.List;
27  
28  import net.sf.magicproject.action.context.ActionContextWrapper;
29  import net.sf.magicproject.action.context.MoveContext;
30  import net.sf.magicproject.action.handler.FollowAction;
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.Detached;
36  import net.sf.magicproject.event.MovedCard;
37  import net.sf.magicproject.event.context.ContextEventListener;
38  import net.sf.magicproject.network.ConnectionManager;
39  import net.sf.magicproject.network.IdMessages;
40  import net.sf.magicproject.stack.StackManager;
41  import net.sf.magicproject.test.TestOn;
42  import net.sf.magicproject.token.IdPositions;
43  import net.sf.magicproject.token.IdZones;
44  import net.sf.magicproject.tools.Log;
45  import net.sf.magicproject.tools.MToolKit;
46  import net.sf.magicproject.ui.i18n.LanguageManagerMDB;
47  import net.sf.magicproject.ui.wizard.Arrange;
48  import net.sf.magicproject.ui.wizard.Wizard;
49  import net.sf.magicproject.zone.MZone;
50  import net.sf.magicproject.zone.ZoneManager;
51  
52  /***
53   * To move the current target list from their place to another. New position
54   * within the new zone, and the new controller have to be specified. <br>
55   * 
56   * @version 0.91
57   * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
58   * @author <a href="mailto:kismet-sl@users.sourceforge.net">Stefano "Kismet"
59   *         Lenzi</a>
60   * @since 0.54
61   * @since 0.80 activable abilities of card are registered before the 'moved
62   *        card' is generated
63   * @since 0.80 support replacement
64   * @since 0.82 card is moved into the destination zone before the event is
65   *        generated. During the event dispatching there is an incoherence.
66   * @since 0.82 timestamp is checked
67   * @since 0.82 if there are several cards to move, controller chooses order
68   * @since 0.86 action ignore non-card element present in the target list
69   */
70  public class MoveCard extends UserAction implements LoopAction, FollowAction,
71  		BackgroundMessaging, AccessibleContext {
72  
73  	/***
74  	 * Create an instance of MoveCardList by reading a file Offset's file must
75  	 * pointing on the first byte of this action <br>
76  	 * <ul>
77  	 * Structure of InputStream : Data[size]
78  	 * <li>new controller [TestOn]</li>
79  	 * <li>destination zone [IdZone]</li>
80  	 * <li>idPosition [int16]</li>
81  	 * <li>silent [boolean]</li>
82  	 * </ul>
83  	 * 
84  	 * @param inputFile
85  	 *          file containing this action
86  	 * @throws IOException
87  	 *           if error occurred during the reading process from the specified
88  	 *           input stream
89  	 */
90  	MoveCard(InputStream inputFile) throws IOException {
91  		super(inputFile);
92  		controller = TestOn.deserialize(inputFile);
93  		destination = inputFile.read();
94  		idPosition = MToolKit.readInt16(inputFile);
95  		silent = inputFile.read() == 1;
96  	}
97  
98  	public final void replayAction(ContextEventListener context, Ability ability,
99  			Wizard wizard) {
100 		wizard.setVisible(true);
101 		if (Wizard.optionAnswer != Wizard.BACKGROUND_OPTION) {
102 			// valid answer
103 			boolean taken = false;
104 			if (!StackManager.noReplayToken.takeNoBlock()) {
105 				taken = true;
106 			}
107 
108 			final List<MCard> toBeSortedCardsCurrent = new ArrayList<MCard>();
109 			final List<MCard> toBeSortedCardsNonCurrent = new ArrayList<MCard>();
110 			fillList(toBeSortedCardsCurrent, toBeSortedCardsNonCurrent);
111 			final int[] order = ((Arrange) wizard).order;
112 			final int[] toSend = new int[2 + order.length];
113 			toSend[0] = IdMessages.MOVE_ORDER_ANSWER;
114 			toSend[1] = order.length;
115 			if (((Arrange) wizard).owner == StackManager.currentPlayer()) {
116 				// current player (you) has arranged these cards
117 
118 				for (int i = order.length; i-- > 0;) {
119 					toSend[i + 2] = order[i];
120 					StackManager.getTargetListAccess().remove(
121 							toBeSortedCardsCurrent.get(order[i]));
122 					StackManager.getTargetListAccess().add(
123 							toBeSortedCardsCurrent.get(order[i]));
124 				}
125 				// we send our choice
126 				Log.debug("Order sent : " + Arrays.toString(toSend));
127 				ConnectionManager.sendToOpponent(toSend);
128 
129 				// then, check the cards owned by non-current player
130 				if (toBeSortedCardsNonCurrent.size() > 1) {
131 					// now we wait the non current player choice
132 					Log.debug("Opponent is arranging moving cards he/she owns");
133 					StackManager.currentPlayer().getOpponent().setHandedPlayer();
134 					// stop here since the recursive call manages the non-current case
135 				} else {
136 					// all is done : current and non-current player have made their choice
137 					StackManager.actionManager.loopingIndex = StackManager
138 							.getTargetListAccess().size();
139 
140 					// free the locking-token
141 					if (taken) {
142 						StackManager.noReplayToken.release();
143 					}
144 
145 					StackManager.resolveStack();
146 				}
147 			} else {
148 				// non current player (you) has arranged these cards
149 
150 				for (int i = order.length; i-- > 0;) {
151 					toSend[i + 2] = order[i];
152 					StackManager.getTargetListAccess().remove(
153 							toBeSortedCardsNonCurrent.get(order[i]));
154 					StackManager.getTargetListAccess().add(
155 							toBeSortedCardsNonCurrent.get(order[i]));
156 				}
157 
158 				// we send our choice
159 				Log.debug("Order sent : " + Arrays.toString(toSend));
160 				ConnectionManager.sendToOpponent(toSend);
161 
162 				// all is done : current and non-current player have made their choice
163 				StackManager.actionManager.loopingIndex = StackManager
164 						.getTargetListAccess().size();
165 
166 				// free the locking-token
167 				if (taken) {
168 					StackManager.noReplayToken.release();
169 				}
170 
171 				StackManager.resolveStack();
172 			}
173 		}
174 	}
175 
176 	/***
177 	 * return the id of this action. This action has been read from the mdb file.
178 	 * 
179 	 * @see Actiontype
180 	 * @return the id of this action
181 	 */
182 	@Override
183 	public final Actiontype getIdAction() {
184 		return Actiontype.MOVE_CARD;
185 	}
186 
187 	/***
188 	 * Move a card in a zone with a specified new controller.
189 	 * 
190 	 * @param card
191 	 *          the card to move.
192 	 * @param controller
193 	 *          the new controller.
194 	 * @param destination
195 	 *          the new zone.
196 	 * @param context
197 	 *          the context of current ability.
198 	 * @param idPosition
199 	 *          the new state of this card.
200 	 * @param ability
201 	 *          the current ability.
202 	 * @param silentMode
203 	 *          Is the silent mode is enabled while playing.
204 	 * @return true if the card has been moved.
205 	 */
206 	public static boolean moveCard(MCard card, TestOn controller,
207 			int destination, ContextEventListener context, int idPosition,
208 			Ability ability, boolean silentMode) {
209 
210 		// check timestamp
211 		if (!checkTimeStamp(context, card)) {
212 			// we ignore this action
213 			return true;
214 		}
215 
216 		return moveCard(card, (Player) controller.getTargetable(ability, card,
217 				context, null), destination, context, idPosition, ability, silentMode);
218 	}
219 
220 	/***
221 	 * @param movingCard
222 	 *          the card to move.
223 	 * @param controller
224 	 *          the new controller.
225 	 * @param destination
226 	 *          the new zone.
227 	 * @param context
228 	 *          the context of current ability.
229 	 * @param idPosition
230 	 *          the new state of this card.
231 	 * @param ability
232 	 *          the current ability.
233 	 * @param silentMode
234 	 *          Is the silent mode is enabled for this move.
235 	 * @return true if the card has been moved.
236 	 */
237 	public static boolean moveCard(MCard movingCard, Player controller,
238 			int destination, ContextEventListener context, int idPosition,
239 			Ability ability, boolean silentMode) {
240 		final MCard card = (MCard) movingCard.getOriginalTargetable();
241 		final int idDestination = MCard.getIdZone(destination, context);
242 		// add new abilities before the card is moved
243 		card.registerReplacementAbilities(idDestination);
244 		if (!MovedCard.tryAction(card, idDestination, controller, silentMode)) {
245 			// this action has been replaced
246 			return false;
247 		}
248 
249 		if (idDestination == IdZones.PLAY) {
250 			/*
251 			 * the card comes into play : the card is moved before the 'moved' event
252 			 * is generated.
253 			 */
254 			final int previousIdZone = card.getIdZone();
255 			card.moveCard(idDestination, controller,
256 					(destination & IdZones.PLAY_TAPPED) == IdZones.PLAY_TAPPED,
257 					idPosition);
258 
259 			// add the modifiers of this card activated only when card is in play
260 			if (card.getModifierModels() != null && previousIdZone != IdZones.PLAY) {
261 				card.getModifierModels().addModifierFromModel(ability, card);
262 			}
263 
264 			// add new abilities
265 			card.registerAbilities(IdZones.PLAY);
266 
267 			// but we do not update the idZone now.
268 			card.setIdZone(previousIdZone);
269 
270 			/*
271 			 * FROM THIS POINT THERE IS AN INCOHERENCE IN MCard#idZone since the card
272 			 * is in a zone Y but MCard#idZone value is X, assuming the card is moving
273 			 * from X to Y
274 			 */
275 
276 			// dispatch the event before performing this action
277 			MovedCard.dispatchEvent(card, idDestination, controller, silentMode);
278 
279 			// we update the idZone now.
280 			card.setIdZone(IdZones.PLAY);
281 
282 			/*
283 			 * FROM THIS POINT THERE IS NO MORE INCOHERENCE IN MCard#idZone
284 			 */
285 		} else {
286 			/*
287 			 * Since the card does not move into play, we proceed as usual : generate
288 			 * events, and then move physically the card.
289 			 */
290 
291 			// dispatch the event before performing this action
292 			MovedCard.dispatchEvent(card, idDestination, controller, silentMode);
293 
294 			// add new abilities
295 			card.registerAbilities(idDestination);
296 
297 			// move now the card
298 			final int previousIdZone = card.getIdZone();
299 			card.moveCard(idDestination, controller, false, idPosition);
300 
301 			// Add the modifiers
302 			if (card.getModifierModels() != null) {
303 				card.getModifierModels().addStaticModifierFromModel(
304 						card.getDummyAbility());
305 			}
306 
307 			// detachment event?
308 			if (previousIdZone == IdZones.PLAY) {
309 				/*
310 				 * since we are leaving play, we generate the event concerning
311 				 * detachment for each components
312 				 */
313 				if (!silentMode) {
314 					for (MCard attachedCard : card.getAttachedCards()) {
315 						Detached.dispatchEvent(attachedCard, card);
316 					}
317 				}
318 			}
319 		}
320 
321 		if (silentMode) {
322 			for (MCard attachedCard : card.getAttachedCards()) {
323 				attachedCard.setIdZone(idDestination);
324 				attachedCard.clearDamages();
325 			}
326 		}
327 
328 		// unregister useless abilities from the eventManager
329 		card.unregisterAbilities();
330 		return true;
331 	}
332 
333 	public boolean continueLoop(ContextEventListener context, int loopingIndex,
334 			Ability ability) {
335 		Log.debug("\t...continue loop, index : " + loopingIndex);
336 		if (!StackManager.getInstance().getTargetedList().get(loopingIndex)
337 				.isCard()
338 				|| moveCard((MCard) StackManager.getInstance().getTargetedList().get(
339 						loopingIndex), controller, destination, context, idPosition,
340 						ability, silent)) {
341 			return true;
342 		}
343 		return false;
344 	}
345 
346 	/***
347 	 * This method is called when the oponent has finished to choose the order of
348 	 * moves.
349 	 * 
350 	 * @param order
351 	 *          integer array corresponding to the order of cards owned by
352 	 *          opponent.
353 	 */
354 	public synchronized void receiveMoveOrder(int[] order) {
355 		Log.debug("receiveMoveOrder : " + Arrays.toString(order));
356 		final List<MCard> toBeSortedCardsCurrnt = new ArrayList<MCard>();
357 		final List<MCard> toBeSortedCardsNonCurrent = new ArrayList<MCard>();
358 		fillList(toBeSortedCardsCurrnt, toBeSortedCardsNonCurrent);
359 		if (StackManager.currentIsYou()) {
360 			/*
361 			 * we are receiving the move order of non current player, and we have
362 			 * already made our choice since we are the current player. Apply
363 			 * arrangement following specified order.
364 			 */
365 			for (int i : order) {
366 				StackManager.getTargetListAccess().remove(
367 						toBeSortedCardsNonCurrent.get(i));
368 				StackManager.getTargetListAccess()
369 						.add(toBeSortedCardsNonCurrent.get(i));
370 			}
371 			// Now all players have made their choice, we resolve the stack
372 			StackManager.actionManager.loopingIndex = StackManager
373 					.getTargetListAccess().size();
374 			StackManager.resolveStack();
375 		} else {
376 			/*
377 			 * we are receiving the move order of current player. We are the
378 			 * non-current player. Apply arrangement following specified order.
379 			 */
380 			for (int i = order.length; i-- > 0;) {
381 				StackManager.getTargetListAccess().remove(
382 						toBeSortedCardsCurrnt.get(order[i]));
383 				StackManager.getTargetListAccess().add(
384 						toBeSortedCardsCurrnt.get(order[i]));
385 			}
386 
387 			// and then, the non-current player can make order choice if needed
388 			if (toBeSortedCardsNonCurrent.size() > 1) {
389 				Log.debug("You are arranging moving cards you own");
390 				StackManager.currentPlayer().getOpponent().setHandedPlayer();
391 				replayAction(StackManager.getInstance().getAbilityContext(),
392 						StackManager.currentAbility, new Arrange(MCard.getIdZone(
393 								destination, StackManager.getInstance().getAbilityContext()),
394 								toBeSortedCardsNonCurrent, new int[toBeSortedCardsNonCurrent
395 										.size()], StackManager.currentPlayer().getOpponent()));
396 			} else {
397 				// all is done : current and non-current player have made their choice
398 				StackManager.actionManager.loopingIndex = StackManager
399 						.getTargetListAccess().size();
400 				StackManager.resolveStack();
401 			}
402 		}
403 	}
404 
405 	private void fillList(List<MCard> toBeSortedCardsCurrnt,
406 			List<MCard> toBeSortedCardsNonCurrent) {
407 		/*
408 		 * list all cards controlled by CURRENT player in order to put them in the
409 		 * destination zone
410 		 */
411 		for (int i = 0; i < StackManager.getInstance().getTargetedList().size(); i++) {
412 			if (StackManager.getInstance().getTargetedList().get(i).isCard()) {
413 				if (((MCard) StackManager.getInstance().getTargetedList().get(i))
414 						.getOwner().isCurrentPlayer()) {
415 					toBeSortedCardsCurrnt.add((MCard) StackManager.getTargetListAccess()
416 							.get(i));
417 				} else {
418 					toBeSortedCardsNonCurrent.add((MCard) StackManager
419 							.getTargetListAccess().get(i));
420 				}
421 			}
422 		}
423 	}
424 
425 	public synchronized int getStartIndex() {
426 		final int count = StackManager.getInstance().getTargetedList().size();
427 		final int idDestination = MCard.getIdZone(destination, StackManager
428 				.getInstance().getAbilityContext());
429 		if (count > 1 && idDestination >= IdZones.FIRST_ADDITIONAL_ZONE
430 				&& idDestination <= IdZones.LAST_ADDITIONAL_ZONE) {
431 			final List<MCard> toBeSortedCardsCurrent = new ArrayList<MCard>(count);
432 			final List<MCard> toBeSortedCardsNonCurrent = new ArrayList<MCard>(count);
433 			fillList(toBeSortedCardsCurrent, toBeSortedCardsNonCurrent);
434 
435 			if (toBeSortedCardsCurrent.size() > 1) {
436 				// current player can arrange order of cards
437 				final int[] order = new int[toBeSortedCardsCurrent.size()];
438 				if (StackManager.currentIsYou()) {
439 					Log.debug("You (current player) are arranging moving cards you own");
440 					StackManager.currentPlayer().setHandedPlayer();
441 					replayAction(StackManager.getInstance().getAbilityContext(),
442 							StackManager.currentAbility, new Arrange(idDestination,
443 									toBeSortedCardsCurrent, order, StackManager.currentPlayer()));
444 				} else {
445 					Log
446 							.debug("Opponent (current player) is arranging moving cards he/she owns");
447 					StackManager.currentPlayer().setHandedPlayer();
448 				}
449 				return Integer.MAX_VALUE;
450 			}
451 			if (toBeSortedCardsNonCurrent.size() > 1) {
452 				// now we wait the non current player choice
453 				if (StackManager.currentIsYou()) {
454 					Log
455 							.debug("Opponent (non-current player) is arranging moving cards he/she owns");
456 					StackManager.currentPlayer().getOpponent().setHandedPlayer();
457 				} else {
458 					Log
459 							.debug("You (non-current player) are arranging moving cards you own");
460 					StackManager.currentPlayer().getOpponent().setHandedPlayer();
461 					final int[] order = new int[toBeSortedCardsNonCurrent.size()];
462 					StackManager.currentPlayer().getOpponent().setHandedPlayer();
463 					replayAction(StackManager.getInstance().getAbilityContext(),
464 							StackManager.currentAbility, new Arrange(idDestination,
465 									toBeSortedCardsNonCurrent, order, StackManager
466 											.currentPlayer().getOpponent()));
467 				}
468 				return Integer.MAX_VALUE;
469 			}
470 		}
471 		return count - 1;
472 	}
473 
474 	public void rollback(ActionContextWrapper actionContext,
475 			ContextEventListener context, Ability ability) {
476 		final MoveContext bContext = (MoveContext) actionContext.actionContext;
477 		for (int loopingIndex = 0; loopingIndex < StackManager.getInstance()
478 				.getTargetedList().size(); loopingIndex++) {
479 			if (StackManager.getInstance().getTargetedList().get(loopingIndex)
480 					.isCard()) {
481 				final MCard card = (MCard) ((MCard) StackManager.getInstance()
482 						.getTargetedList().get(loopingIndex)).getOriginalTargetable();
483 				final MZone zoneSrc = card.controller.zoneManager.getContainer(card
484 						.getIdZone());
485 
486 				zoneSrc.remove(card);
487 				card.setIdZone(bContext.idZones[loopingIndex]);
488 				card.controller = bContext.controllers[loopingIndex];
489 				if (bContext.attachedTo[loopingIndex] != null) {
490 					bContext.attachedTo[loopingIndex].add(card);
491 					// this card was attached to another one in play
492 					bContext.attachedTo[loopingIndex].getMUI().updateLayout();
493 				}
494 
495 				// update positions and controller
496 				card.isHighLighted = false;
497 				card.reversed = card.needReverse();
498 				card.getMUI().updateLayout();
499 
500 				// move to the destination this card
501 				switch (bContext.idZones[loopingIndex]) {
502 				case IdZones.PLAY:
503 					// update card UI
504 					card.tap(bContext.tapPosition[loopingIndex]);
505 					if ((Integer) bContext.indexes[loopingIndex].value != 0) {
506 						card.controller.zoneManager.play.getCard(
507 								bContext.indexes[loopingIndex].key).add(card,
508 								bContext.indexes[loopingIndex].value.intValue());
509 					} else {
510 						card.controller.zoneManager.play.add(card,
511 								bContext.indexes[loopingIndex].key);
512 					}
513 					break;
514 				case IdZones.NOWHERE:
515 					// the specified card will never be seen again
516 					break;
517 				default:
518 					MZone zone = card.controller.zoneManager
519 							.getContainer(bContext.idZones[loopingIndex]);
520 					if ((Integer) bContext.indexes[loopingIndex].value != 0) {
521 						zone.getCard(bContext.indexes[loopingIndex].key).add(card,
522 								bContext.indexes[loopingIndex].value.intValue());
523 					} else {
524 						zone.add(card, bContext.indexes[loopingIndex].key);
525 					}
526 				}
527 			} else {
528 				Log
529 						.warn("In MOVE-CARD action, target list contains non 'Card' object. Ignored");
530 			}
531 		}
532 	}
533 
534 	public void simulate(ActionContextWrapper actionContext,
535 			ContextEventListener context, Ability ability) {
536 		final MoveContext bContext = new MoveContext(StackManager.getInstance()
537 				.getTargetedList().size());
538 		actionContext.actionContext = bContext;
539 		final int idDestination = MCard.getIdZone(destination, context);
540 		final boolean newIsTapped = (destination & IdZones.PLAY_TAPPED) == IdZones.PLAY_TAPPED;
541 		for (int loopingIndex = StackManager.getInstance().getTargetedList().size(); loopingIndex-- > 0;) {
542 			if (StackManager.getInstance().getTargetedList().get(loopingIndex)
543 					.isCard()) {
544 				final MCard card = (MCard) ((MCard) StackManager.getInstance()
545 						.getTargetedList().get(loopingIndex)).getOriginalTargetable();
546 				final Player newController = (Player) controller.getTargetable(ability,
547 						card, context, null);
548 				final MZone zoneSrc = card.controller.zoneManager.getContainer(card
549 						.getIdZone());
550 				// remove card from it's previous zone
551 				bContext.tapPosition[loopingIndex] = card.tapped;
552 				bContext.controllers[loopingIndex] = card.controller;
553 				bContext.idZones[loopingIndex] = card.getIdZone();
554 				bContext.indexes[loopingIndex] = zoneSrc.getRealIndexOf(card);
555 
556 				if (card.getIdZone() == IdZones.PLAY) {
557 					final MCard attachedTo = card.getParent() instanceof MCard ? (MCard) card
558 							.getParent()
559 							: null;
560 					bContext.attachedTo[loopingIndex] = attachedTo;
561 					zoneSrc.remove(card);
562 					card.tap(false);
563 					if (attachedTo != null) {
564 						// this card was attached to another one in play
565 						attachedTo.getMUI().updateLayout();
566 					}
567 				} else if (card.getParent() != null) {
568 					zoneSrc.remove(card);
569 				}
570 
571 				// update positions ans controller
572 				card.controller = newController;
573 				card.setIdZone(idDestination);
574 				card.isHighLighted = false;
575 				card.reversed = card.needReverse();
576 				card.getMUI().updateLayout();
577 
578 				// move to the destination this card
579 				switch (idDestination) {
580 				case IdZones.PLAY:
581 					// update card UI
582 					card.tap(newIsTapped);
583 					newController.zoneManager.play.addBottom(card);
584 					break;
585 				case IdZones.NOWHERE:
586 					// the specified card will never be seen again
587 					break;
588 				default:
589 					switch (idPosition) {
590 					case IdPositions.ON_THE_TOP:
591 						newController.zoneManager.getContainer(idDestination).addTop(card);
592 						break;
593 					case IdPositions.ON_THE_BOTTOM:
594 					default:
595 						newController.zoneManager.getContainer(idDestination).addBottom(
596 								card);
597 					}
598 				}
599 			} else {
600 				Log
601 						.warn("In MOVE-CARD action, target list contains non 'Card' object. Ignored");
602 			}
603 		}
604 	}
605 
606 	@Override
607 	public String toString(Ability ability) {
608 		if (destination == IdZones.PLAY_TAPPED) {
609 			return LanguageManagerMDB.getString("move-"
610 					+ IdZones.ZONE_NAMES[IdZones.PLAY] + "-tapped");
611 		}
612 		if (destination == IdZones.PLAY) {
613 			return LanguageManagerMDB.getString("move-"
614 					+ IdZones.ZONE_NAMES[IdZones.PLAY]);
615 		}
616 		if (idPosition == IdPositions.ON_THE_BOTTOM) {
617 			return LanguageManagerMDB.getString("move-"
618 					+ ZoneManager.getZoneName(MCard.getIdZone(destination, null))
619 					+ "-bottom");
620 		}
621 		return LanguageManagerMDB.getString("move-"
622 				+ ZoneManager.getZoneName(MCard.getIdZone(destination, null)) + "-top");
623 	}
624 
625 	/***
626 	 * the destination place
627 	 * 
628 	 * @see IdZones
629 	 */
630 	private final int destination;
631 
632 	/***
633 	 * The new controller
634 	 */
635 	private final TestOn controller;
636 
637 	/***
638 	 * The position where card would be placed
639 	 * 
640 	 * @see net.sf.magicproject.token.IdPositions
641 	 */
642 	private final int idPosition;
643 
644 	/***
645 	 * Is the silent mode is enabled while playing.
646 	 */
647 	private final boolean silent;
648 
649 	public int getAccessibleInt(String attribute) {
650 		// TODO complete to support the AccessibleContext pattern
651 		return 0;
652 	}
653 
654 	public Targetable getAccessibleTargetable(String attribute) {
655 		// TODO complete to support the AccessibleContext pattern
656 		return null;
657 	}
658 
659 	/***
660 	 * Shared attrribute to access to the destination zone id.
661 	 */
662 	// public static final String SHARE_DESTINATION = "destination";
663 	/***
664 	 * Shared attrribute to access to the destination controller player.
665 	 */
666 	// public static final String SHARE_CONTROLLER = "controller";
667 }