brawl 0.0.0.alpha → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
 - data/.rspec +0 -0
 - data/README.md +43 -0
 - data/_design/ClassDescriptions.txt +98 -0
 - data/_design/Psudo_Program.rb +113 -0
 - data/_design/array.rb +4 -0
 - data/_design/threads.rb +71 -0
 - data/_spike/Communications/communications.rb +2 -0
 - data/_spike/Communications/lib/communications/com_linker.rb +11 -0
 - data/_spike/Communications/lib/communications/null_modem.rb +11 -0
 - data/_spike/Communications/spec/communications/com_linker_spec.rb +37 -0
 - data/_spike/DRb/arena.rb +32 -0
 - data/_spike/DRb/battle_controller.rb +54 -0
 - data/_spike/DRb/bot.rb +23 -0
 - data/_spike/DRb/bot_runner.rb +110 -0
 - data/_spike/DRb/comment.txt +11 -0
 - data/_spike/DRb/server.rb +28 -0
 - data/_spike/DRb/test_bot.rb +6 -0
 - data/_spike/array.rb +7 -0
 - data/_spike/atan2.rb +39 -0
 - data/_spike/battle.rb +202 -0
 - data/_spike/break.rb +10 -0
 - data/_spike/circles.rb +29 -0
 - data/_spike/cleaner_attribs.rb +13 -0
 - data/_spike/comlink.rb +61 -0
 - data/_spike/concat.rb +27 -0
 - data/_spike/example_bot.rb +42 -0
 - data/_spike/forwarding_instance.rb +32 -0
 - data/_spike/hash_loop.rb +17 -0
 - data/_spike/hashing.rb +7 -0
 - data/_spike/hook.rb +19 -0
 - data/_spike/mod.rb +10 -0
 - data/_spike/point_in_cone.rb +20 -0
 - data/_spike/runner.rb +44 -0
 - data/_spike/safe.rb +28 -0
 - data/brawl.gemspec +4 -3
 - data/example/example_battle.rb +173 -0
 - data/example/logview.txt +6394 -0
 - data/lib/brawl.rb +14 -3
 - data/lib/brawl/_helper.rb +65 -0
 - data/lib/brawl/arena.rb +118 -0
 - data/lib/brawl/basic_arena_object.rb +35 -0
 - data/lib/brawl/basic_bot.rb +69 -0
 - data/lib/brawl/battle_controller.rb +97 -0
 - data/lib/brawl/bot_proxy.rb +60 -0
 - data/lib/brawl/clock.rb +36 -0
 - data/lib/brawl/parts.rb +3 -0
 - data/lib/brawl/parts/basic_motor.rb +55 -0
 - data/lib/brawl/parts/basic_scanner.rb +33 -0
 - data/lib/brawl/parts/basic_weapon.rb +47 -0
 - data/lib/brawl/version.rb +1 -1
 - data/lib/brawl/wall.rb +9 -0
 - data/spec/brawl/arena_spec.rb +163 -0
 - data/spec/brawl/basic_arena_object_spec.rb +40 -0
 - data/spec/brawl/basic_bot_spec.rb +84 -0
 - data/spec/brawl/battle_controller_spec.rb +138 -0
 - data/spec/brawl/clock_spec.rb +28 -0
 - data/spec/brawl/helper_spec.rb +23 -0
 - data/spec/brawl/parts/basic_motor_spec.rb +220 -0
 - data/spec/brawl/parts/basic_scanner_spec.rb +101 -0
 - data/spec/brawl/parts/basic_weapon_spec.rb +146 -0
 - data/spec/spec_helper.rb +5 -0
 - metadata +101 -10
 
    
        data/lib/brawl.rb
    CHANGED
    
    | 
         @@ -1,5 +1,16 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require "brawl/version"
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "brawl/_helper"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            require "brawl/clock"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            require "brawl/basic_arena_object"
         
     | 
| 
      
 8 
     | 
    
         
            +
            require "brawl/wall"
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            require "brawl/arena"
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            require "brawl/basic_bot"
         
     | 
