console-shogi 0.2.0 → 0.4.0

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.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +21 -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/images/history_button/left.png +0 -0
  67. data/images/history_button/play.png +0 -0
  68. data/images/history_button/right.png +0 -0
  69. data/lib/console_shogi/board.rb +5 -9
  70. data/lib/console_shogi/game.rb +98 -24
  71. data/lib/console_shogi/game_history.rb +60 -0
  72. data/lib/console_shogi/grid_position.rb +6 -0
  73. data/lib/console_shogi/komadai.rb +22 -18
  74. data/lib/console_shogi/new_board_builder.rb +41 -41
  75. data/lib/console_shogi/piece.rb +39 -23
  76. data/lib/console_shogi/piece_movement_checker.rb +46 -0
  77. data/lib/console_shogi/piece_mover.rb +21 -68
  78. data/lib/console_shogi/piece_mover_from_board.rb +57 -0
  79. data/lib/console_shogi/piece_mover_from_komadai.rb +51 -0
  80. data/lib/console_shogi/player.rb +5 -13
  81. data/lib/console_shogi/teban.rb +8 -0
  82. data/lib/console_shogi/terminal/cursor.rb +74 -0
  83. data/lib/console_shogi/terminal/display_area.rb +122 -0
  84. data/lib/console_shogi/terminal/operator.rb +249 -0
  85. data/lib/console_shogi/version.rb +1 -1
  86. data/lib/console_shogi.rb +11 -3
  87. metadata +110 -39
  88. data/images/gote/nonepiece.png +0 -0
  89. data/lib/console_shogi/piece_mover_on_komadai.rb +0 -65
  90. data/lib/console_shogi/terminal_operator.rb +0 -211
  91. /data/images/{gote/shori.png → gote_shori.png} +0 -0
  92. /data/images/{gote → nomal/gote}/fu.png +0 -0
  93. /data/images/{gote → nomal/gote}/gin.png +0 -0
  94. /data/images/{gote → nomal/gote}/gyoku.png +0 -0
  95. /data/images/{gote → nomal/gote}/hisha.png +0 -0
  96. /data/images/{gote → nomal/gote}/kaku.png +0 -0
  97. /data/images/{gote → nomal/gote}/keima.png +0 -0
  98. /data/images/{gote → nomal/gote}/kin.png +0 -0
  99. /data/images/{gote → nomal/gote}/kyosha.png +0 -0
  100. /data/images/{gote → nomal/gote}/narigin.png +0 -0
  101. /data/images/{gote → nomal/gote}/narikei.png +0 -0
  102. /data/images/{gote → nomal/gote}/narikyo.png +0 -0
  103. /data/images/{gote → nomal/gote}/ohsho.png +0 -0
  104. /data/images/{gote → nomal/gote}/ryu.png +0 -0
  105. /data/images/{gote → nomal/gote}/tokin.png +0 -0
  106. /data/images/{gote → nomal/gote}/uma.png +0 -0
  107. /data/images/{sente → nomal}/nonepiece.png +0 -0
  108. /data/images/{sente → nomal/sente}/fu.png +0 -0
  109. /data/images/{sente → nomal/sente}/gin.png +0 -0
  110. /data/images/{sente → nomal/sente}/gyoku.png +0 -0
  111. /data/images/{sente → nomal/sente}/hisha.png +0 -0
  112. /data/images/{sente → nomal/sente}/kaku.png +0 -0
  113. /data/images/{sente → nomal/sente}/keima.png +0 -0
  114. /data/images/{sente → nomal/sente}/kin.png +0 -0
  115. /data/images/{sente → nomal/sente}/kyosha.png +0 -0
  116. /data/images/{sente → nomal/sente}/narigin.png +0 -0
  117. /data/images/{sente → nomal/sente}/narikei.png +0 -0
  118. /data/images/{sente → nomal/sente}/narikyo.png +0 -0
  119. /data/images/{sente → nomal/sente}/ohsho.png +0 -0
  120. /data/images/{sente → nomal/sente}/ryu.png +0 -0
  121. /data/images/{sente → nomal/sente}/tokin.png +0 -0
  122. /data/images/{sente → nomal/sente}/uma.png +0 -0
  123. /data/images/{sente/shori.png → sente_shori.png} +0 -0
