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
18
* Created on October 12, 2001, 5:23 PM
21
package games.strategy.engine.data;
25
import games.strategy.util.*;
29
* A route between two territories.<p>
31
* A route consists of a start territory, and a sequence of steps. To create a route
35
* Route aRoute = new Route();
36
* route.setStart(someTerritory);
37
* route.add(anotherTerritory);
38
* route.add(yetAnotherTerritory);
43
* @author Sean Bridges
47
public class Route implements java.io.Serializable, Iterable<Territory>
49
private List<Territory> m_route = new ArrayList<Territory>();
51
private Territory m_start;
58
public Route(List<Territory> route) {
60
setStart(route.get(0));
61
if(route.size() == 1) {
64
for(Territory t: route.subList(1, route.size())) {
70
public Route(Territory start, Territory ... route) {
73
for(Territory t: route) {
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
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
89
public static Route join(Route r1, Route r2)
91
if (r1 == null || r2 == null)
92
throw new IllegalArgumentException("route cant be null r1:" + r1 + " r2:" + r2);
94
if (r1.getLength() == 0)
96
if (!r1.getStart().equals(r2.getStart()))
97
throw new IllegalArgumentException("Cannot join, r1 doesnt end where r2 starts. r1:" + r1 + " r2:" + r2);
100
if (!r1.getEnd().equals(r2.getStart()))
101
throw new IllegalArgumentException("Cannot join, r1 doesnt end where r2 starts. r1:" + r1 + " r2:" + r2);
104
Collection<Territory> c1 = new ArrayList<Territory>(r1.m_route);
105
c1.add(r1.getStart());
107
Collection<Territory> c2 = new ArrayList<Territory>(r2.m_route);
109
if (!Util.intersection(c1, c2).isEmpty())
112
Route joined = new Route();
113
joined.setStart(r1.getStart());
115
for (int i = 0; i < r1.getLength(); i++)
117
joined.add(r1.at(i));
120
for (int i = 0; i < r2.getLength(); i++)
122
joined.add(r2.at(i));
128
public boolean equals(Object o)
132
Route other = (Route) o;
133
if (!(other.getLength() == this.getLength()))
135
if (!other.getStart().equals(this.getStart()))
137
return other.getTerritories().equals(this.getTerritories());
140
public int hashCode()
142
return toString().hashCode();
146
* Set the start of this route.
148
public void setStart(Territory t)
151
throw new IllegalStateException("Null territory");
157
* Get the start territory for this route.
159
public Territory getStart()
165
* Determines if the route crosses water by checking if any of the
166
* territories except the start and end are sea territories.
168
* @return whether the route encounters water other than at the start of the
171
public boolean crossesWater()
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())
179
terr = routeIter.next();
189
// If we started on land, went over water, and ended on land, we cross
191
return (startLand && overWater && !terr.isWater());
195
* Add the given territory to the end of the route.
197
public void add(Territory t)
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);
209
* @return the number of steps in this route.
211
public int getLength()
213
return m_route.size();
217
* Get the territory we will be in after the i'th step for this route has been made.
220
public Territory at(int i)
222
return m_route.get(i);
226
* Do all territories in this route match the given match? The start territory
229
public boolean allMatch(Match<Territory> aMatch)
231
for (int i = 0; i < getLength(); i++)
233
if (!aMatch.match(at(i)))
240
* Do some territories in this route match the given match? The start territory
243
public boolean someMatch(Match<Territory> aMatch)
245
for (int i = 0; i < getLength(); i++)
247
if (aMatch.match(at(i)))
254
* Get all territories in this route match the given match? The start territory
257
public Collection<Territory> getMatches(Match<Territory> aMatch)
259
return Match.getMatches(m_route, aMatch);
262
public String toString()
264
StringBuilder buf = new StringBuilder("Route:").append(m_start);
265
for (int i = 0; i < getLength(); i++)
268
buf.append(at(i).getName());
270
return buf.toString();
274
* Returns a collection of all territories in this route, including the start.
276
public List<Territory> getTerritories()
278
ArrayList<Territory> list = new ArrayList<Territory>(m_route);
279
list.add(0, m_start);
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.
287
public Territory getEnd()
289
if (m_route.size() == 0)
291
return m_route.get(m_route.size() - 1);
295
* does this route extend another route
297
public boolean extend(Route baseRoute)
299
if (!baseRoute.m_start.equals(baseRoute.m_start))
304
if (baseRoute.getLength() > getLength())
307
for (int i = 0; i < baseRoute.m_route.size(); i++)
309
if (!baseRoute.at(i).equals(at(i)))
316
public Iterator<Territory> iterator() {
317
return Collections.unmodifiableList(getTerritories()).iterator();