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

« back to all changes in this revision

Viewing changes to src/games/strategy/engine/data/Route.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
/*
 
16
 * Route.java
 
17
 *
 
18
 * Created on October 12, 2001, 5:23 PM
 
19
 */
 
20
 
 
21
package games.strategy.engine.data;
 
22
 
 
23
import java.util.*;
 
24
 
 
25
import games.strategy.util.*;
 
26
 
 
27
/**
 
28
 * 
 
29
 * A route between two territories.<p>
 
30
 * 
 
31
 * A route consists of a start territory, and a sequence of steps.  To create a route
 
32
 * do,
 
33
 * 
 
34
 * <code>
 
35
 * Route aRoute = new Route();
 
36
 * route.setStart(someTerritory);
 
37
 * route.add(anotherTerritory);
 
38
 * route.add(yetAnotherTerritory);
 
39
 * </code>
 
40
 * 
 
41
 * 
 
42
 * 
 
43
 * @author Sean Bridges
 
44
 * @version 1.0
 
45
 * 
 
46
 */
 
47
public class Route implements java.io.Serializable, Iterable<Territory>
 
48
{
 
49
    private List<Territory> m_route = new ArrayList<Territory>();
 
50
 
 
51
    private Territory m_start;
 
52
 
 
53
    
 
54
    public Route() {
 
55
        
 
56
    }
 
57
    
 
58
  public Route(List<Territory> route) {
 
59
        
 
60
        setStart(route.get(0));
 
61
        if(route.size() == 1) {
 
62
            return;
 
63
        }
 
64
        for(Territory t: route.subList(1, route.size())) {
 
65
            add(t);
 
66
        }
 
67
    }
 
68
    
 
69
    
 
70
    public Route(Territory start, Territory ... route) {
 
71
        
 
72
        setStart(start);
 
73
        for(Territory t: route) {
 
74
            add(t);
 
75
        }        
 
76
    }
 
77
    
 
78
    
 
79
    
 
80
    /**
 
81
     * Join the two routes. It must be the case that r1.end() equals r2.start()
 
82
     * or r1.end() == null and r1.start() equals r2
 
83
     * 
 
84
     * @return a new Route starting at r1.start() going to r2.end() along r1,
 
85
     *         r2, or null if the routes cant be joined it the joining would
 
86
     *         form a loop
 
87
     * 
 
88
     */
 
89
    public static Route join(Route r1, Route r2)
 
90
    {
 
91
        if (r1 == null || r2 == null)
 
92
            throw new IllegalArgumentException("route cant be null r1:" + r1 + " r2:" + r2);
 
93
 
 
94
        if (r1.getLength() == 0)
 
95
        {
 
96
            if (!r1.getStart().equals(r2.getStart()))
 
97
                throw new IllegalArgumentException("Cannot join, r1 doesnt end where r2 starts. r1:" + r1 + " r2:" + r2);
 
98
        } else
 
99
        {
 
100
            if (!r1.getEnd().equals(r2.getStart()))
 
101
                throw new IllegalArgumentException("Cannot join, r1 doesnt end where r2 starts. r1:" + r1 + " r2:" + r2);
 
102
        }
 
103
 
 
104
        Collection<Territory> c1 = new ArrayList<Territory>(r1.m_route);
 
105
        c1.add(r1.getStart());
 
106
 
 
107
        Collection<Territory> c2 = new ArrayList<Territory>(r2.m_route);
 
108
 
 
109
        if (!Util.intersection(c1, c2).isEmpty())
 
110
            return null;
 
111
 
 
112
        Route joined = new Route();
 
113
        joined.setStart(r1.getStart());
 
114
 
 
115
        for (int i = 0; i < r1.getLength(); i++)
 
116
        {
 
117
            joined.add(r1.at(i));
 
118
        }
 
119
 
 
120
        for (int i = 0; i < r2.getLength(); i++)
 
121
        {
 
122
            joined.add(r2.at(i));
 
123
        }
 
124
 
 
125
        return joined;
 
126
    }
 
127
 
 
128
    public boolean equals(Object o)
 
129
    {
 
130
        if (o == null)
 
131
            return false;
 
132
        Route other = (Route) o;
 
133
        if (!(other.getLength() == this.getLength()))
 
134
            return false;
 
135
        if (!other.getStart().equals(this.getStart()))
 
136
            return false;
 
137
        return other.getTerritories().equals(this.getTerritories());
 
138
    }
 
139
 
 
140
    public int hashCode()
 
141
    {
 
142
        return toString().hashCode();
 
143
    }
 
144
 
 
145
    /**
 
146
     * Set the start of this route.
 
147
     */
 
148
    public void setStart(Territory t)
 
149
    {
 
150
        if (t == null)
 
151
            throw new IllegalStateException("Null territory");
 
152
 
 
153
        m_start = t;
 
154
    }
 
155
 
 
156
    /**
 
157
     * Get the start territory for this route.
 
158
     */
 
159
    public Territory getStart()
 
160
    {
 
161
        return m_start;
 
162
    }
 
163
 
 
164
    /**
 
165
     * Determines if the route crosses water by checking if any of the
 
166
     * territories except the start and end are sea territories.
 
167
     * 
 
168
     * @return whether the route encounters water other than at the start of the
 
169
     *         route.
 
170
     */
 
171
    public boolean crossesWater()
 
172
    {
 
173
        boolean startLand = !m_start.isWater();
 
174
        boolean overWater = false;
 
175
        Iterator<Territory> routeIter = m_route.iterator();
 
176
        Territory terr = null;
 
177
        while (routeIter.hasNext())
 
178
        {
 
179
            terr = routeIter.next();
 
180
            if (terr.isWater())
 
181
            {
 
182
                overWater = true;
 
183
            }
 
184
        }
 
185
        
 
186
        if(terr == null)
 
187
            return false;
 
188
        
 
189
        // If we started on land, went over water, and ended on land, we cross
 
190
        // water.
 
191
        return (startLand && overWater && !terr.isWater());
 
192
    }
 
193
 
 
194
    /**
 
195
     * Add the given territory to the end of the route.
 
196
     */
 
197
    public void add(Territory t)
 
198
    {
 
199
        if (t == null)
 
200
            throw new IllegalStateException("Null territory");
 
201
        if(t.equals(m_start) || m_route.contains(t))
 
202
            throw new IllegalArgumentException("Loops not allowed in m_routes, route:" + this + " new territory:" + t);
 
203
 
 
204
        m_route.add(t);
 
205
    }
 
206
 
 
207
    /**
 
208
     * 
 
209
     * @return the number of steps in this route.
 
210
     */
 
211
    public int getLength()
 
212
    {
 
213
        return m_route.size();
 
214
    }
 
215
 
 
216
    /**
 
217
     * Get the territory we will be in after the i'th step for this route has been made.
 
218
     *  
 
219
     */
 
220
    public Territory at(int i)
 
221
    {
 
222
        return m_route.get(i);
 
223
    }
 
224
 
 
225
    /**
 
226
     * Do all territories in this route match the given match?  The start territory
 
227
     * is not tested. 
 
228
     */
 
229
    public boolean allMatch(Match<Territory> aMatch)
 
230
    {
 
231
        for (int i = 0; i < getLength(); i++)
 
232
        {
 
233
            if (!aMatch.match(at(i)))
 
234
                return false;
 
235
        }
 
236
        return true;
 
237
    }
 
238
 
 
239
    /**
 
240
     * Do some territories in this route match the given match?  The start territory
 
241
     * is not tested. 
 
242
     */
 
243
    public boolean someMatch(Match<Territory> aMatch)
 
244
    {
 
245
        for (int i = 0; i < getLength(); i++)
 
246
        {
 
247
            if (aMatch.match(at(i)))
 
248
                return true;
 
249
        }
 
250
        return false;
 
251
    }
 
252
 
 
253
    /**
 
254
     * Get all territories in this route match the given match?  The start territory
 
255
     * is not tested. 
 
256
     */
 
257
    public Collection<Territory> getMatches(Match<Territory> aMatch)
 
258
    {
 
259
        return Match.getMatches(m_route, aMatch);
 
260
    }
 
261
 
 
262
    public String toString()
 
263
    {
 
264
        StringBuilder buf = new StringBuilder("Route:").append(m_start);
 
265
        for (int i = 0; i < getLength(); i++)
 
266
        {
 
267
            buf.append(" -> ");
 
268
            buf.append(at(i).getName());           
 
269
        }
 
270
        return buf.toString();
 
271
    }
 
272
 
 
273
    /**
 
274
     * Returns a collection of all territories in this route, including the start.
 
275
     */
 
276
    public List<Territory> getTerritories()
 
277
    {
 
278
        ArrayList<Territory> list = new ArrayList<Territory>(m_route);
 
279
        list.add(0, m_start);
 
280
        return list;
 
281
    }
 
282
 
 
283
    /**
 
284
     * Get the last territory in the route, this is the destination.
 
285
     * If the route consists of only a starting territory, this will return null.
 
286
     */
 
287
    public Territory getEnd()
 
288
    {
 
289
        if (m_route.size() == 0)
 
290
            return null;
 
291
        return m_route.get(m_route.size() - 1);
 
292
    }
 
293
 
 
294
    /**
 
295
     * does this route extend another route
 
296
     */
 
297
    public boolean extend(Route baseRoute)
 
298
    {
 
299
        if (!baseRoute.m_start.equals(baseRoute.m_start))
 
300
        {
 
301
            return false;
 
302
        }
 
303
 
 
304
        if (baseRoute.getLength() > getLength())
 
305
            return false;
 
306
 
 
307
        for (int i = 0; i < baseRoute.m_route.size(); i++)
 
308
        {
 
309
            if (!baseRoute.at(i).equals(at(i)))
 
310
                return false;
 
311
        }
 
312
        return true;
 
313
 
 
314
    }
 
315
 
 
316
    public Iterator<Territory> iterator() {
 
317
        return Collections.unmodifiableList(getTerritories()).iterator();
 
318
    }
 
319
 
 
320
}