google ai challenge vol.2-完善接口库

2014-05-04  本文已影响43人  LinuxNerd

前提

完善工具的前提是先要了解工具,建议先看一遍ant.rb里的内容,了解他实现了哪些数据接口。
当然如果仔细看过官方的教程的话,会发现教程所使用的python和java的库的功能比ruby的强大很多。
没关系,我们这就来丰满手里的工具。

主要接口介绍

Ant类

Ant类是描述单个蚂蚁的类,主要方法是def order direction。命令蚂蚁下一回合走的方向,direction参数为方向('E','S','W','N')。后续会对该方法进行封装。

Square类

描述了地图上每一个格子的类。用于各种判断地形的操作。主要的方法是def neighbor direction,探测临近点的信息。

AI类

这个类很难描述,只能从一些特征上描述,每回合都会刷新内容。
和MyBot.rb中的描述类似

ai.setup do |ai|
    # 执行初始化内容
end

ai.run do |ai|
    # 执行一回合的动作
end

动手完善工具

需要一个公共库,来放置一些类似调试日志、计算距离等功能的方法。计算距离是每个蚂蚁安排命令优先级最基本的功能,因此我们先用这两个功能做例子。

创建公共库

创建utils.rb:

module Utils
  # For ordering ant
  def spherical_distance(loc_a, loc_b, row_max, col_max)
    vertical_side = if (loc_a.row - loc_b.row).abs > row_max/2
                      row_max - (loc_a.row - loc_b.row).abs
                    else
                      (loc_a.row - loc_b.row).abs
                    end

    horizontal_side = if (loc_a.col - loc_b.col).abs > col_max/2
                      col_max - (loc_a.col - loc_b.col).abs
                    else
                      (loc_a.col - loc_b.col).abs
                    end

    Math.hypot(vertical_side, horizontal_side)
  end

  # For calculating vision
  def straight_distance(loc_a, loc_b)
    Math.hypot(loc_a.col - loc_b.col, loc_a.row - loc_b.row)
  end

  class Logger
    attr_accessor :logfile

    def initialize(file)
      @logfile = file
    end

    def info message
      message ||= "nil"
      file_stream = File.new(@logfile, "a")
      file_stream.write("[" + Time.now.strftime("%Y-%m-%d %H:%M:%S") + "]" + message.to_s + "\n")
      file_stream.close  
    end
  end
end

spherical_distancestraight_distance使用Math.hypot计算两点之间的直线距离。spherical_distance因为地图是类似球面到了边界,可以从另一边出现(虽然视野是不能跨边界的)。而straight_distance直线距离计算是用来判断视野的(在ants.rb中有see?方法。

增加Ant类功能

增加了distance方法后,就可以对Ant类进行一些扩展,偷懒直接就在里面ants.rb里加代码了。

...
class Ant
  ...
  def see?(loc)
    distance(@square, loc) <= @ai.viewradius
  end

  def towards(dir)
    @square.neighbor dir
  end

  def inspect
    "<Row #{@square.row}, Col #{@square.col}>"
  end
end
...

see?(loc)方法判断蚂蚁的可是范围,toward(dir)对临近的格子的方法作语义更通畅的封装。

增加Square类功能

ants.rb

...
class Square
  ...
  # Returns true if this square is my hill, false if not
  def my_hill?; @hill && @hill == 0; end
  # Returns true if this square is enemy hill, false if not
  def enemy_hill?; @hill && @hill != 0; end
  ...
  def occupied?
    water? || food? || ant? || my_hill?
  end

  def inspect
    "<Row #{@row}, Col #{@col}>"
  end

增加AI类功能

为了在setup阶段能获取到地图,给后续初始化未探索区域,调整map的位置

class AI
  ...
  def setup
    ...
    @map=Array.new(@rows){|row| Array.new(@cols){|col| Square.new false, false, false, nil, row, col, self } }
    yield self
    @stdout.puts 'go'
    @stdout.flush
    
    @did_setup=true
end

再增加获取地图上资源的方法:地图上可视范围内食物、敌方巢穴、我方巢穴等。

class AI
  ...
  def foods
    @map.flatten.select(&:food?)
  end

  def enemy_hills
    @map.flatten.select { |square| square.hill? && !square.my_hill? }
  end

  def my_ants_in_hill
    self.my_ants.select { |ant| ant.square.hill? }
  end

  def my_hills
    @map.flatten.select { |square| square.hill? && square.my_hill? }
  end
  ...
end
上一篇下一篇

猜你喜欢

热点阅读