~ubuntu-branches/ubuntu/precise/triplea/precise

« back to all changes in this revision

Viewing changes to src/games/strategy/triplea/delegate/UndoableMove.java

  • Committer: Package Import Robot
  • Author(s): Scott Howard
  • Date: 2011-11-11 21:40:11 UTC
  • Revision ID: package-import@ubuntu.com-20111111214011-sehf2rwat36o2xqf
Tags: upstream-1.3.2.2
ImportĀ upstreamĀ versionĀ 1.3.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This program is free software; you can redistribute it and/or modify
 
3
 * it under the terms of the GNU General Public License as published by
 
4
 * the Free Software Foundation; either version 2 of the License, or
 
5
 * (at your option) any later version.
 
6
 * This program is distributed in the hope that it will be useful,
 
7
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
8
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
9
 * GNU General Public License for more details.
 
10
 * You should have received a copy of the GNU General Public License
 
11
 * along with this program; if not, write to the Free Software
 
12
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
13
 */
 
14
 
 
15
package games.strategy.triplea.delegate;
 
16
 
 
17
import java.io.Serializable;
 
18
import java.util.*;
 
19
 
 
20
import games.strategy.engine.data.*;
 
21
import games.strategy.engine.delegate.IDelegateBridge;
 
22
import games.strategy.util.*;
 
23
import games.strategy.triplea.delegate.dataObjects.*;
 
24
import games.strategy.triplea.ui.MovePanel;
 
25
 
 
26
/**
 
27
 * Contains all the data to describe a move and to undo it.
 
28
 */
 
29
 
 
30
public class UndoableMove implements Serializable
 
