From: Stefan F. <ste...@us...> - 2010-05-11 21:47:30
|
Update of /cvsroot/rails/18xx/rails/algorithms In directory sfp-cvsdas-4.v30.ch3.sourceforge.com:/tmp/cvs-serv14662/rails/algorithms Modified Files: NetworkTrain.java RevenueAdapter.java NetworkEdge.java NetworkVertex.java NetworkGraphBuilder.java RevenueCalculator.java NetworkIterator.java Added Files: RevenueBonus.java RevenueBonusTemplate.java Log Message: Added VertexVisitedSets and RevenueBonuses, several other improvements to the RC Index: NetworkVertex.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/algorithms/NetworkVertex.java,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** NetworkVertex.java 20 Apr 2010 22:07:09 -0000 1.8 --- NetworkVertex.java 11 May 2010 21:47:21 -0000 1.9 *************** *** 4,12 **** import java.util.Collection; import java.util.Comparator; - import java.util.HashSet; - import java.util.List; - import java.util.Set; ! import rails.game.BaseToken; import rails.game.City; import rails.game.MapHex; --- 4,10 ---- import java.util.Collection; import java.util.Comparator; ! import org.apache.log4j.Logger; ! import rails.game.City; import rails.game.MapHex; *************** *** 14,18 **** import rails.game.PublicCompanyI; import rails.game.Station; - import rails.game.TokenI; import rails.ui.swing.hexmap.EWHexMap; import rails.ui.swing.hexmap.GUIHex; --- 12,15 ---- *************** *** 21,32 **** public final class NetworkVertex implements Comparable<NetworkVertex> { private static enum VertexType { STATION, SIDE, ! HQ } ! private final VertexType type; ! private final MapHex hex; --- 18,45 ---- public final class NetworkVertex implements Comparable<NetworkVertex> { + protected static Logger log = + Logger.getLogger(NetworkVertex.class.getPackage().getName()); + private static enum VertexType { STATION, SIDE, ! HQ, } ! ! // vertex types and flag for virtual (thus not related to a rails object) private final VertexType type; ! private final boolean virtual; ! ! // vertex properties (for virtual vertexes) ! private final String virtualId; ! ! // general vertex properties ! private boolean major = false; ! private boolean minor = false; ! private int value = 0; ! private boolean sink = false; ! private String cityName = null; ! ! // references to rails objects, if not virtual private final MapHex hex; *************** *** 35,88 **** private final int side; - private PhaseI phase; ! private boolean tokenable; ! private Set<PublicCompanyI> companiesHaveToken; ! private int tokenSlots; ! public NetworkVertex(MapHex hex, Station station) { - this(hex, station, null); - } - - public NetworkVertex(MapHex hex, Station station, PhaseI phase) { this.type = VertexType.STATION; this.hex = hex; this.station = station; ! this.side = 0; ! ! this.phase = phase; ! ! String t = station.getType(); ! if (t.equals(Station.TOWN)){ ! this.tokenable = false; ! this.city = null; } else { ! this.tokenable = true; ! // find tokens ! List<TokenI> tokens = null; ! this.tokenSlots = 0; ! List<City> cities = hex.getCities(); ! City foundCity = null; ! for (City city:cities) { ! if (station == city.getRelatedStation()) { ! foundCity = city; ! tokens = city.getTokens(); ! this.tokenSlots = city.getSlots(); ! break; ! } ! } ! this.city = foundCity; ! this.companiesHaveToken = new HashSet<PublicCompanyI>(); ! if (tokens != null) { ! for (TokenI token:tokens) { ! if (token instanceof BaseToken) { ! BaseToken baseToken = (BaseToken)token; ! this.companiesHaveToken.add(baseToken.getCompany()); ! } ! } ! } } } public NetworkVertex(MapHex hex, int side) { this.type = VertexType.SIDE; --- 48,70 ---- private final int side; ! /** constructor for station on mapHex */ public NetworkVertex(MapHex hex, Station station) { this.type = VertexType.STATION; this.hex = hex; this.station = station; ! this.side = -1; ! this.city = hex.getRelatedCity(station); ! if (city != null) { ! log.info("Found city " + city); } else { ! log.info("No city found"); } + + this.virtual = false; + this.virtualId = null; } + /** constructor for side on mapHex */ public NetworkVertex(MapHex hex, int side) { this.type = VertexType.SIDE; *************** *** 92,112 **** this.side = (side % 6); ! this.phase = null; ! this.tokenable = false; ! this.companiesHaveToken = null; ! this.tokenSlots = 0; } public NetworkVertex(PublicCompanyI company) { ! this.type = VertexType.HQ; this.hex = null; this.station = null; this.city = null; ! this.side = 0; ! ! this.phase = null; ! this.tokenable = false; ! this.companiesHaveToken = null; ! this.tokenSlots = 0; } --- 74,110 ---- this.side = (side % 6); ! this.virtual = false; ! this.virtualId = null; } + /** constructor for public company hq */ public NetworkVertex(PublicCompanyI company) { ! this(VertexType.HQ, "HQ"); ! } ! ! private NetworkVertex(VertexType type, String name) { ! this.type = type; this.hex = null; this.station = null; this.city = null; ! this.side = -1; ! ! this.virtual = true; ! this.virtualId = name; ! } ! ! /** factory method for virtual vertex ! */ ! public static NetworkVertex getVirtualVertex(VertexType type, String name) { ! NetworkVertex vertex = new NetworkVertex(type, name); ! return vertex; ! } ! ! void addToRevenueCalculator(RevenueCalculator rc, int vertexId) { ! rc.setVertex(vertexId, major, minor); ! } ! ! public boolean isVirtual() { ! return virtual; } *************** *** 123,217 **** } ! public boolean isTownType(){ ! return isStation() && station.getType().equals(Station.TOWN); } ! public boolean isCityType(){ ! return isStation() && ! (station.getType().equals(Station.CITY) || station.getType().equals(Station.OFF_MAP_AREA)); } ! public boolean isOffBoardType() { ! return isStation() && station.getType().equals(Station.OFF_MAP_AREA); } ! ! public MapHex getHex(){ ! return hex; } ! ! public Station getStation(){ ! return station; } ! public City getCity() { ! return city; } ! public int getSide(){ ! return side; } ! public int getValue(PhaseI phase){ ! if (isOffBoardType()) { ! return hex.getCurrentOffBoardValue(phase); ! } else if (isStation()) { ! return station.getValue(); ! } else { ! return 0; ! } } ! public int getValue() { ! return getValue(this.phase); } ! ! public PhaseI getPhase(){ ! return phase; } ! public void setPhase(PhaseI phase){ ! this.phase = phase; } ! /** ! * Checks if a vertex is fully tokened ! * If it cannot be tokened, always returns false ! */ ! public boolean isFullyTokened(){ ! return tokenable && companiesHaveToken.size() >= tokenSlots; } ! /** ! * Checks if a public company can pass through a vertex ! */ ! public boolean canCompanyRunThrough(PublicCompanyI company) { ! return !isFullyTokened() || companiesHaveToken.contains(company); } ! /** ! * Checks if a vertex contains a token of the given public company ! */ ! public boolean hasCompanyToken(PublicCompanyI company) { ! return !(company == null) && companiesHaveToken.contains(company); } ! /** ! * Checks if a given company can add a token ! * */ ! public boolean canCompanyAddToken(PublicCompanyI company) { ! return (tokenable && companiesHaveToken.size() < tokenSlots && company != null && ! !companiesHaveToken.contains(company)); } ! public String printTokens(){ ! if (!tokenable) return "Not tokenable"; ! ! StringBuffer result = new StringBuffer("Tokens:"); ! for (PublicCompanyI company:companiesHaveToken) ! result.append(" " + company.getName()); ! if (isFullyTokened()) result.append(", fully tokened"); ! return result.toString(); } --- 121,247 ---- } ! ! public boolean isMajor(){ ! return major; } ! public NetworkVertex setMajor(boolean major) { ! this.major = major; ! return this; } ! public boolean isMinor(){ ! return minor; } ! ! public NetworkVertex setMinor(boolean minor) { ! this.minor = minor; ! return this; } ! ! public int getValue() { ! return value; } ! public int getValueByTrain(NetworkTrain train) { ! int valueByTrain; ! if (major) { ! valueByTrain = value * train.getMultiplyMajors(); ! } else if (minor) { ! if (train.ignoresMinors()) { ! valueByTrain = 0; ! } else { ! valueByTrain = value * train.getMultiplyMinors(); ! } ! } else { ! valueByTrain = value; ! } ! return valueByTrain; } + public NetworkVertex setValue(int value) { + this.value = value; + return this; + } ! public boolean isSink() { ! return sink; } ! public NetworkVertex setSink(boolean sink) { ! this.sink = sink; ! return this; } ! public String getCityName() { ! return cityName; } ! ! public NetworkVertex setCityName(String locationName) { ! this.cityName = locationName; ! return this; } ! // getter for rails objects ! public MapHex getHex(){ ! return hex; } ! public Station getStation(){ ! return station; } ! public City getCity() { ! return city; } ! public int getSide(){ ! return side; } ! ! /** ! * Initialize for rails vertexes */ ! public void initRailsVertex(PublicCompanyI company) { ! // side vertices use the defaults, virtuals cannot use this function ! if (virtual || type == VertexType.SIDE) return; ! ! log.info("Init of vertex " + this); ! ! // check if it is a major or minor ! if (station.getType().equals(Station.CITY) || station.getType().equals(Station.OFF_MAP_AREA)) { ! major = true; ! } else if (station.getType().equals(Station.TOWN) || station.getType().equals(Station.PORT) ! || station.getType().equals(Station.HALT)) { ! minor = true; ! } ! ! // check if it is a sink ! if (company == null) { // if company == null, then all sinks are deactivated ! sink = false; ! } else if (station.getType().equals(Station.OFF_MAP_AREA) || ! station.getType().equals(Station.CITY) && !city.hasTokenSlotsLeft() && !city.hasTokenOf(company)) { ! sink = true; ! } ! ! // define locationName ! if (station.getType().equals(Station.OFF_MAP_AREA)) { ! cityName = hex.getCityName(); ! } else { ! cityName = station.getCityName(); ! } } ! public void setRailsVertexValue(PhaseI phase) { ! // side vertices and virtuals cannot use this function ! if (virtual || type == VertexType.SIDE) return; ! ! // define value ! if (station.getType().equals(Station.OFF_MAP_AREA)) { ! value = hex.getCurrentOffBoardValue(phase); ! } else { ! value = station.getValue(); ! } } *************** *** 225,243 **** } - public String getVertexName(){ - StringBuffer name = new StringBuffer(); - if (isStation()) { - // if (hex.getCityName() != null && !hex.getCityName().equals("")) - // name.append(hex.getCityName()); - // else - // name.append("Station"); - // if (station.getNumber() != 1) - // name.append("." + station.getNumber()); - name.append(this.getValue()); - } else - name.append(hex.getOrientationName(side)); - return name.toString(); - } - @Override public String toString(){ --- 255,258 ---- *************** *** 249,253 **** else message.append("HQ"); ! if (isFullyTokened()) message.append("/*"); return message.toString(); --- 264,268 ---- else message.append("HQ"); ! if (isSink()) message.append("/*"); return message.toString(); *************** *** 268,281 **** } ! public static void setPhaseForAll(Collection<NetworkVertex> vertexes, PhaseI phase) { ! for (NetworkVertex v:vertexes) ! v.setPhase(phase); } public static Point2D getVertexPoint2D(HexMap map, NetworkVertex vertex) { GUIHex guiHex = map.getHexByName(vertex.getHex().getName()); ! if (vertex.isCityType()) { return guiHex.getCityPoint2D(vertex.getCity()); ! } else if (vertex.isTownType()) { return guiHex.getCenterPoint2D(); } else if (vertex.isSide()) { --- 283,301 ---- } ! public static void initAllRailsVertices(Collection<NetworkVertex> vertices, ! PublicCompanyI company, PhaseI phase) { ! for (NetworkVertex v:vertices) { ! if (company != null) ! v.initRailsVertex(company); ! if (phase != null) ! v.setRailsVertexValue(phase); ! } } public static Point2D getVertexPoint2D(HexMap map, NetworkVertex vertex) { GUIHex guiHex = map.getHexByName(vertex.getHex().getName()); ! if (vertex.isMajor()) { return guiHex.getCityPoint2D(vertex.getCity()); ! } else if (vertex.isMinor()) { return guiHex.getCenterPoint2D(); } else if (vertex.isSide()) { Index: RevenueCalculator.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/algorithms/RevenueCalculator.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** RevenueCalculator.java 2 May 2010 17:33:00 -0000 1.10 --- RevenueCalculator.java 11 May 2010 21:47:21 -0000 1.11 *************** *** 8,12 **** private final int nbVertexes; - private final int maxNeighbors; private final int nbTrains; --- 8,11 ---- *************** *** 15,19 **** --- 14,22 ---- private final boolean[] vertexMajor; private final boolean[] vertexMinor; + private final int[] vertexNbNeighbors; + private final int[] vertexNbBlocks; + private final int[][] vertexNeighbors; + private final int[][] vertexVisitSets; // start vertexes *************** *** 79,90 **** ! public RevenueCalculator (RevenueAdapter revenueAdapter, int nbVertexes, int maxNeighbors, int nbTrains) { this.revenueAdapter = revenueAdapter; this.nbVertexes = nbVertexes; ! this.maxNeighbors = maxNeighbors; this.nbTrains = nbTrains; - log.debug("RC defined: nbVertexes = " + nbVertexes + ", maxNeighbors = " + maxNeighbors + ", nbTrains = " + nbTrains); // initialize all required variables --- 82,95 ---- ! public RevenueCalculator (RevenueAdapter revenueAdapter, int nbVertexes, int maxNeighbors, int maxBlocks, int nbTrains) { + log.info("RC defined: nbVertexes = " + nbVertexes + ", maxNeighbors = " + maxNeighbors + + ", maxBlocks = " + maxBlocks + ", nbTrains = " + nbTrains); + this.revenueAdapter = revenueAdapter; this.nbVertexes = nbVertexes; ! this.nbTrains = nbTrains; // initialize all required variables *************** *** 92,96 **** vertexMajor = new boolean[nbVertexes]; vertexMinor = new boolean[nbVertexes]; ! vertexNeighbors = new int[nbVertexes][maxNeighbors]; edgeGreedy = new boolean[nbVertexes][nbVertexes]; --- 97,104 ---- vertexMajor = new boolean[nbVertexes]; vertexMinor = new boolean[nbVertexes]; ! vertexNbNeighbors = new int[nbVertexes]; ! vertexNbBlocks = new int[nbVertexes]; ! vertexNeighbors = new int[nbVertexes][maxNeighbors]; ! vertexVisitSets = new int[nbVertexes][maxBlocks]; edgeGreedy = new boolean[nbVertexes][nbVertexes]; *************** *** 116,126 **** } ! void setVertex(int id, int value, boolean major, boolean minor, int[] neighbors) { ! for (int j=0; j < nbTrains; j++) { ! vertexValueByTrain[id][j] = value; ! } vertexMajor[id] = major; vertexMinor[id] = minor; ! vertexNeighbors[id] = neighbors; } --- 124,154 ---- } ! void setVertex(int id, boolean major, boolean minor) { vertexMajor[id] = major; vertexMinor[id] = minor; ! // default neighbors && blocks ! vertexNbNeighbors[id] = 0; ! vertexNbBlocks[id] = 0; ! } ! ! void setVertexValue(int vertexId, int trainId, int value) { ! vertexValueByTrain[vertexId][trainId] = value; ! } ! ! void setVertexNeighbors(int id, int[] neighbors) { ! // copy neighbors ! for (int j=0; j < neighbors.length; j++) { ! vertexNeighbors[id][j] = neighbors[j]; ! } ! vertexNbNeighbors[id] = neighbors.length; ! ! } ! ! void setVertexVisitSets(int id, int[] blocks) { ! // copy blocks ! for (int j=0; j < blocks.length; j++) { ! vertexVisitSets[id][j] = blocks[j]; ! } ! vertexNbBlocks[id] = blocks.length; } *************** *** 129,132 **** --- 157,161 ---- } + void setEdge(int vertexLo, int vertexHi, boolean greedy, int distance) { edgeGreedy[vertexLo][vertexHi] = greedy; *************** *** 134,159 **** } ! void setTrain(int id, int majors, int minors, boolean ignoreMinors, int multiplyMajors, int multiplyMinors) { trainMaxMajors[id] = majors; trainMaxMinors[id] = minors; trainIgnoreMinors[id] = ignoreMinors; - - for (int j=0; j < nbVertexes; j++) { - if (vertexMajor[j]) { - vertexValueByTrain[j][id] = vertexValueByTrain[j][id] * multiplyMajors; - } else if (vertexMinor[j]) { - if (ignoreMinors) { - vertexValueByTrain[j][id] = 0; - } else { - vertexValueByTrain[j][id] = vertexValueByTrain[j][id] * multiplyMinors; - } - } - } } - // void setPredictionData(int[] maxMajorRevenues, int[] maxMinorRevenues) { - // } - int[][] getOptimalRun() { return currentBestRun; } --- 163,174 ---- } ! void setTrain(int id, int majors, int minors, boolean ignoreMinors) { trainMaxMajors[id] = majors; trainMaxMinors[id] = minors; trainIgnoreMinors[id] = ignoreMinors; } int[][] getOptimalRun() { + log.info("RC: currentBestRun = " + Arrays.deepToString(currentBestRun)); return currentBestRun; } *************** *** 269,273 **** this.startTrain = startTrain; this.finalTrain = finalTrain; ! runTrain(startTrain); --- 284,289 ---- this.startTrain = startTrain; this.finalTrain = finalTrain; ! currentBestValue = 0; ! runTrain(startTrain); *************** *** 312,319 **** // and all edges of it if (trainTerminated == Terminated.NotYet) { ! for (int j = 0; j < maxNeighbors; j++) { int neighborId = vertexNeighbors[vertexId][j]; log.debug("RC: Testing Neighbor Nr. " + j + " of startVertex is " + neighborId); - if (neighborId == -1) break; // no more neighbors if (travelEdge(vertexId, neighborId, true)) { trainStartEdge[trainId] = j; // store edge --- 328,334 ---- // and all edges of it if (trainTerminated == Terminated.NotYet) { ! for (int j = 0; j < vertexNbNeighbors[vertexId]; j++) { int neighborId = vertexNeighbors[vertexId][j]; log.debug("RC: Testing Neighbor Nr. " + j + " of startVertex is " + neighborId); if (travelEdge(vertexId, neighborId, true)) { trainStartEdge[trainId] = j; // store edge *************** *** 349,356 **** trainVertexStack[trainId][trainStackPos[trainId]++] = vertexId; // push to stack ! for (int j = trainStartEdge[trainId] + 1; j < maxNeighbors; j++) { int neighborId = vertexNeighbors[vertexId][j]; log.debug("RC: Testing Neighbor Nr. " + j + " of bottomVertex is " + neighborId); - if (neighborId == -1) break; // no more neighbors if (trainVisited[trainId][neighborId]) { log.debug(" RC: Hex already visited"); --- 364,370 ---- trainVertexStack[trainId][trainStackPos[trainId]++] = vertexId; // push to stack ! for (int j = trainStartEdge[trainId] + 1; j < vertexNbNeighbors[vertexId]; j++) { int neighborId = vertexNeighbors[vertexId][j]; log.debug("RC: Testing Neighbor Nr. " + j + " of bottomVertex is " + neighborId); if (trainVisited[trainId][neighborId]) { log.debug(" RC: Hex already visited"); *************** *** 392,399 **** // 2a. visit neighbors, if train has not terminated if (trainTerminated == Terminated.NotYet) { ! for (int j = 0; j < maxNeighbors; j++) { int neighborId = vertexNeighbors[vertexId][j]; log.debug("RC: Testing Neighbor Nr. " + j + " of " + vertexId + " is " + neighborId); - if (neighborId == -1) break; // no more neighbors if (trainVisited[trainId][neighborId]) { log.debug("RC: Hex already visited"); --- 406,412 ---- // 2a. visit neighbors, if train has not terminated if (trainTerminated == Terminated.NotYet) { ! for (int j = 0; j < vertexNbNeighbors[vertexId]; j++) { int neighborId = vertexNeighbors[vertexId][j]; log.debug("RC: Testing Neighbor Nr. " + j + " of " + vertexId + " is " + neighborId); if (trainVisited[trainId][neighborId]) { log.debug("RC: Hex already visited"); *************** *** 455,458 **** --- 468,480 ---- countVisits--; } + + // check blocks + for (int j=0; j < vertexNbBlocks[vertexId]; j++) { + if (vertexVisitSets[vertexId][j] != -1) { + trainVisited[trainId][vertexVisitSets[vertexId][j]] = arrive; + log.debug("RC: visited = " + arrive + " for vertex " + vertexVisitSets[vertexId][j] + " due to block rule"); + } + } + log.debug("RC: Count Visits = " + countVisits); return valueVertex; *************** *** 552,566 **** currentBestValue = totalValue; // exceed thus deep copy of vertex stack ! for (int j = 0; j <= finalTrain; j++) ! for (int v = 0; v < nbVertexes; v++) ! if (v < trainStackPos[j]) currentBestRun[j][v] = trainVertexStack[j][v]; ! else { currentBestRun[j][v] = -1; // terminator break; } log.info("RC: Found better run with " + totalValue); // inform revenue listener via adapter notifyRevenueAdapter(currentBestValue, false); } } --- 574,590 ---- currentBestValue = totalValue; // exceed thus deep copy of vertex stack ! for (int j = 0; j <= finalTrain; j++) { ! for (int v = 0; v < nbVertexes; v++) { ! if (v < trainStackPos[j]) { currentBestRun[j][v] = trainVertexStack[j][v]; ! } else { currentBestRun[j][v] = -1; // terminator break; } + } log.info("RC: Found better run with " + totalValue); // inform revenue listener via adapter notifyRevenueAdapter(currentBestValue, false); + } } } --- NEW FILE: RevenueBonusTemplate.java --- package rails.algorithms; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import rails.game.ConfigurationException; import rails.game.GameManagerI; import rails.game.MapHex; import rails.game.PhaseI; import rails.game.PhaseManager; import rails.game.TrainManager; import rails.game.TrainTypeI; import rails.util.Tag; /** * defines a template for a revenue bonus at creation time of rails objects * will be converted to a true RevenueBonus object during each revenue calculation * @author freystef */ public class RevenueBonusTemplate { protected static Logger log = Logger.getLogger(RevenueBonusTemplate.class.getPackage().getName()); // bonus value private final int value; // template condition attributes private final List<Integer> identVertices; private final List<String> identTrainTypes; private final List<String> identPhases; public RevenueBonusTemplate(Tag tag) throws ConfigurationException { value = tag.getAttributeAsInteger("value"); identVertices = new ArrayList<Integer>(); identTrainTypes = new ArrayList<String>(); identPhases = new ArrayList<String>(); // check for vertices List<Tag> vertexTags = tag.getChildren("Vertex"); if (vertexTags != null) { for (Tag vertexTag:vertexTags) { Integer id = vertexTag.getAttributeAsInteger("id"); if (id != null) { identVertices.add(id); } } } // check for train (types) List<Tag> trainTags = tag.getChildren("Train"); if (trainTags != null) { for (Tag trainTag:trainTags) { String type = trainTag.getAttributeAsString("type"); if (type != null) { identTrainTypes.add(type); } } } // check for phases List<Tag> phaseTags = tag.getChildren("phase"); if (phaseTags != null) { for (Tag phaseTag:phaseTags) { String type = phaseTag.getAttributeAsString("name"); if (type != null) { identPhases.add(type); } } } log.info("Created " + this); } public RevenueBonus toRevenueBonus(MapHex hex, GameManagerI gm, NetworkGraphBuilder ngb) { log.info("Convert " + this); RevenueBonus bonus = new RevenueBonus(value); if (!convertVertices(bonus, ngb, hex)) { log.info("Not all vertices found"); return null; } convertTrainTypes(bonus, gm.getTrainManager()); convertPhases(bonus, gm.getPhaseManager()); log.info("Converted to " + bonus); return bonus; } private boolean convertVertices(RevenueBonus bonus, NetworkGraphBuilder ngb, MapHex hex) { for (Integer identVertex:identVertices) { NetworkVertex vertex = ngb.getVertex(hex, identVertex); if (vertex == null) { return false; } else { bonus.addVertex(vertex); } } return true; } private void convertTrainTypes(RevenueBonus bonus, TrainManager tm) { for (String identTrainType:identTrainTypes) { TrainTypeI trainType = tm.getTypeByName(identTrainType); if (trainType != null) { bonus.addTrainType(trainType); } } } private void convertPhases(RevenueBonus bonus, PhaseManager pm) { for (String identPhase:identPhases) { PhaseI phase = pm.getPhaseByName(identPhase); if (phase != null) { bonus.addPhase(phase); } } } public String toString() { StringBuffer s = new StringBuffer(); s.append("RevenueBonusTemplate with value " + value); s.append(", identVertices = " + identVertices); s.append(", identTrainTypes = " + identTrainTypes); s.append(", identPhases = " + identPhases); return s.toString(); } } Index: NetworkIterator.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/algorithms/NetworkIterator.java,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** NetworkIterator.java 27 Apr 2010 23:24:50 -0000 1.5 --- NetworkIterator.java 11 May 2010 21:47:21 -0000 1.6 *************** *** 28,32 **** private Map<NetworkVertex, greedyState> seen = new HashMap<NetworkVertex, greedyState>(); - private final PublicCompanyI company; private final Graph<NetworkVertex, NetworkEdge> graph; --- 28,31 ---- *************** *** 55,59 **** this.graph = graph; this.startVertex = startVertex; - this.company = company; } --- 54,57 ---- *************** *** 151,155 **** private void addUnseenChildrenOf(NetworkVertex vertex, boolean greedy) { ! if (company != null && !vertex.canCompanyRunThrough(company)) return; for (NetworkEdge edge : graph.edgesOf(vertex)) { --- 149,153 ---- private void addUnseenChildrenOf(NetworkVertex vertex, boolean greedy) { ! if (vertex.isSink()) return; for (NetworkEdge edge : graph.edgesOf(vertex)) { --- NEW FILE: RevenueBonus.java --- package rails.algorithms; import java.util.List; import java.util.ArrayList; import org.apache.log4j.Logger; import rails.game.PhaseI; import rails.game.TrainTypeI; public final class RevenueBonus { protected static Logger log = Logger.getLogger(RevenueBonus.class.getPackage().getName()); // bonus values private final int value; // internal attributes private List<NetworkVertex> vertices; private List<TrainTypeI> trainTypes; private List<PhaseI> phases; public RevenueBonus(int value) { this.value = value; vertices = new ArrayList<NetworkVertex>(); trainTypes = new ArrayList<TrainTypeI>(); phases = new ArrayList<PhaseI>(); } public void addVertex(NetworkVertex vertex) { vertices.add(vertex); } public void addTrainType(TrainTypeI trainType) { trainTypes.add(trainType); } public void addPhase(PhaseI phase) { phases.add(phase); } public int getValue() { return value; } public List<NetworkVertex> getVertices() { return vertices; } public List<TrainTypeI> getTrainTypes() { return trainTypes; } public List<PhaseI> getPhases() { return phases; } public boolean isSimpleBonus() { return (vertices.size() == 1); } public boolean checkSimpleBonus(NetworkVertex vertex, TrainTypeI trainType, PhaseI phase) { return (isSimpleBonus() && vertices.contains(vertex) && checkConditions(trainType, phase)); } public boolean checkConditions(TrainTypeI trainType, PhaseI phase) { boolean result = true; // check trainTypes if (!trainTypes.isEmpty()) { if (trainType == null) { result = false; } else { result = result && trainTypes.contains(trainType); } } // check phase if (!phases.isEmpty()) { if (phase == null) { result = false; } else { result = result && phases.contains(phase); } } return result; } @Override public String toString() { StringBuffer s = new StringBuffer(); s.append("RevenueBonus with value " + value); s.append(", vertices = " + vertices); s.append(", trainTypes = " + trainTypes); s.append(", phases = " + phases); return s.toString(); } } Index: RevenueAdapter.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/algorithms/RevenueAdapter.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** RevenueAdapter.java 1 May 2010 16:07:05 -0000 1.9 --- RevenueAdapter.java 11 May 2010 21:47:21 -0000 1.10 *************** *** 11,23 **** import java.util.Map; - import org.apache.log4j.Logger; import org.jgrapht.Graphs; import org.jgrapht.graph.SimpleGraph; import rails.game.MapHex; import rails.game.PhaseI; import rails.game.PublicCompanyI; import rails.game.TrainI; import rails.ui.swing.hexmap.HexMap; --- 11,24 ---- import java.util.Map; import org.apache.log4j.Logger; import org.jgrapht.Graphs; import org.jgrapht.graph.SimpleGraph; + import rails.game.GameManagerI; import rails.game.MapHex; import rails.game.PhaseI; import rails.game.PublicCompanyI; import rails.game.TrainI; + import rails.game.TrainTypeI; import rails.ui.swing.hexmap.HexMap; *************** *** 28,35 **** --- 29,41 ---- Logger.getLogger(RevenueAdapter.class.getPackage().getName()); + private GameManagerI gameManager; + private NetworkGraphBuilder graphBuilder; + private PublicCompanyI company; + private PhaseI phase; private SimpleGraph<NetworkVertex, NetworkEdge> graph; private RevenueCalculator rc; private int maxNeighbors; + private int maxBlocks; private List<NetworkVertex> vertexes; *************** *** 37,56 **** private List<NetworkVertex> startVertexes; private List<NetworkTrain> trains; // revenue listener private RevenueListener revenueListener; - ! public RevenueAdapter(SimpleGraph<NetworkVertex, NetworkEdge> graph){ ! this.graph = graph; this.vertexes = new ArrayList<NetworkVertex>(graph.vertexSet()); this.edges = new ArrayList<NetworkEdge>(graph.edgeSet()); this.trains = new ArrayList<NetworkTrain>(); this.startVertexes = new ArrayList<NetworkVertex>(); } public void initRevenueCalculator(){ if (rc == null) { // define the maximum number of vertexes maxNeighbors = 0; --- 43,136 ---- private List<NetworkVertex> startVertexes; private List<NetworkTrain> trains; + private Map<NetworkVertex, List<NetworkVertex>> vertexVisitSets; + private List<RevenueBonus> revenueBonuses; // revenue listener private RevenueListener revenueListener; ! public RevenueAdapter(GameManagerI gameManager, NetworkGraphBuilder graphBuilder, PublicCompanyI company){ ! this.gameManager = gameManager; ! this.graphBuilder = graphBuilder; + this.graph = NetworkGraphBuilder.optimizeGraph(graphBuilder.getRailRoadGraph(company)); this.vertexes = new ArrayList<NetworkVertex>(graph.vertexSet()); this.edges = new ArrayList<NetworkEdge>(graph.edgeSet()); this.trains = new ArrayList<NetworkTrain>(); this.startVertexes = new ArrayList<NetworkVertex>(); + this.vertexVisitSets = new HashMap<NetworkVertex, List<NetworkVertex>>(); + this.revenueBonuses = new ArrayList<RevenueBonus>(); + } + + private void defineRevenueBonuses() { + // check each vertex hex for a potential revenue bonus + for (NetworkVertex vertex:vertexes) { + MapHex hex = vertex.getHex(); + if (hex == null) continue; + + List<RevenueBonusTemplate> bonuses = new ArrayList<RevenueBonusTemplate>(); + List<RevenueBonusTemplate> hexBonuses = hex.getRevenueBonuses(); + if (hexBonuses != null) bonuses.addAll(hexBonuses); + // List<RevenueBonusTemplate> tileBonuses = hex.getCurrentTile().getRevenueBonuses(); + // if (tileBonuses != null) bonuses.addAll(hexBonuses); + + if (bonuses == null) continue; + for (RevenueBonusTemplate bonus:bonuses) { + revenueBonuses.add(bonus.toRevenueBonus(hex, gameManager, graphBuilder)); + } + } + log.info("RevenueBonuses = " + revenueBonuses); } + private int defineVertexVisitSets() { + // define map of all locationNames + Map<String, List<NetworkVertex>> locations = new HashMap<String, List<NetworkVertex>>(); + for (NetworkVertex vertex:vertexes) { + String ln = vertex.getCityName(); + if (ln == null) continue; + if (locations.containsKey(ln)) { + locations.get(ln).add(vertex); + } else { + List<NetworkVertex> v = new ArrayList<NetworkVertex>(); + v.add(vertex); + locations.put(ln, v); + } + } + log.info("Locations = " + locations); + // transfer those locationNames to vertexBlocks + int maxBlocks = 0; + for (List<NetworkVertex> location:locations.values()) { + if (location.size() >= 2) { + for (NetworkVertex vertex:location){ + if (vertexVisitSets.containsKey(vertex)) { + for (NetworkVertex v:location) { + if (v != vertex && !vertexVisitSets.get(vertex).contains(v)) { + vertexVisitSets.get(vertex).add(v); + } + } + } else { + List<NetworkVertex> blocks = new ArrayList<NetworkVertex>(); + for (NetworkVertex v:location) { + if (v != vertex) { + blocks.add(v); + } + } + vertexVisitSets.put(vertex, blocks); + } + } + maxBlocks = Math.max(maxBlocks, location.size()); + } + } + log.info("RA: Block of " + vertexVisitSets + ", maxBlocks = " + maxBlocks); + return maxBlocks; + } + public void initRevenueCalculator(){ if (rc == null) { + // define blocks and return those + maxBlocks = defineVertexVisitSets(); + + // define revenueBonuses + defineRevenueBonuses(); + // define the maximum number of vertexes maxNeighbors = 0; *************** *** 59,63 **** maxNeighbors = Math.max(maxNeighbors, graph.edgesOf(vertex).size()); ! this.rc = new RevenueCalculator(this, vertexes.size(), ++maxNeighbors, trains.size()); // increase maxEdges to allow for cutoff } } --- 139,144 ---- maxNeighbors = Math.max(maxNeighbors, graph.edgesOf(vertex).size()); ! log.info("maxNeighbors = " + maxNeighbors); ! this.rc = new RevenueCalculator(this, vertexes.size(), maxNeighbors, maxBlocks, trains.size()); } } *************** *** 67,83 **** // refresh startVertexes this.startVertexes = new ArrayList<NetworkVertex>(); ! } ! ! ! private int[] revenueList(List<NetworkVertex> vertexes, int maxLength) { ! Collections.sort(vertexes, new NetworkVertex.ValueOrder()); ! ! int[] revenue = new int[maxLength + 1]; ! revenue[0] = 0; ! for (int j=1; j <= maxLength; j++) { ! revenue[j] = revenue[j-1] + vertexes.get(j-1).getValue(); ! } ! ! return revenue; } --- 148,153 ---- // refresh startVertexes this.startVertexes = new ArrayList<NetworkVertex>(); ! // refresh revenueBonuses ! this.revenueBonuses = new ArrayList<RevenueBonus>(); } *************** *** 88,93 **** List<NetworkVertex> towns = new ArrayList<NetworkVertex>(); for (NetworkVertex vertex: vertexes) { ! if (vertex.isCityType()) cities.add(vertex); ! if (vertex.isTownType()) towns.add(vertex); } --- 158,163 ---- List<NetworkVertex> towns = new ArrayList<NetworkVertex>(); for (NetworkVertex vertex: vertexes) { ! if (vertex.isMajor()) cities.add(vertex); ! if (vertex.isMinor()) towns.add(vertex); } *************** *** 98,131 **** int maxCityLength = 0, maxTownLength = 0; for (NetworkTrain train: trains) { ! int trainTowns = train.getTowns(); ! if (train.getCities() > maxCities) { ! trainTowns = trainTowns+ train.getCities() - maxCities; ! train.setCities(maxCities); } ! train.setTowns(Math.min(trainTowns, maxTowns)); ! maxCityLength = Math.max(maxCityLength, train.getCities()); ! maxTownLength = Math.max(maxTownLength, train.getTowns()); } - // if (activatePrediction) { - // // get max revenue results - // int[] maxCityRevenues = revenueList(cities, maxCityLength); - // int[] maxTownRevenues = revenueList(towns, maxTownLength); - // - // // set revenue results in revenue calculator - // rc.setPredictionData(maxCityRevenues, maxTownRevenues); - // } } ! ! public void populateRevenueCalculator(PublicCompanyI company, PhaseI phase, boolean activatePrediction){ if (rc == null) initRevenueCalculator(); ! // prepare and optionaly activate revenue prediction prepareRevenuePrediction(activatePrediction); // Define ordering on vertexes by value ! NetworkVertex.setPhaseForAll(vertexes, phase); Collections.sort(vertexes, new NetworkVertex.ValueOrder()); --- 168,195 ---- int maxCityLength = 0, maxTownLength = 0; for (NetworkTrain train: trains) { ! int trainTowns = train.getMinors(); ! if (train.getMajors() > maxCities) { ! trainTowns = trainTowns+ train.getMajors() - maxCities; ! train.setMajors(maxCities); } ! train.setMinors(Math.min(trainTowns, maxTowns)); ! maxCityLength = Math.max(maxCityLength, train.getMajors()); ! maxTownLength = Math.max(maxTownLength, train.getMinors()); } } ! public void populateRevenueCalculator(PhaseI phase, boolean activatePrediction){ ! // store phase ! this.phase = phase; ! if (rc == null) initRevenueCalculator(); ! // prepare and optionally activate revenue prediction prepareRevenuePrediction(activatePrediction); // Define ordering on vertexes by value ! NetworkVertex.initAllRailsVertices(vertexes, company, phase); Collections.sort(vertexes, new NetworkVertex.ValueOrder()); *************** *** 133,155 **** NetworkVertex v = vertexes.get(id); if (v.isHQ()) { ! // HQ is not added to list, but used to assign startVertexes startVertexes.addAll(Graphs.neighborListOf(graph, v)); ! } else { ! // prepare values ! int value = v.getValue(); ! boolean city = v.isCityType(); ! boolean town = v.isTownType(); ! int j = 0, e[] = new int[maxNeighbors]; ! if (v.canCompanyRunThrough(company)) { ! for (NetworkVertex n:Graphs.neighborListOf(graph, v)){ ! if (!n.isHQ()) { ! e[j++] = vertexes.lastIndexOf(n); ! } ! } } // sort by value order ! Arrays.sort(e, 0, j); ! e[j] = -1; // stop ! rc.setVertex(id, value, city, town, e); } } --- 197,230 ---- NetworkVertex v = vertexes.get(id); if (v.isHQ()) { ! // HQ is not added to list, but used to assign startVertexes startVertexes.addAll(Graphs.neighborListOf(graph, v)); ! continue; ! } ! // add to revenue calculator ! v.addToRevenueCalculator(rc, id); ! for (int trainId=0; trainId < trains.size(); trainId++) { ! NetworkTrain train = trains.get(trainId); ! rc.setVertexValue(id, trainId, getVertexValue(v, train, phase)); ! } ! ! // set neighbors ! if (!v.isSink()) { ! List<NetworkVertex> neighbors = Graphs.neighborListOf(graph, v); ! int j=0, neighborsArray[] = new int[neighbors.size()]; ! for (NetworkVertex n:neighbors){ ! neighborsArray[j++] = vertexes.indexOf(n); } // sort by value order ! neighborsArray = Arrays.copyOfRange(neighborsArray, 0, j); ! Arrays.sort(neighborsArray); ! rc.setVertexNeighbors(id, neighborsArray); ! } ! // set blocks ! if (vertexVisitSets.containsKey(v)) { ! int b = 0, blocks[] = new int[vertexVisitSets.get(v).size()]; ! for (NetworkVertex n: vertexVisitSets.get(v)) { ! blocks[b++] = vertexes.indexOf(n); ! } ! rc.setVertexVisitSets(id, blocks); } } *************** *** 162,166 **** Arrays.sort(sv); // sort by value order rc.setStartVertexes(sv); ! // set edges for (int id=0; id < edges.size(); id++) { --- 237,241 ---- Arrays.sort(sv); // sort by value order rc.setStartVertexes(sv); ! // set edges for (int id=0; id < edges.size(); id++) { *************** *** 182,233 **** train.addToRevenueCalculator(rc, id); } } public void addDefaultTrain(int cities) { String trainName = Integer.valueOf(cities).toString(); ! NetworkTrain train =new NetworkTrain(cities, 0, false, 1, 1, trainName); trains.add(train); } public void addTrain(TrainI railsTrain){ ! int cities = railsTrain.getMajorStops(); ! int towns = railsTrain.getMinorStops(); ! boolean townsCostNothing = (railsTrain.getTownCountIndicator() == 0); ! int multiplyCities = railsTrain.getCityScoreFactor(); ! int multiplyTowns = railsTrain.getTownScoreFactor(); ! String trainName = railsTrain.getName(); ! ! if (cities > 0 || towns > 0) { // protection against pullman ! NetworkTrain networkTrain = new NetworkTrain(cities, towns, townsCostNothing, multiplyCities, multiplyTowns, trainName); ! trains.add(networkTrain); ! } } public void addTrainByString(String trainString) { String t = trainString.trim(); ! ! int cities = 0; int towns = 0; boolean ignoreTowns = false; int multiplyCities = 1; int multiplyTowns = 1; ! if (t.equals("D")) { ! cities = 99; // diesel ! } else if (t.contains("+")) { ! cities = Integer.parseInt(t.split("\\+")[0]); // + train ! towns = Integer.parseInt(t.split("\\+")[1]); ! } else if (t.contains("E")) { ! // express train ! cities = Integer.parseInt(t.replace("E", "")); ! ignoreTowns = true; ! multiplyTowns = 0; ! } else if (t.contains("D")) { ! // double (express) train ! cities = Integer.parseInt(t.replace("D", "")); ! ignoreTowns = true; ! multiplyCities = 2; ! multiplyTowns = 0; ! } else { ! // default train ! cities = Integer.parseInt(t); } - NetworkTrain networkTrain = new NetworkTrain(cities, towns, ignoreTowns, multiplyCities, multiplyTowns, t); - trains.add(networkTrain); } --- 257,322 ---- train.addToRevenueCalculator(rc, id); } + + } + public int getVertexValue(NetworkVertex vertex, NetworkTrain train, PhaseI phase) { + + // base value + int value = vertex.getValueByTrain(train); + + // add potential revenueBonuses + for (RevenueBonus bonus:revenueBonuses) { + if (bonus.checkSimpleBonus(vertex, train.getRailsTrainType(), phase)) { + value += bonus.getValue(); + } + } + + return value; + } + public void addDefaultTrain(int cities) { String trainName = Integer.valueOf(cities).toString(); ! NetworkTrain train =new NetworkTrain(cities, 0, false, 1, 1, trainName, null); trains.add(train); } public void addTrain(TrainI railsTrain){ ! NetworkTrain train = NetworkTrain.createFromRailsTrain(railsTrain); ! if (train != null) trains.add(train); } public void addTrainByString(String trainString) { String t = trainString.trim(); ! TrainTypeI trainType = gameManager.getTrainManager().getTypeByName(trainString); ! if (trainType != null) { // string defines available trainType ! TrainI railsTrain = trainType.cloneTrain(); ! addTrain(railsTrain); ! log.info("RA: found trainType" + trainType); ! } else { // otherwise interpret the train ! int cities = 0; int towns = 0; boolean ignoreTowns = false; int multiplyCities = 1; int multiplyTowns = 1; ! if (t.equals("D")) { ! cities = 99; // diesel ! } else if (t.contains("+")) { ! cities = Integer.parseInt(t.split("\\+")[0]); // + train ! towns = Integer.parseInt(t.split("\\+")[1]); ! } else if (t.contains("E")) { ! // express train ! cities = Integer.parseInt(t.replace("E", "")); ! ignoreTowns = true; ! multiplyTowns = 0; ! } else if (t.contains("D")) { ! // double (express) train ! cities = Integer.parseInt(t.replace("D", "")); ! ignoreTowns = true; ! multiplyCities = 2; ! multiplyTowns = 0; ! } else { ! // default train ! cities = Integer.parseInt(t); ! } ! NetworkTrain networkTrain = new NetworkTrain(cities, towns, ignoreTowns, multiplyCities, multiplyTowns, t, null); ! trains.add(networkTrain); } } *************** *** 236,239 **** --- 325,332 ---- } + public void addRevenueBonus(RevenueBonus bonus) { + revenueBonuses.add(bonus); + } + public Map<NetworkTrain, List<NetworkVertex>> getOptimalRun() { int[][] optimalRunRaw = rc.getOptimalRun(); *************** *** 287,290 **** --- 380,384 ---- } + public String getOptimalRunPrettyPrint() { StringBuffer runPrettyPrint = new StringBuffer(); *************** *** 310,316 **** runPrettyPrint.append(","); } ! runPrettyPrint.append(vertex.getVertexName()); } ! runPrettyPrint.append(")\n"); } return runPrettyPrint.toString(); --- 404,417 ---- runPrettyPrint.append(","); } ! if (vertex.isStation()) { ! runPrettyPrint.append(getVertexValue(vertex, train, phase)); ! } else { ! runPrettyPrint.append(currentHex.getOrientationName(vertex.getSide())); ! } } ! if (currentHex != null) { ! runPrettyPrint.append(")"); ! } ! runPrettyPrint.append("\n"); } return runPrettyPrint.toString(); Index: NetworkGraphBuilder.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/algorithms/NetworkGraphBuilder.java,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** NetworkGraphBuilder.java 1 May 2010 16:07:05 -0000 1.8 --- NetworkGraphBuilder.java 11 May 2010 21:47:21 -0000 1.9 *************** *** 20,24 **** import org.jgrapht.Graphs; import org.jgrapht.ext.JGraphModelAdapter; - import org.jgrapht.graph.Multigraph; import org.jgrapht.graph.SimpleGraph; import org.jgrapht.graph.Subgraph; --- 20,23 ---- *************** *** 30,33 **** --- 29,33 ---- import rails.game.BaseToken; import rails.game.City; + import rails.game.GameManagerI; import rails.game.MapHex; import rails.game.PublicCompanyI; *************** *** 44,48 **** --- 44,50 ---- private SimpleGraph<NetworkVertex, NetworkEdge> mapGraph; + private Map<String, NetworkVertex> mapVertexes; + private NetworkIterator iterator; *************** *** 51,55 **** } ! public void generateGraph(List<MapHex> mHexes) { mapGraph = new SimpleGraph<NetworkVertex, NetworkEdge>(NetworkEdge.class); --- 53,57 ---- } ! public void generateGraph(List<MapHex> mHexes ) { mapGraph = new SimpleGraph<NetworkVertex, NetworkEdge>(NetworkEdge.class); *************** *** 67,71 **** mapGraph.addVertex(stationVertex); mapVertexes.put(stationVertex.getIdentifier(), stationVertex); ! log.debug("Added " + stationVertex + " / " + stationVertex.printTokens()); } --- 69,73 ---- mapGraph.addVertex(stationVertex); mapVertexes.put(stationVertex.getIdentifier(), stationVertex); ! log.info("Added " + stationVertex); } *************** *** 76,80 **** mapGraph.addVertex(sideVertex); mapVertexes.put(sideVertex.getIdentifier(), sideVertex); ! log.debug("Added " + sideVertex); } } --- 78,82 ---- mapGraph.addVertex(sideVertex); mapVertexes.put(sideVertex.getIdentifier(), sideVertex); ! log.info("Added " + sideVertex); } } *************** *** 91,95 **** NetworkVertex startVertex = getVertexRotated(hex, points[0]); NetworkVertex endVertex = getVertexRotated(hex, points[1]); ! log.debug("Track: " + track); NetworkEdge edge = new NetworkEdge(startVertex, endVertex, false); if (startVertex == endVertex) { --- 93,97 ---- NetworkVertex startVertex = getVertexRotated(hex, points[0]); NetworkVertex endVertex = getVertexRotated(hex, points[1]); ! log.info("Track: " + track); NetworkEdge edge = new NetworkEdge(startVertex, endVertex, false); if (startVertex == endVertex) { *************** *** 97,101 **** } else { mapGraph.addEdge(startVertex, endVertex, edge); ! log.debug("Added edge " + edge.getConnection()); } } --- 99,103 ---- } else { mapGraph.addEdge(startVertex, endVertex, edge); ! log.info("Added edge " + edge.getConnection()); } } *************** *** 106,110 **** MapHex neighborHex = hex.getNeighbor(side); if (neighborHex == null) { ! log.debug("No connection for Hex " + hex.getName() + " at " + hex.getOrientationName(side) + ", No Neighbor"); continue; --- 108,112 ---- MapHex neighborHex = hex.getNeighbor(side); if (neighborHex == null) { ! log.info("No connection for Hex " + hex.getName() + " at " + hex.getOrientationName(side) + ", No Neighbor"); continue; *************** *** 112,123 **** NetworkVertex otherVertex = getVertex(neighborHex, side + 3); if (vertex == null && otherVertex == null){ ! log.debug("Hex " + hex.getName() + " has no track at " + hex.getOrientationName(side)); ! log.debug("And Hex " + neighborHex.getName() + " has no track at " + neighborHex.getOrientationName(side + 3)); continue; } else if (vertex == null && otherVertex != null) { ! log.debug("Deadend connection for Hex " + neighborHex.getName() + " at " + neighborHex.getOrientationName(side + 3) + ", NeighborHex " + hex.getName() + " has no track at side " + --- 114,125 ---- NetworkVertex otherVertex = getVertex(neighborHex, side + 3); if (vertex == null && otherVertex == null){ ! log.info("Hex " + hex.getName() + " has no track at " + hex.getOrientationName(side)); ! log.info("And Hex " + neighborHex.getName() + " has no track at " + neighborHex.getOrientationName(side + 3)); continue; } else if (vertex == null && otherVert... [truncated message content] |