feen 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,56 +1,45 @@
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 "dumper/board"
4
+ require_relative "dumper/pieces_in_hand"
5
+ require_relative "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 [Integer] The identifier of the player who must play.
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.
13
14
  # @param indexes [Array] The shape of the board.
14
- # @param pieces_in_hand_by_players [Array] The list of pieces in hand
15
+ # @param pieces_in_hand_grouped_by_sides [Array] The list of pieces in hand
15
16
  # grouped by players.
16
- # @param squares [Array] The list of squares on the board.
17
17
  #
18
- # @example Dump Four-player chess's starting position
18
+ # @example Dump a classic Tsume Shogi problem
19
19
  # call(
20
- # active_side: 0,
21
- # indexes: [14, 14],
22
- # pieces_in_hand_by_players: [
23
- # [],
24
- # [],
25
- # [],
26
- # []
27
- # ],
28
- # squares: [
29
- # nil , nil , nil , "yR", "yN", "yB", "yK", "yQ", "yB", "yN", "yR", nil , nil , nil ,
30
- # nil , nil , nil , "yP", "yP", "yP", "yP", "yP", "yP", "yP", "yP", nil , nil , nil ,
31
- # nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , nil ,
32
- # "bR", "bP", nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , "gP", "gR",
33
- # "bN", "bP", nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , "gP", "gN",
34
- # "bB", "bP", nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , "gP", "gB",
35
- # "bK", "bP", nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , "gP", "gQ",
36
- # "bQ", "bP", nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , "gP", "gK",
37
- # "bB", "bP", nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , "gP", "gB",
38
- # "bN", "bP", nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , "gP", "gN",
39
- # "bR", "bP", nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , "gP", "gR",
40
- # nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , nil ,
41
- # nil , nil , nil , "rP", "rP", "rP", "rP", "rP", "rP", "rP", "rP", nil , nil , nil ,
42
- # nil , nil , nil , "rR", "rN", "rB", "rQ", "rK", "rB", "rN", "rR", nil , nil , nil
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]
43
32
  # ]
44
33
  # )
45
- # # => "3,yR,yN,yB,yK,yQ,yB,yN,yR,3/3,yP,yP,yP,yP,yP,yP,yP,yP,3/14/bR,bP,10,gP,gR/bN,bP,10,gP,gN/bB,bP,10,gP,gB/bK,bP,10,gP,gQ/bQ,bP,10,gP,gK/bB,bP,10,gP,gB/bN,bP,10,gP,gN/bR,bP,10,gP,gR/14/3,rP,rP,rP,rP,rP,rP,rP,rP,3/3,rR,rN,rB,rQ,rK,rB,rN,rR,3 0 ///"
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"
46
35
  #
47
36
  # @return [String] The FEEN string representing the position.
48
- def self.call(active_side:, indexes:, pieces_in_hand_by_players:, squares:)
37
+ def self.call(active_side_id:, board:, indexes:, pieces_in_hand_grouped_by_sides:)
49
38
  [
50
- Board.new(*indexes).to_s(*squares),
51
- Turn.dump(active_side, pieces_in_hand_by_players.length),
52
- PiecesInHand.dump(*pieces_in_hand_by_players)
53
- ].join(' ')
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)
42
+ ].join(" ")
54
43
  end
55
44
  end
56
45
  end
@@ -1,27 +1,65 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'inconsistent_size_error'
4
-
5
3
  module FEEN
6
4
  module Dumper
7
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/俥,傌,相,仕,帥,仕,相,傌,俥"
8
44
  class Board
9
45
  # @param indexes [Array] The shape of the board.
10
- def initialize(*indexes)
46
+ # @param board [Hash] The indexes of each piece on the board.
47
+ def initialize(*indexes, **board)
11
48
  @indexes = indexes
49
+ @squares = Array.new(length) { |i| board.fetch(i.to_s.to_sym, nil) }
12
50
  end
13
51
 
14
- # @param squares [Array] The list of squares on the board.
15
- #
16
52
  # @return [String] The string representing the board.
17
- def to_s(*squares)
18
- raise InconsistentSizeError unless squares.length == @indexes.inject(:*)
19
-
20
- unflatten(squares, *@indexes)
53
+ def to_s
54
+ unflatten(@squares, *@indexes)
21
55
  end
22
56
 
23
57
  private
24
58
 
59
+ def length
60
+ @indexes.inject(:*)
61
+ end
62
+
25
63
  def unflatten(squares, *remaining_indexes)
26
64
  return row(*squares) if remaining_indexes.length == 1
27
65
 
@@ -29,14 +67,14 @@ module FEEN
29
67
  .each_slice(squares.length / remaining_indexes.fetch(0))
30
68
  .to_a
31
69
  .map { |sub_squares| unflatten(sub_squares, *remaining_indexes[1..]) }
