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.
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://developer.sashite.com/specs/fen-easy-extensible-notation
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 pieces_in_hand [Array, nil] The list of pieces in hand.
14
- # @param board_shape [Array] The shape of the board.
15
- # @param side_to_move [String] The identifier of the player who must play.
16
- # @param piece_placement [Hash] The index of each piece on the board.
17
- #
18
- # @example Dump a classic Tsume Shogi problem
19
- # dump(
20
- # "side_to_move": "s",
21
- # "pieces_in_hand": %w[S r r b g g g g s n n n n p p p p p p p p p p p p p p p p p],
22
- # "board_shape": [9, 9],
23
- # "piece_placement": {
24
- # 3 => "s",
25
- # 4 => "k",
26
- # 5 => "s",
27
- # 22 => "+P",
28
- # 43 => "+B"
29
- # }
30
- # )
31
- # # => "3,s,k,s,3/9/4,+P,4/9/7,+B,1/9/9/9/9 s S,b,g*4,n*4,p*17,r*2,s"
32
- #
33
- # @return [String] The FEEN string representing the position.
34
- def self.dump(board_shape:, side_to_move:, piece_placement:, pieces_in_hand: nil)
35
- Dumper.call(
36
- pieces_in_hand:,
37
- board_shape:,
38
- side_to_move:,
39
- piece_placement:
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 feen [String] The FEEN string representing a position.
46
- #
47
- # @example Parse a classic Tsume Shogi problem
48
- # parse("3,s,k,s,3/9/4,+P,4/9/7,+B,1/9/9/9/9 s S,b,g*4,n*4,p*17,r*2,s")
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
- # # "pieces_in_hand": ["S", "b", "g", "g", "g", "g", "n", "n", "n", "n", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "r", "r", "s"],
51
- # # "board_shape": [9, 9],
52
- # # "side_to_move": "s",
53
- # # "piece_placement": {
54
- # # 3 => "s",
55
- # # 4 => "k",
56
- # # 5 => "s",
57
- # # 22 => "+P",
58
- # # 43 => "+B"
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
- # @return [Hash] The position params representing the position.
62
- def self.parse(feen)
63
- Parser.call(feen)
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.beta0
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: 2023-04-25 00:00:00.000000000 Z
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/board_shape.rb
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.2.0
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: 1.3.1
50
+ version: '0'
48
51
  requirements: []
49
- rubygems_version: 3.4.6
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