@@ -0,0 +1,122 @@
1
+ module ConsoleShogi
2
+ module Terminal
3
+ class DisplayArea
4
+ OTHERS = :others
5
+ BOARD = :board
6
+ SENTE_KOMADAI = :sente_komadai
7
+ GOTE_KOMADAI = :gote_komadai
8
+
9
+ Position = Struct.new(:x, :y)
10
+
11
+ class << self
12
+ def fetch_area(x:, y:)
13
+ [Board, Komadai::Gote, Komadai::Sente, History::Back, History::Forward, History::Resume, Infomation].each do |klass|
14
+ return klass if klass.in?(x: x, y: y)
15
+ end
16
+
17
+ Others
18
+ end
19
+
20
+ def start_position
21
+ self::START_POSITION
22
+ end
23
+
24
+ def end_position
25
+ self::END_POSITION
26
+ end
27
+
28
+ def name
29
+ self::NAME
30
+ end
31
+
32
+ def board?
33
+ Board == self
34
+ end
35
+
36
+ def komadai?
37
+ [Komadai::Gote, Komadai::Sente].include?(self)
38
+ end
39
+
40
+ def history?
41
+ [History::Back, History::Forward, History::Resume].include?(self)
42
+ end
43
+
44
+ def outside?
45
+ [History::Back, History::Forward, History::Resume, Infomation, Others].include?(self)
46
+ end
47
+
48
+ def in?(x:, y:)
49
+ Range.new(start_position.x, end_position.x).include?(x) &&
50
+ Range.new(start_position.y, end_position.y).include?(y)
51
+ end
52
+ end
53
+
54
+ class Board < DisplayArea
55
+ START_POSITION = Position.new(x: 1, y: 1)
56
+ END_POSITION = Position.new(x: 18, y: 9)
57
+ NAME = :board
58
+ end
59
+
60
+ module Komadai
61
+ class Gote < DisplayArea
62
+ START_POSITION = Position.new(x: 21, y: 1)
63
+ END_POSITION = Position.new(x: 38, y: 3)
64
+ NAME = :gote_komadai
65
+ end
66
+
67
+ class Sente < DisplayArea
68
+ START_POSITION = Position.new(x: 21, y: 7)
69
+ END_POSITION = Position.new(x: 38, y: 9)
70
+ NAME = :sente_komadai
71
+ end
72
+ end
73
+
74
+ class History < DisplayArea
75
+ START_POSITION = Position.new(x: 1, y: 10)
76
+ END_POSITION = Position.new(x: 6, y: 10)
77
+ NAME = :history
78
+
79
+ class << self
80
+ def back?
81
+ self == Back
82
+ end
83
+
84
+ def forward?
85
+ self == Forward
86
+ end
87
+
88
+ def resume?
89
+ self == Resume
90
+ end
91
+ end
92
+
93
+ class Back < History
94
+ START_POSITION = Position.new(x: 1, y: 10)
95
+ END_POSITION = Position.new(x: 2, y: 10)
96
+ end
97
+
98
+ class Forward < History
99
+ START_POSITION = Position.new(x: 3, y: 10)
100
+ END_POSITION = Position.new(x: 4, y: 10)
101
+ end
102
+
103
+ class Resume < History
104
+ START_POSITION = Position.new(x: 5, y: 10)
105
+ END_POSITION = Position.new(x: 6, y: 10)
106
+ end
107
+ end
108
+
109
+ class Infomation < DisplayArea
110
+ START_POSITION = Position.new(x: 1, y: 11)
111
+ END_POSITION = Position.new(x: 18, y: 15)
112
+ NAME = :infomation
113
+ end
114
+
115
+ class Others < DisplayArea
116
+ START_POSITION = Position.new(x: nil, y: nil)
117
+ END_POSITION = Position.new(x: nil, y: nil)
118
+ NAME = :others
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,249 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+ require 'tty-prompt'
5
+
6
+ module ConsoleShogi
7
+ module Terminal
8
+ class Operator
9
+ class << self
10
+ TEBAN = {
11
+ sente: '先手',
12
+ gote: '後手'
13
+ }
14
+
15
+ module EscapeSequence
16
+ RESET = "\e[0m"
17
+ SCREEN_CLEAR = "\e[2J"
18
+ SCREEN_CLEAR_AFTER_CURSOR = "\e[0J"
19
+ SCREEN_CLEAR_NOW_LINE = "\e[2K"
20
+ MOVE_START_POINT = "\e[1;1H"
21
+ MOVE_HISTORY_AREA = "\e[#{DisplayArea::History.start_position.y};#{DisplayArea::History.start_position.x}H"
22
+ MOVE_INFOMATION_AREA = "\e[#{DisplayArea::Infomation.start_position.y};#{DisplayArea::Infomation.start_position.x}H"
23
+ CURRENT_POSITION = "\e[6n"
24
+ MOVE_RIGHT_2 = "\e[2C"
25
+ end
26
+
27
+ def cursor
28
+ @cursor ||= Cursor.new
29
+ end
30
+
31
+ def image_height
32
+ @image_height ||= calculate_fit_image_height
33
+ end
34
+
35
+ def clear_scrren
36
+ print EscapeSequence::SCREEN_CLEAR
37
+
38
+ print EscapeSequence::MOVE_START_POINT
39
+ end
40
+
41
+ def print_board(board:, sente_komadai:, gote_komadai:)
42
+ print EscapeSequence::MOVE_START_POINT
43
+
44
+ board.matrix.row_vectors.each_with_index do |vector, i|
45
+ vector.each_with_index do |piece, j|
46
+ print_image(image: piece.image, height: image_height)
47
+ end
48
+
49
+ print "#{EscapeSequence::RESET}\n"
50
+ end
51
+
52
+ # NOTE 駒台を表示
53
+ print_komadai(komadai: sente_komadai, start_position: DisplayArea::Komadai::Sente.start_position)
54
+ print_komadai(komadai: gote_komadai, start_position: DisplayArea::Komadai::Gote.start_position)
55
+
56
+ back_to_cursor
57
+ end
58
+
59
+ # TODO 駒台の表示方法も考える
60
+ def print_diff_board(previous_board:, board:, sente_komadai:, gote_komadai:)
61
+ print EscapeSequence::MOVE_START_POINT
62
+
63
+ board.matrix.row_vectors.each_with_index do |vector, i|
64
+ vector.each_with_index do |piece, j|
65
+ if previous_board.matrix[i, j].nil? || previous_board.matrix[i, j].same?(piece)
66
+ print EscapeSequence::MOVE_RIGHT_2
67
+ else
68
+ print_image(image: piece.image, height: image_height)
69
+ end
70
+ end
71
+
72
+ print "#{EscapeSequence::RESET}\n"
73
+ end
74
+
75
+ # NOTE 駒台を表示
76
+ print_komadai(komadai: sente_komadai, start_position: DisplayArea::Komadai::Sente.start_position)
77
+ print_komadai(komadai: gote_komadai, start_position: DisplayArea::Komadai::Gote.start_position)
78
+
79
+ back_to_cursor
80
+ end
81
+
82
+ def print_start_history
83
+ print EscapeSequence::MOVE_INFOMATION_AREA
84
+ print EscapeSequence::SCREEN_CLEAR_AFTER_CURSOR
85
+
86
+ print '履歴モード'
87
+
88
+ back_to_cursor
89
+ end
90
+
91
+ def focus_piece(board:, cursor:)
92
+ piece = board.fetch_piece(x: cursor.grid_position.x, y: cursor.grid_position.y)
93
+
94
+ return if piece.nil?
95
+
96
+ print_image(image: piece.focused_image, height: image_height)
97
+
98
+ back_to_cursor
99
+ end
100
+
101
+ def deactive_piece(board:, previous_cursor:)
102
+ print "\e[#{previous_cursor.terminal_position.y};#{previous_cursor.terminal_position.x}H"
103
+
104
+ piece = board.fetch_piece(x: previous_cursor.grid_position.x, y: previous_cursor.grid_position.y)
105
+
106
+ print_image(image: piece.image, height: image_height) unless piece.nil?
107
+
108
+ back_to_cursor
109
+ end
110
+
111
+ def active_piece(board:, cursor:)
112
+ piece = board.fetch_piece(x: cursor.grid_position.x, y: cursor.grid_position.y)
113
+
114
+ return if piece.nil?
115
+
116
+ print_image(image: piece.active_image, height: image_height)
117
+
118
+ back_to_cursor
119
+ end
120
+
121
+ def select_promotion
122
+ print EscapeSequence::MOVE_INFOMATION_AREA
123
+
124
+ prompt = TTY::Prompt.new
125
+
126
+ prompt.select('成りますか?', show_help: :never) {|menu|
127
+ menu.choice '成る', true
128
+ menu.choice '成らない', false
129
+ }
130
+ end
131
+
132
+ def print_winner(player)
133
+ print "\e[4;7H"
134
+
135
+ print_image(image: player.win_image, height: image_height * 3)
136
+
137
+ print EscapeSequence::MOVE_INFOMATION_AREA
138
+ end
139
+
140
+ # TODO 見た目は後で直す
141
+ def print_teban(teban)
142
+ print EscapeSequence::MOVE_INFOMATION_AREA
143
+ print EscapeSequence::SCREEN_CLEAR_AFTER_CURSOR
144
+
145
+ print "手番 : #{TEBAN[teban.to_sym]}"
146
+
147
+ back_to_cursor
148
+ end
149
+
150
+ # TODO データの指定の仕方は後で整理する
151
+ def print_history_button
152
+ print EscapeSequence::MOVE_HISTORY_AREA
153
+ print EscapeSequence::SCREEN_CLEAR_NOW_LINE
154
+
155
+ print_image(image: File.read("images/history_button/left.png"), height: image_height)
156
+ print_image(image: File.read("images/history_button/right.png"), height: image_height)
157
+ print_image(image: File.read("images/history_button/play.png"), height: image_height)
158
+
159
+ back_to_cursor
160
+ end
161
+
162
+ private
163
+
164
+ IMAGE_HEIGHT_PIXEL = 240
165
+
166
+ # TODO 無理やりなので、実現方法を再考する
167
+ def calculate_fit_image_height
168
+ start_position = fetch_cursor_position_in_stdin
169
+ # NOTE NonePiece を選んでいることに意味はない
170
+ print_image(image: NonePiece.new.image)
171
+ end_position = fetch_cursor_position_in_stdin
172
+
173
+ fixed_height = IMAGE_HEIGHT_PIXEL / (end_position[1].to_i - start_position[1].to_i)
174
+
175
+ print EscapeSequence::SCREEN_CLEAR
176
+ # NOTE カーソルを1行1列に移動
177
+ print EscapeSequence::MOVE_START_POINT
178
+
179
+ fixed_height
180
+ end
181
+
182
+ # TODO view 用の Player 作って整理する
183
+ def print_komadai(komadai:, start_position:)
184
+ komadai.pieces.row_vectors.each_with_index do |row_pieces, i|
185
+ print "\e[#{start_position.y + i};#{start_position.x}H"
186
+
187
+ row_pieces.each do |p|
188
+ print_image(image: p.image, height: image_height)
189
+ end
190
+ end
191
+
192
+ print EscapeSequence::RESET
193
+ end
194
+
195
+ # TODO Cursor にも持っているので整理する
196
+ def fetch_cursor_position_in_stdin
197
+ stdout = ''
198
+
199
+ $stdin.raw do |stdin|
200
+ $stdout << EscapeSequence::CURRENT_POSITION
201
+ $stdout.flush
202
+
203
+ # NOTE \e[n;mR という形式で現在位置が返ってくる
204
+ while (c = stdin.getc) != 'R'
205
+ stdout += c
206
+ end
207
+ end
208
+
209
+ stdout.match /(\d+);(\d+)/
210
+ end
211
+
212
+ def back_to_cursor
213
+ print "\e[#{cursor.terminal_position.y};#{cursor.terminal_position.x}H"
214
+ end
215
+
216
+ # TODO 画像を表示するためのメソッド、場所検討
217
+ def print_image(image:, width: nil, height: nil)
218
+ encoded_image = Base64.strict_encode64(image)
219
+
220
+ print_osc
221
+ print "1337;File=inline=1"
222
+ print ";size=#{image.size}"
223
+ print ";name=#{encoded_image}"
224
+ print ";width=#{width}px" unless width.nil?
225
+ print ";height=#{height}px" unless height.nil?
226
+ print ":#{encoded_image}"
227
+ print_st
228
+ end
229
+
230
+ def print_osc
231
+ # NOTE \e] で始まるシーケンスは全てのターミナルで扱えるわけでは無い
232
+ if ENV['TERM'].start_with?('screen') || ENV['TERM'].start_with?('tmux')
233
+ print "\ePtmux;\e\e]"
234
+ else
235
+ print "\e]"
236
+ end
237
+ end
238
+
239
+ def print_st
240
+ if ENV['TERM'].start_with?('screen') || ENV['TERM'].start_with?('tmux')
241
+ print "\a\e\\"
242
+ else
243
+ print "\a"
244
+ end
245
+ end
246
+ end
247
+ end
248
+ end
249
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ConsoleShogi
4
- VERSION = '0.2.0'
4
+ VERSION = '0.4.0'
5
5
  end
