shogi-ruby 0.0.7 → 0.0.8
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/.travis.yml +9 -3
- data/NEWS.md +10 -0
- data/README.md +8 -2
- data/lib/shogi-ruby.rb +1 -0
- data/lib/shogi/board.rb +33 -221
- data/lib/shogi/cell.rb +8 -39
- data/lib/shogi/format/csa/board.rb +175 -0
- data/lib/shogi/format/csa/cell.rb +19 -0
- data/lib/shogi/format/usi/board.rb +35 -0
- data/lib/shogi/format/usi/cell.rb +35 -0
- data/lib/shogi/version.rb +1 -1
- data/shogi-ruby.gemspec +1 -1
- data/test/test-board.rb +22 -22
- metadata +24 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9d04141b8259822f9f675663b36789155a1cefdd
|
4
|
+
data.tar.gz: 41710950fea3ecf1fe1f8f0a64482bf1a6082874
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b58afe066c75e1aad5879b85b7970e3d1e7ece52c32d762d3e0d05870e920a66a539f0d44289706d5293c86e469431f14d56213138ac398f636629d77867a70d
|
7
|
+
data.tar.gz: dd95ab16a0e4becef1f23cf2d8957d363886156e2280cba54459f80591a46406e7da36b5e84b77bdbae6023faa6d3679554cea720af1e476a5e8ad97edeb655e
|
data/.travis.yml
CHANGED
data/NEWS.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# NEWS
|
2
2
|
|
3
|
+
## 0.0.8: 2015-05-31
|
4
|
+
|
5
|
+
### Changes
|
6
|
+
|
7
|
+
* Improvements
|
8
|
+
* Supported Bundler.require (require "shogi-ruby").
|
9
|
+
* Added Board.register and Cell.register as plugin system.
|
10
|
+
* Fixes
|
11
|
+
* Fixed error messages.
|
12
|
+
|
3
13
|
## 0.0.7: 2013-10-29
|
4
14
|
|
5
15
|
### Changes
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Shogi Library by Pure Ruby [](http://travis-ci.org/myokoym/shogi-ruby)
|
1
|
+
# Shogi Library by Pure Ruby [](http://travis-ci.org/myokoym/shogi-ruby) [](http://badge.fury.io/rb/shogi-ruby)
|
2
2
|
|
3
3
|
Ruby用の将棋ライブラリです。
|
4
4
|
|
@@ -11,20 +11,26 @@ Ruby用の将棋ライブラリです。
|
|
11
11
|
* コンピュータ将棋協会が推奨する標準形式です。
|
12
12
|
|
13
13
|
## 用途
|
14
|
+
|
14
15
|
### 向いていること
|
16
|
+
|
15
17
|
* 将棋盤の簡単なコンソール表示
|
16
18
|
* GUIアプリケーションの内部状態の管理
|
17
19
|
|
18
20
|
### 向いていないこと
|
21
|
+
|
19
22
|
* 速度的に、思考エンジンのデータ構造には向きません。
|
20
23
|
|
21
24
|
## 機能
|
25
|
+
|
22
26
|
### できること
|
27
|
+
|
23
28
|
* CSA形式で、将棋盤オブジェクトを作成、操作、表示
|
24
29
|
* 駒の動きが正しいかどうかのチェック
|
25
30
|
* 棋譜の管理
|
26
31
|
|
27
32
|
### まだできないこと
|
33
|
+
|
28
34
|
* 二歩チェック
|
29
35
|
* 行きどころのない駒のチェック
|
30
36
|
* 詰みチェック
|
@@ -47,7 +53,7 @@ Or install it yourself as:
|
|
47
53
|
|
48
54
|
## Ruby Version
|
49
55
|
|
50
|
-
Ruby 2.0.0 or later.
|
56
|
+
Ruby 2.0.0 or later.
|
51
57
|
|
52
58
|
## Usage
|
53
59
|
|
data/lib/shogi-ruby.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "shogi"
|
data/lib/shogi/board.rb
CHANGED
@@ -1,121 +1,31 @@
|
|
1
|
+
require "shogi/format/csa/board"
|
2
|
+
require "shogi/format/usi/board"
|
3
|
+
|
1
4
|
module Shogi
|
5
|
+
class Error < StandardError; end
|
6
|
+
class CodingError < Error; end
|
7
|
+
class FormatError < Error; end
|
8
|
+
class UndefinedPieceError < Error; end
|
9
|
+
class MoveError < Error; end
|
10
|
+
class MovementError < Error; end
|
11
|
+
|
2
12
|
class Board
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
class MovementError < Error; end
|
13
|
+
def self.register(name)
|
14
|
+
send(:include, Format.const_get(name).const_get("Board"))
|
15
|
+
end
|
16
|
+
self.register("CSA")
|
17
|
+
self.register("USI")
|
9
18
|
|
10
19
|
attr_accessor :default_format
|
11
20
|
attr_accessor :validate_movement
|
12
|
-
def initialize(default_format=:csa,
|
21
|
+
def initialize(default_format=:csa, table=nil)
|
13
22
|
@default_format = default_format
|
14
|
-
|
15
|
-
set_from_csa(position)
|
16
|
-
else
|
17
|
-
@position = default_position
|
18
|
-
@captured = []
|
19
|
-
end
|
23
|
+
set_from_csa(table || default_table)
|
20
24
|
@validate_movement = true
|
21
25
|
end
|
22
26
|
|
23
|
-
def to_csa
|
24
|
-
csa_rows = ""
|
25
|
-
|
26
|
-
@position.each_with_index do |row, i|
|
27
|
-
csa_row = ""
|
28
|
-
row.each do |cell|
|
29
|
-
if cell == ""
|
30
|
-
csa_row << " * "
|
31
|
-
else
|
32
|
-
csa_row << cell
|
33
|
-
end
|
34
|
-
end
|
35
|
-
csa_rows << "P#{i + 1}#{csa_row}\n"
|
36
|
-
end
|
37
|
-
|
38
|
-
sente = "P+"
|
39
|
-
gote = "P-"
|
40
|
-
@captured.each do |piece|
|
41
|
-
if piece[0] == "+"
|
42
|
-
sente << "00#{piece[1..2]}"
|
43
|
-
else
|
44
|
-
gote << "00#{piece[1..2]}"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
csa_rows << "#{sente}\n"
|
48
|
-
csa_rows << "#{gote}\n"
|
49
|
-
|
50
|
-
csa_rows
|
51
|
-
end
|
52
|
-
|
53
27
|
def set_from_csa(csa)
|
54
|
-
|
55
|
-
cell_pattern = '[+-][A-Z]{2}| \* '
|
56
|
-
csa_lines = csa.each_line.to_a
|
57
|
-
csa_lines.slice(0, 9).to_enum.with_index do |row, i|
|
58
|
-
position_row = []
|
59
|
-
row.chomp!
|
60
|
-
unless /\AP#{i + 1}(#{cell_pattern}){9}\z/ =~ row
|
61
|
-
raise FormatError, "Format Error: line P#{i + 1}"
|
62
|
-
end
|
63
|
-
row[2..28].scan(/#{cell_pattern}/) do |cell|
|
64
|
-
if cell == " * "
|
65
|
-
position_row << ""
|
66
|
-
else
|
67
|
-
position_row << cell
|
68
|
-
end
|
69
|
-
end
|
70
|
-
position << position_row
|
71
|
-
end
|
72
|
-
@position = position
|
73
|
-
|
74
|
-
captured = []
|
75
|
-
csa_lines.slice(9, 2).each do |captured_line|
|
76
|
-
captured_line.chomp!
|
77
|
-
unless /\AP[+-](00[A-Z]{2})*\z/ =~ captured_line
|
78
|
-
raise FormatError, "Format Error: captured piece line"
|
79
|
-
end
|
80
|
-
turn = captured_line[1]
|
81
|
-
captured_line[2..-1].scan(/00([A-Z]{2})/) do |cell|
|
82
|
-
captured << turn + cell[0]
|
83
|
-
end
|
84
|
-
end
|
85
|
-
@captured = captured
|
86
|
-
end
|
87
|
-
|
88
|
-
def to_usi
|
89
|
-
@position.map {|row|
|
90
|
-
usi_row = ""
|
91
|
-
space_count = 0
|
92
|
-
row.each do |cell|
|
93
|
-
if cell == ""
|
94
|
-
space_count += 1
|
95
|
-
else
|
96
|
-
if space_count > 0
|
97
|
-
usi_row << space_count.to_s
|
98
|
-
space_count = 0
|
99
|
-
end
|
100
|
-
usi = Piece.const_get(cell[1..2]).new.usi
|
101
|
-
if cell[0] == "-"
|
102
|
-
usi_row << usi.downcase
|
103
|
-
else
|
104
|
-
usi_row << usi
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
if space_count > 0
|
109
|
-
usi_row << space_count.to_s
|
110
|
-
space_count = 0
|
111
|
-
end
|
112
|
-
usi_row
|
113
|
-
}.join("/") << "\n"
|
114
|
-
end
|
115
|
-
|
116
|
-
def move_from_csa(movement)
|
117
|
-
$stderr.puts "warning: Shogi::Board#move_from_csa(movement) is deprecated. Use Shogi::Board#move(movement, :csa)"
|
118
|
-
move(movement, :csa)
|
28
|
+
@table, @captured = parse_from_csa(csa)
|
119
29
|
end
|
120
30
|
|
121
31
|
def move(movement_lines, format=@default_format)
|
@@ -129,7 +39,7 @@ module Shogi
|
|
129
39
|
def at(place)
|
130
40
|
array_x = to_array_x_from_shogi_x(place[0].to_i)
|
131
41
|
array_y = to_array_y_from_shogi_y(place[1].to_i)
|
132
|
-
@
|
42
|
+
@table[array_y][array_x]
|
133
43
|
end
|
134
44
|
|
135
45
|
def show(format=@default_format)
|
@@ -137,118 +47,20 @@ module Shogi
|
|
137
47
|
end
|
138
48
|
|
139
49
|
private
|
140
|
-
def
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
raise FormatError, "Wrong CSA format: #{csa}"
|
155
|
-
end
|
156
|
-
|
157
|
-
unless Piece.const_defined?(csa[5..6])
|
158
|
-
raise UndefinedPieceError, "Undefined piece: #{csa[5..6]}"
|
159
|
-
end
|
160
|
-
|
161
|
-
if csa[1..2] == "00"
|
162
|
-
before_piece = csa[0] + csa[5..6]
|
163
|
-
unless @captured.include?(before_piece)
|
164
|
-
raise MoveError, "Not captured piece: #{before_piece}"
|
165
|
-
end
|
166
|
-
before_cell = before_piece
|
167
|
-
before_piece = Piece.const_get(before_cell[1..2]).new
|
168
|
-
else
|
169
|
-
before_x = to_array_x_from_shogi_x(csa[1].to_i)
|
170
|
-
before_y = to_array_y_from_shogi_y(csa[2].to_i)
|
171
|
-
before_cell = @position[before_y][before_x]
|
172
|
-
if before_cell == ""
|
173
|
-
raise MoveError, "Before cell is blank"
|
174
|
-
end
|
175
|
-
before_piece = Piece.const_get(before_cell[1..2]).new
|
176
|
-
|
177
|
-
unless csa[0] == before_cell[0]
|
178
|
-
raise MoveError, "Not your piece: #{before_cell}"
|
179
|
-
end
|
180
|
-
unless csa[5..6] == before_cell[1..2]
|
181
|
-
after_piece = Piece.const_get(csa[5..6]).new
|
182
|
-
unless before_piece.promoter == after_piece.class
|
183
|
-
raise MoveError, "Don't promote: #{before_cell[1..2]} -> #{csa[5..6]}"
|
184
|
-
end
|
185
|
-
|
186
|
-
after_y = to_array_y_from_shogi_y(csa[4].to_i)
|
187
|
-
if csa[0] == "+"
|
188
|
-
unless after_y < 3 || before_y < 3
|
189
|
-
raise_movement_error("Don't promote this move: #{csa}")
|
190
|
-
end
|
191
|
-
else
|
192
|
-
unless after_y > 5 || before_y > 5
|
193
|
-
raise_movement_error("Don't promote this move: #{csa}")
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
after_x = to_array_x_from_shogi_x(csa[3].to_i)
|
200
|
-
after_y = to_array_y_from_shogi_y(csa[4].to_i)
|
201
|
-
after_cell = @position[after_y][after_x]
|
202
|
-
if csa[0] == after_cell[0]
|
203
|
-
raise MoveError, "Your piece on after cell: #{csa}"
|
204
|
-
end
|
205
|
-
|
206
|
-
if csa[1..2] == "00"
|
207
|
-
unless after_cell == ""
|
208
|
-
raise MoveError, "Exist piece on after cell"
|
209
|
-
end
|
210
|
-
else
|
211
|
-
if csa[0] == "+"
|
212
|
-
movement_x = after_x - before_x
|
213
|
-
movement_y = before_y - after_y
|
214
|
-
else
|
215
|
-
movement_x = before_x - after_x
|
216
|
-
movement_y = after_y - before_y
|
217
|
-
end
|
218
|
-
|
219
|
-
unless before_piece.move?(movement_x, movement_y)
|
220
|
-
raise_movement_error("Invalid movement: #{csa}")
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
unless after_cell == ""
|
225
|
-
after_piece = Piece.const_get(after_cell[1..2]).new
|
226
|
-
if after_piece.class.const_defined?(:CHILD)
|
227
|
-
@captured << "#{csa[0]}#{after_piece.class::CHILD}"
|
228
|
-
else
|
229
|
-
@captured << "#{csa[0]}#{after_cell[1..2]}"
|
230
|
-
end
|
231
|
-
end
|
232
|
-
@position[after_y][after_x] = "#{csa[0]}#{csa[5..6]}"
|
233
|
-
|
234
|
-
if csa[1..2] == "00"
|
235
|
-
used = nil
|
236
|
-
|
237
|
-
@captured.each_with_index do |captured_piece, i|
|
238
|
-
if captured_piece == before_cell
|
239
|
-
used = @captured.delete_at(i)
|
240
|
-
break
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
unless used == before_cell
|
245
|
-
raise CodingError, "[Bug] missing piece in captured"
|
246
|
-
end
|
247
|
-
else
|
248
|
-
@position[before_y][before_x] = ""
|
249
|
-
end
|
250
|
-
|
251
|
-
self
|
50
|
+
def default_table
|
51
|
+
<<-TABLE
|
52
|
+
P1-KY-KE-GI-KI-OU-KI-GI-KE-KY
|
53
|
+
P2 * -HI * * * * * -KA *
|
54
|
+
P3-FU-FU-FU-FU-FU-FU-FU-FU-FU
|
55
|
+
P4 * * * * * * * * *
|
56
|
+
P5 * * * * * * * * *
|
57
|
+
P6 * * * * * * * * *
|
58
|
+
P7+FU+FU+FU+FU+FU+FU+FU+FU+FU
|
59
|
+
P8 * +KA * * * * * +HI *
|
60
|
+
P9+KY+KE+GI+KI+OU+KI+GI+KE+KY
|
61
|
+
P+
|
62
|
+
P-
|
63
|
+
TABLE
|
252
64
|
end
|
253
65
|
|
254
66
|
def raise_movement_error(message)
|
data/lib/shogi/cell.rb
CHANGED
@@ -1,16 +1,13 @@
|
|
1
|
+
require "shogi/format/csa/cell"
|
2
|
+
require "shogi/format/usi/cell"
|
3
|
+
|
1
4
|
module Shogi
|
2
5
|
class Cell
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
"5" => "e",
|
9
|
-
"6" => "f",
|
10
|
-
"7" => "g",
|
11
|
-
"8" => "h",
|
12
|
-
"9" => "i",
|
13
|
-
}
|
6
|
+
def self.register(name)
|
7
|
+
send(:include, Format.const_get(name).const_get("Cell"))
|
8
|
+
end
|
9
|
+
self.register("CSA")
|
10
|
+
self.register("USI")
|
14
11
|
|
15
12
|
attr_reader :x, :y
|
16
13
|
attr_accessor :piece
|
@@ -21,33 +18,5 @@ module Shogi
|
|
21
18
|
@piece = piece
|
22
19
|
@turn = turn
|
23
20
|
end
|
24
|
-
|
25
|
-
def place_csa
|
26
|
-
"#{x}#{y}"
|
27
|
-
end
|
28
|
-
|
29
|
-
def place_usi
|
30
|
-
"#{x}#{USI_VERTICAL_LABELS[y]}"
|
31
|
-
end
|
32
|
-
|
33
|
-
def piece_csa
|
34
|
-
if @piece
|
35
|
-
"#{turn ? "+" : "-"}#{@piece.csa}"
|
36
|
-
else
|
37
|
-
" * "
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def piece_usi
|
42
|
-
if @piece
|
43
|
-
if @turn
|
44
|
-
@piece.usi
|
45
|
-
else
|
46
|
-
@piece.usi.downcase
|
47
|
-
end
|
48
|
-
else
|
49
|
-
1
|
50
|
-
end
|
51
|
-
end
|
52
21
|
end
|
53
22
|
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
module Shogi
|
2
|
+
module Format
|
3
|
+
module CSA
|
4
|
+
module Board
|
5
|
+
def to_csa
|
6
|
+
csa_rows = ""
|
7
|
+
|
8
|
+
@table.each_with_index do |row, i|
|
9
|
+
csa_row = ""
|
10
|
+
row.each do |cell|
|
11
|
+
if cell == ""
|
12
|
+
csa_row << " * "
|
13
|
+
else
|
14
|
+
csa_row << cell
|
15
|
+
end
|
16
|
+
end
|
17
|
+
csa_rows << "P#{i + 1}#{csa_row}\n"
|
18
|
+
end
|
19
|
+
|
20
|
+
sente = "P+"
|
21
|
+
gote = "P-"
|
22
|
+
@captured.each do |piece|
|
23
|
+
if piece[0] == "+"
|
24
|
+
sente << "00#{piece[1..2]}"
|
25
|
+
else
|
26
|
+
gote << "00#{piece[1..2]}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
csa_rows << "#{sente}\n"
|
30
|
+
csa_rows << "#{gote}\n"
|
31
|
+
|
32
|
+
csa_rows
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse_from_csa(csa)
|
36
|
+
table = []
|
37
|
+
cell_pattern = '[+-][A-Z]{2}| \* '
|
38
|
+
csa_lines = csa.each_line.to_a
|
39
|
+
csa_lines.slice(0, 9).to_enum.with_index do |row, i|
|
40
|
+
table_row = []
|
41
|
+
row.chomp!
|
42
|
+
unless /\AP#{i + 1}(#{cell_pattern}){9}\z/ =~ row
|
43
|
+
raise FormatError, "Format Error: line P#{i + 1}"
|
44
|
+
end
|
45
|
+
row[2..28].scan(/#{cell_pattern}/) do |cell|
|
46
|
+
if cell == " * "
|
47
|
+
table_row << ""
|
48
|
+
else
|
49
|
+
table_row << cell
|
50
|
+
end
|
51
|
+
end
|
52
|
+
table << table_row
|
53
|
+
end
|
54
|
+
|
55
|
+
captured = []
|
56
|
+
csa_lines.slice(9, 2).each do |captured_line|
|
57
|
+
captured_line.chomp!
|
58
|
+
unless /\AP[+-](00[A-Z]{2})*\z/ =~ captured_line
|
59
|
+
raise FormatError, "Invalid format: #{captured_line}"
|
60
|
+
end
|
61
|
+
turn = captured_line[1]
|
62
|
+
captured_line[2..-1].scan(/00([A-Z]{2})/) do |cell|
|
63
|
+
captured << turn + cell[0]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
[table, captured]
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
def move_by_csa(csa)
|
72
|
+
unless /\A[+-](00|[1-9]{2})[1-9]{2}[A-Z]{2}\z/ =~ csa
|
73
|
+
raise FormatError, "Invalid CSA format: #{csa}"
|
74
|
+
end
|
75
|
+
|
76
|
+
unless Piece.const_defined?(csa[5..6])
|
77
|
+
raise UndefinedPieceError, "Undefined piece: #{csa[5..6]}"
|
78
|
+
end
|
79
|
+
|
80
|
+
if csa[1..2] == "00"
|
81
|
+
before_piece = csa[0] + csa[5..6]
|
82
|
+
unless @captured.include?(before_piece)
|
83
|
+
raise MoveError, "Not captured piece: #{before_piece}"
|
84
|
+
end
|
85
|
+
before_cell = before_piece
|
86
|
+
before_piece = Piece.const_get(before_cell[1..2]).new
|
87
|
+
else
|
88
|
+
before_x = to_array_x_from_shogi_x(csa[1].to_i)
|
89
|
+
before_y = to_array_y_from_shogi_y(csa[2].to_i)
|
90
|
+
before_cell = @table[before_y][before_x]
|
91
|
+
if before_cell == ""
|
92
|
+
raise MoveError, "Before cell is blank"
|
93
|
+
end
|
94
|
+
before_piece = Piece.const_get(before_cell[1..2]).new
|
95
|
+
|
96
|
+
unless csa[0] == before_cell[0]
|
97
|
+
raise MoveError, "Not your piece: #{before_cell}"
|
98
|
+
end
|
99
|
+
unless csa[5..6] == before_cell[1..2]
|
100
|
+
after_piece = Piece.const_get(csa[5..6]).new
|
101
|
+
unless before_piece.promoter == after_piece.class
|
102
|
+
raise MoveError, "Can't promote: #{before_cell[1..2]} -> #{csa[5..6]}"
|
103
|
+
end
|
104
|
+
|
105
|
+
after_y = to_array_y_from_shogi_y(csa[4].to_i)
|
106
|
+
if csa[0] == "+"
|
107
|
+
unless after_y < 3 || before_y < 3
|
108
|
+
raise_movement_error("Can't promote: #{csa}")
|
109
|
+
end
|
110
|
+
else
|
111
|
+
unless after_y > 5 || before_y > 5
|
112
|
+
raise_movement_error("Can't promote: #{csa}")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
after_x = to_array_x_from_shogi_x(csa[3].to_i)
|
119
|
+
after_y = to_array_y_from_shogi_y(csa[4].to_i)
|
120
|
+
after_cell = @table[after_y][after_x]
|
121
|
+
if csa[0] == after_cell[0]
|
122
|
+
raise MoveError, "Your piece exists in the cell: #{csa}"
|
123
|
+
end
|
124
|
+
|
125
|
+
if csa[1..2] == "00"
|
126
|
+
unless after_cell == ""
|
127
|
+
raise MoveError, "A piece exists in the cell: #{csa}"
|
128
|
+
end
|
129
|
+
else
|
130
|
+
if csa[0] == "+"
|
131
|
+
movement_x = after_x - before_x
|
132
|
+
movement_y = before_y - after_y
|
133
|
+
else
|
134
|
+
movement_x = before_x - after_x
|
135
|
+
movement_y = after_y - before_y
|
136
|
+
end
|
137
|
+
|
138
|
+
unless before_piece.move?(movement_x, movement_y)
|
139
|
+
raise_movement_error("Invalid movement: #{csa}")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
unless after_cell == ""
|
144
|
+
after_piece = Piece.const_get(after_cell[1..2]).new
|
145
|
+
if after_piece.class.const_defined?(:CHILD)
|
146
|
+
@captured << "#{csa[0]}#{after_piece.class::CHILD}"
|
147
|
+
else
|
148
|
+
@captured << "#{csa[0]}#{after_cell[1..2]}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
@table[after_y][after_x] = "#{csa[0]}#{csa[5..6]}"
|
152
|
+
|
153
|
+
if csa[1..2] == "00"
|
154
|
+
used = nil
|
155
|
+
|
156
|
+
@captured.each_with_index do |captured_piece, i|
|
157
|
+
if captured_piece == before_cell
|
158
|
+
used = @captured.delete_at(i)
|
159
|
+
break
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
unless used == before_cell
|
164
|
+
raise CodingError, "[Bug] missing piece in captured"
|
165
|
+
end
|
166
|
+
else
|
167
|
+
@table[before_y][before_x] = ""
|
168
|
+
end
|
169
|
+
|
170
|
+
self
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Shogi
|
2
|
+
module Format
|
3
|
+
module USI
|
4
|
+
module Board
|
5
|
+
def to_usi
|
6
|
+
@table.map {|row|
|
7
|
+
usi_row = ""
|
8
|
+
space_count = 0
|
9
|
+
row.each do |cell|
|
10
|
+
if cell == ""
|
11
|
+
space_count += 1
|
12
|
+
else
|
13
|
+
if space_count > 0
|
14
|
+
usi_row << space_count.to_s
|
15
|
+
space_count = 0
|
16
|
+
end
|
17
|
+
usi = Piece.const_get(cell[1..2]).new.usi
|
18
|
+
if cell[0] == "-"
|
19
|
+
usi_row << usi.downcase
|
20
|
+
else
|
21
|
+
usi_row << usi
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
if space_count > 0
|
26
|
+
usi_row << space_count.to_s
|
27
|
+
space_count = 0
|
28
|
+
end
|
29
|
+
usi_row
|
30
|
+
}.join("/") << "\n"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Shogi
|
2
|
+
module Format
|
3
|
+
module USI
|
4
|
+
module Cell
|
5
|
+
USI_VERTICAL_LABELS = {
|
6
|
+
"1" => "a",
|
7
|
+
"2" => "b",
|
8
|
+
"3" => "c",
|
9
|
+
"4" => "d",
|
10
|
+
"5" => "e",
|
11
|
+
"6" => "f",
|
12
|
+
"7" => "g",
|
13
|
+
"8" => "h",
|
14
|
+
"9" => "i",
|
15
|
+
}
|
16
|
+
|
17
|
+
def place_usi
|
18
|
+
"#{x}#{USI_VERTICAL_LABELS[y]}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def piece_usi
|
22
|
+
if @piece
|
23
|
+
if @turn
|
24
|
+
@piece.usi
|
25
|
+
else
|
26
|
+
@piece.usi.downcase
|
27
|
+
end
|
28
|
+
else
|
29
|
+
1
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/shogi/version.rb
CHANGED
data/shogi-ruby.gemspec
CHANGED
@@ -21,6 +21,6 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_development_dependency("test-unit")
|
22
22
|
spec.add_development_dependency("test-unit-notify")
|
23
23
|
spec.add_development_dependency("test-unit-rr")
|
24
|
-
spec.add_development_dependency("bundler"
|
24
|
+
spec.add_development_dependency("bundler")
|
25
25
|
spec.add_development_dependency("rake")
|
26
26
|
end
|
data/test/test-board.rb
CHANGED
@@ -7,13 +7,13 @@ class BoardTest < Test::Unit::TestCase
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def test_initialize
|
10
|
-
rows = @board.instance_variable_get(:@
|
10
|
+
rows = @board.instance_variable_get(:@table)
|
11
11
|
assert_equal(9, rows.size)
|
12
12
|
assert_true(rows.all? {|row| row.size == 9 })
|
13
13
|
end
|
14
14
|
|
15
15
|
def test_initialize_csa
|
16
|
-
|
16
|
+
table = <<-EOT
|
17
17
|
P1 * * * * +HI * * -KE *
|
18
18
|
P2 * * * * * +KA-OU * -KY
|
19
19
|
P3 * * * * * * -FU-FU-FU
|
@@ -26,8 +26,8 @@ P9 * * * * * * * * *
|
|
26
26
|
P+00HI00GI00KE
|
27
27
|
P-
|
28
28
|
EOT
|
29
|
-
@board = Shogi::Board.new(:csa,
|
30
|
-
assert_equal(
|
29
|
+
@board = Shogi::Board.new(:csa, table)
|
30
|
+
assert_equal(table, @board.to_csa)
|
31
31
|
assert_nothing_raised do
|
32
32
|
@board.move("+0031HI")
|
33
33
|
end
|
@@ -47,7 +47,7 @@ P-
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def test_to_csa
|
50
|
-
before_state = @board.instance_variable_get(:@
|
50
|
+
before_state = @board.instance_variable_get(:@table).dup
|
51
51
|
assert_equal(<<-EOT, @board.to_csa)
|
52
52
|
P1-KY-KE-GI-KI-OU-KI-GI-KE-KY
|
53
53
|
P2 * -HI * * * * * -KA *
|
@@ -61,11 +61,11 @@ P9+KY+KE+GI+KI+OU+KI+GI+KE+KY
|
|
61
61
|
P+
|
62
62
|
P-
|
63
63
|
EOT
|
64
|
-
assert_equal(before_state, @board.instance_variable_get(:@
|
64
|
+
assert_equal(before_state, @board.instance_variable_get(:@table))
|
65
65
|
end
|
66
66
|
|
67
67
|
def test_show
|
68
|
-
before_state = @board.instance_variable_get(:@
|
68
|
+
before_state = @board.instance_variable_get(:@table).dup
|
69
69
|
s = ""
|
70
70
|
io = StringIO.new(s)
|
71
71
|
$stdout = io
|
@@ -87,7 +87,7 @@ P9+KY+KE+GI+KI+OU+KI+GI+KE+KY
|
|
87
87
|
P+
|
88
88
|
P-
|
89
89
|
EOT
|
90
|
-
assert_equal(before_state, @board.instance_variable_get(:@
|
90
|
+
assert_equal(before_state, @board.instance_variable_get(:@table))
|
91
91
|
end
|
92
92
|
|
93
93
|
def test_set_from_csa
|
@@ -112,11 +112,11 @@ P-
|
|
112
112
|
end
|
113
113
|
|
114
114
|
def test_to_usi
|
115
|
-
before_state = @board.instance_variable_get(:@
|
115
|
+
before_state = @board.instance_variable_get(:@table).dup
|
116
116
|
assert_equal(<<-EOT, @board.to_usi)
|
117
117
|
lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL
|
118
118
|
EOT
|
119
|
-
assert_equal(before_state, @board.instance_variable_get(:@
|
119
|
+
assert_equal(before_state, @board.instance_variable_get(:@table))
|
120
120
|
end
|
121
121
|
|
122
122
|
def test_at
|
@@ -126,25 +126,25 @@ lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL
|
|
126
126
|
def test_move_csa
|
127
127
|
@board.default_format = :csa
|
128
128
|
|
129
|
-
assert_raise Shogi::
|
129
|
+
assert_raise Shogi::FormatError do
|
130
130
|
@board.move("+27FU")
|
131
131
|
end
|
132
|
-
assert_raise Shogi::
|
132
|
+
assert_raise Shogi::UndefinedPieceError do
|
133
133
|
@board.move("+2726AA")
|
134
134
|
end
|
135
|
-
assert_raise Shogi::
|
135
|
+
assert_raise Shogi::MoveError do
|
136
136
|
assert_false(@board.move("+2726HI"))
|
137
137
|
end
|
138
|
-
assert_raise Shogi::
|
138
|
+
assert_raise Shogi::MoveError do
|
139
139
|
assert_false(@board.move("+2827HI"))
|
140
140
|
end
|
141
|
-
assert_raise Shogi::
|
141
|
+
assert_raise Shogi::MoveError do
|
142
142
|
assert_false(@board.move("+2625FU"))
|
143
143
|
end
|
144
|
-
assert_raise Shogi::
|
144
|
+
assert_raise Shogi::MovementError do
|
145
145
|
assert_false(@board.move("+2725FU"))
|
146
146
|
end
|
147
|
-
assert_raise Shogi::
|
147
|
+
assert_raise Shogi::MoveError do
|
148
148
|
assert_false(@board.move("-4131KI"))
|
149
149
|
end
|
150
150
|
|
@@ -229,7 +229,7 @@ P-00KA
|
|
229
229
|
def test_move_csa_promote
|
230
230
|
@board.move("+7776FU", :csa)
|
231
231
|
@board.move("-3334FU", :csa)
|
232
|
-
assert_raise Shogi::
|
232
|
+
assert_raise Shogi::MovementError do
|
233
233
|
assert_false(@board.move("+2726TO", :csa))
|
234
234
|
end
|
235
235
|
assert_nothing_raised do
|
@@ -321,7 +321,7 @@ P-00KA
|
|
321
321
|
end
|
322
322
|
|
323
323
|
def test_move_csa_promote_to_7
|
324
|
-
|
324
|
+
table = <<-EOT
|
325
325
|
P1 * * * * * * * * *
|
326
326
|
P2 * * * * * * * * *
|
327
327
|
P3 * * * * * * * * *
|
@@ -334,14 +334,14 @@ P9 * * * * * * * * *
|
|
334
334
|
P+
|
335
335
|
P-
|
336
336
|
EOT
|
337
|
-
@board = Shogi::Board.new(:csa,
|
337
|
+
@board = Shogi::Board.new(:csa, table)
|
338
338
|
assert_nothing_raised do
|
339
339
|
@board.move("-5657TO", :csa)
|
340
340
|
end
|
341
341
|
end
|
342
342
|
|
343
343
|
def test_move_csa_promote_from_7
|
344
|
-
|
344
|
+
table = <<-EOT
|
345
345
|
P1 * * * * * * * * *
|
346
346
|
P2 * * * * * * * * *
|
347
347
|
P3 * * * * * * * * *
|
@@ -354,7 +354,7 @@ P9 * * * * * * * * *
|
|
354
354
|
P+
|
355
355
|
P-
|
356
356
|
EOT
|
357
|
-
@board = Shogi::Board.new(:csa,
|
357
|
+
@board = Shogi::Board.new(:csa, table)
|
358
358
|
assert_nothing_raised do
|
359
359
|
@board.move("-5746NG", :csa)
|
360
360
|
end
|
metadata
CHANGED
@@ -1,83 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shogi-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masafumi Yokoyama
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-05-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: test-unit
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: test-unit-notify
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: test-unit-rr
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: bundler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rake
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
description: A Shogi library by pure Ruby. It supports CSA format.
|
@@ -87,17 +87,22 @@ executables: []
|
|
87
87
|
extensions: []
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
|
-
- .gitignore
|
91
|
-
- .travis.yml
|
90
|
+
- ".gitignore"
|
91
|
+
- ".travis.yml"
|
92
92
|
- Gemfile
|
93
93
|
- LICENSE.txt
|
94
94
|
- NEWS.ja.md
|
95
95
|
- NEWS.md
|
96
96
|
- README.md
|
97
97
|
- Rakefile
|
98
|
+
- lib/shogi-ruby.rb
|
98
99
|
- lib/shogi.rb
|
99
100
|
- lib/shogi/board.rb
|
100
101
|
- lib/shogi/cell.rb
|
102
|
+
- lib/shogi/format/csa/board.rb
|
103
|
+
- lib/shogi/format/csa/cell.rb
|
104
|
+
- lib/shogi/format/usi/board.rb
|
105
|
+
- lib/shogi/format/usi/cell.rb
|
101
106
|
- lib/shogi/game.rb
|
102
107
|
- lib/shogi/piece.rb
|
103
108
|
- lib/shogi/piece/base.rb
|
@@ -119,17 +124,17 @@ require_paths:
|
|
119
124
|
- lib
|
120
125
|
required_ruby_version: !ruby/object:Gem::Requirement
|
121
126
|
requirements:
|
122
|
-
- -
|
127
|
+
- - ">="
|
123
128
|
- !ruby/object:Gem::Version
|
124
129
|
version: '0'
|
125
130
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
131
|
requirements:
|
127
|
-
- -
|
132
|
+
- - ">="
|
128
133
|
- !ruby/object:Gem::Version
|
129
134
|
version: '0'
|
130
135
|
requirements: []
|
131
136
|
rubyforge_project:
|
132
|
-
rubygems_version: 2.
|
137
|
+
rubygems_version: 2.2.2
|
133
138
|
signing_key:
|
134
139
|
specification_version: 4
|
135
140
|
summary: Shogi Library by Pure Ruby
|