View Javadoc

1   /* 
2    * WaitTriggeredBufferChoice.java
3    * Created on 26 févr. 2004
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  package net.sf.magicproject.action;
23  
24  import java.util.ArrayList;
25  import java.util.List;
26  
27  import net.sf.magicproject.Magic;
28  import net.sf.magicproject.action.listener.WaitingAbility;
29  import net.sf.magicproject.action.listener.WaitingCard;
30  import net.sf.magicproject.clickable.ability.Ability;
31  import net.sf.magicproject.clickable.targetable.card.MCard;
32  import net.sf.magicproject.clickable.targetable.player.Player;
33  import net.sf.magicproject.event.CanICast;
34  import net.sf.magicproject.event.context.ContextEventListener;
35  import net.sf.magicproject.stack.ActivatedChoiceList;
36  import net.sf.magicproject.stack.EventManager;
37  import net.sf.magicproject.stack.StackManager;
38  import net.sf.magicproject.ui.component.TableTop;
39  import net.sf.magicproject.zone.MZone;
40  import net.sf.magicproject.zone.ZoneManager;
41  
42  /***
43   * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
44   * @since 0.60
45   */
46  public final class WaitActivatedChoice extends MAction implements WaitingCard,
47  		WaitingAbility {
48  
49  	/***
50  	 * Create a new instance of WaitTriggeredBufferChoice
51  	 */
52  	private WaitActivatedChoice() {
53  		super();
54  	}
55  
56  	/***
57  	 * Generate event associated to this action. Only one or several events are
58  	 * generated and may be collected by event listeners. Then play this action
59  	 * 
60  	 * @param ability
61  	 *          is the ability owning this test. The card component of this
62  	 *          ability should correspond to the card owning this test too.
63  	 * @param context
64  	 *          is the context attached to this action.
65  	 * @return true if the stack resolution can continue. False if the stack
66  	 *         resolution is broken.
67  	 */
68  	public boolean play(ContextEventListener context, Ability ability) {
69  		hasDesclined[0] = false;
70  		hasDesclined[1] = false;
71  		if (!opponentResponse) {
72  			hasDesclined[1 - StackManager.idActivePlayer] = true;
73  		}
74  		zoneList = null;
75  		finished();
76  		if (waitAbilityChoice(StackManager.activePlayer())) {
77  			return finishedActivatedChoice();
78  		}
79  		return false;
80  	}
81  
82  	public boolean clickOn(MCard card) {
83  		return StackManager.idHandedPlayer != 0;
84  	}
85  
86  	public boolean clickOn(Ability ability) {
87  		return StackManager.idHandedPlayer == 0;
88  	}
89  
90  	public boolean succeedClickOn(MCard card) {
91  		throw new InternalError("Card selection was not expected");
92  	}
93  
94  	public boolean succeedClickOn(Ability ability) {
95  		finished();
96  		StackManager.newSpell(ability, ability.isMatching());
97  		return true;
98  	}
99  
100 	@Override
101 	public Actiontype getIdAction() {
102 		return Actiontype.WAIT_ACTIVATED_CHOICE;
103 	}
104 
105 	public boolean manualSkip() {
106 		finished();
107 		hasDesclined[StackManager.oldIdHandedPlayer] = true;
108 		if (waitAbilityChoice(StackManager.nonActivePlayer())) {
109 			return finishedActivatedChoice();
110 		}
111 		return false;
112 	}
113 
114 	public void finished() {
115 		if (activChoiceList != null) {
116 			activChoiceList.disHighLight();
117 			activChoiceList.clear();
118 			activChoiceList = null;
119 		}
120 		if (zoneList != null) {
121 			for (MZone zone : zoneList) {
122 				zone.disHighLight();
123 			}
124 			zoneList.clear();
125 			zoneList = null;
126 			StackManager.PLAYERS[0].disHighLight();
127 			StackManager.PLAYERS[1].disHighLight();
128 		}
129 	}
130 
131 	/***
132 	 * Called when active player and non-active player have finished their choice
133 	 * order of their triggered abilities in the stack
134 	 * 
135 	 * @return true if the stack resolution can continue. False if the stack
136 	 *         resolution is broken.
137 	 */
138 	private boolean finishedActivatedChoice() {
139 		StackManager.disableAbort();
140 		WaitActivatedChoice.getInstance().finished();
141 		if (StackManager.isEmpty()) {
142 			// the stack is empty, so neither new spell, neither waiting triggered
143 			EventManager.gotoNextPhase();
144 			return false;
145 		}
146 		// we start resolving the stack
147 		return true;
148 	}
149 
150 	/***
151 	 * @param firstPlayer
152 	 * @return true if the stack resolution can continue. False if the stack
153 	 *         resolution is broken.
154 	 */
155 	private boolean waitAbilityChoice(Player firstPlayer) {
156 		if (hasDesclined[firstPlayer.idPlayer]) {
157 			if (hasDesclined[1 - firstPlayer.idPlayer]) {
158 				// both players have declined to response, so we resolve stack
159 				return true;
160 			}
161 			return waitAbilityChoice(firstPlayer.getOpponent());
162 		}
163 		final List<Ability> res = new ArrayList<Ability>();
164 		final List<Ability> advRes = new ArrayList<Ability>();
165 		CanICast.dispatchEvent(firstPlayer.idPlayer, res, advRes);
166 		finished();
167 		if (!res.isEmpty()) {
168 			/*
169 			 * at least one playable ability, so this player becomes the new active
170 			 */
171 			activChoiceList = new ActivatedChoiceList(res, advRes);
172 			res.clear();
173 			advRes.clear();
174 			if (firstPlayer.isYou() && StackManager.isEmpty()
175 					&& firstPlayer.declinePlay() || firstPlayer.isYou()
176 					&& StackManager.currentIsYou() && !StackManager.isEmpty()
177 					&& firstPlayer.declineResponseMe() || firstPlayer.isYou()
178 					&& !StackManager.currentIsYou() && !StackManager.isEmpty()
179 					&& firstPlayer.declineResponseOpponent()) {
180 
181 				StackManager.idActivePlayer = 0;
182 				StackManager.idHandedPlayer = 0;
183 				System.out.println(new StringBuilder("You play. Dump [ap :").append(
184 						StackManager.idActivePlayer).append(", cp :").append(
185 						StackManager.idCurrentPlayer).append(", s# :").append(
186 						StackManager.CONTEXTES.size()).append(", action :")
187 						.append(
188 								StackManager.actionManager.currentAction.getClass()
189 										.getSimpleName()).append(", li :").append(
190 								StackManager.actionManager.loopingIndex).append(", hop :")
191 						.append(StackManager.actionManager.hop).append(
192 								"] - (AUTO SKIP IS COMING)"));
193 				StackManager.oldIdHandedPlayer = 0;
194 				Magic.sendManualSkip();
195 				return manualSkip();
196 			}
197 			if (activChoiceList != null) {
198 				zoneList = activChoiceList.highLight();
199 				if (zoneList != null && !StackManager.isEmpty()
200 						&& !zoneList.contains(ZoneManager.stack)) {
201 					TableTop.getInstance().tabbedPane
202 							.setSelectedComponent(ZoneManager.stack.superPanel);
203 				}
204 			}
205 			firstPlayer.setActivePlayer();
206 			return false;
207 		}
208 		// this player has no playable ability, we test the opponent
209 		hasDesclined[firstPlayer.idPlayer] = true;
210 		return waitAbilityChoice(firstPlayer.getOpponent());
211 	}
212 
213 	public List<Ability> abilitiesOf(MCard card) {
214 		return activChoiceList == null ? null : activChoiceList.abilitiesOf(card);
215 	}
216 
217 	public List<Ability> advancedAbilitiesOf(MCard card) {
218 		return activChoiceList == null ? null : activChoiceList
219 				.advancedAbilitiesOf(card);
220 	}
221 
222 	/***
223 	 * return the string representation of this action
224 	 * 
225 	 * @param ability
226 	 *          is the ability owning this test. The card component of this
227 	 *          ability should correspond to the card owning this test too.
228 	 * @return the string representation of this action
229 	 * @see Object#toString()
230 	 */
231 	@Override
232 	public String toString(Ability ability) {
233 		return "Wait activated ability choice";
234 	}
235 
236 	/***
237 	 * Return the unique instance of this class.
238 	 * 
239 	 * @return the unique instance of this class.
240 	 */
241 	public static WaitActivatedChoice getInstance() {
242 		if (instance == null)
243 			instance = new WaitActivatedChoice();
244 		return instance;
245 	}
246 
247 	/***
248 	 * The unique instance of this class
249 	 */
250 	private static WaitActivatedChoice instance;
251 
252 	/***
253 	 * indicates if this player has already declined to response to current spell
254 	 * When the active players gets priority, it would be tested to know if we
255 	 * have to resolve the stack
256 	 */
257 	private boolean[] hasDesclined = new boolean[2];
258 
259 	/***
260 	 * This is the list of zone concerned by highlighted cards
261 	 */
262 	private List<MZone> zoneList;
263 
264 	/***
265 	 * the current list of choices of active player
266 	 */
267 	private ActivatedChoiceList activChoiceList;
268 
269 	/***
270 	 * If true, player can response to opponent effects
271 	 */
272 	public static boolean opponentResponse;
273 }