feen 4.0.3 → 5.0.0.beta1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 98cae677c862ba15d503bd607228abfd3aa06f7b4524c30f1a8890f446978784
4
- data.tar.gz: ce5628e2b182d15d7e51567b67550338308a87508bf4422cae6e710b04aa6e33
3
+ metadata.gz: 2fa56bccbb1911f15569f2f5643646986cbf83661efba3165c69978e7c85fd56
4
+ data.tar.gz: 13d706d1bfe1c09f6d015d0a8f28af621754677711074ec60ec96e395f1a1061
5
5
  SHA512:
6
- metadata.gz: b294ea3521b0e34fbce443942d7c9aec06388f290025977d6995312f0a01492aedd498ea6a9e41b5eb19f9762ae79a6970a512f192fda2ab09ec890cd77c606d
7
- data.tar.gz: 6dd225e8abcf4189f4124225a35d26c1f1faf39e804204f2467bf11350539394f9ea52eeabb3835d1d3ab232c74b1136e341f21669b469a126395473034bdac7
6
+ metadata.gz: 5479cbd02c902aa8c45cc12ecfab31c7b7283eb1f8ec60b110c889505a7ebbcf76fa7b0d2e6ad44c60da954312fa85ae03cd4981d929207b0612754f1d62a033
7
+ data.tar.gz: b6268ce619808bf2c2f889261b55007edbfc030bc37b8edea7f73f505de55e8c0fc1cd4a268e8e2bdc71fe21c9fa33f904c8b26a23b92b471e406e109494bd97
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # FEEN.rb
1
+ # Feen.rb
2
2
 