| 
      
 13 
     | 
    
         
            +
            require "brawl/parts"
         
     | 
| 
      
 14 
     | 
    
         
            +
            require "brawl/bot_proxy"
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            require "brawl/battle_controller"
         
     | 
| 
         @@ -0,0 +1,65 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Brawl
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              DECIMAL_PLACES  = 1
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              class Helper
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def self.to_radians(angle)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  angle * (Math::PI / 180)
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def self.to_degrees(angle)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  angle * (180.0 / Math::PI)
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                # returns a shorter angle if one exists (angle - 180's complement)
         
     | 
| 
      
 16 
     | 
    
         
            +
                # e.g. wrap_angle(270)  = -90
         
     | 
| 
      
 17 
     | 
    
         
            +
                #      wrap_angle(-320) = 40
         
     | 
| 
      
 18 
     | 
    
         
            +
                #      wrap_angle(45)   = 45
         
     | 
| 
      
 19 
     | 
    
         
            +
                def self.wrap_angle(angle)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  # refactor? : can this be simplified?
         
     | 
| 
      
 21 
     | 
    
         
            +
                  return angle unless angle > 180 || angle < -180
         
     | 
| 
      
 22 
     | 
    
         
            +
                  (360 - angle.abs) * (angle.abs / angle) * -1
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def self.point_in_cone?(params)
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  origin    = params[:origin]
         
     | 
| 
      
 28 
     | 
    
         
            +
                  radius    = params[:radius]
         
     | 
| 
      
 29 
     | 
    
         
            +
                  angle     = params[:angle]
         
     | 
| 
      
 30 
     | 
    
         
            +
                  direction = params[:direction]
         
     | 
| 
      
 31 
     | 
    
         
            +
                  point     = params[:point]
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  distance_to_target = distance(origin, point)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  return false if distance_to_target > radius
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  bearing_to_target = bearing(origin, point)
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  min_cone_angle = (direction - (angle / 2)) % 360
         
     | 
| 
      
 39 
     | 
    
         
            +
                  max_cone_angle = (direction + (angle / 2)) % 360
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  greater_than = bearing_to_target >= min_cone_angle
         
     | 
| 
      
 42 
     | 
    
         
            +
                  less_than    = bearing_to_target <= max_cone_angle
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  if (min_cone_angle > max_cone_angle && (greater_than || less_than)) ||
         
     | 
| 
      
 45 
     | 
    
         
            +
                  (min_cone_angle <= max_cone_angle && (greater_than && less_than))
         
     | 
| 
      
 46 
     | 
    
         
            +
                    { distance: distance_to_target.round(DECIMAL_PLACES), 
         
     | 
| 
      
 47 
     | 
    
         
            +
                      bearing: bearing_to_target}
         
     | 
| 
      
 48 
     | 
    
         
            +
                    
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                def self.bearing(origin, target)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  x1, y1, x2, y2 = origin[:x], origin[:y], target[:x], target[:y]
         
     | 
| 
      
 54 
     | 
    
         
            +
                  # correct mathy angles to what everyone on the face of the planet uses
         
     | 
| 
      
 55 
     | 
    
         
            +
                  to_degrees(Math.atan2(x2 - x1, y2 - y1)) % 360
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                def self.distance(point1, point2)
         
     | 
| 
      
 59 
     | 
    
         
            +
                  x1, y1, x2, y2 = point1[:x], point1[:y], point2[:x], point2[:y]
         
     | 
| 
      
 60 
     | 
    
         
            +
                  distance = Math.sqrt((x1 - x2)**2 + (y1 - y2)**2)
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
              end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/brawl/arena.rb
    ADDED
    
    | 
         @@ -0,0 +1,118 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Brawl
         
     | 
| 
      
 2 
     | 
    
         
            +
              
         
     | 
| 
      
 3 
     | 
    
         
            +
              class Arena
         
     | 
