feen 2.0.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 53ffebf45c7d54e896af8ea265e9a3e6be43f5d3367f8f4d75a3be35ede0769c
4
- data.tar.gz: b942b667c90dadea80c7dfadb87872a3024c3a15dbaf866814c530957ad12fd3
3
+ metadata.gz: 730da5cc06535403835733403b2e86d03435337bd7cd36e5af2d47a1442f199f
4
+ data.tar.gz: f3a1b2a952dccbc9bb5eeb15dcfc920d3ea270abb301ed29c098da5260a4c3e4
5
5
  SHA512:
6
- metadata.gz: 921e336e081f5d238e05750f245e81aa5d1b10a8b7fd5eddd1eec95518d3b210c77a4d14ecf3d53f6098217c3113a3dba27abaafddc5cb981f7f3d304bc00202
7
- data.tar.gz: 840842f00f4da13daefefac0389a616296c692e8da099da0c37959e5ea6e1ae2fcb5fbb3a3e0643bbd903874f61d11b1ef398db30e29ee1c432654492ffdd305
6
+ metadata.gz: c001a2c2c8c7f88aba144ca878c45e11fde53b5c71ff3afa4caf8b05724d4a90dd6addfa32e29a4132b099818b4b6dd1dd0a55ab54b629af48b7113095d6cb54
7
+ data.tar.gz: 52f11c59367bc9d7dab6d21ad969cec1f7dd672f7fdab175f577d9076b7443e911b22b63c798198aae176f3939c4142f8eaa4cda1aa775464dbf0ba929f953ae
data/README.md CHANGED
@@ -38,39 +38,22 @@ require "feen"
38
38
 
39
39
  # Dump a classic Tsume Shogi problem
40
40
  FEEN.dump(
41
- "active_side_id": 0,
42
- "board": {
43
- "3": "s",
44
- "4": "k" ,
45
- "5": "s",
46
- "22": "+P",
47
- "43": "+B"
48
- },
49
- "indexes": [9, 9],
50
- "pieces_in_hand_grouped_by_sides": [
51
- %w[S],
52
- %w[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]
53
- ]
41
+ "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],
42
+ "shape": [9, 9],
43
+ "side_id": 0,
44
+ "square": {
45
+ 3 => "s",
46
+ 4 => "k",
47
+ 5 => "s",
48
+ 22 => "+P",
49
+ 43 => "+B"
50
+ }
54
51
  )
55
- # => "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"
52
+ # => "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"
56
53
 
57
54
  # Parse a classic Tsume Shogi problem
