--Apple-Mail-3-871338967 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed Begin forwarded message: > From: Benjohn Barnes <benjohn / fysh.org> > Date: May 28, 2006 6:30:23 AM CDT > To: Gray II <james / grayproductions.net> > Subject: Quiz submission > > Hi James, > > I hope you don't mind if I send you my entry for this weeks quiz > before the end of the spoiler period. I'm not going to be in net > contact after the period ends, or have my laptop on me either. > Would you please forward it to the list at the appointed time? > > Thanks very much for all your work on the quiz, and sorry for any > inconvenience. This weeks has been a really inspiring :) I'm sure I > can feel my brain beating just a little faster now. > > Cheers, > Benjohn > > > --Apple-Mail-3-871338967 Content-Transfer-Encoding: 7bit Content-Type: text/x-ruby-script; x-unix-mode=0644; name="tc_arena.rb" Content-Disposition: attachment; filename=tc_arena.rb require 'test/unit' require 'arena' class TestArena < Test::Unit::TestCase def test_default arena = Arena.new assert_equal('#', arena[0,0]) assert_equal('#', arena[100,100]) end def test_can_use_negatives arena = Arena.new assert_equal('#', arena[-10,-10]) assert_equal('#', arena[-10,10]) assert_equal('#', arena[10,-10]) end def test_can_set arena = Arena.new arena[0,0] = '1' assert_equal('1', arena[0,0]) end def test_barfs_about_bad_coords assert_raise(ArgumentError) {(Arena.new)[123,123,123]} assert_raise(ArgumentError) {(Arena.new)[123]} end def test_extents arena = Arena.new arena[-3,0] = '.' arena[4,0] = '.' arena[0,-5] = '.' arena[0,6] = '.' assert_equal(-3, arena.left) assert_equal(4, arena.right) assert_equal(-5, arena.top) assert_equal(6, arena.bottom) end def test_to_array arena = Arena.new arena[0,0] = '.' assert_equal([%w{# # #}, %w{# . #}, %w{# # #}], arena.to_array) end def test_to_s arena = Arena.new arena[0,0] = '.' assert_equal("###\n#.#\n###", arena.to_s) end end --Apple-Mail-3-871338967 Content-Transfer-Encoding: 7bit Content-Type: text/x-ruby-script; x-unix-mode=0644; name="arena.rb" Content-Disposition: attachment; filename=arena.rb class Arena attr_reader :left, :right, :top, :bottom def initialize @arena = Hash.new {|h,k| h[k]=Hash.new('#')} @left = @right = @top = @bottom = 0 end def [](x,y) @arena[y][x] end def []=(x,y,v) # I originally worked out the width and height at the end by scanning the map. # I was also using a single map, rather than the 'map in a map' now used. I # found that dungeon creation was slow, but almost all of it was the final # rendering stage, so switched over to the current approach. @arena[y][x]=v @left = [@left, x].min @right = [@right, x].max @top = [@top, y].min @bottom = [@bottom, y].max end def to_s to_array.collect {|row| row.join}.join("\n") end def to_array (top-1..bottom+1).collect do |y| (left-1..right+1).collect do |x| self[x,y] end end end end --Apple-Mail-3-871338967 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; format=flowed > --Apple-Mail-3-871338967 Content-Transfer-Encoding: 7bit Content-Type: text/x-ruby-script; x-unix-mode=0644; name="tc_walker.rb" Content-Disposition: attachment; filename=tc_walker.rb require 'test/unit' require 'walker' class TestDungeonWalker < Test::Unit::TestCase def test_direction walker = Walker.new(0,0,0) walker.direction = 1.1 walker.walk assert_equal([0,1], walker.position) end def test_walk walker = Walker.new(0,0,0) assert_equal([1,0], walker.walk(0.1).position) assert_equal([1,1], walker.walk(1.1).position) assert_equal([0,1], walker.walk(1.8).position) assert_equal([0,0], walker.walk(3.1).position) assert_equal([0,-1], walker.walk(-1.1).position) end def test_wonder walker_before = Walker.new walker_after = walker_before.dup.wonder assert_not_equal( walker_before.position, walker_after.position ) end end --Apple-Mail-3-871338967 Content-Transfer-Encoding: 7bit Content-Type: text/x-ruby-script; x-unix-mode=0644; name="walker.rb" Content-Disposition: attachment; filename=walker.rb # This class basically implements a random walk. I remember # my direction, and it's this that I randomly adjust, rather # than simply jittering my position. class Walker attr_accessor :x, :y, :direction def initialize(x=0, y=0, direction=0) @x, @y, @direction = x, y, direction end # Handy for testing. def position [x,y] end # Adjust direction, and walk once. def wonder perturb_direction walk end # Make the child pointing of 90 degrees away from me. def create_child Walker.new(x, y, direction + 2*rand(2) - 1) end def perturb_direction @direction += rand*wiggle_max - (wiggle_max/2) end def walk(d = direction_with_smoothing_fuzz) # Ensure that the direction is correctly wrapped around. d = (d.round)%4 @x += [1,0,-1,0][d] @y += [0,1,0,-1][d] self end # Adding some noise on to the direction "stocastically" samples # it, smoothing off turns, and making it more catacombey. def direction_with_smoothing_fuzz @direction + rand*smoothing - smoothing/2 end # How wiggley are the dungeons? Bigger numbers are more wiggly # and compact. def wiggle_max 0.5 end # How smooth are tunnels? Larger numbers give smoother more # 'catacombe' like tunnels (and smaller dungeons). Smaller # numbers give more cartesian & straight tunnels. def smoothing 0.9 end end --Apple-Mail-3-871338967 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; format=flowed > --Apple-Mail-3-871338967 Content-Transfer-Encoding: 7bit Content-Type: text/x-ruby-script; x-unix-mode=0644; name="dungeon.rb" Content-Disposition: attachment; filename=dungeon.rb require 'walker.rb' require 'arena.rb' def create_dungeon( arena, walk_length, have_stairs = true, walker = Walker.new ) while(walk_length>0) walk_length -=1 # Cut out a bit of tunnel where I am. arena[*walker.position] = ' ' walker.wonder # Bosh down a room ocaissionally. if(walk_length%80==0) create_room(arena, walker) end # Spawn off a child now and then. Split the remaining walk_length with it. # Only one of us gets the stairs though. if(walk_length%40==0) child_walk_length = rand(walk_length) walk_length -= child_walk_length if child_walk_length > walk_length create_dungeon(arena, child_walk_length, have_stairs, walker.create_child) have_stairs = false else create_dungeon(arena, child_walk_length, false, walker.create_child) end end end # Put in the down stairs, if I have them. if(have_stairs) arena[*(walker.position)] = '>' end end def create_room(arena, walker) max = 10 width = -rand(max)..rand(max) height = -rand(max)..rand(max) height.each do |y| width.each do |x| arena[x+walker.x, y+walker.y] = ' ' end end end # Create an arena, and set of a walker in it. arena = Arena.new create_dungeon(arena, 400) # Put in the up stairs. arena[0,0] = '<' # Show the dungeon. puts arena --Apple-Mail-3-871338967 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; format=flowed > --Apple-Mail-3-871338967--