Program: 173766
Project: 173766
Buggy source:
/** 
 * To be called after each change, to re-establish the currently allowed actions. (new method, intended to absorb code from several other methods).
 */
@Override public boolean setPossibleActions(){
  int operatingCompanyIndex=operatingCompanyIndexObject.intValue();
  operatingCompany=operatingCompanyArray[operatingCompanyIndex];
  possibleActions.clear();
  selectedAction=null;
  boolean forced=false;
  if (getStep() == GameDef.OrStep.INITIAL) {
    initTurn();
    if (noMapMode) {
      nextStep(GameDef.OrStep.LAY_TOKEN);
    }
 else {
      setStep(GameDef.OrStep.LAY_TRACK);
    }
  }
  GameDef.OrStep step=getStep();
  if (step == GameDef.OrStep.LAY_TRACK) {
    if (!operatingCompany.hasLaidHomeBaseTokens()) {
      possibleActions.add(new LayBaseToken(operatingCompany.getHomeHex()));
      forced=true;
    }
 else {
      setNormalTileLays();
      setSpecialTileLays();
      log.debug("String_Node_Str" + currentNormalTileLays.size());
      log.debug("String_Node_Str" + currentSpecialTileLays.size());
      possibleActions.addAll(currentNormalTileLays);
      possibleActions.addAll(currentSpecialTileLays);
      possibleActions.add(new NullAction(NullAction.SKIP));
    }
  }
 else   if (step == GameDef.OrStep.LAY_TOKEN) {
    setNormalTokenLays();
    setSpecialTokenLays();
    log.debug("String_Node_Str" + currentNormalTokenLays.size());
    log.debug("String_Node_Str" + currentSpecialTokenLays.size());
    possibleActions.addAll(currentNormalTokenLays);
    possibleActions.addAll(currentSpecialTokenLays);
    possibleActions.add(new NullAction(NullAction.SKIP));
  }
 else   if (step == GameDef.OrStep.CALC_REVENUE) {
    prepareRevenueAndDividendAction();
    if (noMapMode)     prepareNoMapActions();
  }
 else   if (step == GameDef.OrStep.BUY_TRAIN) {
    setBuyableTrains();
    doneAllowed=true;
    if (noMapMode && (operatingCompany.getLastRevenue() == 0))     prepareNoMapActions();
  }
 else   if (step == GameDef.OrStep.DISCARD_TRAINS) {
    forced=true;
    setTrainsToDiscard();
  }
  if (!forced) {
    setBonusTokenLays();
    setDestinationActions();
    setGameSpecificPossibleActions();
    if (getCurrentPhase().isPrivateSellingAllowed()) {
      int currentPlayerIndex=operatingCompany.getPresident().getIndex();
      Player player;
      int minPrice, maxPrice;
      List<Player> players=getPlayers();
      int numberOfPlayers=getNumberOfPlayers();
      for (int i=currentPlayerIndex; i < currentPlayerIndex + numberOfPlayers; i++) {
        player=players.get(i % numberOfPlayers);
        for (        PrivateCompanyI privComp : player.getPortfolio().getPrivateCompanies()) {
          minPrice=(int)(privComp.getBasePrice() * operatingCompany.getLowerPrivatePriceFactor());
          maxPrice=(int)(privComp.getBasePrice() * operatingCompany.getUpperPrivatePriceFactor());
          possibleActions.add(new BuyPrivate(privComp,minPrice,maxPrice));
        }
      }
    }
    if (operatingCompany.canUseSpecialProperties()) {
      List<SpecialPropertyI> commonSP=gameManager.getCommonSpecialProperties();
      if (commonSP != null) {
        SellBonusToken sbt;
        loop:         for (        SpecialPropertyI sp : commonSP) {
          if (sp instanceof SellBonusToken) {
            sbt=(SellBonusToken)sp;
            if (operatingCompany.getBonuses() != null) {
              for (              Bonus bonus : operatingCompany.getBonuses()) {
                if (bonus.getName().equals(sp.getName()))                 continue loop;
              }
            }
            possibleActions.add(new BuyBonusToken(sbt));
          }
        }
      }
      List<SpecialPropertyI> orsps=operatingCompany.getPortfolio().getAllSpecialProperties();
      if (orsps != null) {
        for (        SpecialPropertyI sp : orsps) {
          if (!sp.isExercised() && sp.isUsableIfOwnedByCompany() && sp.isUsableDuringOR()) {
            if (sp instanceof SpecialTokenLay) {
              if (getStep() != GameDef.OrStep.LAY_TOKEN) {
                possibleActions.add(new LayBaseToken((SpecialTokenLay)sp));
              }
            }
 else {
              possibleActions.add(new UseSpecialProperty(sp));
            }
          }
        }
      }
      orsps=getCurrentPlayer().getPortfolio().getAllSpecialProperties();
      if (orsps != null) {
        for (        SpecialPropertyI sp : orsps) {
          if (!sp.isExercised() && sp.isUsableIfOwnedByPlayer() && sp.isUsableDuringOR()) {
            if (sp instanceof SpecialTokenLay) {
              if (getStep() != GameDef.OrStep.LAY_TOKEN) {
                possibleActions.add(new LayBaseToken((SpecialTokenLay)sp));
              }
            }
 else {
              possibleActions.add(new UseSpecialProperty(sp));
            }
          }
        }
      }
    }
  }
  if (doneAllowed) {
    possibleActions.add(new NullAction(NullAction.DONE));
  }
  for (  PossibleAction pa : possibleActions.getList()) {
    try {
      log.debug(operatingCompany.getName() + "String_Node_Str" + pa.toString());
    }
 catch (    Exception e) {
      log.error("String_Node_Str" + pa.getClass(),e);
    }
  }
  return true;
}

