sashite-feen 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +412 -137
- data/lib/sashite/feen/dumper/piece_placement.rb +144 -64
- data/lib/sashite/feen/dumper/pieces_in_hand.rb +124 -34
- data/lib/sashite/feen/dumper/style_turn.rb +29 -45
- data/lib/sashite/feen/dumper.rb +40 -30
- data/lib/sashite/feen/error.rb +72 -29
- data/lib/sashite/feen/hands.rb +62 -20
- data/lib/sashite/feen/parser/piece_placement.rb +324 -118
- data/lib/sashite/feen/parser/pieces_in_hand.rb +210 -44
- data/lib/sashite/feen/parser/style_turn.rb +81 -41
- data/lib/sashite/feen/parser.rb +60 -15
- data/lib/sashite/feen/placement.rb +295 -19
- data/lib/sashite/feen/position.rb +64 -13
- data/lib/sashite/feen/styles.rb +54 -57
- data/lib/sashite/feen.rb +57 -96
- metadata +1 -2
- data/lib/sashite/feen/ordering.rb +0 -16
data/lib/sashite/feen.rb
CHANGED
|
@@ -1,106 +1,67 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# Public API for FEEN (Forsyth–Edwards Enhanced Notation)
|
|
4
|
-
# - Pure functions, no global state
|
|
5
|
-
# - Immutable value objects
|
|
6
|
-
# - Delegates parsing/dumping to dedicated components
|
|
7
|
-
|
|
8
|
-
require "sashite/epin"
|
|
9
|
-
require "sashite/sin"
|
|
10
|
-
|
|
11
|
-
require_relative "feen/error"
|
|
12
|
-
require_relative "feen/position"
|
|
13
|
-
require_relative "feen/placement"
|
|
14
|
-
require_relative "feen/hands"
|
|
15
|
-
require_relative "feen/styles"
|
|
16
|
-
require_relative "feen/ordering"
|
|
17
|
-
require_relative "feen/parser"
|
|
18
3
|
require_relative "feen/dumper"
|
|
4
|
+
require_relative "feen/parser"
|
|
19
5
|
|
|
20
6
|
module Sashite
|
|
7
|
+
# FEEN (Forsyth–Edwards Enhanced Notation) module provides parsing and dumping
|
|
8
|
+
# functionality for board game positions.
|
|
9
|
+
#
|
|
10
|
+
# FEEN is a universal, rule-agnostic notation for representing board game positions.
|
|
11
|
+
# It extends traditional FEN to support multiple game systems, cross-style games,
|
|
12
|
+
# multi-dimensional boards, and captured pieces.
|
|
13
|
+
#
|
|
14
|
+
# A FEEN string consists of three space-separated fields:
|
|
15
|
+
# 1. Piece placement: Board configuration using EPIN notation
|
|
16
|
+
# 2. Pieces in hand: Captured pieces held by each player
|
|
17
|
+
# 3. Style-turn: Game styles and active player
|
|
18
|
+
#
|
|
19
|
+
# @see https://sashite.dev/specs/feen/1.0.0/
|
|
21
20
|
module Feen
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
parse(feen)
|
|
43
|
-
true
|
|
44
|
-
rescue Error::Validation, Error::Syntax, Error::Piece, Error::Style, Error::Count, Error::Bounds
|
|
45
|
-
false
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# Dump a Position to its canonical FEEN string.
|
|
49
|
-
#
|
|
50
|
-
# @param position [Sashite::Feen::Position, String] # String => parse puis dump
|
|
51
|
-
# @return [String] canonical FEEN
|
|
52
|
-
def dump(position)
|
|
53
|
-
pos = _coerce_position(position)
|
|
54
|
-
Dumper.dump(pos).dup.freeze
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# Canonicalize a FEEN string (parse → dump).
|
|
58
|
-
#
|
|
59
|
-
# @param feen [String]
|
|
60
|
-
# @return [String] canonical FEEN
|
|
61
|
-
def normalize(feen)
|
|
62
|
-
dump(parse(feen))
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# Build a Position from its three FEEN fields.
|
|
66
|
-
#
|
|
67
|
-
# Each argument accepts either a String (parsed by its field parser)
|
|
68
|
-
# or the corresponding value-object (Placement/Hands/Styles).
|
|
69
|
-
#
|
|
70
|
-
# @param piece_placement [String, Sashite::Feen::Placement]
|
|
71
|
-
# @param pieces_in_hand [String, Sashite::Feen::Hands]
|
|
72
|
-
# @param style_turn [String, Sashite::Feen::Styles]
|
|
73
|
-
# @return [Sashite::Feen::Position]
|
|
74
|
-
def build(piece_placement:, pieces_in_hand:, style_turn:)
|
|
75
|
-
placement = _coerce_component(Placement, Parser::PiecePlacement, piece_placement)
|
|
76
|
-
hands = _coerce_component(Hands, Parser::PiecesInHand, pieces_in_hand)
|
|
77
|
-
styles = _coerce_component(Styles, Parser::StyleTurn, style_turn)
|
|
78
|
-
|
|
79
|
-
Position.new(placement, hands, styles).freeze
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
private
|
|
83
|
-
|
|
84
|
-
# -- helpers -------------------------------------------------------------
|
|
85
|
-
|
|
86
|
-
def _coerce_position(obj)
|
|
87
|
-
return obj if obj.is_a?(Position)
|
|
88
|
-
return parse(obj) if obj.is_a?(String)
|
|
89
|
-
|
|
90
|
-
raise TypeError, "expected Sashite::Feen::Position or FEEN String, got #{obj.class}"
|
|
91
|
-
end
|
|
21
|
+
# Dump a Position object into its canonical FEEN string representation.
|
|
22
|
+
#
|
|
23
|
+
# Generates a deterministic FEEN string from a position object. The same
|
|
24
|
+
# position will always produce the same canonical string, ensuring
|
|
25
|
+
# position equality can be tested via string comparison.
|
|
26
|
+
#
|
|
27
|
+
# @param position [Position] A position object with placement, hands, and styles
|
|
28
|
+
# @return [String] Canonical FEEN notation string
|
|
29
|
+
#
|
|
30
|
+
# @example Dump a position to FEEN
|
|
31
|
+
# feen_string = Sashite::Feen.dump(position)
|
|
32
|
+
# # => "+rnbq+kbn+r/+p+p+p+p+p+p+p+p/8/8/8/8/+P+P+P+P+P+P+P+P/+RNBQ+KBN+R / C/c"
|
|
33
|
+
#
|
|
34
|
+
# @example Round-trip parsing and dumping
|
|
35
|
+
# original = "+rnbq+kbn+r/+p+p+p+p+p+p+p+p/8/8/8/8/+P+P+P+P+P+P+P+P/+RNBQ+KBN+R / C/c"
|
|
36
|
+
# position = Sashite::Feen.parse(original)
|
|
37
|
+
# Sashite::Feen.dump(position) == original # => true
|
|
38
|
+
def self.dump(position)
|
|
39
|
+
Dumper.dump(position)
|
|
40
|
+
end
|
|
92
41
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
42
|
+
# Parse a FEEN string into an immutable Position object.
|
|
43
|
+
#
|
|
44
|
+
# This method parses the three FEEN fields and constructs an immutable position
|
|
45
|
+
# object with placement, hands, and styles components.
|
|
46
|
+
#
|
|
47
|
+
# @param string [String] A FEEN notation string with three space-separated fields
|
|
48
|
+
# @return [Position] Immutable position object
|
|
49
|
+
# @raise [Error::Syntax] If the FEEN structure is malformed
|
|
50
|
+
# @raise [Error::Piece] If EPIN notation is invalid
|
|
51
|
+
# @raise [Error::Style] If SIN notation is invalid
|
|
52
|
+
# @raise [Error::Count] If piece counts are invalid
|
|
53
|
+
# @raise [Error::Validation] For other semantic violations
|
|
54
|
+
#
|
|
55
|
+
# @example Parse a chess starting position
|
|
56
|
+
# position = Sashite::Feen.parse("+rnbq+kbn+r/+p+p+p+p+p+p+p+p/8/8/8/8/+P+P+P+P+P+P+P+P/+RNBQ+KBN+R / C/c")
|
|
57
|
+
# position.placement # => Placement object (board configuration)
|
|
58
|
+
# position.hands # => Hands object (pieces in hand)
|
|
59
|
+
# position.styles # => Styles object (style-turn information)
|
|
60
|
+
#
|
|
61
|
+
# @example Parse a shogi position with captured pieces
|
|
62
|
+
# position = Sashite::Feen.parse("lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL P/p S/s")
|
|
63
|
+
def self.parse(string)
|
|
64
|
+
Parser.parse(string)
|
|
104
65
|
end
|
|
105
66
|
end
|
|
106
67
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sashite-feen
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Cyril Kato
|
|
@@ -62,7 +62,6 @@ files:
|
|
|
62
62
|
- lib/sashite/feen/dumper/style_turn.rb
|
|
63
63
|
- lib/sashite/feen/error.rb
|
|
64
64
|
- lib/sashite/feen/hands.rb
|
|
65
|
-
- lib/sashite/feen/ordering.rb
|
|
66
65
|
- lib/sashite/feen/parser.rb
|
|
67
66
|
- lib/sashite/feen/parser/piece_placement.rb
|
|
68
67
|
- lib/sashite/feen/parser/pieces_in_hand.rb
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Sashite
|
|
4
|
-
module Feen
|
|
5
|
-
# Deterministic ordering helpers (kept minimal for now).
|
|
6
|
-
# If you later need domain-specific sort (e.g., EPIN-aware), centralize it here.
|
|
7
|
-
module Ordering
|
|
8
|
-
module_function
|
|
9
|
-
|
|
10
|
-
# Default lexicographic sort key for serialized EPIN tokens (String)
|
|
11
|
-
def hand_token_key(token_str)
|
|
12
|
-
String(token_str)
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|