| 
      
 4 
     | 
    
         
            +
                
         
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :size, :clock
         
     | 
| 
      
 6 
     | 
    
         
            +
                
         
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize(params={})
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @size     = params[:size]
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @objects  = []
         
     | 
| 
      
 10 
     | 
    
         
            +
                  
         
     | 
| 
      
 11 
     | 
    
         
            +
                  set_clock(params[:clock])
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  add_walls
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def length
         
     | 
| 
      
 17 
     | 
    
         
            +
                  @size[:length]
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def width
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @size[:width]
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def ticks
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @clock.ticks
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                def set_clock(clock=nil)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @clock = clock || Clock.new
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @clock.start
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def add_object(object)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  add_objects([object]).first
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
                
         
     | 
| 
      
 37 
     | 
    
         
            +
                def add_objects(objects_array)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  objects_array.collect do |object|
         
     | 
| 
      
 39 
     | 
    
         
            +
                    if get_object(id: object.id) || ping(object.location)
         
     | 
| 
      
 40 
     | 
    
         
            +
                      false
         
     | 
| 
      
 41 
     | 
    
         
            +
                    else
         
     | 
| 
      
 42 
     | 
    
         
            +
                      !!(@objects << object)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                def remove_object(object)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  @objects.delete(object)
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                def move_object(object_location_hash)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  object    = object_location_hash.keys.first
         
     | 
| 
      
 53 
     | 
    
         
            +
                  location  = object_location_hash.values.first
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  return if ping(location)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  return unless in_bounds?(location)
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  !!(object.location = location)
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                # allows searching by object properties like location or id
         
     | 
| 
      
 62 
     | 
    
         
            +
                def get_object(property_hash)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  property, value = property_hash.first
         
     | 
| 
      
 64 
     | 
    
         
            +
                  @objects.each do |object|
         
     | 
| 
      
 65 
     | 
    
         
            +
                    return object.properties if object.properties[property] == value
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                def get_all_objects
         
     | 
| 
      
 71 
     | 
    
         
            +
                  @objects.collect {|object| object.properties}
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                def in_bounds?(location)
         
     | 
| 
      
 75 
     | 
    
         
            +
                  return false if location[:x] >= @size[:width]  || location[:x] <  0
         
     | 
| 
      
 76 
     | 
    
         
            +
                  return false if location[:y] >= @size[:length] || location[:y] <  0
         
     | 
| 
      
 77 
     | 
    
         
            +
                  true
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                def ping(location)
         
     | 
| 
      
 81 
     | 
    
         
            +
                  get_object(location: location)
         
     | 
| 
      
 82 
     | 
    
         
            +
                end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                def forward_damage(params)
         
     | 
| 
      
 85 
     | 
    
         
            +
                  target = @objects.select{|object| object.id == params[:target]}.first
         
     | 
| 
      
 86 
     | 
    
         
            +
                  target.damage(params[:damage])
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end_game if victory?
         
     | 
| 
      
 88 
     | 
    
         
            +
                end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                def victory?
         
     | 
| 
      
 91 
     | 
    
         
            +
                  @objects.one? do |object|
         
     | 
| 
      
 92 
     | 
    
         
            +
                    object.class != Wall && object.health > 0
         
     | 
| 
      
 93 
     | 
    
         
            +
                  end ||
         
     | 
| 
      
 94 
     | 
    
         
            +
                  @objects.none? do |object|
         
     | 
| 
      
 95 
     | 
    
         
            +
                    object.class != Wall && object.health > 0
         
     | 
| 
      
 96 
     | 
    
         
            +
                  end
         
     | 
| 
      
 97 
     | 
    
         
            +
                end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                def end_game
         
     | 
| 
      
 100 
     | 
    
         
            +
                  @clock.stop
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                private 
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                def add_walls
         
     | 
| 
      
 106 
     | 
    
         
            +
                  (0...width).each do |col|
         
     | 
| 
      
 107 
     | 
    
         
            +
                    @objects << Wall.new(location: {x: col, y: -1})
         
     | 
