console-shogi 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +19 -0
  4. data/images/active/gote/fu.png +0 -0
  5. data/images/active/gote/gin.png +0 -0
  6. data/images/active/gote/gyoku.png +0 -0
  7. data/images/active/gote/hisha.png +0 -0
  8. data/images/active/gote/kaku.png +0 -0
  9. data/images/active/gote/keima.png +0 -0
  10. data/images/active/gote/kin.png +0 -0
  11. data/images/active/gote/kyosha.png +0 -0
  12. data/images/active/gote/narigin.png +0 -0
  13. data/images/active/gote/narikei.png +0 -0
  14. data/images/active/gote/narikyo.png +0 -0
  15. data/images/active/gote/ohsho.png +0 -0
  16. data/images/active/gote/ryu.png +0 -0
  17. data/images/active/gote/tokin.png +0 -0
  18. data/images/active/gote/uma.png +0 -0
  19. data/images/active/nonepiece.png +0 -0
  20. data/images/active/sente/fu.png +0 -0
  21. data/images/active/sente/gin.png +0 -0
  22. data/images/active/sente/gyoku.png +0 -0
  23. data/images/active/sente/hisha.png +0 -0
  24. data/images/active/sente/kaku.png +0 -0
  25. data/images/active/sente/keima.png +0 -0
  26. data/images/active/sente/kin.png +0 -0
  27. data/images/active/sente/kyosha.png +0 -0
  28. data/images/active/sente/narigin.png +0 -0
  29. data/images/active/sente/narikei.png +0 -0
  30. data/images/active/sente/narikyo.png +0 -0
  31. data/images/active/sente/ohsho.png +0 -0
  32. data/images/active/sente/ryu.png +0 -0
  33. data/images/active/sente/tokin.png +0 -0
  34. data/images/active/sente/uma.png +0 -0
  35. data/images/focused/gote/fu.png +0 -0
  36. data/images/focused/gote/gin.png +0 -0
  37. data/images/focused/gote/gyoku.png +0 -0
  38. data/images/focused/gote/hisha.png +0 -0
  39. data/images/focused/gote/kaku.png +0 -0
  40. data/images/focused/gote/keima.png +0 -0
  41. data/images/focused/gote/kin.png +0 -0
  42. data/images/focused/gote/kyosha.png +0 -0
  43. data/images/focused/gote/narigin.png +0 -0
  44. data/images/focused/gote/narikei.png +0 -0
  45. data/images/focused/gote/narikyo.png +0 -0
  46. data/images/focused/gote/ohsho.png +0 -0
  47. data/images/focused/gote/ryu.png +0 -0
  48. data/images/focused/gote/tokin.png +0 -0
  49. data/images/focused/gote/uma.png +0 -0
  50. data/images/focused/nonepiece.png +0 -0
  51. data/images/focused/sente/fu.png +0 -0
  52. data/images/focused/sente/gin.png +0 -0
  53. data/images/focused/sente/gyoku.png +0 -0
  54. data/images/focused/sente/hisha.png +0 -0
  55. data/images/focused/sente/kaku.png +0 -0
  56. data/images/focused/sente/keima.png +0 -0
  57. data/images/focused/sente/kin.png +0 -0
  58. data/images/focused/sente/kyosha.png +0 -0
  59. data/images/focused/sente/narigin.png +0 -0
  60. data/images/focused/sente/narikei.png +0 -0
  61. data/images/focused/sente/narikyo.png +0 -0
  62. data/images/focused/sente/ohsho.png +0 -0
  63. data/images/focused/sente/ryu.png +0 -0
  64. data/images/focused/sente/tokin.png +0 -0
  65. data/images/focused/sente/uma.png +0 -0
  66. data/lib/console_shogi/board.rb +5 -9
  67. data/lib/console_shogi/game.rb +118 -19
  68. data/lib/console_shogi/komadai.rb +11 -9
  69. data/lib/console_shogi/new_board_builder.rb +41 -41
  70. data/lib/console_shogi/piece.rb +34 -23
  71. data/lib/console_shogi/piece_movement_checker.rb +46 -0
  72. data/lib/console_shogi/piece_mover.rb +31 -48
  73. data/lib/console_shogi/piece_mover_on_komadai.rb +30 -36
  74. data/lib/console_shogi/player.rb +5 -13
  75. data/lib/console_shogi/teban.rb +8 -0
  76. data/lib/console_shogi/terminal/cursor.rb +80 -0
  77. data/lib/console_shogi/terminal/display_area.rb +30 -0
  78. data/lib/console_shogi/terminal/operator.rb +209 -0
  79. data/lib/console_shogi/version.rb +1 -1
  80. data/lib/console_shogi.rb +6 -1
  81. metadata +102 -37
  82. data/images/gote/nonepiece.png +0 -0
  83. data/lib/console_shogi/terminal_operator.rb +0 -211
  84. /data/images/{gote/shori.png → gote_shori.png} +0 -0
  85. /data/images/{gote → nomal/gote}/fu.png +0 -0
  86. /data/images/{gote → nomal/gote}/gin.png +0 -0
  87. /data/images/{gote → nomal/gote}/gyoku.png +0 -0
  88. /data/images/{gote → nomal/gote}/hisha.png +0 -0
  89. /data/images/{gote → nomal/gote}/kaku.png +0 -0
  90. /data/images/{gote → nomal/gote}/keima.png +0 -0
  91. /data/images/{gote → nomal/gote}/kin.png +0 -0
  92. /data/images/{gote → nomal/gote}/kyosha.png +0 -0
  93. /data/images/{gote → nomal/gote}/narigin.png +0 -0
  94. /data/images/{gote → nomal/gote}/narikei.png +0 -0
  95. /data/images/{gote → nomal/gote}/narikyo.png +0 -0
  96. /data/images/{gote → nomal/gote}/ohsho.png +0 -0
  97. /data/images/{gote → nomal/gote}/ryu.png +0 -0
  98. /data/images/{gote → nomal/gote}/tokin.png +0 -0
  99. /data/images/{gote → nomal/gote}/uma.png +0 -0
  100. /data/images/{sente → nomal}/nonepiece.png +0 -0
  101. /data/images/{sente → nomal/sente}/fu.png +0 -0
  102. /data/images/{sente → nomal/sente}/gin.png +0 -0
  103. /data/images/{sente → nomal/sente}/gyoku.png +0 -0
  104. /data/images/{sente → nomal/sente}/hisha.png +0 -0
  105. /data/images/{sente → nomal/sente}/kaku.png +0 -0
  106. /data/images/{sente → nomal/sente}/keima.png +0 -0
  107. /data/images/{sente → nomal/sente}/kin.png +0 -0
  108. /data/images/{sente → nomal/sente}/kyosha.png +0 -0
  109. /data/images/{sente → nomal/sente}/narigin.png +0 -0
  110. /data/images/{sente → nomal/sente}/narikei.png +0 -0
  111. /data/images/{sente → nomal/sente}/narikyo.png +0 -0
  112. /data/images/{sente → nomal/sente}/ohsho.png +0 -0
  113. /data/images/{sente → nomal/sente}/ryu.png +0 -0
  114. /data/images/{sente → nomal/sente}/tokin.png +0 -0
  115. /data/images/{sente → nomal/sente}/uma.png +0 -0
  116. /data/images/{sente/shori.png → sente_shori.png} +0 -0
