On Sep 12, 2007, at 3:51 PM, Joop Van den tillaart wrote:

> Well i'll try to explain very very short what i need...

<snip>

> Sorry for the size of my reply, but when I start typing I have the
> tendacy to get a bit abundant :D:D...

Your reply is really quite concise and very clear. Now I think I  
fully understand what you are trying to accomplish. And as you will  
see, you were already very close to a solution.

With the information you supplied above, I took a shot at completing  
your code. There was really very little I had to add. Here is what I  
coded:

<code>
require 'ostruct'

class Grid
    include Enumerable

    def initialize(width, height)
       @grid = Array.new(height) do |row|
          Array.new(width) do |col|
             OpenStruct.new(:x => col, :y => row, :grid => self)
          end
       end
    end

    def width
       @grid.first.size
    end

    def height
       @grid.size
    end

    def each
       @grid.each do |row|
          row.each do |cell|
             yield cell
          end
       end
    end

    def [](x, y)
       begin
          @grid[y][x]
       rescue
          raise IndexError
       end
    end

    def print_field_values(field_name = :cell_type)
       each_with_index do |cell, i|
          print "%02d " % cell.send(field_name)
          puts if i % width == width - 1
       end
    end

    def each_with_remaining
       each do |cell|
          next if cell.locked
          x, y = cell.x, cell.y
          (x+1...width).each do |col|
             _cell = cell.grid[col, y]
             yield cell, _cell unless _cell.locked
          end
          (y+1...height).each do |row|
             (0...width).each do |col|
                _cell = cell.grid[col, row]
                yield cell, _cell unless _cell.locked
             end
          end
       end
    end

end

DELTAS = [
    [-1, -1], [0, -1], [1, -1],
    [-1, 0],           [1, 0],
    [-1, 1],  [0, 1],  [1, 1]
]
def neighbors(cell)
    result = []
    x, y = cell.x, cell.y
    DELTAS.each do |dx, dy|
       begin
          _cell = cell.grid[x+dx, y+dy]
          p [x+dx, y+dy] if _cell.nil?
          result << _cell unless _cell.locked
       rescue IndexError
          next
       end
    end
    result
end

HOUSING_TABLE = {1=>12, 2=>12, 3=>8}
GREEN_TABLE = {1=>3, 2=>8, 3=>12}
def score(type, neighbors)
    score = 0
    case type
    when 2
       neighbors.each { |cell| score += HOUSING_TABLE[cell.cell_type] }
    when 3
       neighbors.each { |cell| score += GREEN_TABLE[cell.cell_type] }
    end
    score
end

grid = Grid.new(20, 15)
grid.each { |cell| cell.cell_type = 0 }
grid.height.times { |y| grid[19, y].cell_type = 1 }
grid.height.times { |y| grid[9, y].cell_type = 1 }
grid.width.times { |x| grid[x, 9].cell_type = 1 }
grid.each do |cell|
    if cell.cell_type == 1
       cell.distance_road = 0
       cell.locked = true
    end
end

zero_cells = grid.select { |cell| cell.cell_type == 0 }
n = zero_cells.size
k = (0.6 * n).round
(0...k).each { |i| zero_cells[i].cell_type = 2 }
(k...n).each { |i| zero_cells[i].cell_type = 3 }
grid.print_field_values

puts

n = 3
n.times do
    grid.each_with_remaining do |cell, other|
       cn, on = neighbors(cell), neighbors(other)
       before_score = score(cell.cell_type, cn) +
                      score(other.cell_type, on)
       after_score = score(other.cell_type, cn) +
                     score(cell.cell_type, on)
       if after_score <= before_score
          cell.cell_type, other.cell_type = other.cell_type,  
cell.cell_type
       end
    end
    grid.print_field_values
    puts
end
</code>

I ran the script for three iterations. I'm not sure how to interpret  
the results. I'm not even sure it the loop is converging. I leave it  
to you to work that out. It may be working as you expect it to, it  
may be that your scoring function needs adjustment, or may be that  
there's a bug in my code. One thought that occurs to me: would it be  
better to start out with a random distribution of housing and green  
space?

