Program: 173813
Project: 173813
Buggy source:
/** 
 * Prepare a tile upgrade. The actual tile replacement is done in replaceTile(), via a TileMove object.
 */
public void upgrade(TileI newTile,int newRotation){
  City newCity;
  String newTracks;
  if (currentTile.getNumStations() == newTile.getNumStations()) {
    for (    City city : cities) {
      Station oldStation=city.getRelatedStation();
      int[] oldTrackEnds=getTrackEndPoints(currentTile,currentTileRotation,oldStation);
      if (oldTrackEnds.length == 0) {
        Station newStation=newTile.getStations().get(city.getNumber() - 1);
        city.setRelatedStation(newStation);
        city.setSlots(newStation.getBaseSlots());
        log.debug("String_Node_Str" + city.getUniqueId() + "String_Node_Str"+ oldStation.getId()+ "String_Node_Str"+ getConnectionString(currentTile,currentTileRotation,oldStation.getNumber())+ "String_Node_Str"+ newStation.getId()+ "String_Node_Str"+ getConnectionString(newTile,newRotation,newStation.getNumber()));
        continue;
      }
      station:       for (      Station newStation : newTile.getStations()) {
        int[] newTrackEnds=getTrackEndPoints(newTile,newRotation,newStation);
        for (int i=0; i < oldTrackEnds.length; i++) {
          for (int j=0; j < newTrackEnds.length; j++) {
            if (oldTrackEnds[i] == newTrackEnds[j]) {
              city.setRelatedStation(newStation);
              city.setSlots(newStation.getBaseSlots());
              newTracks=getConnectionString(newTile,newRotation,newStation.getNumber());
              city.setTrackEdges(newTracks);
              log.debug("String_Node_Str" + city.getUniqueId() + "String_Node_Str"+ oldStation.getId()+ "String_Node_Str"+ getConnectionString(currentTile,currentTileRotation,oldStation.getNumber())+ "String_Node_Str"+ newStation.getId()+ "String_Node_Str"+ newTracks);
              break station;
            }
          }
        }
      }
    }
    new TileMove(this,currentTile,currentTileRotation,cities,newTile,newRotation,cities);
  }
 else {
    List<City> newCities=new ArrayList<City>(4);
    Map<Integer,City> mNewCities=new HashMap<Integer,City>(4);
    Map<City,City> oldToNewCities=new HashMap<City,City>();
    Map<Station,City> newStationsToCities=new HashMap<Station,City>();
    for (    City oldCity : cities) {
      int cityNumber=oldCity.getNumber();
      Station oldStation=oldCity.getRelatedStation();
      int[] oldTrackEnds=getTrackEndPoints(currentTile,currentTileRotation,oldStation);
      log.debug("String_Node_Str" + currentTile.getId() + "String_Node_Str"+ oldCity.getNumber()+ "String_Node_Str"+ getConnectionString(currentTile,currentTileRotation,oldStation.getNumber()));
      station:       for (      Station newStation : newTile.getStations()) {
        int[] newTrackEnds=getTrackEndPoints(newTile,newRotation,newStation);
        log.debug("String_Node_Str" + newTile.getId() + "String_Node_Str"+ newStation.getNumber()+ "String_Node_Str"+ getConnectionString(newTile,newRotation,newStation.getNumber()));
        for (int i=0; i < oldTrackEnds.length; i++) {
          for (int j=0; j < newTrackEnds.length; j++) {
            if (oldTrackEnds[i] == newTrackEnds[j]) {
              if (!newStationsToCities.containsKey(newStation)) {
                newCity=new City(this,cityNumber,newStation);
                newCities.add(newCity);
                mNewCities.put(cityNumber,newCity);
                newStationsToCities.put(newStation,newCity);
                newCity.setSlots(newStation.getBaseSlots());
              }
 else {
                newCity=newStationsToCities.get(newStation);
              }
              oldToNewCities.put(oldCity,newCity);
              newTracks=getConnectionString(newTile,newRotation,newStation.getNumber());
              newCity.setTrackEdges(newTracks);
              log.debug("String_Node_Str" + oldCity.getUniqueId() + "String_Node_Str"+ currentTile.getId()+ "String_Node_Str"+ currentTileRotation+ "String_Node_Str"+ oldStation.getId()+ "String_Node_Str"+ getConnectionString(currentTile,currentTileRotation,oldStation.getNumber())+ "String_Node_Str"+ newCity.getUniqueId()+ "String_Node_Str"+ newTile.getId()+ "String_Node_Str"+ newRotation+ "String_Node_Str"+ newStation.getId()+ "String_Node_Str"+ newTracks);
              break station;
            }
          }
        }
      }
    }
    for (    Station newStation : newTile.getStations()) {
      if (newStationsToCities.containsKey(newStation))       continue;
      int cityNumber;
      for (cityNumber=1; mNewCities.containsKey(cityNumber); cityNumber++)       ;
      newCity=new City(this,cityNumber,newStation);
      newCities.add(newCity);
      mNewCities.put(cityNumber,newCity);
      newStationsToCities.put(newStation,newCity);
      newCity.setSlots(newStation.getBaseSlots());
      newTracks=getConnectionString(newTile,newRotation,newStation.getNumber());
      newCity.setTrackEdges(newTracks);
      log.debug("String_Node_Str" + newCity.getUniqueId() + "String_Node_Str"+ newTile.getId()+ "String_Node_Str"+ newRotation+ "String_Node_Str"+ newStation.getId()+ "String_Node_Str"+ newTracks);
    }
    Map<TokenI,TokenHolderI> tokenDestinations=new HashMap<TokenI,TokenHolderI>();
    for (    City oldCity : cities) {
      newCity=oldToNewCities.get(oldCity);
      if (newCity != null) {
        oldtoken:         for (        TokenI token : oldCity.getTokens()) {
          if (token instanceof BaseToken) {
            PublicCompanyI company=((BaseToken)token).getCompany();
            for (            TokenI token2 : newCity.getTokens()) {
              if (token2 instanceof BaseToken && company == ((BaseToken)token2).getCompany()) {
                tokenDestinations.put(token,company);
                log.debug("String_Node_Str" + token.getUniqueId() + "String_Node_Str"+ oldCity.getName()+ "String_Node_Str"+ company.getName());
                ReportBuffer.add(LocalText.getText("String_Node_Str",new String[]{company.getName(),getName()}));
                continue oldtoken;
              }
            }
          }
          tokenDestinations.put(token,newCity);
          log.debug("String_Node_Str" + token.getUniqueId() + "String_Node_Str"+ oldCity.getName()+ "String_Node_Str"+ newCity.getName());
        }
        if (!tokenDestinations.isEmpty()) {
          for (          TokenI token : tokenDestinations.keySet()) {
            token.moveTo(tokenDestinations.get(token));
          }
        }
      }
 else {
        log.debug("String_Node_Str");
      }
    }
    new TileMove(this,currentTile,currentTileRotation,cities,newTile,newRotation,newCities);
  }
}

