graphics 1.0.0b1
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.
- checksums.yaml +7 -0
 - checksums.yaml.gz.sig +0 -0
 - data.tar.gz.sig +0 -0
 - data/.autotest +26 -0
 - data/.gemtest +0 -0
 - data/History.rdoc +12 -0
 - data/Manifest.txt +37 -0
 - data/README.rdoc +71 -0
 - data/Rakefile +26 -0
 - data/examples/boid.rb +653 -0
 - data/examples/bounce.rb +86 -0
 - data/examples/collision.rb +74 -0
 - data/examples/demo.rb +90 -0
 - data/examples/editor.rb +70 -0
 - data/examples/fluid.rb +246 -0
 - data/examples/fluid2.rb +199 -0
 - data/examples/lito.rb +108 -0
 - data/examples/lito2.rb +110 -0
 - data/examples/logo.rb +73 -0
 - data/examples/math.rb +42 -0
 - data/examples/radar.rb +31 -0
 - data/examples/tank.rb +160 -0
 - data/examples/tank2.rb +173 -0
 - data/examples/targeting.rb +46 -0
 - data/examples/vants.rb +69 -0
 - data/examples/walker.rb +116 -0
 - data/examples/zenspider1.rb +93 -0
 - data/examples/zenspider2.rb +123 -0
 - data/examples/zenspider3.rb +104 -0
 - data/examples/zenspider4.rb +90 -0
 - data/examples/zombies.rb +385 -0
 - data/lib/graphics.rb +9 -0
 - data/lib/graphics/body.rb +216 -0
 - data/lib/graphics/extensions.rb +48 -0
 - data/lib/graphics/simulation.rb +377 -0
 - data/lib/graphics/trail.rb +69 -0
 - data/lib/graphics/v.rb +71 -0
 - data/resources/images/body.png +0 -0
 - data/resources/images/turret.png +0 -0
 - data/rubysdl_setup.sh +34 -0
 - data/test/test_graphics.rb +408 -0
 - metadata +191 -0
 - metadata.gz.sig +2 -0
 
    
        data/examples/vants.rb
    ADDED
    
    | 
         @@ -0,0 +1,69 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/local/bin/ruby -w
         
     | 
| 
      
 2 
     | 
    
         
            +
            # -*- coding: utf-8 -*-
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            srand 42
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            require "graphics"
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            ##
         
     | 
| 
      
 9 
     | 
    
         
            +
            # Virtual Ants -- inspired by a model in NetLogo.
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            class Vant < Graphics::Body
         
     | 
| 
      
 12 
     | 
    
         
            +
              COUNT = 100
         
     | 
| 
      
 13 
     | 
    
         
            +
              M = 1
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              attr_accessor :white, :black, :red, :s
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              def initialize w
         
     | 
| 
      
 18 
     | 
    
         
            +
                super
         
     | 
| 
      
 19 
     | 
    
         
            +
                self.a = random_angle
         
     | 
| 
      
 20 
     | 
    
         
            +
                self.s = w.screen
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                self.white = w.color[:white]
         
     | 
| 
      
 23 
     | 
    
         
            +
                self.black = w.color[:black]
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              def forward
         
     | 
| 
      
 27 
     | 
    
         
            +
                move_by a, M
         
     | 
| 
      
 28 
     | 
    
         
            +
                mutate
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              def mutate
         
     | 
| 
      
 32 
     | 
    
         
            +
                if s[x, y] == white then
         
     | 
| 
      
 33 
     | 
    
         
            +
                  s[x, y] = black
         
     | 
| 
      
 34 
     | 
    
         
            +
                  turn 270
         
     | 
| 
      
 35 
     | 
    
         
            +
                else
         
     | 
| 
      
 36 
     | 
    
         
            +
                  s[x, y] = white
         
     | 
| 
      
 37 
     | 
    
         
            +
                  turn 90
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
            end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            class Vants < Graphics::Simulation
         
     | 
| 
      
 43 
     | 
    
         
            +
              attr_accessor :vs
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 46 
     | 
    
         
            +
                super 850, 850, 16, self.class.name
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                # cheat and reopen screen w/o double buffering
         
     | 
| 
      
 49 
     | 
    
         
            +
                self.screen = SDL::Screen.open 850, 850, 16, SDL::HWSURFACE
         
     | 