@@ -2,10 +2,10 @@
2
2
 
3
3
  module ConsoleShogi
4
4
  class Piece
5
- attr_reader :player
5
+ attr_accessor :teban
6
6
 
7
- def initialize(player: nil)
8
- @player = player
7
+ def initialize(teban: nil)
8
+ @teban = teban
9
9
  end
10
10
 
11
11
  def move
@@ -27,27 +27,19 @@ module ConsoleShogi
27
27
  end
28
28
 
29
29
  def image
30
- if player.sente?
31
- File.read("images/sente/#{self::class.name.split('::').last.downcase}.png")
32
- else
33
- File.read("images/gote/#{self::class.name.split('::').last.downcase}.png")
34
- end
35
- end
36
-
37
- def none?
38
- self::class == NonePiece
30
+ File.read("images/nomal/#{teban}/#{self::class.name.split('::').last.downcase}.png")
39
31
  end
40
32
 
41
- def kaku?
42
- self::class == Kaku
33
+ def active_image
34
+ File.read("images/active/#{teban}/#{self::class.name.split('::').last.downcase}.png")
43
35
  end
44
36
 
45
- def hisha?
46
- self::class == Hisha
37
+ def focused_image
38
+ File.read("images/focused/#{teban}/#{self::class.name.split('::').last.downcase}.png")
47
39
  end
48
40
 