3
3
  [![Version](https://img.shields.io/github/v/tag/sashite/feen.rb?label=Version&logo=github)](https://github.com/sashite/feen.rb/releases)
4
4
  [![Yard documentation](https://img.shields.io/badge/Yard-documentation-blue.svg?logo=github)](https://rubydoc.info/github/sashite/feen.rb/main)
@@ -6,24 +6,18 @@
6
6
  [![RuboCop](https://github.com/sashite/feen.rb/workflows/RuboCop/badge.svg?branch=main)](https://github.com/sashite/feen.rb/actions?query=workflow%3Arubocop+branch%3Amain)
7
7
  [![License](https://img.shields.io/github/license/sashite/feen.rb?label=License&logo=github)](https://github.com/sashite/feen.rb/raw/main/LICENSE.md)
8
8
 
9
- > __FEEN__ (FEN Easy Extensible Notation) support for the Ruby language.
9
+ > __FEEN__ (Forsyth–Edwards Expanded Notation) support for the Ruby language.
10
10
 
11
11
  ## Overview
12
12
 
13
- This is an implementation of [FEEN](https://developer.sashite.com/specs/fen-easy-extensible-notation), a generic format that can be used for serializing and deserializing chess positions.
14
-
15
- The main chess variants may be supported, including [Chess](https://en.wikipedia.org/wiki/Chess), [Janggi](https://en.wikipedia.org/wiki/Janggi), [Makruk](https://en.wikipedia.org/wiki/Makruk), [Shogi](https://en.wikipedia.org/wiki/Shogi), [Xiangqi](https://en.wikipedia.org/wiki/Xiangqi).
16
-
17
- More exotic variants may be also supported, like: [Dai dai shogi](https://en.wikipedia.org/wiki/Dai_dai_shogi), [Four-player chess](https://en.wikipedia.org/wiki/Four-player_chess), or [Three-dimensional chess](https://en.wikipedia.org/wiki/Three-dimensional_chess) 🖖
18
-
19
- ![3D chess on Star Trek (from the episode "Court Martial")](https://github.com/sashite/feen.rb/raw/main/star-trek-chess.jpg)
13
+ This is an implementation of [FEEN](https://github.com/sashite/specs/blob/main/forsyth-edwards-expanded-notation.md), a flexible and minimalist format for describing chess variant positions.
20
14
 
21
15
  ## Installation
22
16
 
23
17
  Add this line to your application's Gemfile:
24
18
 
25
19
  ```ruby
26
- gem "feen"
20
+ gem "feen", ">= 5.0.0.beta1"
27
21
  ```
28
22
 
29
23
  And then execute:
@@ -35,20 +29,30 @@ bundle install
35
29
  Or install it yourself as:
36
30
 
37
31
  ```sh
38
- gem install feen
32
+ gem install feen --pre
39
33
  ```
40
34
 
41
35
  ## Usage
42
36
 
37
+ ### Serialization
38
+
39
+ A position can be serialized by filling in these fields:
40
+
41
+ - **Board shape**: An array of integers. For instance, it would be `[10, 9]` for a Xiangqi board. Or it would be `[8, 8]` for a Chess board.
42
+ - **Piece placement**: Describes the placement of pieces on the board with a hash that references each piece on the board.
43
+ - **Side to move**: A char that indicates who moves next. In chess, "`w`" would mean that White can play a move.
44
+
45
+ #### Example
46
+
47
+ From a classic Tsume Shogi problem:
48
+
43
49
  ```ruby
44
50
  require "feen"
45
51
 
46
- # Dump a classic Tsume Shogi problem
47
- FEEN.dump(
48
- 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],
49
- shape: [9, 9],
50
- side_id: 0,
51
- square: {
52
+ Feen.dump(
53
+ board_shape: [9, 9],
54
+ side_to_move: "s",
55
+ piece_placement: {
52
56
  3 => "s",
53
57
  4 => "k",
54
58
  5 => "s",
@@ -56,11 +60,22 @@ FEEN.dump(
56
60
  43 => "+B"
57
61
  }
58
62
  )
59
- # => "3,s,k,s,3/9/4,+P,4/9/7,+B,1/9/9/9/9 0 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"
63
+ # => "3sks3/9/4+P4/9/7+B1/9/9/9/9 s"
64
+ ```
65
+
66
+ ### Deserialization
67
+
68
+ Serialized positions can be converted back to fields.
69
+
70
+ #### Example
71
+
72
+ ```ruby
73
+ require "feen"
60
74
 
61
- # Parse a classic Tsume Shogi problem
62
- FEEN.parse("3,s,k,s,3/9/4,+P,4/9/7,+B,1/9/9/9/9 0 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")
63
- # => {:square=>{3=>"s", 4=>"k", 5=>"s", 22=>"+P", 43=>"+B"}, :shape=>[9, 9], :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"], :side_id=>0}
75
+ Feen.parse("3sks3/9/4+P4/9/7+B1/9/9/9/9 s")
76
+ # {:board_shape=>[9, 9],
77
+ # :piece_placement=>{3=>"s", 4=>"k", 5=>"s", 22=>"+P", 43=>"+B"},
78
+ # :side_to_move=>"s"}
64
79
  ```
65
80
 
66
81
  ## License
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module FEEN
3
+ module Feen
4
4
  module Dumper
5
- # The square class.
5
+ # The PiecePlacement class.
6
6
  #
7
7
  # @example Dump an empty board of Xiangqi
8
- # Board.new([10, 9]).to_s # => "9/9/9/9/9/9/9/9/9/9"
8
+ # PiecePlacement.new([10, 9]).to_s # => "9/9/9/9/9/9/9/9/9/9"
9
9
  #
10
10
  # @example Dump the Xiangqi starting position board
11
- # Board.new(
11
+ # PiecePlacement.new(
12
12
  # [10, 9],
13
13
  # {
14
14
  # 0 => "車",
@@ -44,13 +44,13 @@ module FEEN
44
44
  # 88 => "傌",
45
45
  # 89 => "俥"
46
46
  # }
47
- # ).to_s # => "車,馬,象,士,將,士,象,馬,車/9/1,砲,5,砲,1/卒,1,卒,1,卒,1,卒,1,卒/9/9/兵,1,兵,1,兵,1,兵,1,兵/1,炮,5,炮,1/9/俥,傌,相,仕,帥,仕,相,傌,俥"
48
- class Square
47
+ # ).to_s # => "車馬象士將士象馬車/9/151/卒1111卒/9/9/兵1111兵/151/9/俥傌相仕帥仕相傌俥"
48
+ class PiecePlacement
49
49
  # @param indexes [Array] The shape of the board.
50
- # @param board [Hash] The index of each piece on the board.
51
- def initialize(indexes, board)
50
+ # @param piece_placement [Hash] The index of each piece on the board.
51
+ def initialize(indexes, piece_placement = {})
52
52
  @indexes = indexes
53
- @squares = Array.new(length) { |i| board.fetch(i, nil) }
53
+ @squares = ::Array.new(length) { |i| piece_placement.fetch(i, nil) }
54
54
  end
55
55
 
56
56
  # @return [String] The string representing the board.
@@ -79,6 +79,7 @@ module FEEN
79
79
  .map { |square| square.nil? ? 1 : square }
80
80
  .join(",")
81
81
  .gsub(/1,[1,]*1/) { |str| str.split(",").length }
82
+ .delete(",")
82
83
  end
83
84
  end
84
85
  end
data/lib/feen/dumper.rb CHANGED
@@ -1,25 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative File.join("dumper", "in_hand")
4
- require_relative File.join("dumper", "square")
5
- require_relative File.join("dumper", "turn")
3
+ require_relative File.join("dumper", "piece_placement")
6
4
 
7
- module FEEN
5
+ module Feen
8
6
  # The dumper module.
9
7
  module Dumper
10
8
  # Dump position params into a FEEN string.
11
9
  #
12
- # @param in_hand [Array] The list of pieces in hand.
13
- # @param shape [Array] The shape of the board.
14
- # @param side_id [Integer] The identifier of the player who must play.
15
- # @param square [Hash] The index of each piece on the board.
10
+ # @param board_shape [Array] The shape of the board.
11
+ # @param side_to_move [String] Identify the active side.
12
+ # @param piece_placement [Hash] The index of each piece on the board.
16
13
  #
17
14
  # @example Dump a classic Tsume Shogi problem
18
15
  # call(
19
- # "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],
20
- # "shape": [9, 9],
21
- # "side_id": 0,
22
- # "square": {
16
+ # "board_shape": [9, 9],
17
+ # "side_to_move": "s",
18
+ # "piece_placement": {
23
19
  # 3 => "s",
24
20
  # 4 => "k",
25
21
  # 5 => "s",
@@ -27,14 +23,13 @@ module FEEN
27
23
  # 43 => "+B"
28
24
  # }
29
25
  # )
30
- # # => "3,s,k,s,3/9/4,+P,4/9/7,+B,1/9/9/9/9 0 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"
26
+ # # => "3sks3/9/4+P4/9/7+B1/9/9/9/9 s"
31
27
  #
32
28
  # @return [String] The FEEN string representing the position.
33
- def self.call(in_hand:, shape:, side_id:, square:)
29
+ def self.call(board_shape:, side_to_move:, piece_placement:)
34
30
  [
35
- Square.new(shape, square).to_s,
36
- Turn.dump(side_id),
37
- InHand.dump(in_hand)
31
+ PiecePlacement.new(board_shape, piece_placement).to_s,
32
+ side_to_move
38
33
  ].join(" ")
39
34
  end
40
35
  end
@@ -0,0 +1,39 @@
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("3sks3/9/4+P4/9/7+B1/9/9/9/9").to_a # => [9, 9]
9
+ class BoardShape
10
+ # @param board_str [String] The flatten board.
11
+ def initialize(board_str, regex: /\+?[a-z]/i)
12
+ @board_str = board_str
13
+ @regex = regex
14
+ end
15
+
16
+ # @return [Array] The size of each dimension of the board.
17
+ def to_a
18
+ indexes(@board_str, @board_str.scan(%r{/+}).sort.fetch(-1))
19
+ end
20
+
21
+ private
22
+
23
+ def indexes(string, separator)
24
+ if separator.empty?
25
+ last_index = string.scan(/(\d+|#{@regex})/).inject(0) do |counter, match|
26
+ sub_string = match[0]
27
+ number = sub_string.match?(/\d+/) ? Integer(sub_string) : 1
28
+ counter + number
29
+ end
30
+
31
+ return [last_index]
32
+ end
33
+
34
+ sub_strings = string.split(separator)
35
+ [sub_strings.length] + indexes(sub_strings.fetch(0), separator[1..])
36
+ end
37
+ end
38
+ end
39
+ end
data/lib/feen/parser.rb CHANGED
@@ -1,11 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative File.join("parser", "in_hand")
4
- require_relative File.join("parser", "shape")
5
- require_relative File.join("parser", "square")
6
- require_relative File.join("parser", "turn")
3
+ require_relative File.join("parser", "board_shape")
7
4
 
8
- module FEEN
5
+ module Feen
9
6
  # The parser module.
10
7
  module Parser
11
8
  # Parse a FEEN string into position params.
@@ -13,12 +10,11 @@ module FEEN
13
10
  # @param feen [String] The FEEN string representing a position.
14
11
  #
15
12
  # @example Parse a classic Tsume Shogi problem
16
- # call("3,s,k,s,3/9/4,+P,4/9/7,+B,1/9/9/9/9 0 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")
13
+ # call("3sks3/9/4+P4/9/7+B1/9/9/9/9 s")
17
14
  # # => {
18
- # # "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"],
19
- # # "shape": [9, 9],
20
- # # "side_id": 0,
21
- # # "square": {
15
+ # # "board_shape": [9, 9],
16
+ # # "side_to_move": "s",
17
+ # # "piece_placement": {
22
18
  # # 3 => "s",
23
19
  # # 4 => "k",
24
20
  # # 5 => "s",
@@ -27,15 +23,29 @@ module FEEN
27
23
  # # }
28
24
  #
29
25
  # @return [Hash] The position params representing the position.
30
- def self.call(feen)
31
- square_str, side_id_str, in_hand_str = feen.split
26
+ def self.call(feen, regex: /\+?[a-z]/i)
27
+ piece_placement_str, side_to_move_str = feen.split
32
28
 
33
29
  {
34
- in_hand: InHand.parse(in_hand_str),
35
- shape: Shape.new(square_str).to_a,
36
- side_id: Turn.parse(side_id_str),
37
- square: Square.new(square_str).to_h
30
+ board_shape: BoardShape.new(piece_placement_str, regex:).to_a,
31
+ piece_placement: piece_placement(piece_placement_str, regex:),
32
+ side_to_move: side_to_move_str
38
33
  }
39
34
  end
35
+
36
+ def self.piece_placement(string, regex:)
37
+ hash = {}
38
+ index = 0
39
+ string.scan(/(\d+|#{regex})/) do |match|
40
+ if /\d+/.match?(match[0])
41
+ index += match[0].to_i
42
+ else
43
+ hash[index] = match[0]
44
+ index += 1
45
+ end
46
+ end
47
+ hash
48
+ end
49
+ private_class_method :piece_placement
40
50
  end
41
51
  end
data/lib/feen.rb CHANGED
@@ -6,21 +6,19 @@ require_relative File.join("feen", "parser")
6
6
  # This module provides a Ruby interface for data serialization and
7
7
  # deserialization in FEEN format.
8
8
  #
9
- # @see https://developer.sashite.com/specs/fen-easy-extensible-notation
10
- module FEEN
9
+ # @see https://github.com/sashite/specs/blob/main/forsyth-edwards-expanded-notation.md
10
+ module Feen
11
11
  # Dumps position params into a FEEN string.
12
12
  #
13
- # @param in_hand [Array] The list of pieces in hand.
14
- # @param shape [Array] The shape of the board.
15
- # @param side_id [Integer] The identifier of the player who must play.
16
- # @param square [Hash] The index of each piece on the board.
13
+ # @param board_shape [Array] The shape of the board.
14
+ # @param side_to_move [String] The identifier of the player who must play.
15
+ # @param piece_placement [Hash] The index of each piece on the board.
17
16
  #
18
17
  # @example Dump a classic Tsume Shogi problem
19
18
  # dump(
20
- # "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],
21
- # "shape": [9, 9],
22
- # "side_id": 0,
23
- # "square": {
19
+ # "board_shape": [9, 9],
20
+ # "side_to_move": "s",
21
+ # "piece_placement": {
24
22
  # 3 => "s",
25
23
  # 4 => "k",
26
24
  # 5 => "s",
@@ -28,15 +26,14 @@ module FEEN
28
26
  # 43 => "+B"
29
27
  # }
30
28
  # )
31
- # # => "3,s,k,s,3/9/4,+P,4/9/7,+B,1/9/9/9/9 0 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"
29
+ # # => "3sks3/9/4+P4/9/7+B1/9/9/9/9 s"
32
30
  #
33
31
  # @return [String] The FEEN string representing the position.
34
- def self.dump(in_hand:, shape:, side_id:, square:)
32
+ def self.dump(board_shape:, side_to_move:, piece_placement:)
35
33
  Dumper.call(
36
- in_hand:,
37
- shape:,
38
- side_id:,
39
- square:
34
+ board_shape:,
35
+ side_to_move:,
36
+ piece_placement:
40
37
  )
41
38
  end
42
39
 
@@ -45,12 +42,11 @@ module FEEN
45
42
  # @param feen [String] The FEEN string representing a position.
46
43
  #
47
44
  # @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 0 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")
45
+ # parse("3sks3/9/4+P4/9/7+B1/9/9/9/9 s")
49
46
  # # => {
50
- # # "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
- # # "shape": [9, 9],
52
- # # "side_id": 0,
53
- # # "square": {
47
+ # # "board_shape": [9, 9],
48
+ # # "side_to_move": "s",
49
+ # # "piece_placement": {
54
50
  # # 3 => "s",
55
51
  # # 4 => "k",
56
52
  # # 5 => "s",
@@ -59,7 +55,7 @@ module FEEN
59
55
  # # }
60
56
  #
61
57
  # @return [Hash] The position params representing the position.
62
- def self.parse(feen)
63
- Parser.call(feen)
58
+ def self.parse(feen, regex: /\+?[a-z]/i)
59
+ Parser.call(feen, regex:)
64
60
  end
65
61
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: feen
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.3
4
+ version: 5.0.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyril Kato
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-24 00:00:00.000000000 Z
11
+ date: 2023-04-27 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A Ruby interface for data serialization and deserialization in FEEN format.
14
14
  email: contact@cyril.email
@@ -20,14 +20,9 @@ files:
20
20
  - README.md
21
21
  - lib/feen.rb
22
22
  - lib/feen/dumper.rb
23
- - lib/feen/dumper/in_hand.rb
24
- - lib/feen/dumper/square.rb
25
- - lib/feen/dumper/turn.rb
23
+ - lib/feen/dumper/piece_placement.rb
26
24
  - lib/feen/parser.rb
27
- - lib/feen/parser/in_hand.rb
28
- - lib/feen/parser/shape.rb
29
- - lib/feen/parser/square.rb
30
- - lib/feen/parser/turn.rb
25
+ - lib/feen/parser/board_shape.rb
31
26
  homepage: https://github.com/sashite/feen.rb
32
27
  licenses:
33
28
  - MIT
@@ -44,9 +39,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
44
39
  version: 3.2.0
45
40
  required_rubygems_version: !ruby/object:Gem::Requirement
46
41
  requirements:
47
- - - ">="
42
+ - - ">"
48
43
  - !ruby/object:Gem::Version
49
- version: '0'
44
+ version: 1.3.1
50
45
  requirements: []
51
46
  rubygems_version: 3.4.6
52
47
  signing_key:
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FEEN
4
- module Dumper
5
- # The pieces in hand module.
6
- module InHand
7
- # Serialize pieces in hand lists into a string.
8
- #
9
- # @param piece_names [Array] A list of pieces in hand.
10
- #
11
- # @example Dump a list of pieces in hand
12
- # dump(["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"])
13
- # # => "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"
14
- #
15
- # @example Dump an empty list of pieces in hand
16
- # dump([])
17
- # # => "-"
18
- #
19
- # @return [String] A string representing the pieces in hand.
20
- def self.dump(piece_names)
21
- return "-" if piece_names.empty?
22
-
23
- piece_names.sort.join(",")
24
- end
25
- end
26
- end
27
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FEEN
4
- module Dumper
5
- # The turn module.
6
- module Turn
7
- # @param side_id [Integer] The identifier of the active player.
8
- #
9
- # @example Dump the number that identify the player who have to play
10
- # dump(0) # => "0"
11
- #
12
- # @return [String] The number that identify the player who have to play.
13
- def self.dump(side_id)
14
- String(side_id)
15
- end
16
- end
17
- end
18
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FEEN
4
- module Parser
5
- # The pieces in hand module.
6
- module InHand
7
- # The list of pieces in hand grouped by players.
8
- #
9
- # @param piece_names_str [String] The serialized list of pieces in hand.
10
- #
11
- # @example Parse a list of serialized pieces in hand
12
- # parse("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")
13
- # # => ["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"]
14
- #
15
- # @example Parse an empty list of serialized pieces in hand
16
- # parse("-")
17
- # # => []
18
- #
19
- # @return [Array] The list of pieces in hand grouped by players.
20
- def self.parse(piece_names_str)
21
- return [] if piece_names_str == "-"
22
-
23
- piece_names_str.split(",")
24
- end
25
- end
26
- end
27
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FEEN
4
- module Parser
5
- # The shape class.
6
- #
7
- # @example Parse the shape of a shogiban
8
- # Shape.new("3,s,k,s,3/9/4,+P,4/9/7,+B,1/9/9/9/9").to_a # => [9, 9]
9
- class Shape
10
- # @param board [String] The flatten board.
11
- def initialize(board)
12
- @board = board
13
- end
14
-
15
- # @return [Array] The size of each dimension of the board.
16
- def to_a
17
- indexes(@board, @board.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
@@ -1,61 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FEEN
4
- module Parser
5
- # The square class.
6
- #
7
- # @example Parse a Shogi problem board and return an array
8
- # Board.new("3,s,k,s,3/9/4,+P,4/9/7,+B,1/9/9/9/9").to_a
9
- # # => [
10
- # # nil, nil, nil, "s", "k", "s", nil, nil, nil,
11
- # # nil, nil, nil, nil, nil, nil, nil, nil, nil,
12
- # # nil, nil, nil, nil, "+P", nil, nil, nil, nil,
13
- # # nil, nil, nil, nil, nil, nil, nil, nil, nil,
14
- # # nil, nil, nil, nil, nil, nil, nil, "+B", nil,
15
- # # nil, nil, nil, nil, nil, nil, nil, nil, nil,
16
- # # nil, nil, nil, nil, nil, nil, nil, nil, nil,
17
- # # nil, nil, nil, nil, nil, nil, nil, nil, nil,
18
- # # nil, nil, nil, nil, nil, nil, nil, nil, nil
19
- # # ]
20
- #
21
- # @example Parse a Shogi problem board and return a hash
22
- # Board.new("3,s,k,s,3/9/4,+P,4/9/7,+B,1/9/9/9/9").to_h
23
- # # => {
24
- # # 3 => "s",
25
- # # 4 => "k",
26
- # # 5 => "s",
27
- # # 22 => "+P",
28
- # # 43 => "+B"
29
- # # }
30
- class Square
31
- # @param board [String] The flatten board.
32
- def initialize(board)
33
- @board = board
34
- end
35
-
36
- # @return [Array] The list of squares on the board.
37
- def to_a
38
- @board
39
- .split(%r{[/,]+})
40
- .flat_map { |str| row(str) }
41
- end
42
-
43
- # @return [Hash] The index of each piece on the board.
44
- def to_h
45
- to_a
46
- .each_with_index
47
- .inject({}) do |h, (v, i)|
48
- next h if v.nil?
49
-
50
- h.merge(i => v)
51
- end
52
- end
53
-
54
- private
55
-
56
- def row(string)
57
- string.match?(/[0-9]+/) ? ::Array.new(Integer(string)) : string
58
- end
59
- end
60
- end
61
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FEEN
4
- module Parser
5
- # The turn module.
6
- module Turn
7
- # @param side_id [String] The identifier of bottom-side and
8
- # top-side.
9
- #
10
- # @example Parse the number that identify the player who have to play
11
- # parse("0") # => 0
12
- #
13
- # @return [Integer] The number that identify the player who have to play.
14
- def self.parse(side_id)
15
- Integer(side_id)
16
- end
17
- end
18
- end
19
- end