RubyShogi 0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|