| 
      
 50 
     | 
    
         
            +
                clear :white
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                self.vs = populate Vant
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
              def update n
         
     | 
| 
      
 56 
     | 
    
         
            +
                vs.each(&:forward)
         
     | 
| 
      
 57 
     | 
    
         
            +
              end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
              def draw_and_flip n
         
     | 
| 
      
 60 
     | 
    
         
            +
                self.draw n
         
     | 
| 
      
 61 
     | 
    
         
            +
                # no flip
         
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
              def draw n
         
     | 
| 
      
 65 
     | 
    
         
            +
                screen.update_rect 0, 0, 0, 0
         
     | 
| 
      
 66 
     | 
    
         
            +
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
            end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            Vants.new.run if $0 == __FILE__
         
     | 
    
        data/examples/walker.rb
    ADDED
    
    | 
         @@ -0,0 +1,116 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/local/bin/ruby -w
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "graphics"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "graphics/trail"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            class Person < Graphics::Body
         
     | 
| 
      
 7 
     | 
    
         
            +
              COUNT = 40
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              D_A = 5.0
         
     | 
| 
      
 10 
     | 
    
         
            +
              D_M = 0.25
         
     | 
| 
      
 11 
     | 
    
         
            +
              M_M = 5.0
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              AA = SDL::Surface::TRANSFORM_AA
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              attr_accessor :trail, :attack
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              def initialize w
         
     | 
| 
      
 18 
     | 
    
         
            +
                super
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                self.trail = Graphics::Trail.new w, 100, :green
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                self.a  = random_angle
         
     | 
| 
      
 23 
     | 
    
         
            +
                self.ga = random_angle
         
     | 
| 
      
 24 
     | 
    
         
            +
                self.attack = false
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              def update
         
     | 
| 
      
 28 
     | 
    
         
            +
                turn_towards_goal
         
     | 
| 
      
 29 
     | 
    
         
            +
                possibly_change_goal
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                accelerate
         
     | 
| 
      
 32 
     | 
    
         
            +
                move
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                trail << self
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                clip_off_wall
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              def accelerate
         
     | 
| 
      
 40 
     | 
    
         
            +
                self.m += D_M unless m >= M_M
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
              def draw
         
     | 
| 
      
 44 
     | 
    
         
            +
                trail.draw
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                if attack then
         
     | 
| 
      
 47 
     | 
    
         
            +
                  w.angle x, y, a-45, 50, :yellow
         
     | 
| 
      
 48 
     | 
    
         
            +
                  w.angle x, y, a,    60, :red
         
     | 
| 
      
 49 
     | 
    
         
            +
                  w.angle x, y, a+45, 50, :yellow
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                w.angle x, y, ga,   60, :red
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                # the blit looks HORRIBLE when rotated... dunno why
         
     | 
| 
      
 55 
     | 
    
         
            +
                w.blit w.body_img, x, y, 0, AA
         
     | 
| 
      
 56 
     | 
    
         
            +
              end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
              def turn_towards_goal
         
     | 
| 
      
 59 
     | 
    
         
            +
                turn a.relative_angle(ga, D_A)
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
              def change_goal
         
     | 
| 
      
 63 
     | 
    
         
            +
                self.ga = a + random_turn(180)
         
     | 
| 
      
 64 
     | 
    
         
            +
              end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
              def possibly_change_goal
         
     | 
| 
      
 67 
     | 
    
         
            +
                change_goal if ga.close_to?(a) && 1 =~ 25
         
     | 
| 
      
 68 
     | 
    
         
            +
              end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
              def collide_with? other
         
     | 
| 
      
 71 
     | 
    
         
            +
                w.cmap.collision_check(x, y, w.cmap, other.x, other.y) != nil
         
     | 
| 
      
 72 
     | 
    
         
            +
              end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
              def collide
         
     | 
| 
      
 75 
     | 
    
         
            +
                self.a = (a + 180).degrees
         
     | 
| 
      
 76 
     | 
    
         
            +
                change_goal
         
     | 
| 
      
 77 
     | 
    
         
            +
              end
         
     | 
| 
      
 78 
     | 
    
         
            +
            end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
            class WalkerSimulation < Graphics::Simulation
         
     | 
| 
      
 81 
     | 
    
         
            +
              attr_accessor :ps, :body_img, :cmap
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 84 
     | 
    
         
            +
                super 850, 850, 16, "Walker"
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                self.ps = populate Person
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                self.body_img = sprite 20, 20 do
         
     | 