Fixed version (ground truth):
/** 
 * Prepare a tile upgrade. The actual tile replacement is done in replaceTile(), via a TileMove object.
 */
public void upgrade(TileI newTile,int newRotation){
  City newCity;
  String newTracks;
  if (currentTile.getNumStations() == newTile.getNumStations()) {
    for (    City city : cities) {
      Station oldStation=city.getRelatedStation();
      int[] oldTrackEnds=getTrackEndPoints(currentTile,currentTileRotation,oldStation);
      if (oldTrackEnds.length == 0) {
        Station newStation=newTile.getStations().get(city.getNumber() - 1);
        city.setRelatedStation(newStation);
        city.setSlots(newStation.getBaseSlots());
        log.debug("String_Node_Str" + city.getUniqueId() + "String_Node_Str"+ oldStation.getId()+ "String_Node_Str"+ getConnectionString(currentTile,currentTileRotation,oldStation.getNumber())+ "String_Node_Str"+ newStation.getId()+ "String_Node_Str"+ getConnectionString(newTile,newRotation,newStation.getNumber()));
        continue;
      }
      station:       for (      Station newStation : newTile.getStations()) {
        int[] newTrackEnds=getTrackEndPoints(newTile,newRotation,newStation);
        for (int i=0; i < oldTrackEnds.length; i++) {
          for (int j=0; j < newTrackEnds.length; j++) {
            if (oldTrackEnds[i] == newTrackEnds[j]) {
              city.setRelatedStation(newStation);
              city.setSlots(newStation.getBaseSlots());
              newTracks=getConnectionString(newTile,newRotation,newStation.getNumber());
              city.setTrackEdges(newTracks);
              log.debug("String_Node_Str" + city.getUniqueId() + "String_Node_Str"+ oldStation.getId()+ "String_Node_Str"+ getConnectionString(currentTile,currentTileRotation,oldStation.getNumber())+ "String_Node_Str"+ newStation.getId()+ "String_Node_Str"+ newTracks);
              break station;
            }
          }
        }
      }
    }
    new TileMove(this,currentTile,currentTileRotation,cities,newTile,newRotation,cities);
  }
 else {
    List<City> newCities=new ArrayList<City>(4);
    Map<Integer,City> mNewCities=new HashMap<Integer,City>(4);
    Map<City,City> oldToNewCities=new HashMap<City,City>();
    Map<Station,City> newStationsToCities=new HashMap<Station,City>();
    int newCityNumber=0;
    for (    City oldCity : cities) {
      int cityNumber=oldCity.getNumber();
      Station oldStation=oldCity.getRelatedStation();
      int[] oldTrackEnds=getTrackEndPoints(currentTile,currentTileRotation,oldStation);
      log.debug("String_Node_Str" + currentTile.getId() + "String_Node_Str"+ oldCity.getNumber()+ "String_Node_Str"+ getConnectionString(currentTile,currentTileRotation,oldStation.getNumber()));
      station:       for (      Station newStation : newTile.getStations()) {
        int[] newTrackEnds=getTrackEndPoints(newTile,newRotation,newStation);
        log.debug("String_Node_Str" + newTile.getId() + "String_Node_Str"+ newStation.getNumber()+ "String_Node_Str"+ getConnectionString(newTile,newRotation,newStation.getNumber()));
        for (int i=0; i < oldTrackEnds.length; i++) {
          for (int j=0; j < newTrackEnds.length; j++) {
            if (oldTrackEnds[i] == newTrackEnds[j]) {
              if (!newStationsToCities.containsKey(newStation)) {
                newCity=new City(this,++newCityNumber,newStation);
                newCities.add(newCity);
                mNewCities.put(cityNumber,newCity);
                newStationsToCities.put(newStation,newCity);
                newCity.setSlots(newStation.getBaseSlots());
              }
 else {
                newCity=newStationsToCities.get(newStation);
              }
              oldToNewCities.put(oldCity,newCity);
              newTracks=getConnectionString(newTile,newRotation,newStation.getNumber());
              newCity.setTrackEdges(newTracks);
              log.debug("String_Node_Str" + oldCity.getUniqueId() + "String_Node_Str"+ currentTile.getId()+ "String_Node_Str"+ currentTileRotation+ "String_Node_Str"+ oldStation.getId()+ "String_Node_Str"+ getConnectionString(currentTile,currentTileRotation,oldStation.getNumber())+ "String_Node_Str"+ newCity.getUniqueId()+ "String_Node_Str"+ newTile.getId()+ "String_Node_Str"+ newRotation+ "String_Node_Str"+ newStation.getId()+ "String_Node_Str"+ newTracks);
              break station;
            }
          }
        }
      }
    }
    for (    City oldCity : cities) {
      if (oldToNewCities.containsKey(oldCity))       continue;
      Station oldStation=oldCity.getRelatedStation();
      int[] oldTrackEnds=getTrackEndPoints(currentTile,currentTileRotation,oldStation);
      station:       for (int i=0; i < oldTrackEnds.length; i++) {
        log.debug("String_Node_Str" + oldTrackEnds[i]);
        if (oldTrackEnds[i] < 0) {
          int oldStationNumber=-oldTrackEnds[i];
          for (          City oldCity2 : cities) {
            log.debug("String_Node_Str" + oldCity2.getNumber() + "String_Node_Str"+ oldCity2.getRelatedStation().getNumber());
            log.debug("String_Node_Str" + oldToNewCities.get(oldCity2));
            if (oldCity2.getRelatedStation().getNumber() == oldStationNumber && oldToNewCities.containsKey(oldCity2)) {
              newCity=oldToNewCities.get(oldCity2);
              oldToNewCities.put(oldCity,newCity);
              log.debug("String_Node_Str" + oldCity.getUniqueId() + "String_Node_Str"+ currentTile.getId()+ "String_Node_Str"+ currentTileRotation+ "String_Node_Str"+ oldStation.getId()+ "String_Node_Str"+ getConnectionString(currentTile,currentTileRotation,oldStation.getNumber())+ "String_Node_Str"+ newCity.getUniqueId()+ "String_Node_Str"+ newTile.getId()+ "String_Node_Str"+ newRotation+ "String_Node_Str"+ newCity.getRelatedStation().getId()+ "String_Node_Str"+ newCity.getTrackEdges());
              break station;
            }
          }
        }
      }
    }
    for (    Station newStation : newTile.getStations()) {
      if (newStationsToCities.containsKey(newStation))       continue;
      int cityNumber;
      for (cityNumber=1; mNewCities.containsKey(cityNumber); cityNumber++)       ;
      newCity=new City(this,++newCityNumber,newStation);
      newCities.add(newCity);
      mNewCities.put(cityNumber,newCity);
      newStationsToCities.put(newStation,newCity);
      newCity.setSlots(newStation.getBaseSlots());
      newTracks=getConnectionString(newTile,newRotation,newStation.getNumber());
      newCity.setTrackEdges(newTracks);
      log.debug("String_Node_Str" + newCity.getUniqueId() + "String_Node_Str"+ newTile.getId()+ "String_Node_Str"+ newRotation+ "String_Node_Str"+ newStation.getId()+ "String_Node_Str"+ newTracks);
    }
    Map<TokenI,TokenHolderI> tokenDestinations=new HashMap<TokenI,TokenHolderI>();
    for (    City oldCity : cities) {
      newCity=oldToNewCities.get(oldCity);
      if (newCity != null) {
        oldtoken:         for (        TokenI token : oldCity.getTokens()) {
          if (token instanceof BaseToken) {
            PublicCompanyI company=((BaseToken)token).getCompany();
            for (            TokenI token2 : newCity.getTokens()) {
              if (token2 instanceof BaseToken && company == ((BaseToken)token2).getCompany()) {
                tokenDestinations.put(token,company);
                log.debug("String_Node_Str" + token.getUniqueId() + "String_Node_Str"+ oldCity.getName()+ "String_Node_Str"+ company.getName());
                ReportBuffer.add(LocalText.getText("String_Node_Str",new String[]{company.getName(),getName()}));
                continue oldtoken;
              }
            }
          }
          tokenDestinations.put(token,newCity);
          log.debug("String_Node_Str" + token.getUniqueId() + "String_Node_Str"+ oldCity.getName()+ "String_Node_Str"+ newCity.getName());
        }
        if (!tokenDestinations.isEmpty()) {
          for (          TokenI token : tokenDestinations.keySet()) {
            token.moveTo(tokenDestinations.get(token));
          }
        }
      }
 else {
        log.debug("String_Node_Str");
      }
    }
    new TileMove(this,currentTile,currentTileRotation,cities,newTile,newRotation,newCities);
  }
}