data/lib/console_shogi.rb CHANGED
@@ -1,16 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'console_shogi/version'
4
- require_relative 'console_shogi/game'
5
4
  require_relative 'console_shogi/player'
6
5
  require_relative 'console_shogi/board'
7
6
  require_relative 'console_shogi/piece'
8
7
  require_relative 'console_shogi/komadai'
8
+ require_relative 'console_shogi/teban'
9
+ require_relative 'console_shogi/grid_position'
10
+
11
+ require_relative 'console_shogi/terminal/display_area'
12
+ require_relative 'console_shogi/terminal/operator'
13
+ require_relative 'console_shogi/terminal/cursor'
9
14
 
10
- require_relative 'console_shogi/terminal_operator'
15
+ require_relative 'console_shogi/game'
16
+ require_relative 'console_shogi/game_history'
11
17
  require_relative 'console_shogi/new_board_builder'
12
18
  require_relative 'console_shogi/piece_mover'
13
- require_relative 'console_shogi/piece_mover_on_komadai'
19
+ require_relative 'console_shogi/piece_mover_from_board'
20
+ require_relative 'console_shogi/piece_mover_from_komadai'
21
+ require_relative 'console_shogi/piece_movement_checker'
14
22
 
15
23
  module ConsoleShogi
16
24
  class Error < StandardError; end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: console-shogi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - pekepek
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-24 00:00:00.000000000 Z
11
+ date: 2023-06-09 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: You can play the Shogi in terminal
14
14
  email:
@@ -24,50 +24,121 @@ files:
24
24
  - README.md
25
25
  - Rakefile
26
26
  - exe/console-shogi
27
- - images/gote/fu.png
28
- - images/gote/gin.png
29
- - images/gote/gyoku.png
30
- - images/gote/hisha.png
31
- - images/gote/kaku.png
32
- - images/gote/keima.png
33
- - images/gote/kin.png
34
- - images/gote/kyosha.png
35
- - images/gote/narigin.png
36
- - images/gote/narikei.png
37
- - images/gote/narikyo.png
38
- - images/gote/nonepiece.png
39
- - images/gote/ohsho.png
40
- - images/gote/ryu.png
41
- - images/gote/shori.png
42
- - images/gote/tokin.png
43
- - images/gote/uma.png
44
- - images/sente/fu.png
45
- - images/sente/gin.png
46
- - images/sente/gyoku.png
47
- - images/sente/hisha.png
48
- - images/sente/kaku.png
49
- - images/sente/keima.png
50
- - images/sente/kin.png
51
- - images/sente/kyosha.png
52
- - images/sente/narigin.png
53
- - images/sente/narikei.png
54
- - images/sente/narikyo.png
55
- - images/sente/nonepiece.png
56
- - images/sente/ohsho.png
57
- - images/sente/ryu.png
58
- - images/sente/shori.png
59
- - images/sente/tokin.png
60
- - images/sente/uma.png
27
+ - images/active/gote/fu.png
28
+ - images/active/gote/gin.png
29
+ - images/active/gote/gyoku.png
30
+ - images/active/gote/hisha.png
31
+ - images/active/gote/kaku.png
32
+ - images/active/gote/keima.png
33
+ - images/active/gote/kin.png
34
+ - images/active/gote/kyosha.png
35
+ - images/active/gote/narigin.png
36
+ - images/active/gote/narikei.png
37
+ - images/active/gote/narikyo.png
38
+ - images/active/gote/ohsho.png
39
+ - images/active/gote/ryu.png
40
+ - images/active/gote/tokin.png
41
+ - images/active/gote/uma.png
42
+ - images/active/nonepiece.png
43
+ - images/active/sente/fu.png
44
+ - images/active/sente/gin.png
45
+ - images/active/sente/gyoku.png
46
+ - images/active/sente/hisha.png
47
+ - images/active/sente/kaku.png
48
+ - images/active/sente/keima.png
49
+ - images/active/sente/kin.png
50
+ - images/active/sente/kyosha.png
51
+ - images/active/sente/narigin.png
52
+ - images/active/sente/narikei.png
53
+ - images/active/sente/narikyo.png
54
+ - images/active/sente/ohsho.png
55
+ - images/active/sente/ryu.png
56
+ - images/active/sente/tokin.png
57
+ - images/active/sente/uma.png
58
+ - images/focused/gote/fu.png
59
+ - images/focused/gote/gin.png
60
+ - images/focused/gote/gyoku.png
61
+ - images/focused/gote/hisha.png
62
+ - images/focused/gote/kaku.png
63
+ - images/focused/gote/keima.png
64
+ - images/focused/gote/kin.png
65
+ - images/focused/gote/kyosha.png
66
+ - images/focused/gote/narigin.png
67
+ - images/focused/gote/narikei.png
68
+ - images/focused/gote/narikyo.png
69
+ - images/focused/gote/ohsho.png
70
+ - images/focused/gote/ryu.png
71
+ - images/focused/gote/tokin.png
72
+ - images/focused/gote/uma.png
73
+ - images/focused/nonepiece.png
74
+ - images/focused/sente/fu.png
75
+ - images/focused/sente/gin.png
76
+ - images/focused/sente/gyoku.png
77
+ - images/focused/sente/hisha.png
78
+ - images/focused/sente/kaku.png
79
+ - images/focused/sente/keima.png
80
+ - images/focused/sente/kin.png
81
+ - images/focused/sente/kyosha.png
82
+ - images/focused/sente/narigin.png
83
+ - images/focused/sente/narikei.png
84
+ - images/focused/sente/narikyo.png
85
+ - images/focused/sente/ohsho.png
86
+ - images/focused/sente/ryu.png
87
+ - images/focused/sente/tokin.png
88
+ - images/focused/sente/uma.png
89
+ - images/gote_shori.png
90
+ - images/history_button/left.png
91
+ - images/history_button/play.png
92
+ - images/history_button/right.png
93
+ - images/nomal/gote/fu.png
94
+ - images/nomal/gote/gin.png
95
+ - images/nomal/gote/gyoku.png
96
+ - images/nomal/gote/hisha.png
97
+ - images/nomal/gote/kaku.png
98
+ - images/nomal/gote/keima.png
99
+ - images/nomal/gote/kin.png
100
+ - images/nomal/gote/kyosha.png
101
+ - images/nomal/gote/narigin.png
102
+ - images/nomal/gote/narikei.png
103
+ - images/nomal/gote/narikyo.png
104
+ - images/nomal/gote/ohsho.png
105
+ - images/nomal/gote/ryu.png
106
+ - images/nomal/gote/tokin.png
107
+ - images/nomal/gote/uma.png
108
+ - images/nomal/nonepiece.png
109
+ - images/nomal/sente/fu.png
110
+ - images/nomal/sente/gin.png
111
+ - images/nomal/sente/gyoku.png
112
+ - images/nomal/sente/hisha.png
113
+ - images/nomal/sente/kaku.png
114
+ - images/nomal/sente/keima.png
115
+ - images/nomal/sente/kin.png
116
+ - images/nomal/sente/kyosha.png
117
+ - images/nomal/sente/narigin.png
118
+ - images/nomal/sente/narikei.png
119
+ - images/nomal/sente/narikyo.png
120
+ - images/nomal/sente/ohsho.png
121
+ - images/nomal/sente/ryu.png
122
+ - images/nomal/sente/tokin.png
123
+ - images/nomal/sente/uma.png
124
+ - images/sente_shori.png
61
125
  - lib/console_shogi.rb