| 
      
 89 
     | 
    
         
            +
                  circle 10, 10, 5, :white, :filled
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                self.cmap = body_img.make_collision_map
         
     | 
| 
      
 93 
     | 
    
         
            +
              end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
              def update n
         
     | 
| 
      
 96 
     | 
    
         
            +
                ps.each(&:update)
         
     | 
| 
      
 97 
     | 
    
         
            +
                detect_collisions(ps).each(&:collide)
         
     | 
| 
      
 98 
     | 
    
         
            +
              end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
              def draw n
         
     | 
| 
      
 101 
     | 
    
         
            +
                clear
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                ps.each(&:draw)
         
     | 
| 
      
 104 
     | 
    
         
            +
                fps n
         
     | 
| 
      
 105 
     | 
    
         
            +
              end
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
              def detect_collisions sprites
         
     | 
| 
      
 108 
     | 
    
         
            +
                collisions = []
         
     | 
| 
      
 109 
     | 
    
         
            +
                sprites.combination(2).each do |a, b|
         
     | 
| 
      
 110 
     | 
    
         
            +
                  collisions << a << b if a.collide_with? b
         
     | 
| 
      
 111 
     | 
    
         
            +
                end
         
     | 
| 
      
 112 
     | 
    
         
            +
                collisions.uniq
         
     | 
| 
      
 113 
     | 
    
         
            +
              end
         
     | 
| 
      
 114 
     | 
    
         
            +
            end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
            WalkerSimulation.new.run
         
     | 
| 
         @@ -0,0 +1,93 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/ruby -w
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            srand 42
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            class GameOfLife
         
     | 
| 
      
 6 
     | 
    
         
            +
              attr_accessor :cells
         
     | 
| 
      
 7 
     | 
    
         
            +
              attr_accessor :cache
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 10 
     | 
    
         
            +
                self.cells = []
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              def randomize n, m
         
     | 
| 
      
 14 
     | 
    
         
            +
                dimensions = n.times.to_a
         
     | 
| 
      
 15 
     | 
    
         
            +
                cells.replace dimensions.product(dimensions).sample(m).sort
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              def run max = 1.0 / 0
         
     | 
| 
      
 19 
     | 
    
         
            +
                (1..max).each do |n|
         
     | 
| 
      
 20 
     | 
    
         
            +
                  yield n
         
     | 
| 
      
 21 
     | 
    
         
            +
                  update
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              def update
         
     | 
| 
      
 26 
     | 
    
         
            +
                cells.replace considered.select { |(x, y)| alive? x, y }.sort
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              def considered
         
     | 
| 
      
 30 
     | 
    
         
            +
                cells.map { |(x, y)| neighbors_for(x, y) }.flatten(1).uniq
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
              MIN = { true => 2, false => 3 }
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              def alive? x, y
         
     | 
| 
      
 36 
     | 
    
         
            +
                count = (neighbors_for(x, y) & cells).size
         
     | 
| 
      
 37 
     | 
    
         
            +
                min   = MIN[cells.include? [x, y]]
         
     | 
| 
      
 38 
     | 
    
         
            +
                count.between? min, 3
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              delta  = [-1, 0, 1]
         
     | 
| 
      
 42 
     | 
    
         
            +
              same   = [0, 0]
         
     | 
| 
      
 43 
     | 
    
         
            +
              DELTAS = (delta.product(delta) - [same])
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              @@neighbors = Hash.new { |h, k| h[k] = {} }
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
              def neighbors_for x, y
         
     | 
| 
      
 48 
     | 
    
         
            +
                DELTAS.map { |(dx, dy)| [x+dx, y+dy] }.reject { |(m, n)| m < 0 || n < 0 }
         
     | 
| 
      
 49 
     | 
    
         
            +
              end
         
     | 
| 
      
 50 
     | 
    
         
            +
            end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            size, width, count = 20, 32, 512
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            gol = GameOfLife.new
         
     | 
| 
      
 55 
     | 
    
         
            +
            gol.randomize width, count
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            if ARGV.first == "prof" then
         
     | 
| 
      
 58 
     | 
    
         
            +
              gol.run 50 do |n|
         
     | 
| 
      
 59 
     | 
    
         
            +
                $stderr.print "."
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
              warn "done"
         
     | 
