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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +19 -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 +102 -37
- 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
|