feen 4.0.2 → 5.0.0.beta0

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: 59e59d257cf32a7580d7a751f27046a94dc4cc042237d165a2a941d34928c0c5
4
- data.tar.gz: d17e95bad6d8868e37f1a2dab71d198f44b9fd742400bb70d3f314b8e79c2155
3
+ metadata.gz: 53d90951a531e63bc118104956d29e7c71c90075ab4d42d57506ec5197a783cb
4
+ data.tar.gz: 2cbf73113cc4a429420c3c4e0f30c448380a397bf39f264e617fa85119193f7f
5
5
  SHA512:
6
- metadata.gz: d32ac92d63927327f269559bbafe824265504981178ace24f748ec3201f274669802ea3658c813df3747d5b66cbfb183de92fa9aa57444b807a6f3a5989d1fc7
7
- data.tar.gz: 6352db3b19a703f15102ccba19bb8491605307575a901d862fa19df550558af37610d9ed720afe865975f4e7701b85efae55fcfbab9539786c03c1ec7d780921
6
+ metadata.gz: 3919811f24c5ad1f82dfd257eeefe3515efbcb6fd433a1feb20597e4c6a0fbe6a24c33bef56ea7f612e87fac3124b6334b261c1e987a02f7ecf43a6da745f950
7
+ data.tar.gz: 7b16a8ecd4d80444d1ee14477be61906f3c9503f0a05083dc191822d8a663a6a4fee379c6b0d40fd9bec509c98f0ae863282e1512a6035b7f0624279cb774da0
data/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
- The MIT License (MIT)
1
+ # The MIT License
2
2
 
3
- Copyright (c) 2020-2021 Sashite
3
+ Copyright (c) 2020-2023 Sashité
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
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,69 +6,101 @@
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__ (Forsyth–Edwards Expanded Notation) support for the Ruby language.
9
+ > __FEEN__ (FEN Easy Extensible 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/forsyth-edwards-expanded-notation), a generic format that can be used for serializing and deserializing chess positions.
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 positions.
14
14
 
15
- The main chess variants are 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).
15
+ A __FEEN__ string consists of a single line of ASCII text containing three data fields, separated by a space. These are:
16
16
 
17
- More exotic variants are 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) 🖖
17
+ 1. Piece placement
18
+ 2. Side to move
19
+ 3. Pieces in hand
18
20
 