32
- .join('/' * remaining_indexes.length.pred)
70
+ .join("/" * remaining_indexes.length.pred)
33
71
  end
34
72
 
35
73
  def row(*squares)
36
74
  squares
37
75
  .map { |square| square.nil? ? 1 : square }
38
- .join(',')
39
- .gsub(/1,[1,]*1/) { |str| str.split(',').length }
76
+ .join(",")
77
+ .gsub(/1,[1,]*1/) { |str| str.split(",").length }
40
78
  end
41
79
  end
42
80
  end
@@ -3,16 +3,23 @@
3
3
  module FEEN
4
4
  module Dumper
5
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"
6
13
  class PiecesInHand
7
14
  # Serialize pieces in hand lists into a string.
8
15
  #
9
- # @param pieces_in_hand_by_players [Array] The list of pieces in hand
16
+ # @param pieces_in_hand_grouped_by_sides [Array] The list of pieces in hand
10
17
  # grouped by players.
11
18
  #
12
19
  # @return [String] A string representing the pieces in hand of both
13
20
  # players.
14
- def self.dump(*pieces_in_hand_by_players)
15
- pieces_in_hand_by_players.map { |pieces| new(*pieces).to_s }.join('/')
21
+ def self.dump(*pieces_in_hand_grouped_by_sides)
22
+ pieces_in_hand_grouped_by_sides.map { |pieces| new(*pieces).to_s }.join("/")
16
23
  end
17
24
 
18
25
  # @param pieces [Array] A list of pieces in hand.
@@ -22,7 +29,7 @@ module FEEN
22
29
 
23
30
  # @return [String] A string representing the pieces in hand.
24
31
  def to_s
25
- @pieces.join(',')
32
+ @pieces.join(",")
26
33
  end
27
34
  end
28
35
  end
@@ -2,14 +2,17 @@
2
2
 
3
3
  module FEEN
4
4
  module Dumper
5
- # The turn class.
5
+ # The turn module.
6
6
  module Turn
7
- # @param active_side [Integer] The identifier of the active player.
7
+ # @param active_side_id [Integer] The identifier of the active player.
8
8
  # @param sides_count [Integer] The number of players.
9
9
  #
10
+ # @example Dump the number that identify the player who have to play
11
+ # dump(0, 2) # => "0"
12
+ #
10
13
  # @return [String] The number that identify the player who have to play.
11
- def self.dump(active_side, sides_count)
12
- String(Integer(active_side) % Integer(sides_count))
14
+ def self.dump(active_side_id, sides_count)
15
+ String(Integer(active_side_id) % Integer(sides_count))
13
16
  end
14
17
  end
15
18
  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 "parser/board"
4
+ require_relative "parser/pieces_in_hand"
5
+ require_relative "parser/shape"
6
+ require_relative "parser/turn"
7
7
 
8
8
  module FEEN
9
9
  # The parser module.
@@ -12,53 +12,42 @@ module FEEN
12
12
  #
13
13
  # @param feen [String] The FEEN string representing a position.
14
14
  #
15
- # @example Parse Four-player chess's starting position
16
- # call("3,yR,yN,yB,yK,yQ,yB,yN,yR,3/3,yP,yP,yP,yP,yP,yP,yP,yP,3/14/bR,bP,10,gP,gR/bN,bP,10,gP,gN/bB,bP,10,gP,gB/bK,bP,10,gP,gQ/bQ,bP,10,gP,gK/bB,bP,10,gP,gB/bN,bP,10,gP,gN/bR,bP,10,gP,gR/14/3,rP,rP,rP,rP,rP,rP,rP,rP,3/3,rR,rN,rB,rQ,rK,rB,rN,rR,3 0 ///")
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")
17
17
  # # => {
18
- # # active_side: 0,
19
- # # indexes: [14, 14],
20
- # # pieces_in_hand_by_players: [
21
- # # [],
22
- # # [],
23
- # # [],
24
- # # []
25
- # # ],
26
- # # squares: [
27
- # # nil , nil , nil , "yR", "yN", "yB", "yK", "yQ", "yB", "yN", "yR", nil , nil , nil ,
28
- # # nil , nil , nil , "yP", "yP", "yP", "yP", "yP", "yP", "yP", "yP", nil , nil , nil ,
29
- # # nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , nil ,
30
- # # "bR", "bP", nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , "gP", "gR",
31
- # # "bN", "bP", nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , "gP", "gN",
32
- # # "bB", "bP", nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , "gP", "gB",
33
- # # "bK", "bP", nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , "gP", "gQ",
34
- # # "bQ", "bP", nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , "gP", "gK",
35
- # # "bB", "bP", nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , "gP", "gB",
36
- # # "bN", "bP", nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , "gP", "gN",
37
- # # "bR", "bP", nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , "gP", "gR",
38
- # # nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , nil , nil ,
39
- # # nil , nil , nil , "rP", "rP", "rP", "rP", "rP", "rP", "rP", "rP", nil , nil , nil ,
40
- # # nil , nil , nil , "rR", "rN", "rB", "rQ", "rK", "rB", "rN", "rR", nil , nil , nil
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]
41
30
  # # ]
