Class: Sashite::Pnn::Name

Inherits:
Object
  • Object
show all
Defined in:
lib/sashite/pnn/name.rb

Overview

Represents a piece name in PNN (Piece Name Notation) format.

PNN provides a canonical naming system for abstract strategy game pieces. Each name consists of an optional state modifier (+ or -) followed by a case-consistent alphabetic name, encoding piece identity, player assignment, and state in a human-readable format.

All instances are immutable.

Constant Summary collapse

PNN_PATTERN =

PNN validation pattern matching the specification

/\A([+-]?)([A-Z]+|[a-z]+)\z/
ERROR_INVALID_NAME =

Error messages

"Invalid PNN string: %s"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ Name

Create a new piece name instance

Parameters:

  • name (String, Symbol)

    the piece name (e.g., “KING”, :queen, “+ROOK”, “-pawn”)

Raises:

  • (ArgumentError)

    if the name does not match PNN pattern



27
28
29
30
31
32
33
34
# File 'lib/sashite/pnn/name.rb', line 27

def initialize(name)
  string_value = name.to_s
  self.class.validate_format(string_value)

  @value = string_value.freeze
  @parsed = parse_components(string_value)
  freeze
end

Instance Attribute Details

#valueString (readonly)

Returns the canonical piece name.

Returns:

  • (String)

    the canonical piece name



21
22
23
# File 'lib/sashite/pnn/name.rb', line 21

def value
  @value
end

Class Method Details

.parse(string) ⇒ Name

Parse a PNN string into a Name object

Examples:

Sashite::Pnn::Name.parse("KING")   # => #<Pnn::Name value="KING">
Sashite::Pnn::Name.parse("+queen") # => #<Pnn::Name value="+queen">

Parameters:

  • string (String)

    the PNN-formatted piece name

Returns:

  • (Name)

    a new Name instance

Raises:

  • (ArgumentError)

    if the string is invalid



45
46
47
# File 'lib/sashite/pnn/name.rb', line 45

def self.parse(string)
  new(string)
end

.valid?(string) ⇒ Boolean

Check whether the given string is a valid PNN name

Examples:

Sashite::Pnn::Name.valid?("KING")    # => true
Sashite::Pnn::Name.valid?("King")    # => false (mixed case)
Sashite::Pnn::Name.valid?("+queen")  # => true
Sashite::Pnn::Name.valid?("KING1")   # => false (contains digit)

Parameters:

  • string (String)

    input string to validate

Returns:

  • (Boolean)

    true if valid, false otherwise



59
60
61
# File 'lib/sashite/pnn/name.rb', line 59

def self.valid?(string)
  string.is_a?(::String) && string.match?(PNN_PATTERN)
end

.validate_format(str) ⇒ Object

Validate that the string is in proper PNN format

Parameters:

  • str (String)

Raises:

  • (ArgumentError)

    if invalid



67
68
69
# File 'lib/sashite/pnn/name.rb', line 67

def self.validate_format(str)
  raise ::ArgumentError, format(ERROR_INVALID_NAME, str.inspect) unless str.match?(PNN_PATTERN)
end

Instance Method Details

#==(other) ⇒ Boolean Also known as: eql?

Equality based on normalized string value

Parameters:

  • other (Object)

Returns:

  • (Boolean)


167
168
169
# File 'lib/sashite/pnn/name.rb', line 167

def ==(other)
  other.is_a?(self.class) && value == other.value
end

#base_nameString

Returns the base name without state modifier

Examples:

Sashite::Pnn::Name.parse("KING").base_name    # => "KING"
Sashite::Pnn::Name.parse("+queen").base_name  # => "queen"
Sashite::Pnn::Name.parse("-ROOK").base_name   # => "ROOK"

Returns:

  • (String)

    the piece name without + or - prefix



86
87
88
# File 'lib/sashite/pnn/name.rb', line 86

def base_name
  @parsed[:base_name]
end

#diminished?Boolean

Check if the piece has diminished state (-)

Examples:

Sashite::Pnn::Name.parse("-pawn").diminished? # => true
Sashite::Pnn::Name.parse("pawn").diminished?  # => false

Returns:

  • (Boolean)

    true if diminished, false otherwise



108
109
110
# File 'lib/sashite/pnn/name.rb', line 108

def diminished?
  @parsed[:state_modifier] == "-"
end

#enhanced?Boolean

Check if the piece has enhanced state (+)

Examples:

Sashite::Pnn::Name.parse("+KING").enhanced?   # => true
Sashite::Pnn::Name.parse("KING").enhanced?    # => false

Returns:

  • (Boolean)

    true if enhanced, false otherwise



97
98
99
# File 'lib/sashite/pnn/name.rb', line 97

def enhanced?
  @parsed[:state_modifier] == "+"
end

#first_player?Boolean

Check if the piece belongs to the first player (uppercase)

Examples:

Sashite::Pnn::Name.parse("KING").first_player?    # => true
Sashite::Pnn::Name.parse("queen").first_player?   # => false

Returns:

  • (Boolean)

    true if first player, false otherwise



130
131
132
# File 'lib/sashite/pnn/name.rb', line 130

def first_player?
  @parsed[:base_name] == @parsed[:base_name].upcase
end

#hashInteger

Hash based on class and value

Returns:

  • (Integer)


177
178
179
# File 'lib/sashite/pnn/name.rb', line 177

def hash
  [self.class, value].hash
end

#normal?Boolean

Check if the piece has normal state (no modifier)

Examples:

Sashite::Pnn::Name.parse("KING").normal?      # => true
Sashite::Pnn::Name.parse("+KING").normal?     # => false

Returns:

  • (Boolean)

    true if normal, false otherwise



119
120
121
# File 'lib/sashite/pnn/name.rb', line 119

def normal?
  @parsed[:state_modifier].empty?
end

#same_base_name?(other) ⇒ Boolean

Check if another piece has the same base name (ignoring case and state)

Examples:

king = Sashite::Pnn::Name.parse("KING")
queen = Sashite::Pnn::Name.parse("king")
enhanced = Sashite::Pnn::Name.parse("+KING")

king.same_base_name?(queen)    # => true (same piece, different player)
king.same_base_name?(enhanced) # => true (same piece, different state)

Parameters:

  • other (Name)

    another piece name to compare

Returns:

  • (Boolean)

    true if same base name, false otherwise



157
158
159
160
161
# File 'lib/sashite/pnn/name.rb', line 157

def same_base_name?(other)
  return false unless other.is_a?(self.class)

  base_name.downcase == other.base_name.downcase
end

#second_player?Boolean

Check if the piece belongs to the second player (lowercase)

Examples:

Sashite::Pnn::Name.parse("king").second_player?   # => true
Sashite::Pnn::Name.parse("QUEEN").second_player?  # => false

Returns:

  • (Boolean)

    true if second player, false otherwise



141
142
143
# File 'lib/sashite/pnn/name.rb', line 141

def second_player?
  @parsed[:base_name] == @parsed[:base_name].downcase
end

#to_sString

Returns the string representation of the name

Returns:

  • (String)


74
75
76
# File 'lib/sashite/pnn/name.rb', line 74

def to_s
  value
end