49
- def kyosha?
50
- self::class == Kyosha
41
+ def none?
42
+ self::class == NonePiece
51
43
  end
52
44
 
53
45
  def fu?
@@ -57,7 +49,7 @@ module ConsoleShogi
57
49
  def moves
58
50
  ms = base_moves
59
51
 
60
- if player.sente?
52
+ if teban == Teban::SENTE
61
53
  ms
62
54
  else
63
55
  ms.map {|m| m.transform_values {|v| v * -1 } }
@@ -67,6 +59,10 @@ module ConsoleShogi
67
59
  def change_player!(player)
68
60
  @player = player
69
61
  end
62
+
63
+ def can_move_long_distance?
64
+ [Kaku, Hisha, Kyosha, PromotedPiece::Uma, PromotedPiece::Ryu].include?(self::class)
65
+ end
70
66
  end
71
67
 
72
68
  class NonePiece < Piece
@@ -76,8 +72,16 @@ module ConsoleShogi
76
72
  []
77
73
  end
78
74
 
79
- def player
80
- NonPlayer.new
75
+ def image
76
+ File.read("images/nomal/nonepiece.png")
77
+ end
78
+
79
+ def active_image
80
+ File.read("images/active/nonepiece.png")
81
+ end
82
+
83
+ def focused_image
84
+ File.read("images/focused/nonepiece.png")
81
85
  end
82
86
 
83
87
  def can_promote?
@@ -249,13 +253,20 @@ module ConsoleShogi
249
253
  end
250
254
 
251
255
  class PromotedPiece < Piece
252
- attr_reader :player, :original
256
+ attr_reader :original
253
257
 
254
258
  def initialize(original: nil)
255
- @player = original.player
256
259
  @original = original
257
260
  end
258
261
 
262
+ def teban
263
+ original.teban
264
+ end
265
+
266
+ def teban=(val)
267
+ original.teban = val
268
+ end
269
+
259
270
  def can_promote?
260
271
  false
261
272
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConsoleShogi
4
+ class PieceMovementChecker
5
+ def initialize(board:, from:, to:)
6
+ @board = board
7
+ @from = from
8
+ @to = to
9
+ end
10
+
11
+ def can_move?
12
+ return false unless board.within_range?(x: to[:x], y: to[:y])
13
+
14
+ diff = {x: to[:x] - from[:x], y: to[:y] - from[:y]}
15
+
16
+ return false if from_piece.moves.none? {|m| m[:x] == diff[:x] && m[:y] == diff[:y] }
17
+
18
+ return false if from_piece.teban == to_piece.teban
19
+
20
+ return true unless from_piece.can_move_long_distance?
21
+
22
+ distance = (diff[:x].nonzero? || diff[:y]).abs
23
+ element = [diff[:x] / distance, diff[:y] / distance]
24
+
25
+ 1.upto(distance - 1) do |d|
26
+ piece = board.fetch_piece(x: from[:x] + element[0] * d, y: from[:y] + element[1] * d)
27
+
28
+ return false unless piece.none?
29
+ end
30
+
31
+ true
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :board, :from, :to
37
+
38
+ def from_piece
39
+ @from_piece ||= board.fetch_piece(x: from[:x], y: from[:y])
40
+ end
41
+
42
+ def to_piece
43
+ @to_piece ||= board.fetch_piece(x: to[:x], y: to[:y])
44
+ end
45
+ end
46
+ end
@@ -2,79 +2,62 @@
2
2
 
3
3
  module ConsoleShogi
4
4
  class PieceMover
5
- def initialize(board:, from:)
5
+ def initialize(board:, player:, from:, to:)
6
6
  @board = board
7
- @from_piece_index = from
7
+ @player = player
8
+ @from = from
9
+ @to = to
10
+ @moved_piece = false
8
11
  end
9
12
 
10
13
  def move!
11
- return if target_piece.nil? || target_piece.none?
12
-
13
- while key = STDIN.getch
14
- if key == "\e" && STDIN.getch == "["
15
- key = STDIN.getch
16
-
17
- TerminalOperator.move_cursor(key)
18
- elsif key == "\r"
19
- to_piece_index = TerminalOperator.squares_index
20
-
21
- return unless can_move?(piece: target_piece, to_piece_index: to_piece_index)
22
-
23
- board.move_piece!(
24
- from: {x: from_piece_index[:x], y: from_piece_index[:y]},
25
- to: {x: to_piece_index[:x], y: to_piece_index[:y]}
26
- )
27
-
28
- # TODO とりあえずここに実装してしまっている。整理したい
29
- piece = board.fetch_piece(x: to_piece_index[:x], y: to_piece_index[:y])
30
- return unless can_promote?(piece, from_piece_index, to_piece_index)
31
-
32
- board.promote_piece!(x: to_piece_index[:x], y: to_piece_index[:y]) if TerminalOperator.select_promotion
14
+ @moved_piece = move_piece!
15
+ end
33
16
 