31
{
 
32
    /**
 
33
     * Stores data about a move so that it can be undone.
 
34
     * Stores the serialized state of the move and battle delegates (just
 
35
     * as if they were saved), and a CompositeChange that represents all the changes that
 
36
     * were made during the move.
 
37
     *
 
38
     * Some moves (such as those following an aa fire) can't be undone.
 
39
     */
 
40
    private int m_index;
 
41
    private CompositeChange m_undoChange = new CompositeChange();
 
42
    private String m_reasonCantUndo;
 
43
    private String m_description;
 
44
 
 
45
    //this move is dependent on these moves
 
46
    //these moves cant be undone until this one has been
 
47
    private Set<UndoableMove> m_iDependOn = new HashSet<UndoableMove>();
 
48
    //these moves depend on me
 
49
    //we cant be undone until this is empty
 
50
    private Set<UndoableMove> m_dependOnMe = new HashSet<UndoableMove>();
 
51
 
 
52
    //list of countries we took over
 
53
    private Set<Territory> m_conquered = new HashSet<Territory>();
 
54
 
 
55
    //transports loaded by this move
 
56
    private Set<Unit> m_loaded = new HashSet<Unit>();
 
57
 
 
58
    //transports unloaded by this move
 
59
    private Set<Unit> m_unloaded = new HashSet<Unit>();;
 
60
 
 
61
    private final Route m_route;
 
62
    private final Collection<Unit> m_units;
 
63
 
 
64
    public Collection<Unit> getUnits()
 
65
    {
 
66
        return m_units;
 
67
    }
 
68
 
 
69
    public void addToConquered(Territory t)
 
70
    {
 
71
        m_conquered.add(t);
 
72
    }
 
73
 
 
74
    public Route getRoute()
 
75
    {
 
76
        return m_route;
 
77
    }
 
78
 
 
79
    public int getIndex()
 
80
    {
 
81
        return m_index;
 
82
    }
 
83
 
 
84
    public void setIndex(int index)
 
85
    {
 
86
        m_index = index;
 
87
    }
 
88
 
 
89
    public boolean getcanUndo()
 
90
    {
 
91
        return m_reasonCantUndo == null && m_dependOnMe.isEmpty();
 
92
    }
 
93
 
 
94
    public String getReasonCantUndo()
 
95
    {
 
96
        if(m_reasonCantUndo != null)
 
97
            return m_reasonCantUndo;
 
98
        else if(!m_dependOnMe.isEmpty())
 
99
            return "Move " +
 
100
                   (m_dependOnMe.iterator().next().getIndex() + 1) +
 
101
                   " must be undone first";
 
102
        else
 
103
            throw new IllegalStateException("no reason");
 
104
 
 
105
    }
 
106
 
 
107
    public void setCantUndo(String reason)
 
108
    {
 
109
        m_reasonCantUndo = reason;
 
110
    }
 
111
 
 
112
    public void addChange(Change aChange)
 
113
    {
 
114
        m_undoChange.add(aChange);
 
115
    }
 
116
 
 
117
    public String getDescription()
 
118
    {
 
119
        return m_description;
 
120
    }
 
121
 
 
122
    public void setDescription(String description)
 
123
    {
 
124
        m_description = description;
 
125
    }
 
126
 
 
127
    public UndoableMove(GameData data, Collection<Unit> units, Route route)
 
128
    {        
 
129
        m_route = route;
 
130
        m_units = units;
 
131
    }
 
132
 
 
133
    public void load(Unit transport)
 
134
    {
 
135
        m_loaded.add(transport);
 
136
    }
 
137
 
 
138
    public void unload(Unit transport)
 
139
    {
 
140
        m_unloaded.add(transport);
 
141
    }
 
142
 
 
143
    public void undo(IDelegateBridge bridge, GameData data)
 
144
    {        
 
145
        BattleTracker battleTracker = DelegateFinder.battleDelegate(data).getBattleTracker();
 
146
        
 
147
 
 
148
        bridge.getHistoryWriter().startEvent(bridge.getPlayerID().getName() +
 
149
                                     " undo move " + (m_index + 1)+ ".");
 
150
        bridge.getHistoryWriter().setRenderingData(new MoveDescription(m_units, m_route));
 
151
 
 
152
        //undo any changes to the game data
 
153
        bridge.addChange(m_undoChange.invert());
 
154
 
 
155
        battleTracker.undoBattle(m_route, m_units, bridge.getPlayerID(), data, bridge);
 
156
 
 
157
        //clean up dependencies
 
158
        Iterator iter = m_iDependOn.iterator();
 
159
        while (iter.hasNext()) {
 
160
            UndoableMove other = (UndoableMove)iter.next();
 
161
            other.m_dependOnMe.remove(this);
 
162
        }
 
163
 
 
164
        
 
165
        //if we are moving out of a battle zone, mark it
 
166
        //this can happen for air units moving out of a battle zone
 
167
        Battle battleLand =battleTracker.getPendingBattle(m_route.getStart(), false);
 
168
        Battle battleAir =battleTracker.getPendingBattle(m_route.getStart(), true);
 
169
        if(battleLand != null || battleAir != null)
 
170
        {
 
171
            iter = m_units.iterator();
 
172
            while(iter.hasNext())
 
173
            {
 
174
                Unit unit = (Unit) iter.next();
 
175
                Route routeUnitUsedToMove = DelegateFinder.moveDelegate(data).getRouteUsedToMoveInto(unit, m_route.getStart());
 
176
                if(battleLand != null && !battleLand.isOver())
 
177
                {
 
178
                    //route units used to move will be null in the case
 
179
                    //where an enemry sub is submerged in the territory, and another unit
 
180
                    //moved in to attack it, but some of the units in the original 
 
181
                    //territory are moved out.  Undoing this last move, the route used to move
 
182
                    //into the battle zone will be null
 
183
                    if(routeUnitUsedToMove != null) {
 
184
                        Change change = battleLand.addAttackChange(routeUnitUsedToMove, Collections.singleton(unit));
 
185
                        bridge.addChange(change);
 
186
                    }
 
187
                }
 
188
                if(battleAir != null && !battleAir.isOver())
 
189
                {
 
190
                    Change change = battleAir.addAttackChange(routeUnitUsedToMove, Collections.singleton(unit));                    
 
191
                    bridge.addChange(change);
 
192
                }
 
193
            }
 
194
        }
 
195
        
 
196
        //Clear any temporary dependents
 
197
        MovePanel.clearDependents(m_units);        
 
198
    }
 
199
 
 
200
    /**
 
201
     * Update the dependencies.
 
202
     */
 
203
    public void initializeDependencies(List<UndoableMove> undoableMoves)
 
204
    {
 
205
        Iterator<UndoableMove> iter = undoableMoves.iterator();
 
206
        while (iter.hasNext())
 
207
        {
 
208
            UndoableMove other = iter.next();
 
209
 
 
210
            if(other == null)
 
211
            {
 
212
              System.err.println(undoableMoves);
 
213
              throw new IllegalStateException("other should not be null");
 
214
            }
 
215
 
 
216
            if( //if the other move has moves that depend on this
 
217
                !Util.intersection(other.getUnits(), this.getUnits() ).isEmpty() ||
 
218
                //if the other move has transports that we are loading
 
219
                !Util.intersection(other.m_units, this.m_loaded).isEmpty() ||
 
220
                //or we are moving through a previously conqueured territory
 
221
                //we should be able to take this out later
 
222
                //we need to add logic for this move to take over the same territories
 
223
                //when the other move is undone
 
224
                !Util.intersection(other.m_conquered, m_route.getTerritories()).isEmpty() ||
 
225
                //or we are unloading transports that have moved in another turn 
 
226
                !Util.intersection(other.m_units, this.m_unloaded).isEmpty() ||
 
227
                !Util.intersection(other.m_unloaded, this.m_unloaded).isEmpty()
 
228
               )
 
229
            {
 
230
                m_iDependOn.add(other);
 
231
                other.m_dependOnMe.add(this);
 
232
            }
 
233
        }
 
234
    }
 
235
    
 
236
    public boolean wasTransportUnloaded(Unit transport)
 
237
    {
 
238
        return m_unloaded.contains(transport);
 
239
    }
 
240
    
 
241
    public boolean wasTransportLoaded(Unit transport) 
 
242
    {
 
243
        return m_loaded.contains(transport);
 
244
    }
 
245
 
 
246
    public String toString()
 
247
    {
 
248
        return "UndoableMove index;" + m_index + " description:" + m_description;
 
249
    }
 
250
    
 
251
}