View Javadoc

1   /*
2    * Created on Sep 10, 2004 
3    * 
4    *   Magic-Project is a turn based strategy simulator
5    *   Copyright (C) 2003-2007 Fabrice Daugan
6    *
7    *   This program is free software; you can redistribute it and/or modify it 
8    * under the terms of the GNU General Public License as published by the Free 
9    * Software Foundation; either version 2 of the License, or (at your option) any
10   * later version.
11   *
12   *   This program is distributed in the hope that it will be useful, but WITHOUT 
13   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14   * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
15   * details.
16   *
17   *   You should have received a copy of the GNU General Public License along  
18   * with this program; if not, write to the Free Software Foundation, Inc., 
19   * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20   * 
21   */
22  package net.sf.magicproject.modifier;
23  
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.util.ArrayList;
27  import java.util.List;
28  
29  import net.sf.magicproject.clickable.ability.Ability;
30  import net.sf.magicproject.clickable.targetable.card.MCard;
31  import net.sf.magicproject.clickable.targetable.card.SystemCard;
32  import net.sf.magicproject.event.EventFactory;
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.test.And;
37  import net.sf.magicproject.test.InZone;
38  import net.sf.magicproject.test.IsTested;
39  import net.sf.magicproject.test.Not;
40  import net.sf.magicproject.test.Test;
41  import net.sf.magicproject.test.TestFactory;
42  import net.sf.magicproject.test.True;
43  import net.sf.magicproject.test.TestOn;
44  import net.sf.magicproject.token.IdZones;
45  import net.sf.magicproject.tools.MToolKit;
46  
47  /***
48   * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
49   * @since 0.85 Recalculate attribute is supported
50   */
51  public abstract class ModifierModel {
52  
53  	/***
54  	 * Creates a new instance of ModifierModel <br>
55  	 * <ul>
56  	 * Structure of InputStream : Data[size]
57  	 * <li>modifier name [String]</li>
58  	 * <li>initial registers value [IdTokens.MODIFIER_REGISTER_SIZE]</li>
59  	 * <li>activated while this condition [Test]</li>
60  	 * <li>linked to creator [boolean]</li>
61  	 * <li>exists until this triggered event [Event[]]</li>
62  	 * <li>layer [int]</li>
63  	 * </ul>
64  	 * The while condition must not refer to any register value of this modifier
65  	 * 
66  	 * @param inputFile
67  	 * @throws IOException
68  	 *           if error occured during the reading process from the specified
69  	 *           input stream
70  	 */
71  	protected ModifierModel(InputStream inputFile) throws IOException {
72  		this();
73  		name = MToolKit.readString(inputFile);
74  		recalculate = inputFile.read() == 1;
75  
76  		// while
77  		whileCondition = TestFactory.readNextTest(inputFile);
78  		linkedEvents = new ArrayList<MEventListener>();
79  		whileCondition.extractTriggeredEvents(linkedEvents, SystemCard.instance,
80  				True.getInstance());
81  
82  		// creator link
83  		linked = inputFile.read() == 1;
84  
85  		// until events
86  		int count = inputFile.read();
87  		until = new ArrayList<MEventListener>(count + 1);
88  		while (count-- > 0) {
89  			until.add(EventFactory.readNextEvent(inputFile, SystemCard.instance));
90  		}
91  
92  		// add the event : if the 'to' leave play, the modifier is destroyed
93  		until.add(new MovedCard(IdZones.PLAY, And.append(IsTested.TESTED_IS_ME,
94  				new InZone(IdZones.PLAY, TestOn.THIS)), new Not(new InZone(
95  				IdZones.PLAY, TestOn.THIS)), SystemCard.instance));
96  		layer = inputFile.read();
97  	}
98  
99  	/***
100 	 * Create a new instance from the given model.
101 	 * 
102 	 * @param other
103 	 *          the instance to copy
104 	 */
105 	protected ModifierModel(ModifierModel other) {
106 		name = other.name;
107 		linked = other.linked;
108 		until = other.until;
109 		whileCondition = other.whileCondition;
110 		layer = other.layer;
111 		recalculate = other.recalculate;
112 		if (other.next != null) {
113 			next = other.next.clone();
114 		}
115 	}
116 
117 	/***
118 	 * Read the name of this model
119 	 */
120 	protected ModifierModel() {
121 		super();
122 	}
123 
124 	/***
125 	 * Add to the list of modifierModels of the specified card, this instance.
126 	 * 
127 	 * @param modelToAdd
128 	 *          This new modifier will be added to the tail of modifier list.
129 	 */
130 	public final void addModel(ModifierModel modelToAdd) {
131 		if (next == null) {
132 			next = modelToAdd;
133 		} else {
134 			next.addModel(modelToAdd);
135 		}
136 	}
137 
138 	@Override
139 	public abstract ModifierModel clone();
140 
141 	/***
142 	 * Create modifier(s) on the specified target.
143 	 * 
144 	 * @param ability
145 	 *          is the ability owning causin the creation of this modifier. The
146 	 *          card component of this ability should correspond to the card
147 	 *          owning this test too.
148 	 * @param target
149 	 *          is the card this new modifier would be attached to.
150 	 */
151 	public abstract void addModifierFromModel(Ability ability, MCard target);
152 
153 	/***
154 	 * Return the HTML code representing this action. If this action is named,
155 	 * it's name will be returned. If not, if existing, the picture associated to
156 	 * this action is returned. Otherwise, built-in action's text will be
157 	 * returned.
158 	 * 
159 	 * @param ability
160 	 *          is the ability owning this test. The card component of this
161 	 *          ability should correspond to the card owning this test too.
162 	 * @param context
163 	 *          the context needed by event activated
164 	 * @return the HTML code representing this action. If this action is named,
165 	 *         it's name will be returned. If not, if existing, the picture
166 	 *         associated to this action is returned. Otherwise, built-in action's
167 	 *         text will be returned.
168 	 * @since 0.86
169 	 */
170 	public abstract String toHtmlString(Ability ability,
171 			ContextEventListener context);
172 
173 	/***
174 	 * Remove one instance of this object from the given card.
175 	 * 
176 	 * @param fromCard
177 	 * @param objectTest
178 	 *          The test applied on specific modifier to be removed.
179 	 */
180 	public void removeObject(MCard fromCard, Test objectTest) {
181 		if (next != null) {
182 			next.removeObject(fromCard, objectTest);
183 		}
184 	}
185 
186 	/***
187 	 * Add all static modifiers.
188 	 * 
189 	 * @param ability
190 	 *          is the ability owning this test. The card component of this
191 	 *          ability should correspond to the card owning this test too.
192 	 */
193 	public void addStaticModifierFromModel(Ability ability) {
194 		if (next != null) {
195 			next.addStaticModifierFromModel(ability);
196 		}
197 	}
198 
199 	/***
200 	 * When this test is true, this modifier is activated. Otherwise this modifier
201 	 * does nothing.
202 	 */
203 	protected Test whileCondition;
204 
205 	/***
206 	 * The modifier name
207 	 */
208 	protected String name;
209 
210 	/***
211 	 * When this event is generated this modifier is removed from the attached
212 	 * object. If this event is equal to null, this modifier can be removed only
213 	 * by the attached component.
214 	 */
215 	protected List<MEventListener> until;
216 
217 	/***
218 	 * Represents the events forcing this event to be refreshed
219 	 */
220 	protected List<MEventListener> linkedEvents;
221 
222 	/***
223 	 * The next register modifier
224 	 */
225 	protected ModifierModel next;
226 
227 	/***
228 	 * Indicates this modifier must be destroyed if the creator of this modifier
229 	 * has been destroyed or has moved
230 	 */
231 	protected boolean linked;
232 
233 	/***
234 	 * Is the parameters are recalculated.
235 	 */
236 	protected boolean recalculate;
237 
238 	/***
239 	 * Is the strategy used to add this modifier within the existing chain
240 	 */
241 	protected int layer;
242 
243 }