private void gen_moves(GameState initial_position) {

    int steps_available = initial_position.getStepsRemaining();
    move_list_stack[steps_available].clear();
    // Generate all legal steps from current position
    initial_position.GENERATE_MOVES(move_list_stack[steps_available], FULL_BB,
      FULL_BB);

    for (ArimaaMove move : move_list_stack[steps_available]) {

      // Play the move
      GameState new_position = gs_stack[steps_available];
      new_position.play(move, initial_position);


      // Test for returning to initial position
      if (new_position.equals(this.saved_initial_position)) {
        initial_repeated_positions++;
        continue;
      }

      // Test for repetition of position
      long hash_code = new_position.getPositionHash();
      if (repetition.isRepetition(hash_code)) { // Has side effects
        repeated_positions++;
        continue;
      }


      // Check if we're getting official arimaa notation
      if ( get_notation && new_position.full_equals(desired_position) ) {
        calculate_notation();
        throw new ArrayIndexOutOfBoundsException();
      }


      // Base case for recursion
      if (new_position.getStepsRemaining() == 4) {
        if ( !get_notation ) {
          total_moves++;
          // Record the move
          ArimaaMove result = move_data.getMove();
          result.difference(saved_initial_position, new_position);
        }
      }

      else {
        // Generate the next steps
        gen_moves(new_position);
      }

    }
  }