Skip to content

@montas /gist:5604340
Created

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
class Numeric
def degrees
self * Math::PI / 180
end
end
module RobotJoust
TIME_PRECISION = 0.1
BOUNCE_FALLOFF = 0.9 # -10%
class Robot
RADIUS = 250
attr_accessor :position, :vector, :speed
def initialize position, angle, initial_speed
@speed = initial_speed
@pos_x = position[:x]
@pos_y = position[:y]
@vector = {
x: (Math.cos(angle.degrees) * @speed * RobotJoust::TIME_PRECISION),
y: (Math.sin(-angle.degrees) * @speed * RobotJoust::TIME_PRECISION)
}
end
def move bounds
@pos_x += @vector[:x]
new_pos_y = (@pos_y + @vector[:y])
if 0 >= new_pos_y - RADIUS or new_pos_y + RADIUS >= bounds[:height]
bounce bounds
else
@pos_y += @vector[:y]
end
end
def bounce bounds
# top bounce
if @vector[:y] >= 0
dist_from_bounce = (bounds[:height] - @pos_y) - RADIUS
dist_after_bounce = (@vector[:y] - dist_from_bounce) * RobotJoust::BOUNCE_FALLOFF
@pos_y = bounds[:height] - RADIUS - dist_after_bounce
# bottom bounce
else
dist_from_bounce = @pos_y - RADIUS
dist_after_bounce = (-@vector[:y] - dist_from_bounce) * RobotJoust::BOUNCE_FALLOFF
@pos_y = RADIUS + dist_after_bounce
end
@vector[:y] *= -RobotJoust::BOUNCE_FALLOFF
@vector[:x] *= RobotJoust::BOUNCE_FALLOFF
@speed *= RobotJoust::BOUNCE_FALLOFF
end
def position
{x: @pos_x, y: @pos_y}
end
def to_s
"Robot: #{position.to_s} | #{@vector}"
end
end
class Arena
attr_accessor :bounds, :robots
def initialize(width, height)
@cycles = 0
@robots = []
@bounds = {width: width, height: height}
end
def add_robot(robot)
@robots << robot
end
def check_collisions!
@robots.each do |robot|
if robot.position[:x] < 0 or robot.position[:x] > @bounds[:width]
puts "No winner found"
return true
end
end
x_dist = @robots[0].position[:x] - @robots[1].position[:x]
y_dist = @robots[0].position[:y] - @robots[1].position[:y]
if Math.sqrt(x_dist * x_dist + y_dist * y_dist) <= 2*RobotJoust::Robot::RADIUS
if @robots[0].speed > @robots[1].speed
puts "Left robot wins at #{elapsed_time} seconds."
else
puts "Right robot wins at #{elapsed_time} seconds."
end
return true
end
false
end
def joust!
while true
@robots.each do |robot|
robot.move(@bounds)
end
break if check_collisions!
@cycles += 1
end
end
def elapsed_time
@cycles * RobotJoust::TIME_PRECISION
end
def to_s
"Arena: #{@bounds.to_s}"
end
end
class Match
def initialize input
lines = input
arena_details = lines[0].split(" ").map(&:to_i)
@arena = RobotJoust::Arena.new(arena_details[0] * 1000, arena_details[1] * 1000)
left_robot_details = lines[1].split(" ").map(&:to_i)
@arena.add_robot(RobotJoust::Robot.new(
{
x: 0,
y: @arena.bounds[:height]/2
},
left_robot_details[0],
left_robot_details[1])
)
right_robot_details = lines[2].split(" ").map(&:to_i)
@arena.add_robot(RobotJoust::Robot.new(
{
x: @arena.bounds[:width],
y: @arena.bounds[:height]/2
},
right_robot_details[0] + 180,
right_robot_details[1])
)
end
def play!
@arena.joust!
end
end
end
match = RobotJoust::Match.new(readlines)
match.play!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.