| 
      
 108 
     | 
    
         
            +
                    @objects << Wall.new(location: {x: col, y: length})
         
     | 
| 
      
 109 
     | 
    
         
            +
                  end
         
     | 
| 
      
 110 
     | 
    
         
            +
                  (0...length).each do |row|
         
     | 
| 
      
 111 
     | 
    
         
            +
                    @objects << Wall.new(location: {x: -1, y: row})
         
     | 
| 
      
 112 
     | 
    
         
            +
                    @objects << Wall.new(location: {x: width, y: row})
         
     | 
| 
      
 113 
     | 
    
         
            +
                  end
         
     | 
| 
      
 114 
     | 
    
         
            +
                end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
              end
         
     | 
| 
      
 117 
     | 
    
         
            +
              
         
     | 
| 
      
 118 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,35 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'uuidtools'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Brawl
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              class BasicArenaObject
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                attr_reader   :id, :clock, :name
         
     | 
| 
      
 8 
     | 
    
         
            +
                attr_accessor :location, :heading, :health
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def initialize(params={})
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @clock      = params[:clock]
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @id         = params[:id] || UUIDTools::UUID.timestamp_create.to_s
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @name       = params[:name] || self.object_id
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @location   = params[:location] || {x: 0, y: 0}
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @heading    = params[:heading] || 0
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @health     = params[:health] || 1
         
     | 
| 
      
 17 
     | 
    
         
            +
                  @properties = params[:properties] || 
         
     | 
| 
      
 18 
     | 
    
         
            +
                    [:id, :name, :class, :location, :health, :heading]
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                # properties are values that are OK to be publicly 'seen' in the arena
         
     | 
| 
      
 22 
     | 
    
         
            +
                def properties
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @properties.each_with_object({}) do |property, hash|
         
     | 
| 
      
 24 
     | 
    
         
            +
                    hash[property] = self.send(property)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
                
         
     | 
| 
      
 28 
     | 
    
         
            +
                def damage(damage_points)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @health -= damage_points
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @health < 0 ? @health = 0 : @health
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,69 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'forwardable'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'uuidtools'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'eventable'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Brawl
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              class BasicBot < BasicArenaObject
         
     | 
| 
      
 8 
     | 
    
         
            +
                extend Forwardable
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                include Eventable
         
     | 
| 
      
 11 
     | 
    
         
            +
                event :bot_ran_method
         
     | 
| 
      
 12 
     | 
    
         
            +
                event :bot_damaged
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                attr_reader :parts
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                DECIMAL_PLACES = 1
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def initialize(params={})
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @arena = params[:arena]
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @parts = params[:parts]
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  add_parts(@parts, params)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  hook_methods_for_listeners
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  super
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  @arena.add_object(self)
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def damage(damage_points)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  super
         
     | 
| 
      
 32 
     | 
    
         
            +
                  fire_event(:bot_damaged,
         
     | 
| 
      
 33 
     | 
    
         
            +
                    properties,
         
     | 
| 
      
 34 
     | 
    
         
            +
                    :damage,
         
     | 
| 
      
 35 
     | 
    
         
            +
                    damage_points
         
     | 
| 
      
 36 
     | 
    
         
            +
                  )
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @arena.remove_object(self) if @health <= 0
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                private
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                def add_parts(parts, params)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  return unless parts
         
     | 
| 
      
 44 
     | 
    
         
            +
                  parts.each do |part_module, init_params|
         
     | 
| 
      
 45 
     | 
    
         
            +
                    params.merge! init_params
         
     | 
| 
      
 46 
     | 
    
         
            +
                    # make sure we can fire the module's initialize method
         
     | 
| 
      
 47 
     | 
    
         
            +
                    part_module.send :alias_method, :initialize_parts, :initialize
         
     | 
| 
      
 48 
     | 
    
         
            +
                    extend part_module
         
     | 
