public void decideNextStep(LocalSearchStepScope localSearchStepScope) {
   WorkingMemory workingMemory = localSearchStepScope.getWorkingMemory();
   Iterator<Move> moveIterator = selector.moveIterator(localSearchStepScope);
   while (moveIterator.hasNext()) {
     Move move = moveIterator.next();
     MoveScope moveScope = new MoveScope(localSearchStepScope);
     moveScope.setMove(move);
     // Filter out not doable moves
     if (move.isMoveDoable(workingMemory)) {
       doMove(moveScope);
       if (forager.isQuitEarly()) {
         break;
       }
     } else {
       logger.debug("    Ignoring not doable move ({}).", move);
     }
   }
   MoveScope pickedMoveScope = forager.pickMove(localSearchStepScope);
   if (pickedMoveScope != null) {
     Move step = pickedMoveScope.getMove();
     localSearchStepScope.setStep(step);
     if (logger.isInfoEnabled()) {
       localSearchStepScope.setStepString(step.toString());
     }
     localSearchStepScope.setUndoStep(step.createUndoMove(workingMemory));
     localSearchStepScope.setScore(pickedMoveScope.getScore());
   }
 }
 @Override
 protected Collection<? extends Object> findNewTabu(LocalSearchStepScope localSearchStepScope) {
   Move tabuMove;
   if (useUndoMoveAsTabuMove) {
     tabuMove = localSearchStepScope.getUndoStep();
   } else {
     tabuMove = localSearchStepScope.getStep();
   }
   return Collections.singletonList(tabuMove);
 }
 public void beforeDeciding(LocalSearchStepScope localSearchStepScope) {
   deciderScoreComparatorFactory.beforeDeciding(localSearchStepScope);
   localSearchStepScope.setDeciderScoreComparator(
       deciderScoreComparatorFactory.createDeciderScoreComparator());
   selector.beforeDeciding(localSearchStepScope);
   acceptor.beforeDeciding(localSearchStepScope);
   forager.beforeDeciding(localSearchStepScope);
 }
 @Override
 public void stepEnded(LocalSearchStepScope localSearchStepScope) {
   if (localSearchStepScope.getStepIndex()
       == localSearchStepScope.getLocalSearchSolverPhaseScope().getBestSolutionStepIndex()) {
     // New best score
     waterLevelScore =
         localSearchStepScope
             .getLocalSearchSolverPhaseScope()
             .getBestScore()
             .multiply(waterLevelUpperBoundRate);
   } else {
     Score perfectMaximumScore =
         localSearchStepScope
             .getLocalSearchSolverPhaseScope()
             .getScoreDefinition()
             .getPerfectMaximumScore();
     Score waterLevelAugend =
         perfectMaximumScore.subtract(waterLevelScore).multiply(waterRisingRate);
     waterLevelScore = waterLevelScore.add(waterLevelAugend);
     // TODO maybe if waterlevel is higher than bestScore, than ...
   }
 }
 @Override
 protected Collection<? extends Object> findNewTabu(LocalSearchStepScope stepScope) {
   return stepScope.getStep().getPlanningEntities();
 }