| 
      
 62 
     | 
    
         
            +
            else
         
     | 
| 
      
 63 
     | 
    
         
            +
              require "sdl"
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
              SDL.init SDL::INIT_VIDEO
         
     | 
| 
      
 66 
     | 
    
         
            +
              SDL::WM::set_caption "Conway's Game of Life", "Conway's Game of Life"
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
              screen = SDL::Screen.open 640, 640, 16, SDL::DOUBLEBUF
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
              black = screen.format.map_rgb   0,   0,   0
         
     | 
| 
      
 71 
     | 
    
         
            +
              white = screen.format.map_rgb 255, 255, 255
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
              w, h = screen.w, screen.h
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
              gol.run do
         
     | 
| 
      
 76 
     | 
    
         
            +
                screen.fill_rect 0, 0, w, h, black
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                gol.cells.each do |(x, y)|
         
     | 
| 
      
 79 
     | 
    
         
            +
                  screen.fill_rect x*size, y*size, size-1, size-1, white
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                screen.flip
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                while event = SDL::Event.poll
         
     | 
| 
      
 85 
     | 
    
         
            +
                  case event
         
     | 
| 
      
 86 
     | 
    
         
            +
                  when SDL::Event::KeyDown,  SDL::Event::Quit
         
     | 
| 
      
 87 
     | 
    
         
            +
                    exit
         
     | 
| 
      
 88 
     | 
    
         
            +
                  end
         
     | 
| 
      
 89 
     | 
    
         
            +
                end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                gol.update
         
     | 
| 
      
 92 
     | 
    
         
            +
              end
         
     | 
| 
      
 93 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,123 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/ruby -w
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            srand 42
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            class Array
         
     | 
| 
      
 6 
     | 
    
         
            +
              include Comparable
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              alias old_spaceship <=>
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              def <=> other
         
     | 
| 
      
 11 
     | 
    
         
            +
                x = first <=> other.first
         
     | 
| 
      
 12 
     | 
    
         
            +
                x.zero? ? self[1] <=> other[1] : x
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            class GameOfLife
         
     | 
| 
      
 17 
     | 
    
         
            +
              delta   = [-1, 0, 1]
         
     | 
| 
      
 18 
     | 
    
         
            +
              same    = [0, 0]
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              DELTAS  = (delta.product(delta) - [same]).sort
         
     | 
| 
      
 21 
     | 
    
         
            +
              MIN     = { true => 2, false => 3 }
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              @@neighbors = Hash.new { |h, k| h[k] = {} }
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              attr_accessor :cells
         
     | 
| 
      
 26 
     | 
    
         
            +
              attr_accessor :cache
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 29 
     | 
    
         
            +
                self.cells = []
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              def randomize n, m
         
     | 
| 
      
 33 
     | 
    
         
            +
                dimensions = n.times.to_a
         
     | 
| 
      
 34 
     | 
    
         
            +
                cells.replace dimensions.product(dimensions).sample(m).sort
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
              def run max = 1.0 / 0
         
     | 
| 
      
 38 
     | 
    
         
            +
                (1..max).each do |n|
         
     | 
| 
      
 39 
     | 
    
         
            +
                  yield n
         
     | 
| 
      
 40 
     | 
    
         
            +
                  update
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
              end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              def update
         
     | 
| 
      
 45 
     | 
    
         
            +
                cells.replace considered.select { |(x, y)| alive? x, y }.sort
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
              def considered
         
     | 
| 
      
 49 
     | 
    
         
            +
                cells.map { |(x, y)| neighbors_for(x, y) }.flatten(1).uniq
         
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              def binary_search(container, item)
         
     | 
| 
      
 53 
     | 
    
         
            +
                return nil if item.nil?
         
     | 
| 
      
 54 
     | 
    
         
            +
                low = 0
         
     | 
| 
      
 55 
     | 
    
         
            +
                high = container.size - 1
         
     | 
| 
      
 56 
     | 
    
         
            +
                while low <= high do
         
     | 
| 
      
 57 
     | 
    
         
            +
                  mid = (low + high) / 2
         
     | 
| 
      
 58 
     | 
    
         
            +
                  val = container[mid]
         
     | 
| 
      
 59 
     | 
    
         
            +
                  if val > item then
         
     | 
| 
      
 60 
     | 
    
         
            +
                    high = mid - 1
         
     | 