34
- return
35
- end
36
- end
17
+ def moved_piece?
18
+ @moved_piece
37
19
  end
38
20
 
39
- def can_move?(piece:, to_piece_index:)
40
- return false unless board.within_range?(x: to_piece_index[:x], y: to_piece_index[:y])
21
+ private
41
22
 
42
- diff = {x: to_piece_index[:x] - from_piece_index[:x], y: to_piece_index[:y] - from_piece_index[:y]}
23
+ attr_reader :board, :player, :from, :to
43
24
 
44
- return false if piece.moves.none? {|m| m[:x] == diff[:x] && m[:y] == diff[:y] }
25
+ def from_piece
26
+ @from_piece ||= board.fetch_piece(x: from[:x], y: from[:y])
27
+ end
45
28
 
46
- to_piece = board.fetch_piece(x: to_piece_index[:x], y: to_piece_index[:y])
29
+ def move_piece!
30
+ return false if from_piece.nil? || from_piece.none?
31
+ return false if from_piece.teban != player.teban
47
32
 
48
- return false if piece.player.teban == to_piece.player.teban
33
+ return false unless piece_movement_checker.can_move?
49
34
 
50
- return true unless piece.kaku? || piece.hisha? || piece.kyosha?
35
+ to_piece = board.fetch_piece(x: to[:x], y: to[:y])
36
+ player.capture_piece!(to_piece) unless to_piece.none?
51
37
 
52
- distance = (diff[:x].nonzero? || diff[:y]).abs
53
- element = [diff[:x] / distance, diff[:y] / distance]
38
+ board.move_piece!(
39
+ from: {x: from[:x], y: from[:y]},
40
+ to: {x: to[:x], y: to[:y]}
41
+ )
54
42
 
55
- 1.upto(distance - 1) do |d|
56
- piece = board.fetch_piece(x: from_piece_index[:x] + element[0] * d, y: from_piece_index[:y] + element[1] * d)
43
+ # TODO とりあえずここに実装してしまっている。整理したい
44
+ return true unless can_promote?(from_piece, from, to)
57
45
 
58
- return false unless piece.none?
59
- end
46
+ board.promote_piece!(x: to[:x], y: to[:y]) if Terminal::Operator.select_promotion
60
47
 
61
48
  true
62
49
  end
63
50
 
64
- private
65
-
66
- attr_reader :board, :from_piece_index
67
-
68
- def target_piece
69
- @target_piece ||= board.fetch_piece(x: from_piece_index[:x], y: from_piece_index[:y])
51
+ def piece_movement_checker
52
+ PieceMovementChecker.new(board: board, from: from, to: to)
70
53
  end
71
54
 
72
55
  def can_promote?(piece, from, to)
73
56
  return false unless piece.can_promote?
74
57
 
75
- if piece.player.sente?
58
+ if piece.teban == Teban::SENTE
76
59
  from[:y].between?(0, 2) || to[:y].between?(0, 2)
77
- elsif piece.player.gote?
60
+ elsif piece.teban == Teban::GOTE
78
61
  from[:y].between?(6, 8) || to[:y].between?(6, 8)
79
62
  end
80
63
  end
@@ -2,64 +2,58 @@
2
2
 
3
3
  module ConsoleShogi
4
4
  class PieceMoverOnKomadai
5
- def initialize(board:, komadai:, from:)
5
+ def initialize(board:, komadai:, from:, to:)
6
6
  @board = board
7
7
  @komadai = komadai
8
8
  # 駒台の index に直す必要がある
9
- @from_piece_index = from
9
+ @from = from
10
+ @to = to
11
+ @moved_piece = false
10
12
  end
11
13
 
12
- def drop!
13
- return if target_piece.nil? || target_piece.none?
14
+ def move!
15
+ @moved_piece = move_piece!
16
+ end
14
17
 
