code: @Override
      protected void searchStep() {
          // use k-th neighbourhood to get a random valid move
          Move<? super SolutionType> move = getNeighbourhoods().get(k).getRandomMove(getCurrentSolution(), getRandom());
          // check: got move ?
          if(move != null){
              // check: improvement ?
              if(isImprovement(move)){
                  // improvement: accept move and reset k
                  accept(move);
                  k = 0;
              } else {
                  reject(move);
                  // no improvement: switch to next neighbourhood, if any
                  nextNeighbourhood();
              }
          } else {
              // k-th neighbourhood did not produce any random move: switch to next neighbourhood, if any
              nextNeighbourhood();
          }
      }
docs: Samples a random neighbour of the current solution, using the k-th neighbourhood, and accepts it as the new
  current solution if it is an improvement. If no improvement is found, k is increased. Upon each improvement,
  k is reset to 0. If cycling is enabled (which is the default setting), k is also reset to 0 when all
  neighbourhoods have been used so that the first neighbourhood will again be applied in the next step.
  If cycling is disabled, the search stops if no improvement was found using the last available neighbourhood.
  <p>
  If the k-th neighbourhood is unable to generate any move, k is also increased to try the next neighbourhood
  (if any) in the next step.
  
  @throws JamesRuntimeException if depending on malfunctioning components (problem, neighbourhood, ...)