42
31
  # # }
43
32
  #
44
33
  # @return [Hash] The position params representing the position.
45
34
  def self.call(feen)
46
- params(*feen.split(' '))
35
+ params(*feen.split(" "))
47
36
  end
48
37
 
49
38
  # Parse the FEEN string's three fields and return the position params.
50
39
  #
51
40
  # @param board [String] The flatten board.
52
- # @param active_side [String] The active side identifier.
41
+ # @param active_side_id [String] The active side identifier.
53
42
  # @param in_hand [String] The captured actors.
54
43
  #
55
44
  # @return [Hash] The position params representing the position.
56
- private_class_method def self.params(board, active_side, in_hand)
45
+ private_class_method def self.params(board, active_side_id, in_hand)
57
46
  {
58
- active_side: Turn.parse(active_side),
47
+ active_side_id: Turn.parse(active_side_id),
48
+ board: Board.new(board).to_h,
59
49
  indexes: Shape.new(board).to_a,
60
- pieces_in_hand_by_players: PiecesInHand.parse(in_hand),
61
- squares: Board.new(board).to_a
50
+ pieces_in_hand_grouped_by_sides: PiecesInHand.parse(in_hand)
62
51
  }
63
52
  end
64
53
  end
@@ -4,7 +4,7 @@ module FEEN
4
4
  module Parser
5
5
  # The board class.
6
6
  #
7
- # @example Parse a Shogi problem board
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
9
9
  # # => [
10
10
  # # nil, nil, nil, "s", "k", "s", nil, nil, nil,
@@ -17,6 +17,16 @@ module FEEN
17
17
  # # nil, nil, nil, nil, nil, nil, nil, nil, nil,
18
18
  # # nil, nil, nil, nil, nil, nil, nil, nil, nil
19
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
+ # # }
20
30
  class Board
21
31
  # @param board [String] The flatten board.
22
32
  def initialize(board)
@@ -30,6 +40,17 @@ module FEEN
30
40
  .flat_map { |str| row(str) }
31
41
  end
32
42
 
43
+ # @return [Hash] The indexes 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.to_s.to_sym => v)
51
+ end
52
+ end
53
+
33
54
  private
34
55
 
35
56
  def row(string)
@@ -2,11 +2,11 @@
2
2
 
3
3
  module FEEN
4
4
  module Parser
5
- # The pieces in hand class.
5
+ # The pieces in hand module.
6
6
  module PiecesInHand
7
7
  # The list of pieces in hand grouped by players.
8
8
  #
9
- # @param pieces_in_hand_by_players_str [String] The serialized list of
9
+ # @param pieces_in_hand_grouped_by_sides_str [String] The serialized list of
10
10
  # pieces in hand grouped by players.
11
11
  #
12
12
  # @example Parse a list of serialized pieces in hand
@@ -17,10 +17,10 @@ module FEEN
17
17
  # # ]
18
18
  #
19
19
  # @return [Array] The list of pieces in hand grouped by players.
20
- def self.parse(pieces_in_hand_by_players_str)
21
- pieces_in_hand_by_players_str
22
- .split('/', -1)
23
- .map { |pieces_in_hand_str| pieces_in_hand_str.split(',') }
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
24
  end
25
25
  end
26
26
  end
@@ -21,7 +21,7 @@ module FEEN
21
21
 
22
22
  def indexes(string, separator)
23
23
  if separator.empty?
24
- last_index = string.split(',').inject(0) do |counter, sub_string|
24
+ last_index = string.split(",").inject(0) do |counter, sub_string|
25
25
  number = sub_string.match?(/[0-9]+/) ? Integer(sub_string) : 1
26
26
  counter + number
27
27
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module FEEN
4
4
  module Parser
5
- # The turn class.
5
+ # The turn module.
6
6
  module Turn
7
7
  # @param active_side_id [String] The identifier of bottom-side and
8
8
  # top-side.
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: feen
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.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-16 00:00:00.000000000 Z
11
+ date: 2020-08-24 00:00:00.000000000 Z
12
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'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -119,7 +133,6 @@ files:
119
133
  - lib/feen.rb
120
134
  - lib/feen/dumper.rb
121
135
  - lib/feen/dumper/board.rb
122
- - lib/feen/dumper/inconsistent_size_error.rb
123
136
  - lib/feen/dumper/pieces_in_hand.rb
124
137
  - lib/feen/dumper/turn.rb
125
138
  - lib/feen/parser.rb