code: @Override
      protected void searchStep() {
          // get list of possible moves
          List<? extends Move<? super SolutionType>> moves = getNeighbourhood().getAllMoves(getCurrentSolution());
          // shuffle moves
          Collections.shuffle(moves);
          // find best admissible move, or first admissible improvement (if any)
          Move<? super SolutionType> move = getBestMove(
              // inspect all moves
              moves,
              // not necessarily an improvement
              false,
              // return first improvement move, if any
              true,
              // filter tabu moves (with aspiration criterion)
              getTabuFilter()
          );
          // process chosen move
          if (move != null) {
              // accept move (automatically updates tabu memory)
              accept(move);
          } else {
              // no valid non-tabu neighbour found: terminate search
              stop();
          }
      }
docs: One step of the first-best-admissible tabu search algorithm.
  All possible moves are inspected in random order, and either the first admissible improvement,
  if any, or, else, the best admissible move, is applied to the current solution.
  
  @throws IncompatibleTabuMemoryException if the applied tabu memory is not compatible with the type of moves
  generated by the applied neighbourhood
  @throws JamesRuntimeException if depending on malfunctioning components (problem, neighbourhood, ...)