console-shogi 0.1.0 → 0.3.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +19 -0
- data/exe/console-shogi +7 -0
- data/images/active/gote/fu.png +0 -0
- data/images/active/gote/gin.png +0 -0
- data/images/active/gote/gyoku.png +0 -0
- data/images/active/gote/hisha.png +0 -0
- data/images/active/gote/kaku.png +0 -0
- data/images/active/gote/keima.png +0 -0
- data/images/active/gote/kin.png +0 -0
- data/images/active/gote/kyosha.png +0 -0
- data/images/active/gote/narigin.png +0 -0
- data/images/active/gote/narikei.png +0 -0
- data/images/active/gote/narikyo.png +0 -0
- data/images/active/gote/ohsho.png +0 -0
- data/images/active/gote/ryu.png +0 -0
- data/images/active/gote/tokin.png +0 -0
- data/images/active/gote/uma.png +0 -0
- data/images/active/nonepiece.png +0 -0
- data/images/active/sente/fu.png +0 -0
- data/images/active/sente/gin.png +0 -0
- data/images/active/sente/gyoku.png +0 -0
- data/images/active/sente/hisha.png +0 -0
- data/images/active/sente/kaku.png +0 -0
- data/images/active/sente/keima.png +0 -0
- data/images/active/sente/kin.png +0 -0
- data/images/active/sente/kyosha.png +0 -0
- data/images/active/sente/narigin.png +0 -0
- data/images/active/sente/narikei.png +0 -0
- data/images/active/sente/narikyo.png +0 -0
- data/images/active/sente/ohsho.png +0 -0
- data/images/active/sente/ryu.png +0 -0
- data/images/active/sente/tokin.png +0 -0
- data/images/active/sente/uma.png +0 -0
- data/images/focused/gote/fu.png +0 -0
- data/images/focused/gote/gin.png +0 -0
- data/images/focused/gote/gyoku.png +0 -0
- data/images/focused/gote/hisha.png +0 -0
- data/images/focused/gote/kaku.png +0 -0
- data/images/focused/gote/keima.png +0 -0
- data/images/focused/gote/kin.png +0 -0
- data/images/focused/gote/kyosha.png +0 -0
- data/images/focused/gote/narigin.png +0 -0
- data/images/focused/gote/narikei.png +0 -0
- data/images/focused/gote/narikyo.png +0 -0
- data/images/focused/gote/ohsho.png +0 -0
- data/images/focused/gote/ryu.png +0 -0
- data/images/focused/gote/tokin.png +0 -0
- data/images/focused/gote/uma.png +0 -0
- data/images/focused/nonepiece.png +0 -0
- data/images/focused/sente/fu.png +0 -0
- data/images/focused/sente/gin.png +0 -0
- data/images/focused/sente/gyoku.png +0 -0
- data/images/focused/sente/hisha.png +0 -0
- data/images/focused/sente/kaku.png +0 -0
- data/images/focused/sente/keima.png +0 -0
- data/images/focused/sente/kin.png +0 -0
- data/images/focused/sente/kyosha.png +0 -0
- data/images/focused/sente/narigin.png +0 -0
- data/images/focused/sente/narikei.png +0 -0
- data/images/focused/sente/narikyo.png +0 -0
- data/images/focused/sente/ohsho.png +0 -0
- data/images/focused/sente/ryu.png +0 -0
- data/images/focused/sente/tokin.png +0 -0
- data/images/focused/sente/uma.png +0 -0
- data/lib/console_shogi/board.rb +5 -9
- data/lib/console_shogi/game.rb +118 -19
- data/lib/console_shogi/komadai.rb +11 -9
- data/lib/console_shogi/new_board_builder.rb +41 -41
- data/lib/console_shogi/piece.rb +34 -23
- data/lib/console_shogi/piece_movement_checker.rb +46 -0
- data/lib/console_shogi/piece_mover.rb +31 -48
- data/lib/console_shogi/piece_mover_on_komadai.rb +30 -36
- data/lib/console_shogi/player.rb +5 -13
- data/lib/console_shogi/teban.rb +8 -0
- data/lib/console_shogi/terminal/cursor.rb +80 -0
- data/lib/console_shogi/terminal/display_area.rb +30 -0
- data/lib/console_shogi/terminal/operator.rb +209 -0
- data/lib/console_shogi/version.rb +1 -1
- data/lib/console_shogi.rb +6 -1
- metadata +105 -38
- data/images/gote/nonepiece.png +0 -0
- data/lib/console_shogi/terminal_operator.rb +0 -211
- /data/images/{gote/shori.png → gote_shori.png} +0 -0
- /data/images/{gote → nomal/gote}/fu.png +0 -0
- /data/images/{gote → nomal/gote}/gin.png +0 -0
- /data/images/{gote → nomal/gote}/gyoku.png +0 -0
- /data/images/{gote → nomal/gote}/hisha.png +0 -0
- /data/images/{gote → nomal/gote}/kaku.png +0 -0
- /data/images/{gote → nomal/gote}/keima.png +0 -0
- /data/images/{gote → nomal/gote}/kin.png +0 -0
- /data/images/{gote → nomal/gote}/kyosha.png +0 -0
- /data/images/{gote → nomal/gote}/narigin.png +0 -0
- /data/images/{gote → nomal/gote}/narikei.png +0 -0
- /data/images/{gote → nomal/gote}/narikyo.png +0 -0
- /data/images/{gote → nomal/gote}/ohsho.png +0 -0
- /data/images/{gote → nomal/gote}/ryu.png +0 -0
- /data/images/{gote → nomal/gote}/tokin.png +0 -0
- /data/images/{gote → nomal/gote}/uma.png +0 -0
- /data/images/{sente → nomal}/nonepiece.png +0 -0
- /data/images/{sente → nomal/sente}/fu.png +0 -0
- /data/images/{sente → nomal/sente}/gin.png +0 -0
- /data/images/{sente → nomal/sente}/gyoku.png +0 -0
- /data/images/{sente → nomal/sente}/hisha.png +0 -0
- /data/images/{sente → nomal/sente}/kaku.png +0 -0
- /data/images/{sente → nomal/sente}/keima.png +0 -0
- /data/images/{sente → nomal/sente}/kin.png +0 -0
- /data/images/{sente → nomal/sente}/kyosha.png +0 -0
- /data/images/{sente → nomal/sente}/narigin.png +0 -0
- /data/images/{sente → nomal/sente}/narikei.png +0 -0
- /data/images/{sente → nomal/sente}/narikyo.png +0 -0
- /data/images/{sente → nomal/sente}/ohsho.png +0 -0
- /data/images/{sente → nomal/sente}/ryu.png +0 -0
- /data/images/{sente → nomal/sente}/tokin.png +0 -0
- /data/images/{sente → nomal/sente}/uma.png +0 -0
- /data/images/{sente/shori.png → sente_shori.png} +0 -0
data/lib/console_shogi/piece.rb
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
module ConsoleShogi
|
4
4
|
class Piece
|
5
|
-
|
5
|
+
attr_accessor :teban
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
@
|
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
|
-
|
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
|
42
|
-
self::class
|
33
|
+
def active_image
|
34
|
+
File.read("images/active/#{teban}/#{self::class.name.split('::').last.downcase}.png")
|
43
35
|
end
|
44
36
|
|
45
|
-
def
|
46
|
-
self::class
|
37
|
+
def focused_image
|
38
|
+
File.read("images/focused/#{teban}/#{self::class.name.split('::').last.downcase}.png")
|
47
39
|
end
|
48
40
|
|
49
|
-
def
|
50
|
-
self::class ==
|
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
|
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
|
80
|
-
|
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 :
|
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
|
-
@
|
7
|
+
@player = player
|
8
|
+
@from = from
|
9
|
+
@to = to
|
10
|
+
@moved_piece = false
|
8
11
|
end
|
9
12
|
|
10
13
|
def move!
|
11
|
-
|
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
|
-
|
35
|
-
|
36
|
-
end
|
17
|
+
def moved_piece?
|
18
|
+
@moved_piece
|
37
19
|
end
|
38
20
|
|
39
|
-
|
40
|
-
return false unless board.within_range?(x: to_piece_index[:x], y: to_piece_index[:y])
|
21
|
+
private
|
41
22
|
|
42
|
-
|
23
|
+
attr_reader :board, :player, :from, :to
|
43
24
|
|
44
|
-
|
25
|
+
def from_piece
|
26
|
+
@from_piece ||= board.fetch_piece(x: from[:x], y: from[:y])
|
27
|
+
end
|
45
28
|
|
46
|
-
|
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
|
33
|
+
return false unless piece_movement_checker.can_move?
|
49
34
|
|
50
|
-
|
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
|
-
|
53
|
-
|
38
|
+
board.move_piece!(
|
39
|
+
from: {x: from[:x], y: from[:y]},
|
40
|
+
to: {x: to[:x], y: to[:y]}
|
41
|
+
)
|
54
42
|
|
55
|
-
|
56
|
-
|
43
|
+
# TODO とりあえずここに実装してしまっている。整理したい
|
44
|
+
return true unless can_promote?(from_piece, from, to)
|
57
45
|
|
58
|
-
|
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
|
-
|
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.
|
58
|
+
if piece.teban == Teban::SENTE
|
76
59
|
from[:y].between?(0, 2) || to[:y].between?(0, 2)
|
77
|
-
elsif piece.
|
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
|
-
@
|
9
|
+
@from = from
|
10
|
+
@to = to
|
11
|
+
@moved_piece = false
|
10
12
|
end
|
11
13
|
|
12
|
-
def
|
13
|
-
|
14
|
+
def move!
|
15
|
+
@moved_piece = move_piece!
|
16
|
+
end
|
14
17
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
+
def moved_piece?
|
19
|
+
@moved_piece
|
20
|
+
end
|
18
21
|
|
19
|
-
|
20
|
-
elsif key == "\r"
|
21
|
-
to_piece_index = TerminalOperator.squares_index
|
22
|
+
private
|
22
23
|
|
23
|
-
|
24
|
-
return unless can_drop?(piece: target_piece, to_piece_index: to_piece_index)
|
24
|
+
attr_reader :board, :komadai, :from, :to
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
def move_piece!
|
27
|
+
return false if from_piece.nil? || from_piece.none?
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
33
|
+
komadai.pick_up_piece!(from: from)
|
34
|
+
board.put_piece!(piece: from_piece, to: to)
|
35
35
|
|
36
|
-
|
36
|
+
true
|
37
|
+
end
|
37
38
|
|
38
|
-
def
|
39
|
-
@
|
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:,
|
43
|
-
to_piece = board.fetch_piece(x:
|
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,
|
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
|
-
|
56
|
-
|
57
|
-
}
|
50
|
+
# TODO 動かせない場所に打つことはできないようにする
|
51
|
+
true
|
58
52
|
end
|
59
53
|
|
60
|
-
def nifu?(piece,
|
54
|
+
def nifu?(piece, to)
|
61
55
|
piece.fu? &&
|
62
|
-
board.matrix.column(
|
56
|
+
board.matrix.column(to[:x]).any? {|p| p.fu? && piece.teban == p.teban }
|
63
57
|
end
|
64
58
|
end
|
65
59
|
end
|
data/lib/console_shogi/player.rb
CHANGED
@@ -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
|
31
|
-
|
32
|
-
|
33
|
-
piece = piece.original if piece.promoted?
|
25
|
+
def win_image
|
26
|
+
File.read("images/#{teban}_shori.png")
|
27
|
+
end
|
34
28
|
|
35
|
-
|
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,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
|