shurikenengine 0.31

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.
@@ -0,0 +1,222 @@
1
+ ##
2
+ # Shuriken, a Ruby chess variant engine
3
+ # Author: Toni Helminen
4
+ # License: GPLv3
5
+ ##
6
+
7
+ module Shuriken
8
+
9
+ class MgenCaparandomBlack < Shuriken::MgenCaparandom
10
+ def initialize(board)
11
+ super(board)
12
+ end
13
+
14
+ ##
15
+ # Utils
16
+ ##
17
+
18
+ def add_new_move(me, to, type_of_move = 0)
19
+ fail unless good_coord?(to)
20
+ board2 = @board
21
+ copy = @board.copy_me
22
+ copy.from = @from_gen
23
+ copy.to = to
24
+ copy.eat = copy.brd[to]
25
+ fail "Can't eat king" if copy.eat == 6
26
+ return if @only_captures && copy.eat <= 0
27
+ copy.wtm = ! copy.wtm
28
+ ep = copy.ep
29
+ copy.ep = -1
30
+ copy.r50 += 1
31
+ copy.promo = type_of_move == MOVE_TYPE_PROMO ? me : 0
32
+ copy.castled = 0
33
+ copy.brd[@from_gen] = 0
34
+ copy.brd[to] = me
35
+ copy.r50 = 0 if copy.eat != 0
36
+ if me == -1
37
+ copy.r50 = 0
38
+ copy.ep = @from_gen - 10 if type_of_move == MOVE_TYPE_EP
39
+ copy.brd[to + 10] = 0 if to == ep
40
+ elsif me == -6
41
+ copy.castle &= 0x1 | 0x2
42
+ if type_of_move == MOVE_TYPE_CASTLING
43
+ if to == 70 + 8
44
+ copy.castled = 1
45
+ copy.brd[70 + copy.castle_squares[1]] = 0 if 70 + copy.castle_squares[1] != to
46
+ copy.brd[to - 1] = -4
47
+ else
48
+ copy.castled = 2
49
+ copy.brd[70 + copy.castle_squares[1 + 4]] = 0 if 70 + copy.castle_squares[1 + 4] != to
50
+ copy.brd[to + 1] = -4
51
+ end
52
+ end
53
+ end
54
+ @board = copy
55
+ if @pseudo_moves
56
+ @moves.push << copy
57
+ elsif !checks_w?(@board.find_black_king)
58
+ copy.handle_castle_rights
59
+ @moves.push << copy
60
+ end
61
+ @board = board2
62
+ end
63
+
64
+ # have to check promos
65
+ def add_new_pawn_move(to)
66
+ if to < 10
67
+ @promotion_to.each { |i| add_new_move(-1 * i, to, MOVE_TYPE_PROMO) }
68
+ else
69
+ add_new_move(-1, to)
70
+ end
71
+ end
72
+
73
+ ##
74
+ # Generate moves
75
+ ##
76
+
77
+ def generate_pawn_moves_1
78
+ to = @x_gen + (@y_gen - 1) * 10
79
+ add_new_pawn_move(to) if (to >= 0 && @board.empty?(to))
80
+ end
81
+
82
+ def generate_pawn_moves_2
83
+ to = @from_gen - 2 * 10
84
+ add_new_move(-1, to, MOVE_TYPE_EP) if (y_coord(@from_gen) == 7 - 1 && @board.empty?(to + 10) && @board.empty?(to))
85
+ end
86
+
87
+ def generate_pawn_eat_moves
88
+ [-1, 1].each do |dir|
89
+ px, py = @x_gen + dir, @y_gen - 1
90
+ if is_on_board?(px, py)
91
+ to = px + py * 10
92
+ if @board.white?(to)
93
+ add_new_pawn_move(to)
94
+ elsif @board.ep > 0 && to == @board.ep
95
+ add_new_pawn_move(to)
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ def generate_pawn_moves
102
+ generate_pawn_moves_1
103
+ generate_pawn_moves_2
104
+ generate_pawn_eat_moves
105
+ end
106
+
107
+ def generate_jump_moves(jumps, me = -2)
108
+ jumps.each do |jmp|
109
+ px, py = @x_gen + jmp[0], @y_gen + jmp[1]
110
+ to = px + py * 10
111
+ add_new_move(me, to) if (is_on_board?(px, py) && @board.walkable_b?(to))
112
+ end
113
+ end
114
+
115
+ def generate_slider_moves(slider, me = -3)
116
+ slider.each do |jmp|
117
+ px, py = @x_gen, @y_gen
118
+ loop do
119
+ px, py = px + jmp[0], py + jmp[1]
120
+ break if !is_on_board?(px, py)
121
+ to = px + py * 10
122
+ add_new_move(me, to) if @board.walkable_b?(to)
123
+ break if !@board.empty?(to)
124
+ end
125
+ end
126
+ end
127
+
128
+ def generate_falcon_moves
129
+ isin = []
130
+ Shuriken::FalconMoves::MOVES.each do |mv|
131
+ px1, py1 = @x_gen + mv[0], @y_gen + mv[1]
132
+ to1 = px1 + py1 * 10
133
+ px2, py2 = px1 + mv[2], py1 + mv[3]
134
+ to2 = px2 + py2 * 10
135
+ px3, py3 = px2 + mv[4], py2 + mv[5]
136
+ to3 = px3 + py3 * 10
137
+ if (is_on_board?(px1, py1) && @board.empty?(to1) && is_on_board?(px2, py2) && @board.empty?(to2) \
138
+ && is_on_board?(px3, py3) && @board.walkable_b?(to3) && !isin.include?(to3))
139
+ add_new_move(-9, to3)
140
+ isin.push << to3
141
+ end
142
+ end
143
+ end
144
+
145
+ def generate_castle_O_O_moves
146
+ return unless @board.castle & 0x4 == 0x4
147
+ king, rook = 70 + @board.castle_squares[0], 70 + @board.castle_squares[1]
148
+ return unless (@board.brd[king] == -6 && @board.brd[rook] == -4)
149
+ castle_square = 70 + @board.castle_squares[2]
150
+ direction = @board.castle_squares[3]
151
+
152
+ no_checks = [castle_square] # calculate no checks squares
153
+ position = king
154
+ loop do
155
+ no_checks.push << position
156
+ return if (position != king && position != rook && @board.brd[position] != 0)
157
+ break if position == castle_square
158
+ position += direction
159
+ end
160
+ return if ![0, -6].include?(@board.brd[70 + 7])
161
+
162
+ return if any_white_checks_here?(no_checks)
163
+ add_new_move(-6, castle_square, MOVE_TYPE_CASTLING)
164
+ end
165
+
166
+ # setboard r2qck3r/ppp1pp1ppp/2n1bapn2/3p6/10/7P2/PPPPPPP1PP/RNBQC1KBNR b kq - 3 8
167
+ def generate_castle_O_O_O_moves
168
+ return unless @board.castle & 0x8 == 0x8
169
+ king, rook = 70 + @board.castle_squares[0 + 4], 70 + @board.castle_squares[1 + 4]
170
+ return unless (@board.brd[king] == -6 && @board.brd[rook] == -4)
171
+ castle_square = 70 + @board.castle_squares[2 + 4]
172
+ direction = @board.castle_squares[3 + 4]
173
+
174
+ no_checks = [castle_square] # calculate no checks squares
175
+ position = king
176
+ loop do
177
+ no_checks.push << position
178
+ return if (position != king && position != rook && @board.brd[position] != 0)
179
+ break if position == castle_square
180
+ position += direction
181
+ end
182
+
183
+ return if ![0, -6].include?(@board.brd[70 + 3])
184
+ return if rook == 70 && @board.brd[71] != 0 # space between rook && castle square
185
+ return if any_white_checks_here?(no_checks)
186
+ add_new_move(-6, castle_square, MOVE_TYPE_CASTLING)
187
+ end
188
+
189
+ def generate_moves
190
+ @moves = []
191
+ 80.times do |i|
192
+ @x_gen, @y_gen, @from_gen = x_coord(i), y_coord(i), i
193
+ case @board.brd[i]
194
+ when -1
195
+ generate_pawn_moves
196
+ when -2
197
+ generate_jump_moves(KNIGHT_MOVES, -2)
198
+ when -3
199
+ generate_slider_moves(BISHOP_MOVES, -3)
200
+ when -4
201
+ generate_slider_moves(ROOK_MOVES, -4)
202
+ when -5
203
+ generate_slider_moves(BISHOP_MOVES + ROOK_MOVES, -5)
204
+ when -6
205
+ generate_jump_moves(KING_MOVES, -6)
206
+ generate_castle_O_O_moves
207
+ generate_castle_O_O_O_moves
208
+ when -7
209
+ generate_jump_moves(KNIGHT_MOVES, -7)
210
+ generate_slider_moves(BISHOP_MOVES, -7)
211
+ when -8
212
+ generate_jump_moves(KNIGHT_MOVES, -8)
213
+ generate_slider_moves(ROOK_MOVES, -8)
214
+ when -9
215
+ generate_falcon_moves
216
+ end
217
+ end
218
+ @moves#.dup
219
+ end
220
+ end # class MgenCaparandomBlack
221
+
222
+ end # module Shuriken
@@ -0,0 +1,225 @@
1
+ ##
2
+ # Shuriken, a Ruby chess variant engine
3
+ # Author: Toni Helminen
4
+ # License: GPLv3
5
+ ##
6
+
7
+ module Shuriken
8
+
9
+ class MgenCaparandomWhite < Shuriken::MgenCaparandom
10
+ def initialize(board)
11
+ super board
12
+ end
13
+
14
+ ##
15
+ # Utils
16
+ ##
17
+
18
+ def add_new_move(me, to, type_of_move = 0)
19
+ fail unless good_coord?(to)
20
+ board2 = @board
21
+ copy = @board.copy_me
22
+ copy.from = @from_gen
23
+ copy.to = to
24
+ copy.eat = copy.brd[to]
25
+ fail "Can't eat king" if copy.eat == -6
26
+ #fail if copy.eat == -6
27
+ return if @only_captures && copy.eat >= 0
28
+ copy.wtm = ! copy.wtm
29
+ ep = copy.ep
30
+ copy.ep = -1
31
+ copy.r50 += 1
32
+ copy.promo = type_of_move == MOVE_TYPE_PROMO ? me : 0
33
+ copy.castled = 0
34
+ copy.brd[@from_gen] = 0
35
+ copy.brd[to] = me
36
+ copy.r50 = 0 if copy.eat != 0
37
+ if me == 1
38
+ copy.r50 = 0
39
+ copy.ep = @from_gen + 10 if type_of_move == MOVE_TYPE_EP
40
+ copy.brd[to - 10] = 0 if to == ep
41
+ elsif me == 6
42
+ copy.castle &= 0x4 | 0x8
43
+ if type_of_move == MOVE_TYPE_CASTLING
44
+ if to == 8
45
+ copy.castled = 1
46
+ copy.brd[copy.castle_squares[1]] = 0 if copy.castle_squares[1] != to
47
+ copy.brd[to - 1] = 4
48
+ else
49
+ copy.castled = 2
50
+ copy.brd[copy.castle_squares[1 + 4]] = 0 if copy.castle_squares[1 + 4] != to
51
+ copy.brd[to + 1] = 4
52
+ end
53
+ end
54
+ end
55
+ @board = copy
56
+ if @pseudo_moves
57
+ @moves.push << copy
58
+ elsif !checks_b?(@board.find_white_king)
59
+ copy.handle_castle_rights
60
+ @moves.push << copy
61
+ end
62
+ @board = board2
63
+ end
64
+
65
+ # have to check promos
66
+ def add_new_pawn_move(to)
67
+ if to >= 70
68
+ @promotion_to.each do | i |
69
+ add_new_move(i, to, MOVE_TYPE_PROMO)
70
+ end
71
+ else
72
+ add_new_move(1, to)
73
+ end
74
+ end
75
+
76
+ ##
77
+ # Generate moves
78
+ ##
79
+
80
+ def generate_pawn_moves_1
81
+ to = @x_gen + (@y_gen + 1) * 10
82
+ add_new_pawn_move(to) if (to < 80 && @board.empty?(to))
83
+ end
84
+
85
+ def generate_pawn_moves_2
86
+ to = @from_gen + 2 * 10
87
+ add_new_move(1, to, MOVE_TYPE_EP) if (y_coord(@from_gen) == 1 && @board.empty?(to - 10) && @board.empty?(to))
88
+ end
89
+
90
+ def generate_pawn_eat_moves
91
+ [-1, 1].each do | dir |
92
+ px, py = @x_gen + dir, @y_gen + 1
93
+ if is_on_board?(px, py)
94
+ to = px + py * 10
95
+ if @board.black?(to)
96
+ add_new_pawn_move(to)
97
+ elsif @board.ep > 0 && to == @board.ep
98
+ add_new_pawn_move(to)
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ def generate_pawn_moves
105
+ generate_pawn_moves_1
106
+ generate_pawn_moves_2
107
+ generate_pawn_eat_moves
108
+ end
109
+
110
+ def generate_jump_moves(jumps, me = 2)
111
+ jumps.each do | jmp |
112
+ px, py = @x_gen + jmp[0], @y_gen + jmp[1]
113
+ to = px + py * 10
114
+ add_new_move(me, to) if (is_on_board?(px, py) && @board.walkable_w?(to))
115
+ end
116
+ end
117
+
118
+ def generate_slider_moves(slider, me = 3)
119
+ slider.each do | jmp |
120
+ px, py = @x_gen, @y_gen
121
+ loop do
122
+ px, py = px + jmp[0], py + jmp[1]
123
+ break if !is_on_board?(px, py)
124
+ to = px + py * 10
125
+ add_new_move(me, to) if @board.walkable_w?(to)
126
+ break if !@board.empty?(to)
127
+ end
128
+ end
129
+ end
130
+
131
+ def generate_falcon_moves
132
+ isin = []
133
+ Shuriken::FalconMoves::MOVES.each do | mv |
134
+ px1, py1 = @x_gen + mv[0], @y_gen + mv[1]
135
+ to1 = px1 + py1 * 10
136
+ px2, py2 = px1 + mv[2], py1 + mv[3]
137
+ to2 = px2 + py2 * 10
138
+ px3, py3 = px2 + mv[4], py2 + mv[5]
139
+ to3 = px3 + py3 * 10
140
+ if is_on_board?(px1, py1) && @board.empty?(to1) && is_on_board?(px2, py2) && @board.empty?(to2) \
141
+ and is_on_board?(px3, py3) && @board.walkable_w?(to3) && !isin.include?(to3)
142
+ add_new_move(9, to3)
143
+ isin.push << to3
144
+ end
145
+ end
146
+ end
147
+
148
+ def generate_castle_O_O_moves
149
+ return unless @board.castle & 0x1 == 0x1
150
+ king, rook = @board.castle_squares[0], @board.castle_squares[1]
151
+ return unless (@board.brd[king] == 6 && @board.brd[rook] == 4)
152
+ castle_square = @board.castle_squares[2]
153
+ direction = @board.castle_squares[3]
154
+
155
+ no_checks = [castle_square] # calculate no checks squares
156
+ position = king
157
+ loop do
158
+ no_checks.push << position
159
+ return if (position != king && position != rook && @board.brd[position] != 0)
160
+ break if position == castle_square
161
+ position += direction
162
+ end
163
+ return if ![0, 6].include?(@board.brd[7])
164
+
165
+ return if any_black_checks_here? no_checks
166
+ add_new_move(6, castle_square, MOVE_TYPE_CASTLING)
167
+ end
168
+
169
+ # setboard r4k3r/10/10/10/10/10/10/R4K3R w KQkq - 0 1
170
+ def generate_castle_O_O_O_moves
171
+ return unless @board.castle & 0x2 == 0x2
172
+ king, rook = @board.castle_squares[0 + 4], @board.castle_squares[1 + 4]
173
+ return unless (@board.brd[king] == 6 && @board.brd[rook] == 4)
174
+ castle_square = @board.castle_squares[2 + 4]
175
+ direction = @board.castle_squares[3 + 4]
176
+
177
+ no_checks = [castle_square] # calculate no checks squares
178
+ position = king
179
+ loop do
180
+ no_checks.push << position
181
+ return if (position != king && position != rook && @board.brd[position] != 0)
182
+ break if position == castle_square
183
+ position += direction
184
+ end
185
+ return if ![0, 6].include?(@board.brd[3])
186
+ return if (rook == 0 && @board.brd[1] != 0) # space between rook && castle square
187
+
188
+ return if any_black_checks_here?(no_checks)
189
+ add_new_move(6, castle_square, MOVE_TYPE_CASTLING)
190
+ end
191
+
192
+ def generate_moves
193
+ @moves = []
194
+ 80.times do | i |
195
+ @x_gen, @y_gen, @from_gen = x_coord(i), y_coord(i), i
196
+ case @board.brd[i]
197
+ when 1
198
+ generate_pawn_moves
199
+ when 2
200
+ generate_jump_moves(KNIGHT_MOVES, 2)
201
+ when 3
202
+ generate_slider_moves(BISHOP_MOVES, 3)
203
+ when 4
204
+ generate_slider_moves(ROOK_MOVES, 4)
205
+ when 5
206
+ generate_slider_moves(BISHOP_MOVES + ROOK_MOVES, 5)
207
+ when 6
208
+ generate_jump_moves(KING_MOVES, 6)
209
+ generate_castle_O_O_moves
210
+ generate_castle_O_O_O_moves
211
+ when 7
212
+ generate_jump_moves(KNIGHT_MOVES, 7)
213
+ generate_slider_moves(BISHOP_MOVES, 7)
214
+ when 8
215
+ generate_jump_moves(KNIGHT_MOVES, 8)
216
+ generate_slider_moves(ROOK_MOVES, 8)
217
+ when 9
218
+ generate_falcon_moves
219
+ end
220
+ end
221
+ @moves#.dup
222
+ end
223
+ end # class MgenCaparandomWhite
224
+
225
+ end # module Shuriken
@@ -0,0 +1,26 @@
1
+ ##
2
+ # Shuriken, a Ruby chess variant engine
3
+ # Author: Toni Helminen
4
+ # License: GPLv3
5
+ ##
6
+
7
+ module Shuriken
8
+
9
+ class PerftCapablancaCaparandom < Shuriken::PerftCaparandom
10
+ NUMS = { # from sjeng
11
+ 0 => 1,
12
+ 1 => 28,
13
+ 2 => 784,
14
+ 3 => 25228,
15
+ 4 => 805128,
16
+ 5 => 28741319,
17
+ 6 => 1015802437
18
+ }
19
+
20
+ def initialize
21
+ super("capablanca")
22
+ @nums = NUMS
23
+ end
24
+ end # class PerftCapablancaCaparandom
25
+
26
+ end # module Shuriken