<commit_before>require 'ostruct'

module Rubots
  class Robot
    attr_reader :x, :y, :angle, :gun_angle
    attr_writer :desired_angle, :desired_throttle, :desired_gun_angle

    # Some constants
    MAX_ANGLE      = 360 # Maximum angle. Wraps around to zero after this.
    ANGLE_STEP     = 1   # How much we change angle each tick.

    MAX_THROTTLE   = 10  # Max throttle. Can't go above.
    THROTTLE_STEP  = 1   # How much we change throttle each tick.

    SPEED_FACTOR   = 1   # How much movement does each throttle step represent

    MAX_GUN_ANGLE  = 360 # Maximum gun angle. Wraps around to zero after this.
    GUN_ANGLE_STEP = 2   # How much we change angle each tick.


    def initialize(strategy_class, game, x, y)
      @x = x
      @y = y
      @throttle  = @desired_throttle  = 0.0
      @angle     = @desired_angle     = 0.0
      @gun_angle = @desired_gun_angle = 0.0
      @game = game

      @strategy = strategy_class.new(@game.map, robot_data, nil)

      @destroyed = false

      @cooldown_timer = 0
    end

    def process_command
      return if @destroyed

      if @cooldown_timer > 0
        @cooldown_timer -= 1
      else
        command = @strategy.get_command(robot_data, targets_data)
        command.apply_to(self)
        @cooldown_timer = command.cooldown
      end
    end

    def tick
      return if @destroyed

      tick_angle
      tick_throttle
      tick_movement
      tick_gun
      tick_fire
    end

    def name
      @strategy.name
    end

    def do_fire
      @firing = true
    end

    def distance_to(other)
      x_dist = @x - other.x
      y_dist = @y - other.y
      Math.sqrt(x_dist ** 2 + y_dist ** 2)
    end

    def destroy
      @throttle = 0
      @destroyed = true
    end

    def destroyed?
      @destroyed
    end

  private

    def robot_data
      OpenStruct.new x: @x, y: @y, angle: @angle, throttle: @throttle, gun_angle: @gun_angle
    end

    def targets_data
      @game.robots.map do |target_robot|
        next if target_robot == self
        x_dist = @x - target_robot.x
        y_dist = @y - target_robot.y
        distance = Math.sqrt(x_dist ** 2 + y_dist ** 2)
        actual_angle = Math.atan2(x_dist, -y_dist) * 180 / Math::PI + 180
        relative_angle = (actual_angle - @angle) % 360
<commit_msg>Don't send the same array of targets to each robot.<commit_after>require 'ostruct'

module Rubots
  class Robot
    attr_reader :x, :y, :angle, :gun_angle
    attr_writer :desired_angle, :desired_throttle, :desired_gun_angle

    # Some constants
    MAX_ANGLE      = 360 # Maximum angle. Wraps around to zero after this.
    ANGLE_STEP     = 1   # How much we change angle each tick.

    MAX_THROTTLE   = 10  # Max throttle. Can't go above.
    THROTTLE_STEP  = 1   # How much we change throttle each tick.

    SPEED_FACTOR   = 1   # How much movement does each throttle step represent

    MAX_GUN_ANGLE  = 360 # Maximum gun angle. Wraps around to zero after this.
    GUN_ANGLE_STEP = 2   # How much we change angle each tick.


    def initialize(strategy_class, game, x, y)
      @x = x
      @y = y
      @throttle  = @desired_throttle  = 0.0
      @angle     = @desired_angle     = 0.0
      @gun_angle = @desired_gun_angle = 0.0
      @game = game

      @strategy = strategy_class.new(@game.map, robot_data, nil)

      @destroyed = false

      @cooldown_timer = 0
    end

    def process_command
      return if @destroyed

      if @cooldown_timer > 0
        @cooldown_timer -= 1
      else
        command = @strategy.get_command(robot_data, targets_data)
        command.apply_to(self)
        @cooldown_timer = command.cooldown
      end
    end

    def tick
      return if @destroyed

      tick_angle
      tick_throttle
      tick_movement
      tick_gun
      tick_fire
    end

    def name
      @strategy.name
    end

    def do_fire
      @firing = true
    end

    def distance_to(other)
      x_dist = @x - other.x
      y_dist = @y - other.y
      Math.sqrt(x_dist ** 2 + y_dist ** 2)
    end

    def destroy
      @throttle = 0
      @destroyed = true
    end

    def destroyed?
      @destroyed
    end

  private

    def robot_data
      OpenStruct.new x: @x, y: @y, angle: @angle, throttle: @throttle, gun_angle: @gun_angle
    end

    def targets_data
      robots_arrays = @game.robots.slice_before(self).to_a
      robots_arrays.last.shift # First is self
      robots = robots_arrays.reverse.inject(&:+)
      robots.map do |target_robot|
        next if target_robot == self
        x_dist = @x - target_robot.x
        y_dist = @y - target_robot.y
        distance = Math.sqrt(x_dist ** 2 + y_dist ** 2)
        actual_angle = Math.atan2(x_dist, -y_dist) * 180 / Math::PI + 180
        relative_angle = (actual_angle - @angle) % 360

{'fraction_non_alphanumeric': 0.08083769633507853, 'fraction_numerical': 0.015078534031413612, 'mean_word_length': 2.1215686274509804, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5174238', 'n_tokens_mistral': 1753, 'n_tokens_neox': 1616, 'n_words': 455}