Fixed version (ground truth):
/** 
 * To be called after each change, to re-establish the currently allowed actions. (new method, intended to absorb code from several other methods).
 */
@Override public boolean setPossibleActions(){
  int operatingCompanyIndex=operatingCompanyIndexObject.intValue();
  operatingCompany=operatingCompanyArray[operatingCompanyIndex];
  possibleActions.clear();
  selectedAction=null;
  boolean forced=false;
  if (getStep() == GameDef.OrStep.INITIAL) {
    initTurn();
    if (noMapMode) {
      nextStep(GameDef.OrStep.LAY_TOKEN);
    }
 else {
      getNormalTileLays();
      setStep(GameDef.OrStep.LAY_TRACK);
    }
  }
  GameDef.OrStep step=getStep();
  if (step == GameDef.OrStep.LAY_TRACK) {
    if (!operatingCompany.hasLaidHomeBaseTokens()) {
      possibleActions.add(new LayBaseToken(operatingCompany.getHomeHex()));
      forced=true;
    }
 else {
      setNormalTileLays();
      setSpecialTileLays();
      log.debug("String_Node_Str" + currentNormalTileLays.size());
      log.debug("String_Node_Str" + currentSpecialTileLays.size());
      possibleActions.addAll(currentNormalTileLays);
      possibleActions.addAll(currentSpecialTileLays);
      possibleActions.add(new NullAction(NullAction.SKIP));
    }
  }
 else   if (step == GameDef.OrStep.LAY_TOKEN) {
    setNormalTokenLays();
    setSpecialTokenLays();
    log.debug("String_Node_Str" + currentNormalTokenLays.size());
    log.debug("String_Node_Str" + currentSpecialTokenLays.size());
    possibleActions.addAll(currentNormalTokenLays);
    possibleActions.addAll(currentSpecialTokenLays);
    possibleActions.add(new NullAction(NullAction.SKIP));
  }
 else   if (step == GameDef.OrStep.CALC_REVENUE) {
    prepareRevenueAndDividendAction();
    if (noMapMode)     prepareNoMapActions();
  }
 else   if (step == GameDef.OrStep.BUY_TRAIN) {
    setBuyableTrains();
    doneAllowed=true;
    if (noMapMode && (operatingCompany.getLastRevenue() == 0))     prepareNoMapActions();
  }
 else   if (step == GameDef.OrStep.DISCARD_TRAINS) {
    forced=true;
    setTrainsToDiscard();
  }
  if (!forced) {
    setBonusTokenLays();
    setDestinationActions();
    setGameSpecificPossibleActions();
    if (getCurrentPhase().isPrivateSellingAllowed()) {
      int currentPlayerIndex=operatingCompany.getPresident().getIndex();
      Player player;
      int minPrice, maxPrice;
      List<Player> players=getPlayers();
      int numberOfPlayers=getNumberOfPlayers();
      for (int i=currentPlayerIndex; i < currentPlayerIndex + numberOfPlayers; i++) {
        player=players.get(i % numberOfPlayers);
        for (        PrivateCompanyI privComp : player.getPortfolio().getPrivateCompanies()) {
          minPrice=(int)(privComp.getBasePrice() * operatingCompany.getLowerPrivatePriceFactor());
          maxPrice=(int)(privComp.getBasePrice() * operatingCompany.getUpperPrivatePriceFactor());
          possibleActions.add(new BuyPrivate(privComp,minPrice,maxPrice));
        }
      }
    }
    if (operatingCompany.canUseSpecialProperties()) {
      List<SpecialPropertyI> commonSP=gameManager.getCommonSpecialProperties();
      if (commonSP != null) {
        SellBonusToken sbt;
        loop:         for (        SpecialPropertyI sp : commonSP) {
          if (sp instanceof SellBonusToken) {
            sbt=(SellBonusToken)sp;
            if (operatingCompany.getBonuses() != null) {
              for (              Bonus bonus : operatingCompany.getBonuses()) {
                if (bonus.getName().equals(sp.getName()))                 continue loop;
              }
            }
            possibleActions.add(new BuyBonusToken(sbt));
          }
        }
      }
      List<SpecialPropertyI> orsps=operatingCompany.getPortfolio().getAllSpecialProperties();
      if (orsps != null) {
        for (        SpecialPropertyI sp : orsps) {
          if (!sp.isExercised() && sp.isUsableIfOwnedByCompany() && sp.isUsableDuringOR()) {
            if (sp instanceof SpecialTokenLay) {
              if (getStep() != GameDef.OrStep.LAY_TOKEN) {
                possibleActions.add(new LayBaseToken((SpecialTokenLay)sp));
              }
            }
 else {
              possibleActions.add(new UseSpecialProperty(sp));
            }
          }
        }
      }
      orsps=getCurrentPlayer().getPortfolio().getAllSpecialProperties();
      if (orsps != null) {
        for (        SpecialPropertyI sp : orsps) {
          if (!sp.isExercised() && sp.isUsableIfOwnedByPlayer() && sp.isUsableDuringOR()) {
            if (sp instanceof SpecialTokenLay) {
              if (getStep() != GameDef.OrStep.LAY_TOKEN) {
                possibleActions.add(new LayBaseToken((SpecialTokenLay)sp));
              }
            }
 else {
              possibleActions.add(new UseSpecialProperty(sp));
            }
          }
        }
      }
    }
  }
  if (doneAllowed) {
    possibleActions.add(new NullAction(NullAction.DONE));
  }
  for (  PossibleAction pa : possibleActions.getList()) {
    try {
      log.debug(operatingCompany.getName() + "String_Node_Str" + pa.toString());
    }
 catch (    Exception e) {
      log.error("String_Node_Str" + pa.getClass(),e);
    }
  }
  return true;
}