15
- while key = STDIN.getch
16
- if key == "\e" && STDIN.getch == "["
17
- key = STDIN.getch
18
+ def moved_piece?
19
+ @moved_piece
20
+ end
18
21
 
19
- TerminalOperator.move_cursor(key)
20
- elsif key == "\r"
21
- to_piece_index = TerminalOperator.squares_index
22
+ private
22
23
 
23
- return if to_piece_index[:location] != :board
24
- return unless can_drop?(piece: target_piece, to_piece_index: to_piece_index)
24
+ attr_reader :board, :komadai, :from, :to
25
25
 
26
- komadai.pick_up_piece!(from: from_piece_index)
27
- board.put_piece!(piece: target_piece, to: to_piece_index)
26
+ def move_piece!
27
+ return false if from_piece.nil? || from_piece.none?
28
28
 
29
- return
30
- end
31
- end
32
- end
29
+ # TODO ここで location の key もってるの期待してるの酷い、修正する
30
+ return false if to[:location] != :board
31
+ return false unless can_drop?(piece: from_piece, to: to)
33
32
 
34
- private
33
+ komadai.pick_up_piece!(from: from)
34
+ board.put_piece!(piece: from_piece, to: to)
35
35
 
36
- attr_reader :board, :komadai, :from_piece_index
36
+ true
37
+ end
37
38
 
38
- def target_piece
39
- @target_piece ||= komadai.fetch_piece(x: from_piece_index[:x], y: from_piece_index[:y])
39
+ def from_piece
40
+ @from_piece ||= komadai.fetch_piece(x: from[:x], y: from[:y])
40
41
  end
41
42
 
42
- def can_drop?(piece:, to_piece_index:)
43
- to_piece = board.fetch_piece(x: to_piece_index[:x], y: to_piece_index[:y])
43
+ def can_drop?(piece:, to:)
44
+ to_piece = board.fetch_piece(x: to[:x], y: to[:y])
44
45
 
45
46
  return false unless to_piece.none?
46
47
 
47
- return false if nifu?(piece, to_piece_index)
48
-
49
- can_move_next_turn?(piece, to_piece_index)
50
- end
51
-
52
- def can_move_next_turn?(piece, to_piece_index)
53
- piece_mover = PieceMover.new(board: board, from: to_piece_index)
48
+ return false if nifu?(piece, to)
54
49
 
55
- piece.moves.any? {|m|
56
- piece_mover.can_move?(piece: piece, to_piece_index: {x: to_piece_index[:x] + m[:x], y: to_piece_index[:y] + m[:y]})
57
- }
50
+ # TODO 動かせない場所に打つことはできないようにする
51
+ true
58
52
  end
59
53
 
60
- def nifu?(piece, to_piece_index)
54
+ def nifu?(piece, to)
61
55
  piece.fu? &&
62
- board.matrix.column(to_piece_index[:x]).any? {|p| p.fu? && piece.player == p.player }
56
+ board.matrix.column(to[:x]).any? {|p| p.fu? && piece.teban == p.teban }
63
57
  end
64
58
  end
65
59
  end
@@ -2,11 +2,6 @@
2
2
 
3
3
  module ConsoleShogi
4
4
  class Player
5
- module Teban
6
- SENTE = :sente
7
- GOTE = :gote
8
- end
9
-
10
5
  attr_reader :teban, :komadai
11
6
 
12
7
  def initialize(teban: nil)
@@ -27,16 +22,13 @@ module ConsoleShogi
27
22
  komadai.pieces.any? {|p| p.class == Ohsho }
28
23
  end
29
24
 
30
- def capture_piece!(piece)
31
- @komadai.expand! unless komadai.have_space?
32
-
33
- piece = piece.original if piece.promoted?
25
+ def win_image
26
+ File.read("images/#{teban}_shori.png")
27
+ end
34
28
 
35
- piece.change_player!(self)
29
+ def capture_piece!(piece)
30
+ piece.teban = teban
36
31
  komadai.put(piece: piece)
37
32
  end
38
33
  end