<results>
# 1st iteration
03 03 03 03 03 03 03 03 03 01 03 03 03 03 03 03 03 03 03 01
03 03 03 03 03 03 03 03 03 01 03 03 03 03 03 03 03 03 03 01
03 03 03 03 03 03 03 03 03 01 03 03 03 03 03 03 03 03 03 01
03 03 03 03 03 03 03 03 03 01 03 03 03 03 03 03 03 03 03 01
03 02 03 02 03 02 03 02 03 01 03 02 03 02 03 02 03 02 02 01
03 02 03 02 03 02 03 02 02 01 02 02 03 02 03 02 03 02 02 01
02 02 03 02 03 02 02 02 02 01 02 02 02 02 02 02 02 02 02 01
02 02 02 02 02 03 03 02 02 01 02 03 02 03 02 03 02 03 02 01
02 02 02 02 02 02 02 02 02 01 02 02 02 02 02 02 02 02 02 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
02 02 02 02 02 02 02 02 02 01 02 02 02 02 02 02 02 02 02 01
02 03 02 03 02 03 02 03 02 01 02 03 02 02 02 02 02 02 02 01
02 02 02 02 02 02 02 02 02 01 02 02 02 02 02 02 02 02 02 01
02 02 02 02 02 02 02 02 02 01 02 02 02 02 02 02 02 02 02 01
02 02 02 02 02 02 02 02 02 01 02 02 02 02 02 02 02 02 02 01

# 2nd iteration
02 02 02 02 02 02 02 02 02 01 02 02 02 02 02 02 02 02 02 01
02 02 02 02 02 02 02 02 02 01 02 02 02 02 02 02 02 02 02 01
02 02 02 02 02 02 02 02 02 01 02 02 02 02 02 02 02 02 02 01
02 02 02 02 02 02 02 02 02 01 02 02 02 02 02 02 02 02 02 01
02 02 02 02 02 02 03 03 02 01 02 03 02 03 02 03 03 03 02 01
02 03 03 02 03 02 03 02 03 01 02 03 02 03 02 03 02 03 02 01
02 03 03 02 03 03 03 03 03 01 03 03 02 03 02 03 02 03 03 01
03 02 03 02 03 02 03 02 03 01 02 03 02 03 02 03 02 03 02 01
03 02 03 02 03 02 03 02 03 01 03 03 02 03 02 03 02 03 02 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
03 03 02 03 02 03 02 02 03 01 03 03 02 02 03 02 03 02 03 01
02 03 03 03 03 03 03 03 03 01 02 02 03 03 03 02 03 02 03 01
03 02 02 02 02 02 02 02 02 01 03 03 03 02 02 02 03 02 03 01
03 02 03 03 03 03 03 03 03 01 02 02 02 03 03 03 03 02 03 01
03 02 03 02 03 02 03 02 03 01 03 03 03 03 02 02 03 02 03 01

# 3rd iteration
03 03 03 03 03 03 03 03 03 01 03 03 03 03 03 03 03 03 03 01
03 03 03 03 03 03 03 03 03 01 03 03 02 03 03 02 03 02 03 01
03 02 03 02 03 02 02 02 02 01 02 03 02 03 02 03 03 02 03 01
03 02 03 02 03 02 03 03 03 01 02 03 02 02 02 02 02 02 02 01
03 02 03 02 03 02 03 02 02 01 03 02 02 03 03 03 02 03 02 01
03 02 03 02 03 02 02 02 03 01 03 02 03 02 02 02 02 03 02 01
02 02 03 02 03 02 03 03 02 01 02 02 02 02 03 03 02 03 02 01
03 02 03 02 03 02 02 03 02 01 03 02 03 02 02 02 02 03 02 01
02 02 02 02 02 02 02 02 02 01 02 02 02 02 02 03 02 02 02 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
02 02 02 02 02 02 02 02 02 01 02 02 03 02 02 02 02 02 02 01
02 03 02 03 02 03 02 03 02 01 02 02 02 02 03 03 03 03 02 01
02 03 02 02 02 02 02 02 02 01 02 03 03 02 02 02 02 02 02 01
02 03 02 03 02 03 03 03 02 01 02 02 02 02 03 03 03 03 02 01
02 02 02 02 02 02 02 02 02 01 02 02 03 02 02 02 02 02 02 01
</results>

Regards, Morton