| 
      
 49 
     | 
    
         
            +
                    initialize_parts(params)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                def hook_methods_for_listeners
         
     | 
| 
      
 54 
     | 
    
         
            +
                  public_methods(false).each do |method|
         
     | 
| 
      
 55 
     | 
    
         
            +
                    next if [:properties,:damage].include?(method)
         
     | 
| 
      
 56 
     | 
    
         
            +
                    singleton_class.send :alias_method, "_hook_#{method}", method
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                    singleton_class.send :define_method, method do |*params, &block|
         
     | 
| 
      
 59 
     | 
    
         
            +
                      return if @health <= 0
         
     | 
| 
      
 60 
     | 
    
         
            +
                      fire_event(:bot_ran_method, properties, method, *params)
         
     | 
| 
      
 61 
     | 
    
         
            +
                      send "_hook_#{method}".to_sym, *params, &block
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,97 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'eventable'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Brawl
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              class BattleController
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                include Eventable
         
     | 
| 
      
 8 
     | 
    
         
            +
                event :bot_msg
         
     | 
| 
      
 9 
     | 
    
         
            +
                
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_accessor :arena, :bots, :clock
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def initialize(params = {})
         
     | 
| 
      
 13 
     | 
    
         
            +
                  super
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  arena_data = params[:arena]
         
     | 
| 
      
 16 
     | 
    
         
            +
                  make_arena(arena_data)
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  bot_data = params[:bots]
         
     | 
| 
      
 19 
     | 
    
         
            +
                  make_bots(bot_data)
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  clock_data = params[:clock]
         
     | 
| 
      
 22 
     | 
    
         
            +
                  make_clock(clock_data)
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def make_arena(arena_data)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  return unless arena_data
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @arena = Brawl::Arena.new(arena_data)
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                def make_clock(clock_data)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  return unless clock_data
         
     | 
| 
      
 33 
     | 
    
         
            +
                  @clock = Clock.new(clock_data[:tick_rate])
         
     | 
| 
      
 34 
     | 
    
         
            +
                  @arena.set_clock(clock) if @arena
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                def make_bots(bot_data)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  return unless bot_data
         
     | 
| 
      
 39 
     | 
    
         
            +
                  
         
     | 
| 
      
 40 
     | 
    
         
            +
                  @bots = []
         
     | 
| 
      
 41 
     | 
    
         
            +
                  bot_data.each do |bot_datum|
         
     | 
| 
      
 42 
     | 
    
         
            +
                    bot_params = bot_datum[:params]
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                    bot_params.merge!(arena: arena)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    bot_params.merge!(name: bot_datum[:name])
         
     | 
| 
      
 46 
     | 
    
         
            +
                    
         
     | 
| 
      
 47 
     | 
    
         
            +
                    location = {location: {x: rand(arena.width), y:rand(arena.length)}}
         
     | 
| 
      
 48 
     | 
    
         
            +
                    bot_params.merge!(location)
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                    bot_instance  = bot_datum[:class].new(bot_params)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    
         
     | 
| 
      
 52 
     | 
    
         
            +
                    bot_instance.register_for_event(
         
     | 
| 
      
 53 
     | 
    
         
            +
                      event:    :bot_ran_method, 
         
     | 
| 
      
 54 
     | 
    
         
            +
                      listener: self, 
         
     | 
| 
      
 55 
     | 
    
         
            +
                      callback: :bot_msg_callback
         
     | 
| 
      
 56 
     | 
    
         
            +
                    )
         
     | 
