Module: Feen::Parser::PiecePlacement

Defined in:
lib/feen/parser/piece_placement.rb

Overview

Handles parsing of the piece placement section of a FEEN string

This module is responsible for converting the first field of a FEEN string (piece placement) into a hierarchical array structure representing the board. It supports arbitrary dimensions and handles both pieces (with optional PNN modifiers) and empty squares (represented by numbers).

Constant Summary collapse

ERRORS =

Simplified error messages

{
  invalid_type:   "Piece placement must be a string, got %s",
  empty_string:   "Piece placement string cannot be empty",
  invalid_format: "Invalid piece placement format"
}.freeze
DIMENSION_SEPARATOR =

Dimension separator character

"/"

Class Method Summary collapse

Class Method Details

.parse(piece_placement_str) ⇒ Array

Parses the piece placement section of a FEEN string

Converts a FEEN piece placement string into a hierarchical array structure representing the board where empty squares are represented by empty strings and pieces are represented by strings containing their PNN identifier and optional modifiers.

Examples:

Parse a simple 2D chess position (initial position)

PiecePlacement.parse("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR")
# => [
#      ["r", "n", "b", "q", "k", "b", "n", "r"],
#      ["p", "p", "p", "p", "p", "p", "p", "p"],
#      ["", "", "", "", "", "", "", ""],
#      ["", "", "", "", "", "", "", ""],
#      ["", "", "", "", "", "", "", ""],
#      ["", "", "", "", "", "", "", ""],
#      ["P", "P", "P", "P", "P", "P", "P", "P"],
#      ["R", "N", "B", "Q", "K", "B", "N", "R"]
#    ]

Parse a single rank with mixed pieces and empty squares

PiecePlacement.parse("r2k1r")
# => ["r", "", "", "k", "", "r"]

Parse pieces with PNN modifiers (promoted pieces in Shogi)

PiecePlacement.parse("+P+Bk")
# => ["+P", "+B", "k"]

Parse a 3D board structure (2 planes of 2x2)

PiecePlacement.parse("rn/pp//RN/PP")
# => [
#      [["r", "n"], ["p", "p"]],
#      [["R", "N"], ["P", "P"]]
#    ]

Parse complex Shogi position with promoted pieces

PiecePlacement.parse("9/9/9/9/4+P4/9/5+B3/9/9")
# => [
#      ["", "", "", "", "", "", "", "", ""],
#      ["", "", "", "", "", "", "", "", ""],
#      ["", "", "", "", "", "", "", "", ""],
#      ["", "", "", "", "", "", "", "", ""],
#      ["", "", "", "", "+P", "", "", "", ""],
#      ["", "", "", "", "", "", "", "", ""],
#      ["", "", "", "", "", "+B", "", "", ""],
#      ["", "", "", "", "", "", "", "", ""],
#      ["", "", "", "", "", "", "", "", ""]
#    ]

Parse irregular board shapes (different rank sizes)

PiecePlacement.parse("rnbqkbnr/ppppppp/8")
# => [
#      ["r", "n", "b", "q", "k", "b", "n", "r"],  # 8 cells
#      ["p", "p", "p", "p", "p", "p", "p"],       # 7 cells
#      ["", "", "", "", "", "", "", ""]           # 8 cells
#    ]

Parse large numbers of empty squares

PiecePlacement.parse("15")
# => ["", "", "", "", "", "", "", "", "", "", "", "", "", "", ""]

Parse pieces with all PNN modifier types

PiecePlacement.parse("+P'-R'k")
# => ["+P'", "-R'", "k"]
# Where:
# - "+P'" = enhanced state with intermediate suffix
# - "-R'" = diminished state with intermediate suffix
# - "k"   = base piece without modifiers

Parameters:

  • piece_placement_str (String)

    FEEN piece placement string

Returns:

  • (Array)

    Hierarchical array structure representing the board where:

    • Empty squares are represented by empty strings (“”)

    • Pieces are represented by strings containing their identifier and optional modifiers

Raises:

  • (ArgumentError)

    If the input string is invalid



99
100
101
102
# File 'lib/feen/parser/piece_placement.rb', line 99

def self.parse(piece_placement_str)
  validate_input(piece_placement_str)
  parse_structure(piece_placement_str)
end

.validate_input(str) ⇒ void

This method returns an undefined value.

Validates the input string for basic requirements

Ensures the input is a non-empty string containing only valid FEEN characters. Valid characters include: letters (a-z, A-Z), digits (0-9), and modifiers (+, -, ‘).

Examples:

Valid input

validate_input("rnbqkbnr/pppppppp/8/8")
# => (no error)

Invalid input (empty string)

validate_input("")
# => ArgumentError: Piece placement string cannot be empty

Invalid input (wrong type)

validate_input(123)
# => ArgumentError: Piece placement must be a string, got Integer

Parameters:

  • str (String)

    Input string to validate

Raises:

  • (ArgumentError)

    If the string is invalid



124
125
126
127
128
129
130
131
132
# File 'lib/feen/parser/piece_placement.rb', line 124

def self.validate_input(str)
  raise ArgumentError, format(ERRORS[:invalid_type], str.class) unless str.is_a?(String)
  raise ArgumentError, ERRORS[:empty_string] if str.empty?

  # Basic format validation
  return if str.match?(%r{\A[a-zA-Z0-9+\-'/]+\z})

  raise ArgumentError, ERRORS[:invalid_format]
end