62
126
  - lib/console_shogi/board.rb
63
127
  - lib/console_shogi/game.rb
128
+ - lib/console_shogi/game_history.rb
129
+ - lib/console_shogi/grid_position.rb
64
130
  - lib/console_shogi/komadai.rb
65
131
  - lib/console_shogi/new_board_builder.rb
66
132
  - lib/console_shogi/piece.rb
133
+ - lib/console_shogi/piece_movement_checker.rb
67
134
  - lib/console_shogi/piece_mover.rb
68
- - lib/console_shogi/piece_mover_on_komadai.rb
135
+ - lib/console_shogi/piece_mover_from_board.rb
136
+ - lib/console_shogi/piece_mover_from_komadai.rb
69
137
  - lib/console_shogi/player.rb
70
- - lib/console_shogi/terminal_operator.rb
138
+ - lib/console_shogi/teban.rb
139
+ - lib/console_shogi/terminal/cursor.rb
140
+ - lib/console_shogi/terminal/display_area.rb
141
+ - lib/console_shogi/terminal/operator.rb
71
142
  - lib/console_shogi/version.rb
72
143
  homepage: https://github.com/pekepek/console-shogi
73
144
  licenses:
@@ -91,7 +162,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
91
162
  - !ruby/object:Gem::Version
92
163
  version: '0'