| 
      
 61 
     | 
    
         
            +
                  elsif val < item then
         
     | 
| 
      
 62 
     | 
    
         
            +
                    low = mid + 1
         
     | 
| 
      
 63 
     | 
    
         
            +
                  else
         
     | 
| 
      
 64 
     | 
    
         
            +
                    return val
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
                nil
         
     | 
| 
      
 68 
     | 
    
         
            +
              end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
              def alive? x, y
         
     | 
| 
      
 71 
     | 
    
         
            +
                count = (neighbors_for(x, y) & cells).size
         
     | 
| 
      
 72 
     | 
    
         
            +
                min   = MIN[!!binary_search(cells, [x, y])] # .include? [x, y]]
         
     | 
| 
      
 73 
     | 
    
         
            +
                count.between? min, 3
         
     | 
| 
      
 74 
     | 
    
         
            +
              end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
              def neighbors_for x, y
         
     | 
| 
      
 77 
     | 
    
         
            +
                @@neighbors[x][y] ||=
         
     | 
| 
      
 78 
     | 
    
         
            +
                  DELTAS.map { |(dx, dy)| [x+dx, y+dy] }.reject { |(m, n)| m < 0 || n < 0 }
         
     | 
| 
      
 79 
     | 
    
         
            +
              end
         
     | 
| 
      
 80 
     | 
    
         
            +
            end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
            size, width, count = 20, 32, 256
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
            gol = GameOfLife.new
         
     | 
| 
      
 85 
     | 
    
         
            +
            gol.randomize width, count
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
            if ARGV.first == "prof" then
         
     | 
| 
      
 88 
     | 
    
         
            +
              gol.run 50 do |n|
         
     | 
| 
      
 89 
     | 
    
         
            +
                $stderr.print "."
         
     | 
| 
      
 90 
     | 
    
         
            +
              end
         
     | 
| 
      
 91 
     | 
    
         
            +
              warn "done"
         
     | 
| 
      
 92 
     | 
    
         
            +
            else
         
     | 
| 
      
 93 
     | 
    
         
            +
              require "sdl"
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
              SDL.init SDL::INIT_VIDEO
         
     | 
| 
      
 96 
     | 
    
         
            +
              SDL::WM::set_caption "Conway's Game of Life", "Conway's Game of Life"
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
              screen = SDL::Screen.open 640, 640, 16, SDL::DOUBLEBUF
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
              black = screen.format.map_rgb   0,   0,   0
         
     | 
| 
      
 101 
     | 
    
         
            +
              white = screen.format.map_rgb 255, 255, 255
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
              w, h = screen.w, screen.h
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
              gol.run do
         
     | 
| 
      
 106 
     | 
    
         
            +
                screen.fill_rect 0, 0, w, h, black
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                gol.cells.each do |(x, y)|
         
     | 
| 
      
 109 
     | 
    
         
            +
                  screen.fill_rect x*size, y*size, size-1, size-1, white
         
     | 
| 
      
 110 
     | 
    
         
            +
                end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                screen.flip
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                while event = SDL::Event.poll
         
     | 
| 
      
 115 
     | 
    
         
            +
                  case event
         
     | 
| 
      
 116 
     | 
    
         
            +
                  when SDL::Event::KeyDown,  SDL::Event::Quit
         
     | 
| 
      
 117 
     | 
    
         
            +
                    exit
         
     | 
| 
      
 118 
     | 
    
         
            +
                  end
         
     | 
| 
      
 119 
     | 
    
         
            +
                end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                gol.update
         
     | 
| 
      
 122 
     | 
    
         
            +
              end
         
     | 
| 
      
 123 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,104 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/ruby -w
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            srand 42
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            class Array
         
     | 
| 
      
 6 
     | 
    
         
            +
              def sorted_include? o
         
     | 
| 
      
 7 
     | 
    
         
            +
                a, b = o
         
     | 
| 
      
 8 
     | 
    
         
            +
                !!bsearch { |(x, y)|
         
     | 
| 
      
 9 
     | 
    
         
            +
                  c = a - x
         
     | 
| 
      
 10 
     | 
    
         
            +
                  c.zero? ? b - y : c
         
     | 
| 
      
 11 
     | 
    
         
            +
                }
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            class GameOfLife
         
     | 
| 
      
 16 
     | 
    
         
            +
              delta   = [-1, 0, 1]
         
     | 