39
-
40
- class NonPlayer < Player
41
- end
42
34
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConsoleShogi
4
+ module Teban
5
+ SENTE = :sente
6
+ GOTE = :gote
7
+ end
8
+ end
@@ -0,0 +1,80 @@
1
+ module ConsoleShogi
2
+ module Terminal
3
+ class Cursor
4
+ module Location
5
+ NONE = :none
6
+ BOARD = :board
7
+ SENTE_KOMADAI = :sente_komadai
8
+ GOTE_KOMADAI = :gote_komadai
9
+ end
10
+
11
+ TerminalPosition = Struct.new(:x, :y)
12
+ SquaresPosition = Struct.new(:x, :y, :location)
13
+
14
+ VERTICAL_DISTANCE = 1
15
+ HORIZONTAL_DISTANCE = 2
16
+ CURSOR_DIRECTIONS = %w(A B C D)
17
+
18
+ attr_reader :terminal_position, :squares_position
19
+
20
+ def initialize(terminal_index_x: 1, terminal_index_y: 1)
21
+ @terminal_position = TerminalPosition.new(x: 1, y: 1)
22
+ @squares_position = SquaresPosition.new(**calculate_squares_position)
23
+ end
24
+
25
+ def move(direction)
26
+ return unless CURSOR_DIRECTIONS.include?(direction)
27
+
28
+ distance =
29
+ case direction
30
+ when 'A', 'B'
31
+ VERTICAL_DISTANCE
32
+ when 'C', 'D'
33
+ HORIZONTAL_DISTANCE
34
+ end
35
+
36
+ print "\e[#{distance}#{direction}"
37
+
38
+ update_terminal_position!
39
+ end
40
+
41
+ private
42
+
43
+ def update_terminal_position!
44
+ positions = fetch_cursor_position_in_stdin
45
+
46
+ @terminal_position = TerminalPosition.new(x: positions[2].to_i, y: positions[1].to_i)
47
+ @squares_position = SquaresPosition.new(**calculate_squares_position)
48
+ end
49
+
50
+ def calculate_squares_position
51
+ case terminal_position.to_h
52
+ in x: 1..18, y: 1..9
53
+ {x: (terminal_position.x - 1) / HORIZONTAL_DISTANCE, y: terminal_position.y - 1, location: Location::BOARD}
54
+ in x: 21..38, y: 1..3
55
+ {x: (terminal_position.x - 21) / HORIZONTAL_DISTANCE, y: terminal_position.y - 1, location: Location::GOTE_KOMADAI}
56
+ in x: 21..38, y: 7..9
57
+ {x: (terminal_position.x - 21) / HORIZONTAL_DISTANCE, y: terminal_position.y - 7, location: Location::SENTE_KOMADAI}
58
+ else
59
+ {x: (terminal_position.x - 1) / HORIZONTAL_DISTANCE, y: terminal_position.y - 1, location: Location::NONE}
60
+ end
61
+ end
62
+
63
+ def fetch_cursor_position_in_stdin
64
+ stdout = ''
65
+
66
+ $stdin.raw do |stdin|
67
+ $stdout << "\e[6n"
68
+ $stdout.flush
69
+
70
+ # NOTE \e[n;mR という形式で現在位置が返ってくる
71
+ while (c = stdin.getc) != 'R'
72
+ stdout += c
73
+ end
74
+ end
75
+
76
+ stdout.match /(\d+);(\d+)/
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,30 @@
1
+ module ConsoleShogi
2
+ module Terminal
3
+ module DisplayArea
4
+ module Board
5
+ START_INDEX = {x: 1, y: 1}
6
+ END_INDEX = {x: 18, y: 9}
7
+ RANGE = {x: Range.new(START_INDEX[:x], END_INDEX[:x]), y: Range.new(START_INDEX[:y], END_INDEX[:y])}
8
+ end
9
+
10
+ module Komadai
11
+ module Gote
12
+ START_INDEX = {x: 21, y: 1}
13
+ END_INDEX = {x: 38, y: 3}
14
+ RANGE = {x: Range.new(START_INDEX[:x], END_INDEX[:x]), y: Range.new(START_INDEX[:y], END_INDEX[:y])}
15
+ end
16
+
17
+ module Sente
18
+ START_INDEX = {x: 21, y: 7}
19
+ END_INDEX = {x: 38, y: 9}
20
+ RANGE = {x: Range.new(START_INDEX[:x], END_INDEX[:x]), y: Range.new(START_INDEX[:y], END_INDEX[:y])}
21
+ end
22
+ end
23
+
24
+ module OutSide
25
+ START_INDEX = {x: 10, y: 1}
26
+ RANGE = {x: Range.new(START_INDEX[:x], nil), y: Range.new(START_INDEX[:y], nil)}
27
+ end
28
+ end
29
+ end
30
+ end