93
164
  requirements: []
94
- rubygems_version: 3.4.10
165
+ rubygems_version: 3.4.13
95
166
  signing_key:
96
167
  specification_version: 4
97
168
  summary: You can play the Shogi in terminal
Binary file
@@ -1,65 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ConsoleShogi
4
- class PieceMoverOnKomadai
5
- def initialize(board:, komadai:, from:)
6
- @board = board
7
- @komadai = komadai
8
- # 駒台の index に直す必要がある
9
- @from_piece_index = from
10
- end
11
-
12
- def drop!
13
- return if target_piece.nil? || target_piece.none?
14
-
15
- while key = STDIN.getch
16
- if key == "\e" && STDIN.getch == "["
17
- key = STDIN.getch
18
-
19
- TerminalOperator.move_cursor(key)
20
- elsif key == "\r"
21
- to_piece_index = TerminalOperator.squares_index
22
-
23
- return if to_piece_index[:location] != :board
24
- return unless can_drop?(piece: target_piece, to_piece_index: to_piece_index)
25
-
26
- komadai.pick_up_piece!(from: from_piece_index)
27
- board.put_piece!(piece: target_piece, to: to_piece_index)
28
-
29
- return
30
- end
31
- end
32
- end
33
-
34
- private
35
-
36
- attr_reader :board, :komadai, :from_piece_index
37
-
38
- def target_piece
39
- @target_piece ||= komadai.fetch_piece(x: from_piece_index[:x], y: from_piece_index[:y])
40
- end
41
-
42
- def can_drop?(piece:, to_piece_index:)
43
- to_piece = board.fetch_piece(x: to_piece_index[:x], y: to_piece_index[:y])
44
-
45
- return false unless to_piece.none?
46
-
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)
54
-
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
- }
58
- end
59
-
60
- def nifu?(piece, to_piece_index)
61
- piece.fu? &&
62
- board.matrix.column(to_piece_index[:x]).any? {|p| p.fu? && piece.player == p.player }
63
- end
64
- end
65
- end