| 
      
 17 
     | 
    
         
            +
              same    = [0, 0]
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              DELTAS  = (delta.product(delta) - [same]).sort
         
     | 
| 
      
 20 
     | 
    
         
            +
              MIN     = { true => 2, false => 3 }
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              @@neighbors = Hash.new { |h, k| h[k] = {} }
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              attr_accessor :cells
         
     | 
| 
      
 25 
     | 
    
         
            +
              attr_accessor :cache
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 28 
     | 
    
         
            +
                self.cells = []
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              def randomize n, m
         
     | 
| 
      
 32 
     | 
    
         
            +
                dimensions = n.times.to_a
         
     | 
| 
      
 33 
     | 
    
         
            +
                cells.replace dimensions.product(dimensions).sample(m).sort
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              def run max = 1.0 / 0
         
     | 
| 
      
 37 
     | 
    
         
            +
                (1..max).each do |n|
         
     | 
| 
      
 38 
     | 
    
         
            +
                  yield n
         
     | 
| 
      
 39 
     | 
    
         
            +
                  update
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
              def update
         
     | 
| 
      
 44 
     | 
    
         
            +
                cells.replace considered.select { |(x, y)| alive? x, y }.sort
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
              def considered
         
     | 
| 
      
 48 
     | 
    
         
            +
                cells.map { |(x, y)| neighbors_for(x, y) }.flatten(1).uniq
         
     | 
| 
      
 49 
     | 
    
         
            +
              end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
              def alive? x, y
         
     | 
| 
      
 52 
     | 
    
         
            +
                count = (neighbors_for(x, y) & cells).size
         
     | 
| 
      
 53 
     | 
    
         
            +
                min   = MIN[cells.sorted_include? [x, y]]
         
     | 
| 
      
 54 
     | 
    
         
            +
                count.between? min, 3
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
              def neighbors_for x, y
         
     | 
| 
      
 58 
     | 
    
         
            +
                @@neighbors[x][y] ||=
         
     | 
| 
      
 59 
     | 
    
         
            +
                  DELTAS.map { |(dx, dy)| [x+dx, y+dy] }.reject { |(m, n)| m < 0 || n < 0 }
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
            end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
            size, width, count = 10, 64, 1000
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
            gol = GameOfLife.new
         
     | 
| 
      
 66 
     | 
    
         
            +
            gol.randomize width, count
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            if ARGV.first == "prof" then
         
     | 
| 
      
 69 
     | 
    
         
            +
              gol.run 50 do |n|
         
     | 
| 
      
 70 
     | 
    
         
            +
                $stderr.print "."
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
      
 72 
     | 
    
         
            +
              warn "done"
         
     | 
| 
      
 73 
     | 
    
         
            +
            else
         
     | 
| 
      
 74 
     | 
    
         
            +
              require "sdl"
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
              SDL.init SDL::INIT_VIDEO
         
     | 
| 
      
 77 
     | 
    
         
            +
              SDL::WM::set_caption "Conway's Game of Life", "Conway's Game of Life"
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
              screen = SDL::Screen.open 640, 640, 16, SDL::DOUBLEBUF
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
              black = screen.format.map_rgb   0,   0,   0
         
     | 
| 
      
 82 
     | 
    
         
            +
              white = screen.format.map_rgb 255, 255, 255
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
              w, h = screen.w, screen.h
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
              gol.run do
         
     | 
| 
      
 87 
     | 
    
         
            +
                screen.fill_rect 0, 0, w, h, black
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                gol.cells.each do |(x, y)|
         
     | 
| 
      
 90 
     | 
    
         
            +
                  screen.fill_rect x*size, y*size, size-1, size-1, white
         
     | 
| 
      
 91 
     | 
    
         
            +
                end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                screen.flip
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                while event = SDL::Event.poll
         
     | 
| 
      
 96 
     | 
    
         
            +
                  case event
         
     | 
| 
      
 97 
     | 
    
         
            +
                  when SDL::Event::KeyDown,  SDL::Event::Quit
         
     | 
| 
      
 98 
     | 
    
         
            +
                    exit
         
     | 
| 
      
 99 
     | 
    
         
            +
                  end
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                gol.update
         
     | 
| 
      
 103 
     | 
    
         
            +
              end
         
     | 
| 
      
 104 
     | 
    
         
            +
            end
         
     |