On Thu, 2004-09-23 at 14:34, Warren Brown wrote:
> Graham,
> 
>     You can save yourself an enormous number of headaches by simply
> adding two more rows and columns to your array.  For example, if you
> wanted the world to be 80x24, make your array 82x26 and then make your
> loops from 1..80 and 1..24.  That way you can safely reference
> cell[x-1][y-1] and cell[x+1][y+1] and you don't need all of your special
> cases.

     I agree with the spirit, but I would take it even farther.  Why
bound the board at all?  It should be a lot easier to just have an
infinite board (or at least, limited to Bignum#"max", whatever that
is).  Easier, that is, after you reach in one ear, grab your brain, and
give it a sharp twist (about 0.76 radians to the NW should do it if
you've been coding in C).

     A sketch:

WARNING: THIS CODE WAS TYPE IN MAIL AND HAS NEVER BEEN RUN

     class A_cell
         attr_accessor(
            :state,      # :filled or :empty
            :neighbors,  # 0..8
            :loc         # [x,y]
            )
         def initialize(x,y)
             @state = :empty
             @neighbors = 0
             @loc = [x,y]
             end
         def fate
            #depending on @state & @neighbors, return :filled or :empty
            end
         end

     class A_board
         attr_reader :cells   # a hash of [x,y] => A_cell
         def initialize
              @cells = Hash.new
              end
         def step
             update_neighbor_count
             update_states
             end
         def update_neighbor_counts
             @cells.keys.each { |x,y|
                 if @cells[[x,y]].state.filled
                     ((x-1)..(x+1)).each { |x0|
                         ((y-1)..(y+1)).each { |y0|
                             @cells[[x0,y0]] ||= A_cell.new(x0,y0)
                             @cells[[x0,y0]].neighbors += 1 unless 
                                x0 == x and y0 == y
                             }
                          }  
                     end
                 }
             end
         def update_states
             @cells.keys.each { |x,y|
                 case @cells[[x,y]].fate
                   when :filled
                     @cells[[x,y]].state = :filled
                     @cells[[x,y]].neighbors = 0
                   when :empty
                     @cells.delete_at [x,y]
                   end
             end 
         end

This has some fat & may be missing some details, but at least it should
give you the idea.

-- Markus