19
- ![3D chess on Star Trek (from the episode "Court Martial")](https://github.com/sashite/feen.rb/raw/master/star-trek-chess.jpg)
21
+ 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).
22
+
23
+ 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) 🖖
24
+
25
+ ![3D chess on Star Trek (from the episode "Court Martial")](https://github.com/sashite/feen.rb/raw/main/star-trek-chess.jpg)
20
26
 
21
27
  ## Installation
22
28
 
23
29
  Add this line to your application's Gemfile:
24
30
 
25
31
  ```ruby
26
- gem "feen"
32
+ gem "feen", ">= 5.0.0.beta0"
27
33
  ```
28
34
 
29
35
  And then execute:
30
36
 
31
37
  ```sh
32
- bundle
38
+ bundle install
33
39
  ```
34
40
 
35
41
  Or install it yourself as:
36
42
 
37
43
  ```sh
38
- gem install feen
44
+ gem install feen --pre
39
45
  ```
40
46
 
41
47
  ## Usage
42
48
 
49
+ ### Serialization
50
+
51
+ A position can be serialized by filling in these fields:
52
+
53
+ - **Piece placement**: Describes the placement of pieces on the board with a hash that references each piece on the board. The keys could be numbers, or strings of characters representing coordinates.
54
+ - **Side to move**: A char that indicates who moves next. In chess, "`w`" would mean that White must move, and "`b`" that Black must move. In Shogi, "`s`" could mean that Sente must move, and "`g`" that Gote must move. In Xiangqi, "`r`" could mean that Red must move, and "`b`" that Black must move.
55
+ - **Pieces in hand**: An array of all captured pieces that remain _in hand_, like in Shogi.
56
+ - **Board shape**: An array of integers. For instance, it would be `[10, 9]` in Xiangqi. And it would be `[8, 8]` in Chess.
57
+
58
+ #### Examples
59
+
60
+ ##### A classic Tsume Shogi problem
61
+
43
62
  ```ruby
44
63
  require "feen"
45
64
 
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
- 3 => "s",
53
- 4 => "k",
54
- 5 => "s",
65
+ Feen.dump(
66
+ side_to_move: "s",
67
+ 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],
68
+ board_shape: [9, 9],
69
+ piece_placement: {
70
+ 3 => "s",
71
+ 4 => "k",
72
+ 5 => "s",
55
73
  22 => "+P",
56
74
  43 => "+B"
57
75
  }
58
76
  )
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"
77
+ # => "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"
78
+ ```
79
+
80
+ ### Deserialization
81
+
82
+ Serialized positions can be converted back to fields.
83
+
84
+ #### Examples
85
+
86
+ ##### A classic Tsume Shogi problem
87
+
88
+ ```ruby
89
+ require "feen"
60
90
 
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}
91
+ Feen.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")
92
+ # {:board_shape=>[9, 9],
93
+ # :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"],
94
+ # :piece_placement=>{3=>"s", 4=>"k", 5=>"s", 22=>"+P", 43=>"+B"},
95
+ # :side_to_move=>"s"}
64
96
  ```
65
97
 
66
98
  ## License
67
99
 
68
100
  The code is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
69
101
 
70
- ## About Sashite
102
+ ## About Sashité
71
103
 
72
- This [gem](https://rubygems.org/gems/feen) is maintained by [Sashite](https://sashite.com/).
104
+ This [gem](https://rubygems.org/gems/feen) is maintained by [Sashité](https://sashite.com/).
73
105
 
74
106
  With some [lines of code](https://github.com/sashite/), let's share the beauty of Chinese, Japanese and Western cultures through the game of chess!
@@ -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 => "車",
@@ -45,12 +45,12 @@ module FEEN
45
45
  # 89 => "俥"
46
46
  # }
47
47
  # ).to_s # => "車,馬,象,士,將,士,象,馬,車/9/1,砲,5,砲,1/卒,1,卒,1,卒,1,卒,1,卒/9/9/兵,1,兵,1,兵,1,兵,1,兵/1,炮,5,炮,1/9/俥,傌,相,仕,帥,仕,相,傌,俥"
48
- class Square
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.
@@ -1,26 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module FEEN
3
+ module Feen
4
4
  module Dumper
5
- # The pieces in hand module.
6
- module InHand
5
+ # A module that serializes pieces in hand lists into a string.
6
+ module PiecesInHand
7
7
  # Serialize pieces in hand lists into a string.
8
8
  #
9
9
  # @param piece_names [Array] A list of pieces in hand.
10
10
  #
11
11
  # @example Dump a list of pieces in hand
12
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"
13
+ # # => "S,b,g*4,n*4,p*17,r*2,s"
14
14
  #
15
15
  # @example Dump an empty list of pieces in hand
16
16
  # dump([])
17
- # # => "-"
17
+ # # => nil
18
18
  #
19
- # @return [String] A string representing the pieces in hand.
19
+ # @return [String, nil] A serialized list of pieces in hand.
20
20
  def self.dump(piece_names)
21
- return "-" if piece_names.empty?
21
+ return if piece_names.empty?
22
22
 
23
- piece_names.sort.join(",")
23
+ hash = piece_names.group_by(&:itself).transform_values(&:count)
24
+ hash.map { |k, v| v > 1 ? "#{k}*#{v}" : k }.sort.join(",")
24
25
  end
25
26
  end
26
27
  end
data/lib/feen/dumper.rb CHANGED
@@ -1,25 +1,24 @@
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")
4
+ require_relative File.join("dumper", "pieces_in_hand")
6
5
 
7
- module FEEN
6
+ module Feen
8
7
  # The dumper module.
9
8
  module Dumper
10
9
  # Dump position params into a FEEN string.
11
10
  #
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.
11
+ # @param side_to_move [String] Identify the active side.
12
+ # @param pieces_in_hand [Array, nil] The list of pieces in hand.
13
+ # @param board_shape [Array] The shape of the board.
14
+ # @param piece_placement [Hash] The index of each piece on the board.
16
15
  #
17
16
  # @example Dump a classic Tsume Shogi problem
18
17
  # 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": {
18
+ # "side_to_move": "s",
19
+ # "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],
20
+ # "board_shape": [9, 9],
21
+ # "piece_placement": {
23
22
  # 3 => "s",
24
23
  # 4 => "k",
25
24
  # 5 => "s",
@@ -27,15 +26,17 @@ module FEEN
27
26
  # 43 => "+B"
28
27
  # }
29
28
  # )
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"
29
+ # # => "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"
31
30
  #
32
31
  # @return [String] The FEEN string representing the position.
33
- def self.call(in_hand:, shape:, side_id:, square:)
34
- [
35
- Square.new(shape, square).to_s,
36
- Turn.dump(side_id),
37
- InHand.dump(in_hand)
38
- ].join(" ")
32
+ def self.call(board_shape:, side_to_move:, piece_placement:, pieces_in_hand: nil)
33
+ array = [
34
+ PiecePlacement.new(board_shape, piece_placement).to_s,
35
+ side_to_move
36
+ ]
37
+
38
+ array << PiecesInHand.dump(pieces_in_hand) if Array(pieces_in_hand).any?
39
+ array.join(" ")
39
40
  end
40
41
  end
41
42
  end
@@ -1,20 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module FEEN
3
+ module Feen
4
4
  module Parser
5
- # The shape class.
5
+ # The BoardShape class.
6
6
  #
7
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
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
13
  end
14
14
 
15
15
  # @return [Array] The size of each dimension of the board.
16
16
  def to_a
17
- indexes(@board, @board.scan(%r{/+}).sort.fetch(-1))
17
+ indexes(@board_str, @board_str.scan(%r{/+}).sort.fetch(-1))
18
18
  end
19
19
 
20
20
  private
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module FEEN
3
+ module Feen
4
4
  module Parser
5
- # The square class.
5
+ # The PiecePlacement class.
6
6
  #
7
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
8
+ # PiecePlacement.new("3,s,k,s,3/9/4,+P,4/9/7,+B,1/9/9/9/9").to_a
9
9
  # # => [
10
10
  # # nil, nil, nil, "s", "k", "s", nil, nil, nil,
11
11
  # # nil, nil, nil, nil, nil, nil, nil, nil, nil,
@@ -19,7 +19,7 @@ module FEEN
19
19
  # # ]
20
20
  #
21
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
22
+ # PiecePlacement.new("3,s,k,s,3/9/4,+P,4/9/7,+B,1/9/9/9/9").to_h
23
23
  # # => {
24
24
  # # 3 => "s",
25
25
  # # 4 => "k",
@@ -27,15 +27,15 @@ module FEEN
27
27
  # # 22 => "+P",
28
28
  # # 43 => "+B"
29
29
  # # }
30
- class Square
31
- # @param board [String] The flatten board.
32
- def initialize(board)
33
- @board = board
30
+ class PiecePlacement
31
+ # @param piece_placement_str [String] The placement of pieces on the board.
32
+ def initialize(piece_placement_str)
33
+ @piece_placement_str = piece_placement_str
34
34
  end
35
35
 
36
- # @return [Array] The list of squares on the board.
36
+ # @return [Array] The list of pieces on the board.
37
37
  def to_a
38
- @board
38
+ @piece_placement_str
39
39
  .split(%r{[/,]+})
40
40
  .flat_map { |str| row(str) }
41
41
  end
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module FEEN
3
+ module Feen
4
4
  module Parser
5
5
  # The pieces in hand module.
6
- module InHand
6
+ module PiecesInHand
7
7
  # The list of pieces in hand grouped by players.
8
8
  #
9
- # @param piece_names_str [String] The serialized list of pieces in hand.
9
+ # @param pieces_in_hand [String, nil] The serialized list of pieces in hand.
10
10
  #
11
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")
12
+ # parse("S,b,g*4,n*4,p*17,r*2,s")
13
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
14
  #
15
15
  # @example Parse an empty list of serialized pieces in hand
@@ -17,10 +17,17 @@ module FEEN
17
17
  # # => []
18
18
  #
19
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 == "-"
20
+ def self.parse(pieces_in_hand)
21
+ return if pieces_in_hand.nil?
22
22
 
23
- piece_names_str.split(",")
23
+ pieces_in_hand.split(",").flat_map do |piece|
24
+ if piece.include?("*")
25
+ letter, count = piece.split("*")
26
+ [letter] * count.to_i
27
+ else
28
+ piece
29
+ end
30
+ end.sort
24
31
  end
25
32
  end
26
33
  end
data/lib/feen/parser.rb CHANGED
@@ -1,11 +1,10 @@
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")
4
+ require_relative File.join("parser", "pieces_in_hand")
5
+ require_relative File.join("parser", "piece_placement")
7
6
 
8
- module FEEN
7
+ module Feen
9
8
  # The parser module.
10
9
  module Parser
11
10
  # Parse a FEEN string into position params.
@@ -13,12 +12,12 @@ module FEEN
13
12
  # @param feen [String] The FEEN string representing a position.
14
13
  #
15
14
  # @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")
15
+ # call("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")
17
16
  # # => {
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": {
17
+ # # "side_to_move": "s",
18
+ # # "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"],
19
+ # # "board_shape": [9, 9],
20
+ # # "piece_placement": {
22
21
  # # 3 => "s",
23
22
  # # 4 => "k",
24
23
  # # 5 => "s",
@@ -28,13 +27,13 @@ module FEEN
28
27
  #
29
28
  # @return [Hash] The position params representing the position.
30
29
  def self.call(feen)
31
- square_str, side_id_str, in_hand_str = feen.split
30
+ piece_placement, side_to_move, pieces_in_hand = feen.split
32
31
 
33
32
  {
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
33
+ board_shape: BoardShape.new(piece_placement).to_a,
34
+ pieces_in_hand: PiecesInHand.parse(pieces_in_hand),
35
+ piece_placement: PiecePlacement.new(piece_placement).to_h,
36
+ side_to_move:
38
37
  }
39
38
  end
40
39
  end
data/lib/feen.rb CHANGED
@@ -6,21 +6,21 @@ 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/forsyth-edwards-expanded-notation
10
- module FEEN
9
+ # @see https://developer.sashite.com/specs/fen-easy-extensible-notation
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 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
17
  #
18
18
  # @example Dump a classic Tsume Shogi problem
19
19
  # 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": {
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
24
  # 3 => "s",
25
25
  # 4 => "k",
26
26
  # 5 => "s",
@@ -28,15 +28,15 @@ module FEEN
28
28
  # 43 => "+B"
29
29
  # }
30
30
  # )
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"
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
32
  #
33
33
  # @return [String] The FEEN string representing the position.
34
- def self.dump(in_hand:, shape:, side_id:, square:)
34
+ def self.dump(board_shape:, side_to_move:, piece_placement:, pieces_in_hand: nil)
35
35
  Dumper.call(
36
- in_hand: in_hand,
37
- shape: shape,
38
- side_id: side_id,
39
- square: square
36
+ pieces_in_hand:,
37
+ board_shape:,
38
+ side_to_move:,
39
+ piece_placement:
40
40
  )
41
41
  end
42
42
 
@@ -45,12 +45,12 @@ module FEEN
45
45
  # @param feen [String] The FEEN string representing a position.
46
46
  #
47
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 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")
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")
49
49
  # # => {
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": {
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
54
  # # 3 => "s",
55
55
  # # 4 => "k",
56
56
  # # 5 => "s",
metadata CHANGED
@@ -1,155 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: feen
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.2
4
+ version: 5.0.0.beta0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyril Kato
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-13 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: brutal
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: bundler
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: byebug
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: rake
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: rubocop-md
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: rubocop-performance
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: rubocop-rake
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: rubocop-thread_safety
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: simplecov
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
130
- - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- version: '0'
139
- - !ruby/object:Gem::Dependency
140
- name: yard
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - ">="
144
- - !ruby/object:Gem::Version
145
- version: '0'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - ">="
151
- - !ruby/object:Gem::Version
152
- version: '0'
11
+ date: 2023-04-25 00:00:00.000000000 Z
12
+ dependencies: []
153
13
  description: A Ruby interface for data serialization and deserialization in FEEN format.
154
14
  email: contact@cyril.email
155
15
  executables: []
@@ -160,22 +20,18 @@ files:
160
20
  - README.md
161
21
  - lib/feen.rb
162
22
  - lib/feen/dumper.rb
163
- - lib/feen/dumper/in_hand.rb
164
- - lib/feen/dumper/square.rb
165
- - lib/feen/dumper/turn.rb
23
+ - lib/feen/dumper/piece_placement.rb
24
+ - lib/feen/dumper/pieces_in_hand.rb
166
25
  - lib/feen/parser.rb
167
- - lib/feen/parser/in_hand.rb
168
- - lib/feen/parser/shape.rb
169
- - lib/feen/parser/square.rb
170
- - lib/feen/parser/turn.rb
171
- homepage: https://developer.sashite.com/specs/forsyth-edwards-expanded-notation
26
+ - lib/feen/parser/board_shape.rb
27
+ - lib/feen/parser/piece_placement.rb
28
+ - lib/feen/parser/pieces_in_hand.rb
29
+ homepage: https://github.com/sashite/feen.rb
172
30
  licenses:
173
31
  - MIT
174
32
  metadata:
175
- bug_tracker_uri: https://github.com/sashite/feen.rb/issues
176
- documentation_uri: https://rubydoc.info/gems/feen/index
177
- source_code_uri: https://github.com/sashite/feen.rb
178
- post_install_message:
33
+ rubygems_mfa_required: 'true'
34
+ post_install_message:
179
35
  rdoc_options: []
180
36
  require_paths:
181
37
  - lib
@@ -183,15 +39,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
183
39
  requirements:
184
40
  - - ">="
185
41
  - !ruby/object:Gem::Version
186
- version: 3.0.0
42
+ version: 3.2.0
187
43
  required_rubygems_version: !ruby/object:Gem::Requirement
188
44
  requirements:
189
- - - ">="
45
+ - - ">"
190
46
  - !ruby/object:Gem::Version
191
- version: '0'
47
+ version: 1.3.1
192
48
  requirements: []
193
- rubygems_version: 3.2.22
194
- signing_key:
49
+ rubygems_version: 3.4.6
50
+ signing_key:
195
51
  specification_version: 4
196
52
  summary: FEEN support for the Ruby language.
197
53
  test_files: []
@@ -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,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