feen 5.0.0.beta0 → 5.0.0.beta2
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/LICENSE.md +1 -1
- data/README.md +139 -51
- data/lib/feen/converter/from_fen.rb +170 -0
- data/lib/feen/converter/to_fen.rb +153 -0
- data/lib/feen/converter.rb +16 -0
- data/lib/feen/dumper/games_turn.rb +92 -0
- data/lib/feen/dumper/piece_placement.rb +104 -67
- data/lib/feen/dumper/pieces_in_hand.rb +44 -16
- data/lib/feen/dumper.rb +43 -30
- data/lib/feen/parser/games_turn.rb +136 -0
- data/lib/feen/parser/piece_placement.rb +204 -44
- data/lib/feen/parser/pieces_in_hand.rb +63 -22
- data/lib/feen/parser.rb +39 -27
- data/lib/feen/sanitizer.rb +119 -0
- data/lib/feen.rb +91 -46
- metadata +12 -10
- data/lib/feen/parser/board_shape.rb +0 -37
data/lib/feen.rb
CHANGED
@@ -1,65 +1,110 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative File.join("feen", "converter")
|
3
4
|
require_relative File.join("feen", "dumper")
|
4
5
|
require_relative File.join("feen", "parser")
|
5
6
|
|
6
7
|
# This module provides a Ruby interface for data serialization and
|
7
8
|
# deserialization in FEEN format.
|
8
9
|
#
|
9
|
-
# @see https://
|
10
|
+
# @see https://sashite.dev/documents/feen/1.0.0/
|
10
11
|
module Feen
|
11
12
|
# Dumps position params into a FEEN string.
|
12
13
|
#
|
13
|
-
# @param
|
14
|
-
# @
|
15
|
-
# @
|
16
|
-
# @
|
17
|
-
#
|
18
|
-
# @
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
)
|
14
|
+
# @param position [Hash] Hash containing the position data
|
15
|
+
# @option position [Array] :piece_placement Board position data
|
16
|
+
# @option position [Hash] :games_turn Games and turn data
|
17
|
+
# @option position [Array<Hash>] :pieces_in_hand Pieces in hand data
|
18
|
+
# @return [String] FEEN notation string
|
19
|
+
# @raise [ArgumentError] If the position data is invalid
|
20
|
+
# @example
|
21
|
+
# position = {
|
22
|
+
# piece_placement: [[{id: 'r'}, {id: 'n'}, {id: 'b'}, {id: 'q'}, {id: 'k'}, {id: 'b'}, {id: 'n'}, {id: 'r'}],
|
23
|
+
# [{id: 'p'}, {id: 'p'}, {id: 'p'}, {id: 'p'}, {id: 'p'}, {id: 'p'}, {id: 'p'}, {id: 'p'}],
|
24
|
+
# [nil, nil, nil, nil, nil, nil, nil, nil],
|
25
|
+
# [nil, nil, nil, nil, nil, nil, nil, nil],
|
26
|
+
# [nil, nil, nil, nil, nil, nil, nil, nil],
|
27
|
+
# [nil, nil, nil, nil, nil, nil, nil, nil],
|
28
|
+
# [{id: 'P'}, {id: 'P'}, {id: 'P'}, {id: 'P'}, {id: 'P'}, {id: 'P'}, {id: 'P'}, {id: 'P'}],
|
29
|
+
# [{id: 'R'}, {id: 'N'}, {id: 'B'}, {id: 'Q'}, {id: 'K'}, {id: 'B'}, {id: 'N'}, {id: 'R'}]],
|
30
|
+
# games_turn: {
|
31
|
+
# active_player: 'CHESS',
|
32
|
+
# inactive_player: 'chess',
|
33
|
+
# uppercase_game: 'CHESS',
|
34
|
+
# lowercase_game: 'chess'
|
35
|
+
# },
|
36
|
+
# pieces_in_hand: []
|
37
|
+
# }
|
38
|
+
# Feen.dump(position) # => "rnbqk=bnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQK=BNR CHESS/chess -"
|
39
|
+
def self.dump(position)
|
40
|
+
Dumper.dump(position)
|
41
41
|
end
|
42
42
|
|
43
43
|
# Parses a FEEN string into position params.
|
44
44
|
#
|
45
|
-
# @param
|
46
|
-
#
|
47
|
-
# @
|
48
|
-
#
|
45
|
+
# @param feen_string [String] FEEN notation string
|
46
|
+
# @return [Hash] Hash containing the parsed position data
|
47
|
+
# @raise [ArgumentError] If the FEEN string is invalid
|
48
|
+
# @example
|
49
|
+
# feen_string = "rnbqk=bnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQK=BNR CHESS/chess -"
|
50
|
+
# Feen.parse(feen_string)
|
49
51
|
# # => {
|
50
|
-
# #
|
51
|
-
# #
|
52
|
-
# #
|
53
|
-
# #
|
54
|
-
# #
|
55
|
-
# #
|
56
|
-
# #
|
57
|
-
# #
|
58
|
-
# #
|
59
|
-
# #
|
52
|
+
# # piece_placement: [[{id: 'r'}, {id: 'n'}, {id: 'b'}, {id: 'q'}, {id: 'k', suffix: '='}, {id: 'b'}, {id: 'n'}, {id: 'r'}],
|
53
|
+
# # [{id: 'p'}, {id: 'p'}, {id: 'p'}, {id: 'p'}, {id: 'p'}, {id: 'p'}, {id: 'p'}, {id: 'p'}],
|
54
|
+
# # [nil, nil, nil, nil, nil, nil, nil, nil],
|
55
|
+
# # [nil, nil, nil, nil, nil, nil, nil, nil],
|
56
|
+
# # [nil, nil, nil, nil, nil, nil, nil, nil],
|
57
|
+
# # [nil, nil, nil, nil, nil, nil, nil, nil],
|
58
|
+
# # [{id: 'P'}, {id: 'P'}, {id: 'P'}, {id: 'P'}, {id: 'P'}, {id: 'P'}, {id: 'P'}, {id: 'P'}],
|
59
|
+
# # [{id: 'R'}, {id: 'N'}, {id: 'B'}, {id: 'Q'}, {id: 'K', suffix: '='}, {id: 'B'}, {id: 'N'}, {id: 'R'}]],
|
60
|
+
# # games_turn: {
|
61
|
+
# # active_player: 'CHESS',
|
62
|
+
# # inactive_player: 'chess',
|
63
|
+
# # uppercase_game: 'CHESS',
|
64
|
+
# # lowercase_game: 'chess',
|
65
|
+
# # active_player_casing: :uppercase
|
66
|
+
# # },
|
67
|
+
# # pieces_in_hand: []
|
68
|
+
# # }
|
69
|
+
def self.parse(feen_string)
|
70
|
+
Parser.parse(feen_string)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Validates if the given string is a valid FEEN string
|
74
|
+
#
|
75
|
+
# @param feen_string [String] FEEN string to validate
|
76
|
+
# @return [Boolean] True if the string is a valid FEEN string, false otherwise
|
77
|
+
# @example
|
78
|
+
# Feen.valid?("rnbqk=bnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQK=BNR CHESS/chess -") # => true
|
79
|
+
# Feen.valid?("invalid feen string") # => false
|
80
|
+
def self.valid?(feen_string)
|
81
|
+
parse(feen_string)
|
82
|
+
true
|
83
|
+
rescue ::ArgumentError
|
84
|
+
false
|
85
|
+
end
|
86
|
+
|
87
|
+
# Converts a FEN string to a FEEN string for chess positions
|
88
|
+
#
|
89
|
+
# @param fen_string [String] Standard FEN notation string for chess
|
90
|
+
# @return [String] Equivalent FEEN notation string
|
91
|
+
# @raise [ArgumentError] If the FEN string is invalid
|
92
|
+
# @example
|
93
|
+
# Feen.from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
|
94
|
+
# # => "rnbqk=bnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQK=BNR CHESS/chess -"
|
95
|
+
def self.from_fen(fen_string)
|
96
|
+
Converter.from_fen(fen_string)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Converts a FEEN string to a FEN string for chess positions
|
60
100
|
#
|
61
|
-
# @
|
62
|
-
|
63
|
-
|
101
|
+
# @param feen_string [String] FEEN notation string
|
102
|
+
# @return [String] Equivalent FEN notation string
|
103
|
+
# @raise [ArgumentError] If the FEEN string is invalid
|
104
|
+
# @example
|
105
|
+
# Feen.to_fen("rnbqk=bnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQK=BNR CHESS/chess -")
|
106
|
+
# # => "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
|
107
|
+
def self.to_fen(feen_string)
|
108
|
+
Converter.to_fen(feen_string)
|
64
109
|
end
|
65
110
|
end
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: feen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0.0.
|
4
|
+
version: 5.0.0.beta2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cyril Kato
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies: []
|
13
12
|
description: A Ruby interface for data serialization and deserialization in FEEN format.
|
14
13
|
email: contact@cyril.email
|
@@ -19,19 +18,23 @@ files:
|
|
19
18
|
- LICENSE.md
|
20
19
|
- README.md
|
21
20
|
- lib/feen.rb
|
21
|
+
- lib/feen/converter.rb
|
22
|
+
- lib/feen/converter/from_fen.rb
|
23
|
+
- lib/feen/converter/to_fen.rb
|
22
24
|
- lib/feen/dumper.rb
|
25
|
+
- lib/feen/dumper/games_turn.rb
|
23
26
|
- lib/feen/dumper/piece_placement.rb
|
24
27
|
- lib/feen/dumper/pieces_in_hand.rb
|
25
28
|
- lib/feen/parser.rb
|
26
|
-
- lib/feen/parser/
|
29
|
+
- lib/feen/parser/games_turn.rb
|
27
30
|
- lib/feen/parser/piece_placement.rb
|
28
31
|
- lib/feen/parser/pieces_in_hand.rb
|
32
|
+
- lib/feen/sanitizer.rb
|
29
33
|
homepage: https://github.com/sashite/feen.rb
|
30
34
|
licenses:
|
31
35
|
- MIT
|
32
36
|
metadata:
|
33
37
|
rubygems_mfa_required: 'true'
|
34
|
-
post_install_message:
|
35
38
|
rdoc_options: []
|
36
39
|
require_paths:
|
37
40
|
- lib
|
@@ -39,15 +42,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
39
42
|
requirements:
|
40
43
|
- - ">="
|
41
44
|
- !ruby/object:Gem::Version
|
42
|
-
version: 3.
|
45
|
+
version: 3.4.0
|
43
46
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
47
|
requirements:
|
45
|
-
- - "
|
48
|
+
- - ">="
|
46
49
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
50
|
+
version: '0'
|
48
51
|
requirements: []
|
49
|
-
rubygems_version: 3.
|
50
|
-
signing_key:
|
52
|
+
rubygems_version: 3.6.7
|
51
53
|
specification_version: 4
|
52
54
|
summary: FEEN support for the Ruby language.
|
53
55
|
test_files: []
|
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Feen
|
4
|
-
module Parser
|
5
|
-
# The BoardShape class.
|
6
|
-
#
|
7
|
-
# @example Parse the shape of a shogiban
|
8
|
-
# BoardShape.new("3,s,k,s,3/9/4,+P,4/9/7,+B,1/9/9/9/9").to_a # => [9, 9]
|
9
|
-
class BoardShape
|
10
|
-
# @param board_str [String] The flatten board.
|
11
|
-
def initialize(board_str)
|
12
|
-
@board_str = board_str
|
13
|
-
end
|
14
|
-
|
15
|
-
# @return [Array] The size of each dimension of the board.
|
16
|
-
def to_a
|
17
|
-
indexes(@board_str, @board_str.scan(%r{/+}).sort.fetch(-1))
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def indexes(string, separator)
|
23
|
-
if separator.empty?
|
24
|
-
last_index = string.split(",").inject(0) do |counter, sub_string|
|
25
|
-
number = sub_string.match?(/[0-9]+/) ? Integer(sub_string) : 1
|
26
|
-
counter + number
|
27
|
-
end
|
28
|
-
|
29
|
-
return [last_index]
|
30
|
-
end
|
31
|
-
|
32
|
-
sub_strings = string.split(separator)
|
33
|
-
[sub_strings.length] + indexes(sub_strings.fetch(0), separator[1..])
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|