module Doku::PuzzleOnGrid
This module is meant to be included in subclasses of {Puzzle} where the squares are arranged in a grid.
The {Puzzle} class contains only very abstract code, dealing with the abstract concepts of {Puzzle.squares squares}, {Puzzle.glyphs glyphs}, and {Puzzle.groups groups}. The {Puzzle} class can represent a wide variety of puzzles, including three-dimensional puzzles or puzzles that don’t have any particular spatial arrangement. However, most of the puzzles we are interested in studying are arranged in a grid, and this module contains code that makes it easy to define and work with those puzzles.
Every {Puzzle.squares square} in a {PuzzleOnGrid} puzzle is a {SquareOnGrid} with x and y coordinates to represent its position on the grid. The x coordinate is 0 for the first row, 1 for the second row, etc. The y coordinate is 0 for the first column, 1 for the second column, etc.
See the {ClassMethods} module for the class methods that are added to each class that includes PuzzleOnGrid
.
Constants
- Separators
These are the separators that can appear in the {ClassMethods#template template} string or the string argument to the {#initialize} to make it more readable.
Public Class Methods
Creates a new instance of the puzzle. @param grid_string (String) A multi-line string defining which glyphs are
currently written in which squares. You can use {Separators} to make this string more readable. This parameter is provided to make it easy to manually type in puzzles. If you are not typing the puzzle in, you should probably use {#set} instead. A good way to type this string is to copy the class's {ClassMethods#template template} and replace some of the periods with {ClassMethods#glyph_chars glyph_chars} (e.g. replace a '.' with '3').
# File lib/doku/grid.rb, line 163 def initialize(grid_string=nil) super() parse_initial_grid_string grid_string if grid_string end
Private Class Methods
# File lib/doku/grid.rb, line 28 def self.included(klass) klass.extend ClassMethods end
# File lib/doku/grid.rb, line 32 def self.parse_grid_string(string) y = 0 string.lines.each_with_index do |line, line_number| line.chomp! next if (line.chars.to_a - Separators).empty? x = 0 line.chars.each_with_index do |char, char_number| next if Separators.include?(char) yield char, char_number, line_number, x, y x += 1 end y += 1 end end
Public Instance Methods
Gets the glyph assignment for a given square. @param x (Integer) The x coordinate of the square. @param x (Integer) The y coordinate of the square. @return (Object) The {Puzzle.glyphs glyph} assigned to that square, or nil if
none is assigned.
# File lib/doku/grid.rb, line 194 def get(x, y) self[SquareOnGrid.new(x, y)] end
Assigns a glyph to a square. This will modify the state of the puzzle, overwriting the previous glyph assignment. @param x (Integer) The x coordinate of the square. @param y (Integer) The y coordinate of the square. @param glyph The {Puzzle.glyphs glyph} to assign to that square, or nil.
# File lib/doku/grid.rb, line 185 def set(x, y, glyph) self[SquareOnGrid.new(x, y)] = glyph end
@return (String) A multi-line string representation of the puzzle suitable
for displaying, based on the {ClassMethods#template template}.
# File lib/doku/grid.rb, line 170 def to_grid_string lines = self.class.template.split("\n") each do |square, glyph| line_number, char_number = self.class.coordinates_in_grid_string square lines[line_number][char_number] = self.class.glyph_char glyph end lines.join "\n" end
@return (String) The same as {#to_grid_string}.
# File lib/doku/grid.rb, line 199 def to_s to_grid_string end
Private Instance Methods
# File lib/doku/grid.rb, line 204 def parse_initial_grid_string(grid_string) PuzzleOnGrid.parse_grid_string(grid_string) do |original_char, char_number, line_number, x, y| square = SquareOnGrid.new(x, y) char = original_char.upcase if !squares.include?(square) raise "Line #{line_number}, character #{char_number}: Invalid character. Expected space." if char != ' ' elsif char == '.' # No glyph specified for this square. elsif self.class.glyph_chars.include?(char) self[square] = self.class.glyph_parse(char) else raise ArgumentError, "Line #{line_number}, character #{char_number}: Invalid character '#{original_char}'. Expected period (.) or glyph (#{self.class.glyph_chars.join ','})." end end end