58
- 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")
59
- # => {
60
- # "active_side_id": 0,
61
- # "board": {
62
- # "3": "s",
63
- # "4": "k" ,
64
- # "5": "s",
65
- # "22": "+P",
66
- # "43": "+B"
67
- # },
68
- # "indexes": [9, 9],
69
- # "pieces_in_hand_grouped_by_sides": [
70
- # %w[S],
71
- # %w[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]
72
- # ]
73
- # }
55
+ 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")
56
+ # => {: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}
74
57
  ```
75
58
 
76
59
  ## License
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "feen/dumper"
4
- require_relative "feen/parser"
3
+ require_relative File.join("feen", "dumper")
4
+ require_relative File.join("feen", "parser")
5
5
 
6
6
  # This module provides a Ruby interface for data serialization and
7
7
  # deserialization in FEEN format.
@@ -10,37 +10,33 @@ require_relative "feen/parser"
10
10
  module FEEN
11
11
  # @example Dumps position params into a FEEN string.
12
12
  #
13
- # @param active_side_id [Integer] The identifier of the player who must play.
14
- # @param board [Hash] The indexes of each piece on the board.
15
- # @param indexes [Array] The shape of the board.
16
- # @param pieces_in_hand_grouped_by_sides [Array] The list of pieces in hand
17
- # grouped by players.
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.
18
17
  #
19
18
  # @example Dump a classic Tsume Shogi problem
20
19
  # dump(
21
- # "active_side_id": 0,
22
- # "board": {
23
- # "3": "s",
24
- # "4": "k" ,
25
- # "5": "s",
26
- # "22": "+P",
27
- # "43": "+B"
28
- # },
29
- # "indexes": [9, 9],
30
- # "pieces_in_hand_grouped_by_sides": [
31
- # %w[S],
32
- # %w[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]
33
- # ]
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": {
24
+ # 3 => "s",
25
+ # 4 => "k",
26
+ # 5 => "s",
27
+ # 22 => "+P",
28
+ # 43 => "+B"
29
+ # }
34
30
  # )
35
- # # => "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 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"
36
32
  #
37
33
  # @return [String] The FEEN string representing the position.
38
- def self.dump(active_side_id:, board: {}, indexes:, pieces_in_hand_grouped_by_sides:)
34
+ def self.dump(in_hand:, shape:, side_id:, square:)
39
35
  Dumper.call(
40
- active_side_id: active_side_id,
41
- board: board,
42
- indexes: indexes,
43
- pieces_in_hand_grouped_by_sides: pieces_in_hand_grouped_by_sides
36
+ in_hand: in_hand,
37
+ shape: shape,
38
+ side_id: side_id,
39
+ square: square
44
40
  )
45
41
  end
46
42
 
@@ -49,22 +45,18 @@ module FEEN
49
45
  # @param feen [String] The FEEN string representing a position.
50
46
  #
51
47
  # @example Parse a classic Tsume Shogi problem
52
- # 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 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")
53
49
  # # => {
54
- # # "active_side_id": 0,
55
- # # "board": {
56
- # # "3": "s",
57
- # # "4": "k" ,
58
- # # "5": "s",
59
- # # "22": "+P",
60
- # # "43": "+B"
61
- # # },
62
- # # "indexes": [9, 9],
63
- # # "pieces_in_hand_grouped_by_sides": [
64
- # # %w[S],
65
- # # %w[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]
66
- # # ]
67
- # # }
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": {
54
+ # # 3 => "s",
55
+ # # 4 => "k",
56
+ # # 5 => "s",
57
+ # # 22 => "+P",
58
+ # # 43 => "+B"
59
+ # # }
68
60
  #
69
61
  # @return [Hash] The position params representing the position.
70
62
  def self.parse(feen)
@@ -1,44 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "dumper/board"
4
- require_relative "dumper/pieces_in_hand"
5
- require_relative "dumper/turn"
3
+ require_relative File.join("dumper", "in_hand")
4
+ require_relative File.join("dumper", "square")
5
+ require_relative File.join("dumper", "turn")
6
6
 
7
7
  module FEEN
8
8
  # The dumper module.
9
9
  module Dumper
10
10
  # Dump position params into a FEEN string.
11
11
  #
12
- # @param active_side_id [Integer] The identifier of the player who must play.
13
- # @param board [Hash] The indexes of each piece on the board.
14
- # @param indexes [Array] The shape of the board.
15
- # @param pieces_in_hand_grouped_by_sides [Array] The list of pieces in hand
16
- # grouped by players.
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.
17
16
  #
18
17
  # @example Dump a classic Tsume Shogi problem
19
18
  # call(
20
- # "active_side_id": 0,
21
- # "board": {
22
- # "3": "s",
23
- # "4": "k" ,
24
- # "5": "s",
25
- # "22": "+P",
26
- # "43": "+B"
27
- # },
28
- # "indexes": [9, 9],
29
- # "pieces_in_hand_grouped_by_sides": [
30
- # %w[S],
31
- # %w[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]
32
- # ]
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": {
23
+ # 3 => "s",
24
+ # 4 => "k",
25
+ # 5 => "s",
26
+ # 22 => "+P",
27
+ # 43 => "+B"
28
+ # }
33
29
  # )
34
- # # => "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"
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"
35
31
  #
36
32
  # @return [String] The FEEN string representing the position.
37
- def self.call(active_side_id:, board:, indexes:, pieces_in_hand_grouped_by_sides:)
33
+ def self.call(in_hand:, shape:, side_id:, square:)
38
34
  [
39
- Board.new(*indexes, **board).to_s,
40
- Turn.dump(active_side_id, pieces_in_hand_grouped_by_sides.length),
41
- PiecesInHand.dump(*pieces_in_hand_grouped_by_sides)
35
+ Square.new(shape, square).to_s,
36
+ Turn.dump(side_id),
37
+ InHand.dump(in_hand)
42
38
  ].join(" ")
43
39
  end
44
40
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FEEN
4
+ module Dumper
5
+ # The pieces in hand class.
6
+ #
7
+ # @example Serialize a list of pieces in hand grouped by sides
8
+ # PiecesInHand.dump(%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])
9
+ # # => "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"
10
+ module InHand
11
+ # Serialize pieces in hand lists into a string.
12
+ #
13
+ # @param piece_names [Array] A list of pieces in hand.
14
+ #
15
+ # @return [String] A string representing the pieces in hand.
16
+ def self.dump(piece_names)
17
+ return "-" if piece_names.empty?
18
+
19
+ piece_names.sort.join("/")
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FEEN
4
+ module Dumper
5
+ # The square class.
6
+ #
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"
9
+ #
10
+ # @example Dump the Xiangqi starting position board
11
+ # Board.new(
12
+ # [10, 9],
13
+ # {
14
+ # 0 => "車",
15
+ # 1 => "馬",
16
+ # 2 => "象",
17
+ # 3 => "士",
18
+ # 4 => "將",
19
+ # 5 => "士",
20
+ # 6 => "象",
21
+ # 7 => "馬",
22
+ # 8 => "車",
23
+ # 19 => "砲",
24
+ # 25 => "砲",
25
+ # 27 => "卒",
26
+ # 29 => "卒",
27
+ # 31 => "卒",
28
+ # 33 => "卒",
29
+ # 35 => "卒",
30
+ # 54 => "兵",
31
+ # 56 => "兵",
32
+ # 58 => "兵",
33
+ # 60 => "兵",
34
+ # 62 => "兵",
35
+ # 64 => "炮",
36
+ # 70 => "炮",
37
+ # 81 => "俥",
38
+ # 82 => "傌",
39
+ # 83 => "相",
40
+ # 84 => "仕",
41
+ # 85 => "帥",
42
+ # 86 => "仕",
43
+ # 87 => "相",
44
+ # 88 => "傌",
45
+ # 89 => "俥"
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
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)
52
+ @indexes = indexes
53
+ @squares = Array.new(length) { |i| board.fetch(i, nil) }
54
+ end
55
+
56
+ # @return [String] The string representing the board.
57
+ def to_s
58
+ unflatten(@squares, @indexes)
59
+ end
60
+
61
+ private
62
+
63
+ def length
64
+ @indexes.inject(:*)
65
+ end
66
+
67
+ def unflatten(squares, remaining_indexes)
68
+ return row(squares) if remaining_indexes.length == 1
69
+
70
+ squares
71
+ .each_slice(squares.length / remaining_indexes.fetch(0))
72
+ .to_a
73
+ .map { |sub_squares| unflatten(sub_squares, remaining_indexes[1..]) }
74
+ .join("/" * remaining_indexes.length.pred)
75
+ end
76
+
77
+ def row(squares)
78
+ squares
79
+ .map { |square| square.nil? ? 1 : square }
80
+ .join(",")
81
+ .gsub(/1,[1,]*1/) { |str| str.split(",").length }
82
+ end
83
+ end
84
+ end
85
+ end
@@ -4,15 +4,14 @@ module FEEN
4
4
  module Dumper
5
5
  # The turn module.
6
6
  module Turn
7
- # @param active_side_id [Integer] The identifier of the active player.
8
- # @param sides_count [Integer] The number of players.
7
+ # @param side_id [Integer] The identifier of the active player.
9
8
  #
10
9
  # @example Dump the number that identify the player who have to play
11
- # dump(0, 2) # => "0"
10
+ # dump(0) # => "0"
12
11
  #
13
12
  # @return [String] The number that identify the player who have to play.
14
- def self.dump(active_side_id, sides_count)
15
- String(Integer(active_side_id) % Integer(sides_count))
13
+ def self.dump(side_id)
14
+ String(side_id)
16
15
  end
17
16
  end
18
17
  end
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "parser/board"
4
- require_relative "parser/pieces_in_hand"
5
- require_relative "parser/shape"
6
- require_relative "parser/turn"
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")
7
7
 
8
8
  module FEEN
9
9
  # The parser module.
@@ -13,41 +13,28 @@ module FEEN
13
13
  # @param feen [String] The FEEN string representing a position.
14
14
  #
15
15
  # @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")
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")
17
17
  # # => {
18
- # # "active_side_id": 0,
19
- # # "board": {
20
- # # "3": "s",
21
- # # "4": "k" ,
22
- # # "5": "s",
23
- # # "22": "+P",
24
- # # "43": "+B"
25
- # # },
26
- # # "indexes": [9, 9],
27
- # # "pieces_in_hand_grouped_by_sides": [
28
- # # %w[S],
29
- # # %w[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]
30
- # # ]
31
- # # }
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": {
22
+ # # 3 => "s",
23
+ # # 4 => "k",
24
+ # # 5 => "s",
25
+ # # 22 => "+P",
26
+ # # 43 => "+B"
27
+ # # }
32
28
  #
33
29
  # @return [Hash] The position params representing the position.
34
30
  def self.call(feen)
35
- params(*feen.split(" "))
36
- end
31
+ square_str, side_id_str, in_hand_str = feen.split(" ")
37
32
 
38
- # Parse the FEEN string's three fields and return the position params.
39
- #
40
- # @param board [String] The flatten board.
41
- # @param active_side_id [String] The active side identifier.
42
- # @param in_hand [String] The captured actors.
43
- #
44
- # @return [Hash] The position params representing the position.
45
- private_class_method def self.params(board, active_side_id, in_hand)
46
33
  {
47
- active_side_id: Turn.parse(active_side_id),
48
- board: Board.new(board).to_h,
49
- indexes: Shape.new(board).to_a,
50
- pieces_in_hand_grouped_by_sides: PiecesInHand.parse(in_hand)
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
51
38
  }
52
39
  end
53
40
  end
@@ -0,0 +1,21 @@
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
+ # @return [Array] The list of pieces in hand grouped by players.
16
+ def self.parse(piece_names_str)
17
+ piece_names_str.split(",")
18
+ end
19
+ end
20
+ end
21
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module FEEN
4
4
  module Parser
5
- # The board class.
5
+ # The square class.
6
6
  #
7
7
  # @example Parse a Shogi problem board and return an array
8
8
  # Board.new("3,s,k,s,3/9/4,+P,4/9/7,+B,1/9/9/9/9").to_a
@@ -21,13 +21,13 @@ module FEEN
21
21
  # @example Parse a Shogi problem board and return a hash
22
22
  # Board.new("3,s,k,s,3/9/4,+P,4/9/7,+B,1/9/9/9/9").to_h
23
23
  # # => {
24
- # # "3": "s",
25
- # # "4": "k" ,
26
- # # "5": "s",
27
- # # "22": "+P",
28
- # # "43": "+B"
24
+ # # 3 => "s",
25
+ # # 4 => "k",
26
+ # # 5 => "s",
27
+ # # 22 => "+P",
28
+ # # 43 => "+B"
29
29
  # # }
30
- class Board
30
+ class Square
31
31
  # @param board [String] The flatten board.
32
32
  def initialize(board)
33
33
  @board = board
@@ -40,14 +40,14 @@ module FEEN
40
40
  .flat_map { |str| row(str) }
41
41
  end
42
42
 
43
- # @return [Hash] The indexes of each piece on the board.
43
+ # @return [Hash] The index of each piece on the board.
44
44
  def to_h
45
45
  to_a
46
46
  .each_with_index
47
47
  .inject({}) do |h, (v, i)|
48
48
  next h if v.nil?
49
49
 
50
- h.merge(i.to_s.to_sym => v)
50
+ h.merge(i => v)
51
51
  end
52
52
  end
53
53
 
@@ -4,15 +4,15 @@ module FEEN
4
4
  module Parser
5
5
  # The turn module.
6
6
  module Turn
7
- # @param active_side_id [String] The identifier of bottom-side and
7
+ # @param side_id [String] The identifier of bottom-side and
8
8
  # top-side.
9
9
  #
10
10
  # @example Parse the number that identify the player who have to play
11
11
  # parse("0") # => 0
12
12
  #
13
13
  # @return [Integer] The number that identify the player who have to play.
14
- def self.parse(active_side_id)
15
- Integer(active_side_id)
14
+ def self.parse(side_id)
15
+ Integer(side_id)
16
16
  end
17
17
  end
18
18
  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: 2.0.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyril Kato
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-24 00:00:00.000000000 Z
11
+ date: 2020-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: brutal
@@ -132,13 +132,13 @@ files:
132
132
  - README.md
133
133
  - lib/feen.rb
134
134
  - lib/feen/dumper.rb
135
- - lib/feen/dumper/board.rb
136
- - lib/feen/dumper/pieces_in_hand.rb
135
+ - lib/feen/dumper/in_hand.rb
136
+ - lib/feen/dumper/square.rb
137
137
  - lib/feen/dumper/turn.rb
138
138
  - lib/feen/parser.rb
139
- - lib/feen/parser/board.rb
140
- - lib/feen/parser/pieces_in_hand.rb
139
+ - lib/feen/parser/in_hand.rb
141
140
  - lib/feen/parser/shape.rb
141
+ - lib/feen/parser/square.rb
142
142
  - lib/feen/parser/turn.rb
143
143
  homepage: https://developer.sashite.com/specs/forsyth-edwards-expanded-notation
144
144
  licenses:
@@ -155,7 +155,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
155
155
  requirements:
156
156
  - - ">="
157
157
  - !ruby/object:Gem::Version
158
- version: '0'
158
+ version: 2.7.0
159
159
  required_rubygems_version: !ruby/object:Gem::Requirement
160
160
  requirements:
161
161
  - - ">="
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FEEN
4
- module Dumper
5
- # The board class.
6
- #
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"
9
- #
10
- # @example Dump the Xiangqi starting position board
11
- # Board.new(10, 9,
12
- # "0": "車",
13
- # "1": "馬",
14
- # "2": "象",
15
- # "3": "士",
16
- # "4": "將",
17
- # "5": "士",
18
- # "6": "象",
19
- # "7": "馬",
20
- # "8": "車",
21
- # "19": "砲",
22
- # "25": "砲",
23
- # "27": "卒",
24
- # "29": "卒",
25
- # "31": "卒",
26
- # "33": "卒",
27
- # "35": "卒",
28
- # "54": "兵",
29
- # "56": "兵",
30
- # "58": "兵",
31
- # "60": "兵",
32
- # "62": "兵",
33
- # "64": "炮",
34
- # "70": "炮",
35
- # "81": "俥",
36
- # "82": "傌",
37
- # "83": "相",
38
- # "84": "仕",
39
- # "85": "帥",
40
- # "86": "仕",
41
- # "87": "相",
42
- # "88": "傌",
43
- # "89": "俥").to_s # => "車,馬,象,士,將,士,象,馬,車/9/1,砲,5,砲,1/卒,1,卒,1,卒,1,卒,1,卒/9/9/兵,1,兵,1,兵,1,兵,1,兵/1,炮,5,炮,1/9/俥,傌,相,仕,帥,仕,相,傌,俥"
44
- class Board
45
- # @param indexes [Array] The shape of the board.
46
- # @param board [Hash] The indexes of each piece on the board.
47
- def initialize(*indexes, **board)
48
- @indexes = indexes
49
- @squares = Array.new(length) { |i| board.fetch(i.to_s.to_sym, nil) }
50
- end
51
-
52
- # @return [String] The string representing the board.
53
- def to_s
54
- unflatten(@squares, *@indexes)
55
- end
56
-
57
- private
58
-
59
- def length
60
- @indexes.inject(:*)
61
- end
62
-
63
- def unflatten(squares, *remaining_indexes)
64
- return row(*squares) if remaining_indexes.length == 1
65
-
66
- squares
67
- .each_slice(squares.length / remaining_indexes.fetch(0))
68
- .to_a
69
- .map { |sub_squares| unflatten(sub_squares, *remaining_indexes[1..]) }
70
- .join("/" * remaining_indexes.length.pred)
71
- end
72
-
73
- def row(*squares)
74
- squares
75
- .map { |square| square.nil? ? 1 : square }
76
- .join(",")
77
- .gsub(/1,[1,]*1/) { |str| str.split(",").length }
78
- end
79
- end
80
- end
81
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FEEN
4
- module Dumper
5
- # The pieces in hand class.
6
- #
7
- # @example Serialize a list of pieces in hand grouped by sides
8
- # PiecesInHand.dump(
9
- # %w[S],
10
- # %w[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]
11
- # )
12
- # # => "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
- class PiecesInHand
14
- # Serialize pieces in hand lists into a string.
15
- #
16
- # @param pieces_in_hand_grouped_by_sides [Array] The list of pieces in hand
17
- # grouped by players.
18
- #
19
- # @return [String] A string representing the pieces in hand of both
20
- # players.
21
- def self.dump(*pieces_in_hand_grouped_by_sides)
22
- pieces_in_hand_grouped_by_sides.map { |pieces| new(*pieces).to_s }.join("/")
23
- end
24
-
25
- # @param pieces [Array] A list of pieces in hand.
26
- def initialize(*pieces)
27
- @pieces = pieces.sort
28
- end
29
-
30
- # @return [String] A string representing the pieces in hand.
31
- def to_s
32
- @pieces.join(",")
33
- end
34
- end
35
- end
36
- 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 PiecesInHand
7
- # The list of pieces in hand grouped by players.
8
- #
9
- # @param pieces_in_hand_grouped_by_sides_str [String] The serialized list of
10
- # pieces in hand grouped by players.
11
- #
12
- # @example Parse a list of serialized pieces in hand
13
- # 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")
14
- # # => [
15
- # # %w[S],
16
- # # %w[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]
17
- # # ]
18
- #
19
- # @return [Array] The list of pieces in hand grouped by players.
20
- def self.parse(pieces_in_hand_grouped_by_sides_str)
21
- pieces_in_hand_grouped_by_sides_str
22
- .split("/", -1)
23
- .map { |pieces_in_hand_str| pieces_in_hand_str.split(",") }
24
- end
25
- end
26
- end
27
- end