RubyShogi 0.1
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 +7 -0
- data/bin/ruby_shogi +11 -0
- data/lib/ruby_shogi.rb +7 -0
- data/lib/ruby_shogi/bench.rb +127 -0
- data/lib/ruby_shogi/board.rb +451 -0
- data/lib/ruby_shogi/cmd.rb +188 -0
- data/lib/ruby_shogi/engine.rb +276 -0
- data/lib/ruby_shogi/eval.rb +102 -0
- data/lib/ruby_shogi/history.rb +63 -0
- data/lib/ruby_shogi/mgen.rb +169 -0
- data/lib/ruby_shogi/mgen_black.rb +238 -0
- data/lib/ruby_shogi/mgen_white.rb +237 -0
- data/lib/ruby_shogi/perft.rb +87 -0
- data/lib/ruby_shogi/ruby_shogi.rb +66 -0
- data/lib/ruby_shogi/tactics.rb +33 -0
- data/lib/ruby_shogi/tokens.rb +42 -0
- data/lib/ruby_shogi/utils.rb +15 -0
- data/lib/ruby_shogi/xboard.rb +117 -0
- data/lib/ruby_shogi/zobrist.rb +25 -0
- metadata +62 -0
@@ -0,0 +1,102 @@
|
|
1
|
+
##
|
2
|
+
# RubyShogi, a Shogi Engine
|
3
|
+
# Author: Toni Helminen
|
4
|
+
# License: GPLv3
|
5
|
+
##
|
6
|
+
|
7
|
+
module RubyShogi
|
8
|
+
|
9
|
+
module Eval
|
10
|
+
# https://en.wikipedia.org/wiki/Shogi_strategy#Relative_piece_value
|
11
|
+
MATERIAL_SCORE = {
|
12
|
+
1 => 1,
|
13
|
+
2 => 4.2,
|
14
|
+
3 => 4.3,
|
15
|
+
4 => 6.3,
|
16
|
+
5 => 4.5,
|
17
|
+
6 => 6.4,
|
18
|
+
7 => 6.4,
|
19
|
+
8 => 6.7,
|
20
|
+
9 => 6.9,
|
21
|
+
10 => 8.9,
|
22
|
+
11 => 11.5,
|
23
|
+
12 => 10.4,
|
24
|
+
13 => 13,
|
25
|
+
14 => 0
|
26
|
+
}
|
27
|
+
|
28
|
+
MATERIAL_HAND_SCORE = {
|
29
|
+
1 => 1.15,
|
30
|
+
3 => 4.8,
|
31
|
+
5 => 5.1,
|
32
|
+
7 => 7.2,
|
33
|
+
9 => 7.8,
|
34
|
+
10 => 11.10,
|
35
|
+
12 => 10.4,
|
36
|
+
13 => 12.7
|
37
|
+
}
|
38
|
+
|
39
|
+
CENTRAL_BONUS = [1,2,3,4,5,4,3,2,1].freeze
|
40
|
+
|
41
|
+
CENTRAL_SCORE = {
|
42
|
+
1 => 0,
|
43
|
+
2 => 2,
|
44
|
+
3 => 1,
|
45
|
+
4 => 2,
|
46
|
+
5 => 1,
|
47
|
+
6 => 2,
|
48
|
+
7 => 2,
|
49
|
+
8 => 2,
|
50
|
+
9 => 2,
|
51
|
+
10 => 2,
|
52
|
+
11 => 2,
|
53
|
+
12 => 2,
|
54
|
+
13 => 2,
|
55
|
+
14 => 0
|
56
|
+
}
|
57
|
+
|
58
|
+
EVAL_PST_MG = []
|
59
|
+
|
60
|
+
def Eval.init
|
61
|
+
return if EVAL_PST_MG.length > 0
|
62
|
+
14.times do |i|
|
63
|
+
arr = []
|
64
|
+
81.times do |j|
|
65
|
+
score = 0.1 * (MATERIAL_SCORE[i + 1] + 2 * CENTRAL_SCORE[i + 1] * (CENTRAL_BONUS[j % 9 ] + CENTRAL_BONUS[j / 9]))
|
66
|
+
arr.push(score)
|
67
|
+
end
|
68
|
+
EVAL_PST_MG.push(arr)
|
69
|
+
end
|
70
|
+
EVAL_PST_MG.freeze
|
71
|
+
end
|
72
|
+
|
73
|
+
def Eval.eval(board)
|
74
|
+
score = 0
|
75
|
+
board.brd.each_with_index do |p, i|
|
76
|
+
score += case p
|
77
|
+
when 1..14 then EVAL_PST_MG[p - 1][i]
|
78
|
+
when -14..-1 then EVAL_PST_MG[-p - 1][i]
|
79
|
+
else
|
80
|
+
0
|
81
|
+
end
|
82
|
+
end
|
83
|
+
0.01 * score
|
84
|
+
end
|
85
|
+
|
86
|
+
def Eval.material(board)
|
87
|
+
score = 0
|
88
|
+
board.brd.each do |p|
|
89
|
+
score += case p
|
90
|
+
when 1..14 then MATERIAL_SCORE[p]
|
91
|
+
when -14..-1 then -MATERIAL_SCORE[-p]
|
92
|
+
else
|
93
|
+
0
|
94
|
+
end
|
95
|
+
end
|
96
|
+
board.white_pocket.each { |p| score += MATERIAL_HAND_SCORE[p] }
|
97
|
+
board.black_pocket.each { |p| score -= MATERIAL_HAND_SCORE[-p] }
|
98
|
+
score
|
99
|
+
end
|
100
|
+
end # module Eval
|
101
|
+
|
102
|
+
end # module RubyShogi
|
@@ -0,0 +1,63 @@
|
|
1
|
+
##
|
2
|
+
# RubyShogi, a Shogi Engine
|
3
|
+
# Author: Toni Helminen
|
4
|
+
# License: GPLv3
|
5
|
+
##
|
6
|
+
|
7
|
+
module RubyShogi
|
8
|
+
|
9
|
+
class History
|
10
|
+
def initialize
|
11
|
+
reset
|
12
|
+
end
|
13
|
+
|
14
|
+
def reset
|
15
|
+
@data = []
|
16
|
+
@pos = -1
|
17
|
+
end
|
18
|
+
|
19
|
+
def debug
|
20
|
+
puts "@pos: #{@pos} .. @data: #{@data.length}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def remove
|
24
|
+
if @pos > 1
|
25
|
+
board = @data[@pos - 2]
|
26
|
+
@pos -= 2
|
27
|
+
return board
|
28
|
+
end
|
29
|
+
@data.last
|
30
|
+
end
|
31
|
+
|
32
|
+
def undo
|
33
|
+
if @pos > 0
|
34
|
+
board = @data[@pos - 1]
|
35
|
+
@pos -= 1
|
36
|
+
return board
|
37
|
+
end
|
38
|
+
@data.last
|
39
|
+
end
|
40
|
+
|
41
|
+
def add(board)
|
42
|
+
@data.push(board)
|
43
|
+
@pos += 1
|
44
|
+
end
|
45
|
+
|
46
|
+
def draw_too_long?
|
47
|
+
@data.length > 900 # I give up...
|
48
|
+
end
|
49
|
+
|
50
|
+
def is_draw?(board, repsn = 4)
|
51
|
+
len, hash = @data.length, board.hash
|
52
|
+
i, n, reps = len - 1, 0, 0
|
53
|
+
while i > 0
|
54
|
+
break if n >= 100
|
55
|
+
reps += 1 if hash == @data[i].hash
|
56
|
+
n, i = n + 1, i - 1
|
57
|
+
return true if reps >= repsn
|
58
|
+
end
|
59
|
+
false
|
60
|
+
end
|
61
|
+
end # class History
|
62
|
+
|
63
|
+
end # module RubyShogi
|
@@ -0,0 +1,169 @@
|
|
1
|
+
##
|
2
|
+
# RubyShogi, a Shogi Engine
|
3
|
+
# Author: Toni Helminen
|
4
|
+
# License: GPLv3
|
5
|
+
##
|
6
|
+
|
7
|
+
module RubyShogi
|
8
|
+
|
9
|
+
class Mgen
|
10
|
+
# both
|
11
|
+
ROOK_MOVES = [[1, 0], [0, 1], [-1, 0], [0, -1]].freeze
|
12
|
+
BISHOP_MOVES = [[1, 1], [-1, 1], [1, -1], [-1, -1]].freeze
|
13
|
+
KING_MOVES = (ROOK_MOVES + BISHOP_MOVES).freeze
|
14
|
+
|
15
|
+
PROMOTED_BISHOP_MOVES = ROOK_MOVES
|
16
|
+
PROMOTED_ROOK_MOVES = BISHOP_MOVES
|
17
|
+
|
18
|
+
# white
|
19
|
+
WHITE_GOLD_GENERAL_MOVES = [[1, 0], [-1, 0], [0, -1], [0, 1], [1, 1], [-1, 1]].freeze
|
20
|
+
WHITE_SILVER_GENERAL_MOVES = [[-1, -1], [-1, 1], [0, 1], [1, 1], [1, -1]].freeze
|
21
|
+
WHITE_KNIGHT_MOVES = [[-1, 2], [1, 2]].freeze
|
22
|
+
WHITE_LANCE_MOVES = [[0, 1]].freeze
|
23
|
+
|
24
|
+
# black
|
25
|
+
BLACK_GOLD_GENERAL_MOVES = [[1, 0], [-1, 0], [0, 1], [0, -1], [1, -1], [-1, -1]].freeze
|
26
|
+
BLACK_SILVER_GENERAL_MOVES = [[-1, 1], [-1, -1], [0, -1], [1, -1], [1, 1]].freeze
|
27
|
+
BLACK_KNIGHT_MOVES = [[-1, -2], [1, -2]].freeze
|
28
|
+
BLACK_LANCE_MOVES = [[0, -1]].freeze
|
29
|
+
|
30
|
+
# promotions
|
31
|
+
PROMO_NO = 0
|
32
|
+
PROMO_STAY = 1
|
33
|
+
PROMO_YES = 2
|
34
|
+
|
35
|
+
attr_accessor :pseudo_moves, :only_captures
|
36
|
+
|
37
|
+
def initialize(board)
|
38
|
+
@board, @moves = board, []
|
39
|
+
@x_gen, @y_gen, @from_gen = 0, 0, 0 # move generation
|
40
|
+
@x_checks, @y_checks = 0, 0 # checks
|
41
|
+
@pseudo_moves = false # 3x speed up
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Utils
|
46
|
+
##
|
47
|
+
|
48
|
+
def print_move_list
|
49
|
+
@moves.each_with_index { |board, i| puts "#{i}: #{board.move_str}" }
|
50
|
+
end
|
51
|
+
|
52
|
+
def is_on_board?(x, y)
|
53
|
+
x >= 0 && x <= 8 && y >= 0 && y <= 8
|
54
|
+
end
|
55
|
+
|
56
|
+
def remove_from_array(array, x)
|
57
|
+
found, a = false, []
|
58
|
+
array.each do |q|
|
59
|
+
if q == x
|
60
|
+
a.push(q) if found
|
61
|
+
found = true
|
62
|
+
else
|
63
|
+
a.push(q)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
fail if !found
|
67
|
+
a
|
68
|
+
end
|
69
|
+
|
70
|
+
def good_coord?(i)
|
71
|
+
i >= 0 && i <= 80
|
72
|
+
end
|
73
|
+
|
74
|
+
def eaten_piece(eat)
|
75
|
+
case eat
|
76
|
+
when 2 then 1
|
77
|
+
when 4 then 3
|
78
|
+
when 6 then 5
|
79
|
+
when 8 then 7
|
80
|
+
when 11 then 10
|
81
|
+
when 13 then 12
|
82
|
+
else eat
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Checks
|
88
|
+
##
|
89
|
+
|
90
|
+
def pawn_checks_w?(here)
|
91
|
+
@x_checks + 9 * (@y_checks + 1) == here
|
92
|
+
end
|
93
|
+
|
94
|
+
def pawn_checks_b?(here)
|
95
|
+
@x_checks + 9 * (@y_checks - 1) == here
|
96
|
+
end
|
97
|
+
|
98
|
+
def slider_checks_to?(slider, here)
|
99
|
+
slider.each do |jmp|
|
100
|
+
px, py = @x_checks, @y_checks
|
101
|
+
loop do
|
102
|
+
px, py = px + jmp[0], py + jmp[1]
|
103
|
+
break if !is_on_board?(px, py)
|
104
|
+
to = px + py * 9
|
105
|
+
return true if to == here
|
106
|
+
break if !@board.empty?(to)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
false
|
110
|
+
end
|
111
|
+
|
112
|
+
def jump_checks_to?(jumps, here)
|
113
|
+
jumps.each do |jmp|
|
114
|
+
px, py = @x_checks + jmp[0], @y_checks + jmp[1]
|
115
|
+
return true if px + py * 9 == here
|
116
|
+
end
|
117
|
+
false
|
118
|
+
end
|
119
|
+
|
120
|
+
def checks_w?#(here)
|
121
|
+
here = @board.bking
|
122
|
+
81.times do |i|
|
123
|
+
@x_checks, @y_checks = i % 9, i / 9
|
124
|
+
case @board.brd[i]
|
125
|
+
when 1 then return true if pawn_checks_w?(here)
|
126
|
+
when 2 then return true if jump_checks_to?(WHITE_GOLD_GENERAL_MOVES, here)
|
127
|
+
when 3 then return true if slider_checks_to?(WHITE_LANCE_MOVES, here)
|
128
|
+
when 4 then return true if jump_checks_to?(WHITE_GOLD_GENERAL_MOVES, here)
|
129
|
+
when 5 then return true if jump_checks_to?(WHITE_KNIGHT_MOVES, here)
|
130
|
+
when 6 then return true if jump_checks_to?(WHITE_GOLD_GENERAL_MOVES, here)
|
131
|
+
when 7 then return true if jump_checks_to?(WHITE_SILVER_GENERAL_MOVES, here)
|
132
|
+
when 8 then return true if jump_checks_to?(WHITE_GOLD_GENERAL_MOVES, here)
|
133
|
+
when 9 then return true if jump_checks_to?(WHITE_GOLD_GENERAL_MOVES, here)
|
134
|
+
when 10 then return true if slider_checks_to?(BISHOP_MOVES, here)
|
135
|
+
when 11 then return true if slider_checks_to?(BISHOP_MOVES, here) || jump_checks_to?(PROMOTED_BISHOP_MOVES, here)
|
136
|
+
when 12 then return true if slider_checks_to?(ROOK_MOVES, here)
|
137
|
+
when 13 then return true if slider_checks_to?(ROOK_MOVES, here) || jump_checks_to?(PROMOTED_ROOK_MOVES, here)
|
138
|
+
when 14 then return true if jump_checks_to?(KING_MOVES, here)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
false
|
142
|
+
end
|
143
|
+
|
144
|
+
def checks_b?#(here)
|
145
|
+
here = @board.wking
|
146
|
+
81.times do |i|
|
147
|
+
@x_checks, @y_checks = i % 9, i / 9
|
148
|
+
case @board.brd[i]
|
149
|
+
when -1 then return true if pawn_checks_b?(here)
|
150
|
+
when -2 then return true if jump_checks_to?(BLACK_GOLD_GENERAL_MOVES, here)
|
151
|
+
when -3 then return true if slider_checks_to?(BLACK_LANCE_MOVES, here)
|
152
|
+
when -4 then return true if jump_checks_to?(BLACK_GOLD_GENERAL_MOVES, here)
|
153
|
+
when -5 then return true if jump_checks_to?(BLACK_KNIGHT_MOVES, here)
|
154
|
+
when -6 then return true if jump_checks_to?(BLACK_GOLD_GENERAL_MOVES, here)
|
155
|
+
when -7 then return true if jump_checks_to?(BLACK_SILVER_GENERAL_MOVES, here)
|
156
|
+
when -8 then return true if jump_checks_to?(BLACK_GOLD_GENERAL_MOVES, here)
|
157
|
+
when -9 then return true if jump_checks_to?(BLACK_GOLD_GENERAL_MOVES, here)
|
158
|
+
when -10 then return true if slider_checks_to?(BISHOP_MOVES, here)
|
159
|
+
when -11 then return true if slider_checks_to?(BISHOP_MOVES, here) || jump_checks_to?(PROMOTED_BISHOP_MOVES, here)
|
160
|
+
when -12 then return true if slider_checks_to?(ROOK_MOVES, here)
|
161
|
+
when -13 then return true if slider_checks_to?(ROOK_MOVES, here) || jump_checks_to?(PROMOTED_ROOK_MOVES, here)
|
162
|
+
when -14 then return true if jump_checks_to?(KING_MOVES, here)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
false
|
166
|
+
end
|
167
|
+
end # class Mgen
|
168
|
+
|
169
|
+
end # module RubyShogi
|
@@ -0,0 +1,238 @@
|
|
1
|
+
##
|
2
|
+
# RubyShogi, a Shogi Engine
|
3
|
+
# Author: Toni Helminen
|
4
|
+
# License: GPLv3
|
5
|
+
##
|
6
|
+
|
7
|
+
module RubyShogi
|
8
|
+
|
9
|
+
class MgenBlack < RubyShogi::Mgen
|
10
|
+
def initialize(board)
|
11
|
+
@board = board
|
12
|
+
end
|
13
|
+
|
14
|
+
def handle_capture(copy, eat)
|
15
|
+
piece = case eat
|
16
|
+
when -2..-1 then -1
|
17
|
+
when -4..-3 then -3
|
18
|
+
when -6..-5 then -5
|
19
|
+
when -8..-7 then -7
|
20
|
+
when -9 then -9
|
21
|
+
when -11..-10 then -10
|
22
|
+
when -13..-12 then -12
|
23
|
+
end
|
24
|
+
copy.white_pocket.push(piece)
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_new_move(me, to, promo = 0)
|
28
|
+
return if handle_promotion?(me, to)
|
29
|
+
push_move(me, to, promo)
|
30
|
+
end
|
31
|
+
|
32
|
+
def push_move(me, to, promo)
|
33
|
+
board2 = @board
|
34
|
+
copy = @board.copy_me
|
35
|
+
copy.from = @from_gen
|
36
|
+
copy.promo = promo
|
37
|
+
copy.r50 += 1
|
38
|
+
copy.fullmoves += 1
|
39
|
+
copy.r50 = 0 if [-1, -3, -5].include?(me)
|
40
|
+
copy.to = to
|
41
|
+
copy.eat = copy.brd[to]
|
42
|
+
copy.black_pocket.push(-1 * eaten_piece(copy.eat)) if copy.eat != 0
|
43
|
+
copy.wtm = !copy.wtm
|
44
|
+
copy.brd[@from_gen] = 0
|
45
|
+
copy.brd[to] = me
|
46
|
+
copy.bking = to if me == -14
|
47
|
+
#fail if copy.find_black_king != copy.bking
|
48
|
+
@board = copy
|
49
|
+
@moves.push << copy if !checks_w?
|
50
|
+
@board = board2
|
51
|
+
end
|
52
|
+
|
53
|
+
def pawn_drop_checkmate?(to)
|
54
|
+
@board.brd[to - 9] == 14 && !checks_w?(to - 9) ? true : false
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_new_drop_move(me, to)
|
58
|
+
return if me == -3 && to / 9 == 0
|
59
|
+
return if me == -5 && to / 9 <= 1
|
60
|
+
board2 = @board
|
61
|
+
copy = @board.copy_me
|
62
|
+
copy.from = @from_gen
|
63
|
+
copy.to = to
|
64
|
+
copy.drop = me
|
65
|
+
copy.r50 += 1
|
66
|
+
copy.fullmoves += 1
|
67
|
+
copy.eat = 0
|
68
|
+
copy.wtm = ! copy.wtm
|
69
|
+
copy.brd[@from_gen] = 0
|
70
|
+
copy.brd[to] = me
|
71
|
+
copy.black_pocket = remove_from_array(copy.black_pocket, me)
|
72
|
+
#fail if copy.find_black_king != copy.bking
|
73
|
+
@board = copy
|
74
|
+
if !checks_w? && !(me == 1 && pawn_drop_checkmate?(to))
|
75
|
+
@moves.push << copy
|
76
|
+
end
|
77
|
+
@board = board2
|
78
|
+
end
|
79
|
+
|
80
|
+
def handle_promotion?(me, to)
|
81
|
+
return true if must_promote?(me, to)
|
82
|
+
return false if to / 9 > 2 && @from_gen / 9 > 2
|
83
|
+
case me
|
84
|
+
when -1
|
85
|
+
push_move(-1, to, PROMO_STAY)
|
86
|
+
push_move(-2, to, PROMO_YES)
|
87
|
+
return true
|
88
|
+
when -3
|
89
|
+
push_move(-3, to, PROMO_STAY)
|
90
|
+
push_move(-4, to, PROMO_YES)
|
91
|
+
return true
|
92
|
+
when -5
|
93
|
+
push_move(-5, to, PROMO_STAY)
|
94
|
+
push_move(-6, to, PROMO_YES)
|
95
|
+
return true
|
96
|
+
when -7
|
97
|
+
push_move(-7, to, PROMO_STAY)
|
98
|
+
push_move(-8, to, PROMO_YES)
|
99
|
+
return true
|
100
|
+
when -10
|
101
|
+
push_move(-10, to, PROMO_STAY)
|
102
|
+
push_move(-11, to, PROMO_YES)
|
103
|
+
return true
|
104
|
+
when -12
|
105
|
+
push_move(-12, to, PROMO_STAY)
|
106
|
+
push_move(-13, to, PROMO_YES)
|
107
|
+
return true
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def must_promote?(me, to)
|
112
|
+
if me == -5 && to / 9 <= 1
|
113
|
+
push_move(-6, to, PROMO_YES)
|
114
|
+
return true
|
115
|
+
end
|
116
|
+
return false if to / 9 != 0
|
117
|
+
case me
|
118
|
+
when -1
|
119
|
+
push_move(-2, to, PROMO_YES)
|
120
|
+
return true
|
121
|
+
when -3
|
122
|
+
push_move(-4, to, PROMO_YES)
|
123
|
+
return true
|
124
|
+
end
|
125
|
+
false
|
126
|
+
end
|
127
|
+
|
128
|
+
def add_new_pawn_move(to)
|
129
|
+
case to / 9
|
130
|
+
when 1..2
|
131
|
+
push_move(-1, to, PROMO_STAY)
|
132
|
+
push_move(-2, to, PROMO_YES)
|
133
|
+
when 0 then push_move(-2, to, PROMO_YES)
|
134
|
+
else
|
135
|
+
push_move(-1, to, PROMO_NO)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def generate_pawn_moves
|
140
|
+
to = @x_gen + (@y_gen - 1) * 9
|
141
|
+
add_new_pawn_move(to) if to >= 0 && @board.walkable_b?(to)
|
142
|
+
end
|
143
|
+
|
144
|
+
def generate_jump_moves(jumps, me)
|
145
|
+
jumps.each do |jmp|
|
146
|
+
px, py = @x_gen + jmp[0], @y_gen + jmp[1]
|
147
|
+
to = px + 9 * py
|
148
|
+
add_new_move(me, to) if is_on_board?(px, py) && @board.walkable_b?(to)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def generate_slider_moves(slider, me)
|
153
|
+
slider.each do | jmp |
|
154
|
+
px, py = @x_gen, @y_gen
|
155
|
+
loop do
|
156
|
+
px, py = px + jmp[0], py + jmp[1]
|
157
|
+
break if !is_on_board?(px, py)
|
158
|
+
to = px + 9 * py
|
159
|
+
add_new_move(me, to) if @board.walkable_b?(to)
|
160
|
+
break if !@board.empty?(to)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def pawn_on_column?(c)
|
166
|
+
ret = false
|
167
|
+
9.times do |i|
|
168
|
+
to = -9 * i + 8 * 9 + c
|
169
|
+
if to != @from_gen && @board.brd[to] == -1
|
170
|
+
ret = true
|
171
|
+
break
|
172
|
+
end
|
173
|
+
end
|
174
|
+
ret
|
175
|
+
end
|
176
|
+
|
177
|
+
def put_pawn_drops
|
178
|
+
(9*8).times do |i2|
|
179
|
+
i = i2 + 9
|
180
|
+
@x_gen, @y_gen, @from_gen = i % 9, i / 9, i
|
181
|
+
add_new_drop_move(-1, i) if !pawn_on_column?(i % 9 ) && @board.brd[i] == 0
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def put_drops(piece)
|
186
|
+
81.times do |i|
|
187
|
+
@x_gen, @y_gen, @from_gen = i % 9, i / 9, i
|
188
|
+
add_new_drop_move(piece, i) if @board.brd[i] == 0
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def generate_drops
|
193
|
+
@board.black_pocket.each do |piece|
|
194
|
+
case piece
|
195
|
+
when -1 then put_pawn_drops
|
196
|
+
when -3 then put_drops(-3)
|
197
|
+
when -5 then put_drops(-5)
|
198
|
+
when -7 then put_drops(-7)
|
199
|
+
when -9 then put_drops(-9)
|
200
|
+
when -10 then put_drops(-10)
|
201
|
+
when -11 then put_drops(-11)
|
202
|
+
when -12 then put_drops(-12)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
@moves
|
206
|
+
end
|
207
|
+
|
208
|
+
def generate_moves
|
209
|
+
@moves = []
|
210
|
+
81.times do |i|
|
211
|
+
@x_gen, @y_gen, @from_gen = i % 9, i / 9, i
|
212
|
+
#puts @board.brd[i]
|
213
|
+
case @board.brd[i]
|
214
|
+
when -1 then generate_pawn_moves
|
215
|
+
when -2 then generate_jump_moves(BLACK_GOLD_GENERAL_MOVES, -2)
|
216
|
+
when -3 then generate_slider_moves(BLACK_LANCE_MOVES, -3)
|
217
|
+
when -4 then generate_jump_moves(BLACK_GOLD_GENERAL_MOVES, -4)
|
218
|
+
when -5 then generate_jump_moves(BLACK_KNIGHT_MOVES, -5)
|
219
|
+
when -6 then generate_jump_moves(BLACK_GOLD_GENERAL_MOVES, -6)
|
220
|
+
when -7 then generate_jump_moves(BLACK_SILVER_GENERAL_MOVES, -7)
|
221
|
+
when -8 then generate_jump_moves(BLACK_GOLD_GENERAL_MOVES, -8)
|
222
|
+
when -9 then generate_jump_moves(BLACK_GOLD_GENERAL_MOVES, -9)
|
223
|
+
when -10 then generate_slider_moves(BISHOP_MOVES, -10)
|
224
|
+
when -11
|
225
|
+
generate_slider_moves(BISHOP_MOVES, -11)
|
226
|
+
generate_jump_moves(PROMOTED_BISHOP_MOVES, -11)
|
227
|
+
when -12 then generate_slider_moves(ROOK_MOVES, -12)
|
228
|
+
when -13
|
229
|
+
generate_slider_moves(ROOK_MOVES, -13)
|
230
|
+
generate_jump_moves(PROMOTED_ROOK_MOVES, -13)
|
231
|
+
when -14 then generate_jump_moves(KING_MOVES, -14)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
generate_drops
|
235
|
+
end
|
236
|
+
end # class MgenBlack
|
237
|
+
|
238
|
+
end # module RubyShogi
|