| 
      
 57 
     | 
    
         
            +
                    bot_instance.register_for_event(
         
     | 
| 
      
 58 
     | 
    
         
            +
                      event:    :bot_damaged, 
         
     | 
| 
      
 59 
     | 
    
         
            +
                      listener: self, 
         
     | 
| 
      
 60 
     | 
    
         
            +
                      callback: :bot_msg_callback
         
     | 
| 
      
 61 
     | 
    
         
            +
                    )
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                    bot_proxy = BotProxy.new(
         
     | 
| 
      
 64 
     | 
    
         
            +
                      clock:  clock,
         
     | 
| 
      
 65 
     | 
    
         
            +
                      bot:    bot_instance,
         
     | 
| 
      
 66 
     | 
    
         
            +
                      code:   bot_datum[:code]
         
     | 
| 
      
 67 
     | 
    
         
            +
                    )
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                    @bots << {
         
     | 
| 
      
 70 
     | 
    
         
            +
                      name:  bot_datum[:name],
         
     | 
| 
      
 71 
     | 
    
         
            +
                      proxy: bot_proxy
         
     | 
| 
      
 72 
     | 
    
         
            +
                    }
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                def bot_msg_callback(*params, &block)
         
     | 
| 
      
 77 
     | 
    
         
            +
                  fire_event(:bot_msg, *params, &block)
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                def victory?
         
     | 
| 
      
 81 
     | 
    
         
            +
                  arena.victory?
         
     | 
| 
      
 82 
     | 
    
         
            +
                end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                def start
         
     | 
| 
      
 85 
     | 
    
         
            +
                  @bots.each do |bot|
         
     | 
| 
      
 86 
     | 
    
         
            +
                    bot[:proxy].start
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
                  @clock.start
         
     | 
| 
      
 89 
     | 
    
         
            +
                end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                def stop
         
     | 
| 
      
 92 
     | 
    
         
            +
                  @clock.stop
         
     | 
| 
      
 93 
     | 
    
         
            +
                end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
              end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,60 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Brawl
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              class BotProxy
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                attr_accessor :bot, :last_tick, :msg_log, :clock
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize(params)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @clock      = params[:clock]
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @bot        = params[:bot]
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @code       = params[:code]
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  @last_tick  = @clock.ticks
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @run        = false
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  add_proxy_methods
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def name
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @bot.name
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                def add_proxy_methods
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # I'm sure there's a better way of doing this
         
     | 
| 
      
 24 
     | 
    
         
            +
                  combined_methods = @bot.public_methods(false)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  combined_methods.concat BasicArenaObject.instance_methods(false)
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  combined_methods.each do |method|
         
     | 
| 
      
 28 
     | 
    
         
            +
                    next if method.to_s[0] == "_"
         
     | 
| 
      
 29 
     | 
    
         
            +
                    singleton_class.send :define_method, method do |*params, &block|
         
     | 
| 
      
 30 
     | 
    
         
            +
                      sleep(0.01) while @clock.ticks <= @last_tick
         
     | 
| 
      
 31 
     | 
    
         
            +
                      @last_tick = @clock.ticks
         
     | 
| 
      
 32 
     | 
    
         
            +
                      @bot.send method, *params, &block
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def start
         
     | 
| 
      
 39 
     | 
    
         
            +
                  @run = true
         
     | 
| 
      
 40 
     | 
    
         
            +
                  Thread.start {
         
     | 
| 
      
 41 
     | 
    
         
            +
                    until @clock.state == :stopped || !@run || @health == 0
         
     | 
| 
      
 42 
     | 
    
         
            +
                      sleep(0.01) if @clock.state == :wait
         
     | 
| 
      
 43 
     | 
    
         
            +
                      if @clock.state == :running
         
     | 
| 
      
 44 
     | 
    
         
            +
                        instance_eval("Thread.start{$SAFE=3;#{@code}}.join")
         
     | 
| 
      
 45 
     | 
    
         
            +
                      end
         
     | 
| 
      
 46 
     | 
    
         
            +
                    end
         
     | 
| 
      
 47 
     | 
    
         
            +
                    @run = false
         
     | 
| 
      
 48 
     | 
    
         
            +
                  }
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                def stop
         
     | 
| 
      
 52 
     | 
    
         
            +
                  @run = false
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                def code
         
     | 
| 
      
 56 
     | 
    
         
            +
                  yield self
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
              end
         
     | 
| 
      
 60 
     | 
    
         
            +
            end
         
     |