puts <<EOS
    Minesweeper game.

    There is an n by m grid that has a random number of between 20% to 60%
    of randomly hidden mines that need to be found. 

    Positions in the grid are modified by entering their coordinates
    where the first coordinate is horizontal in the grid and the second
    vertical. The top left of the grid is position 1,1; the bottom right is
    at n,m.

    * The total number of mines to be found is shown at the beginning of the
    game.
    * Each mine occupies a single grid point, and its position is initially
    unknown to the player
    * The grid is shown as a rectangle of characters between moves.
    * You are initially shown all grids as obscured, by a single dot '.'
    * You may mark what you think is the position of a mine which will show
    as a '?'
    * You can mark what you think is free space by entering its coordinates.
   :*  If the point is free space then it is cleared, as are any adjacent
    points that are also free space- this is repeated recursively for
    subsequent adjacent free points unless that point is marked as a mine
    or is a mine.
   ::*   Points marked as a mine show as a '?'.
   ::*   Other free points show as an integer count of the number of adjacent
    true mines in its immediate neighbourhood, or as a single space ' ' if the
    free point is not adjacent to any true mines.
    * Of course you loose if you try to clear space that starts on a mine.
    * You win when you have correctly identified all mines.


    When prompted you may:
        Toggle where you think a mine is at position x, y:
          m <x> <y>
        Clear the grid starting at position x, y (and print the result):
          c <x> <y>
        Print the grid so far:
          p
        Quit
          q
    Resigning will first show the grid with an 'N' for unfound true mines, a
    'Y' for found true mines and a '?' for where you marked clear space as a
    mine
EOS

WIDTH, HEIGHT = 6, 4
PCT = 0.15
NUM_MINES = (WIDTH * HEIGHT * PCT).round

def create_mines sx, sy
  arr = Array.new(WIDTH) { Array.new(HEIGHT, false) }
  NUM_MINES.times do
    x, y = rand(WIDTH), rand(HEIGHT)
    
    redo if arr[x][y] or (x == sx and y == sy)
    arr[x][y] = true
  end
  arr
end

def num_marks
  $screen.inject(0) { |sum, row| sum + row.count() }
end

def show_grid revealed = false
  if revealed
    puts $mines.transpose.map { |row| row.map { |cell| cell? :  }.join() }
  else
    puts 
    puts $screen.transpose.map{ |row| row.join() }
  end
end

SURROUND = [-1,0,1].product([-1,0,1]) - [[0,0]]     
def surrounding x, y
  
  SURROUND.each do |dx, dy|
    
    yield(x+dx, y+dy) if (0...WIDTH).cover?(x+dx) and (0...HEIGHT).cover?(y+dy)
  end
end

def clear_space x, y
  return unless $screen[x][y] == 
  
  count = 0
  surrounding(x, y) { |px, py| count += 1 if $mines[px][py] }
  if count == 0
    $screen[x][y] = 
    surrounding(x, y) { |px, py| clear_space px, py }
  else
    $screen[x][y] = count.to_s
  end
end

def victory?
  return false if $mines.nil?  
  return false if num_marks!= NUM_MINES
  mines_left = NUM_MINES
  WIDTH.times do |x|
    HEIGHT.times do |y|
      mines_left -= 1 if $mines[x][y] and $screen[x][y] == 
    end
  end

  mines_left == 0
end

def check_input x, y
  x, y = x.to_i - 1, y.to_i - 1
  [x, y] if (0...WIDTH).cover?(x) and (0...HEIGHT).cover?(y)
end

$mines = nil
$screen = Array.new(WIDTH) { Array.new(HEIGHT, ) }

puts 
show_grid

loop do
  print 
  action = gets.chomp.downcase

  case action
  when , , , 
    puts 
    break
  when /^m (\d+) (\d+)$/
    
    x, y = check_input $1, $2
    next unless x
    if $screen[x][y] == 
      
      $screen[x][y] = 
      if victory?
        show_grid
        puts 
        break
      end
    elsif $screen[x][y] == 
      
      $screen[x][y] = 
    end
    show_grid
  when /^c (\d+) (\d+)$/
    x, y = check_input $1, $2
    next unless x
    $mines ||= create_mines(x, y)
    if $mines[x][y]
      puts 
      show_grid true
      break
    else
      clear_space x, y
      show_grid
      if victory?
        puts 
        break
      end
    end
  when 
    show_grid
  end
end