Source

snake-challenge / examples / makestory / musashi.rb

Full commit
#! /usr/bin/ruby
require 'rubygems'
require 'json'
require 'net/http'

@http = Net::HTTP.new("50.56.97.47", 80)
@room_id = ARGV[0] || 0
@user_name = ARGV[1] || 'Musashi'
@direction_hash = {0 => 'left',1 => 'up',2 => 'right',3 => 'down'}

def move(position=[0,0],directions=0)
  directions.each do |direction|
    case direction
    when 0
      position = [(position[0] - 1),position[1]]
    when 1
      position = [position[0],(position[1] - 1)]
    when 2
      position = [(position[0] + 1),position[1]]
    when 3
      position = [position[0],(position[1] + 1)]
    end
  end
  position
end

def map
  request = Net::HTTP::Get.new("/room/#{@room_id}/map")
  response = @http.request(request)
  result = JSON.parse(response.body)
  @map = result
end

def distance(from,to)
  sub_x = (from[0] - to[0]).abs
  sub_y = (from[1] - to[1]).abs
  (sub_x > @map['size'][0]/2 ? @map['size'][0] - sub_x : sub_x) + (sub_y > @map['size'][1]/2 ? @map['size'][1] - sub_y : sub_y) 
end

def info
  request = Net::HTTP::Get.new("/room/#{@room_id}/info")
  response = @http.request(request)
  result = JSON.parse(response.body)
  @info = result
end

def turn
  request = Net::HTTP::Post.new("/room/#{@room_id}/turn")
  request.set_form_data(:id => @me["id"], :round => @info["round"], :direction => @next)
  response = @http.request(request)
  result = JSON.parse(response.body)
  @turn, @info = result[0], result[1]
end

def add
  request = Net::HTTP::Post.new("/room/#{@room_id}/add")
  request.set_form_data(:name => @user_name, :type => "ruby")
  response = @http.request(request)
  result = JSON.parse(response.body)
  @me, @info = result[0], result[1]
end

def think
  @prev = @info["snakes"][@me["seq"]]["direction"]
  @head = @info["snakes"][@me["seq"]]['body'].first
  @obstacles = @map['walls'] + @info['eggs'] + @info['snakes'].map{|s| s['body'][0..-2]}.flatten(1) 
  # s['body'][0..-2] means ignore snake`s last tail but no consider snake change his length here
  @choices = Range.new(0,3).to_a
  @choices -= [((@prev + 2) % 4)]  # avoid turnback
  @bangs = @choices.map{|d| d if @obstacles.include?(move(@head,[d]))} 
  @traps = @choices.map{|d| d if (@obstacles & [move(@head,[d,0]),move(@head,[d,1]),move(@head,[d,2]),move(@head,[d,3])]).length > 3}
  @choices -= @bangs
  @choices -= @traps
  @homogeneous = (@info["snakes"] - [@info["snakes"][@me["seq"]]]).select{|s| s['alive'] && s['type'] == 'ruby'}  # aliving homogeneous
  if @homogeneous.empty? 
    @goal = @info['gems'].sort_by{|g| distance(g,@head)}.first 
  else
    @goal = @info['gems'].select{|g| distance(g,@head) - @homogeneous.map{|s| distance(g,s['body'][0])}.min < 0 }.sort_by{|g| distance(g,@head)}.first  
  end
  if @goal
    @next = @choices.sort_by{|d| distance(move(@head,[d]),@goal)}.first
  else
    @next = @choices.shuffle[0]
  end
end

map
add
while @info['status'] == 'waitplayer'
  p 'Waiting Player...' 
  info
  sleep 0.5
end
puts 'Game started'
while @info['status'] == 'running'
  think
  turn
  puts "#{@direction_hash[@next]}"
end

puts "Total Round #{@info['round']}"
puts "Score:"
@info['snakes'].each do |s|
  puts " #{s['name']}[#{s['alive'] ? 'alive' : 'dead'}]: #{s['body'].size} "
end
puts 'Game Over'