```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

```