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.
- checksums.yaml +7 -0
- data/bin/shuriken +5 -0
- data/lib/shuriken.rb +1 -0
- data/lib/shuriken/bench.rb +118 -0
- data/lib/shuriken/board.rb +70 -0
- data/lib/shuriken/board_caparandom.rb +422 -0
- data/lib/shuriken/cmd.rb +185 -0
- data/lib/shuriken/engine.rb +53 -0
- data/lib/shuriken/engine_caparandom.rb +226 -0
- data/lib/shuriken/eval_caparandom.rb +110 -0
- data/lib/shuriken/falcon_moves.rb +40 -0
- data/lib/shuriken/fen.rb +52 -0
- data/lib/shuriken/history.rb +60 -0
- data/lib/shuriken/mgen_caparandom.rb +181 -0
- data/lib/shuriken/mgen_caparandom_black.rb +222 -0
- data/lib/shuriken/mgen_caparandom_white.rb +225 -0
- data/lib/shuriken/perft_capablanca_caparandom.rb +26 -0
- data/lib/shuriken/perft_caparandom.rb +77 -0
- data/lib/shuriken/perft_falcon_caparandom.rb +20 -0
- data/lib/shuriken/perft_gothic_caparandom.rb +26 -0
- data/lib/shuriken/shuriken.rb +75 -0
- data/lib/shuriken/tactics_caparandom.rb +72 -0
- data/lib/shuriken/tokens.rb +42 -0
- data/lib/shuriken/utils.rb +25 -0
- data/lib/shuriken/xboard.rb +134 -0
- data/lib/shuriken/zobrist.rb +25 -0
- metadata +69 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 1567b25d621478c1c3b9625b0d7ae5838e869b8d8e5fc4027354f512741d7101
|
|
4
|
+
data.tar.gz: f0760bfb2e51e5b882152e830f9a0ab45e3b62a49785b71e4ee4d3e215fd50f8
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: becdc3f1bf04b553988adce2c88c82a501b23289579a0aefe40616707c57be207ff600647e3972150cfa0387a3d46bb26b9fb9a08a23f8305786961d86a3fbdf
|
|
7
|
+
data.tar.gz: 3597b8407a4fbb60b2334225ab4f035119428db37c11c5709cca89bbe4222286a2cb29c4a5198313d4631268bf89a18428ea5300a5b4a6207232cf75ca0c0676
|
data/bin/shuriken
ADDED
data/lib/shuriken.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require_relative "./shuriken/shuriken"
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
##
|
|
2
|
+
# Shuriken, a Ruby chess variant engine
|
|
3
|
+
# Author: Toni Helminen
|
|
4
|
+
# License: GPLv3
|
|
5
|
+
##
|
|
6
|
+
|
|
7
|
+
module Shuriken
|
|
8
|
+
|
|
9
|
+
require 'benchmark'
|
|
10
|
+
|
|
11
|
+
module Bench
|
|
12
|
+
def Bench.f1
|
|
13
|
+
n = 0
|
|
14
|
+
1000_000.times { |i| n += (i%80) }
|
|
15
|
+
n
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def Bench.f2
|
|
19
|
+
n = 0
|
|
20
|
+
1000_000.times { |i| n += (i%80) }
|
|
21
|
+
n
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def Bench.f3
|
|
25
|
+
n, i = 0, 0
|
|
26
|
+
while i < 1000_000
|
|
27
|
+
n, i = n + (i%80), i + 1
|
|
28
|
+
end
|
|
29
|
+
n
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def Bench.f4
|
|
33
|
+
n = 0
|
|
34
|
+
1000_000.times { |i| n += i%42 }
|
|
35
|
+
n
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def Bench.f5
|
|
39
|
+
n = 0
|
|
40
|
+
1000_000.times { |i| n += i.modulo 42 }
|
|
41
|
+
n
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def Bench.f6
|
|
45
|
+
s, caps = ["abc", "def", "ghi", "jkl"], ""
|
|
46
|
+
100_000.times { caps = s.map { |str| str.upcase } }
|
|
47
|
+
caps
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def Bench.f7
|
|
51
|
+
s, caps = ["abc", "def", "ghi", "jkl"], ""
|
|
52
|
+
100_000.times { caps = s.map(&:upcase) }
|
|
53
|
+
caps
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def Bench.f8
|
|
57
|
+
s, s2 = "a", "abc"
|
|
58
|
+
20_000.times { s += s2 }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def Bench.f9
|
|
62
|
+
s, s2 = "a", "abc"
|
|
63
|
+
20_000.times { s << s2 }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def Bench.f10
|
|
67
|
+
s, s2 = "a", "abc"
|
|
68
|
+
20_000.times { s = "#{s}#{s2}" }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def Bench.header(msg)
|
|
72
|
+
puts "... #{msg} ..."
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def Bench.loops
|
|
76
|
+
header("loops")
|
|
77
|
+
Benchmark.bm(10) do |x|
|
|
78
|
+
x.report("each") { f1 }
|
|
79
|
+
x.report("times") { f2 }
|
|
80
|
+
x.report("while") { f3 }
|
|
81
|
+
#x.compare!
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def Bench.modulo
|
|
86
|
+
header("modulo")
|
|
87
|
+
Benchmark.bm(10) do |x|
|
|
88
|
+
x.report("%") { f4 }
|
|
89
|
+
x.report("modulo") { f5 }
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def Bench.caps
|
|
94
|
+
header("caps")
|
|
95
|
+
Benchmark.bm(10) do |x|
|
|
96
|
+
x.report(".upcase") { f6 }
|
|
97
|
+
x.report("&:upcase") { f7 }
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def Bench.strings
|
|
102
|
+
header("strings")
|
|
103
|
+
Benchmark.bm(10) do |x|
|
|
104
|
+
x.report("+=") { f8 }
|
|
105
|
+
x.report("<<") { f9 }
|
|
106
|
+
x.report("\#\{\}") { f10 }
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def Bench.go
|
|
111
|
+
loops
|
|
112
|
+
modulo
|
|
113
|
+
caps
|
|
114
|
+
strings
|
|
115
|
+
end
|
|
116
|
+
end # module Bench
|
|
117
|
+
|
|
118
|
+
end # module Shuriken
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
##
|
|
2
|
+
# Shuriken, a Ruby chess variant engine
|
|
3
|
+
# Author: Toni Helminen
|
|
4
|
+
# License: GPLv3
|
|
5
|
+
##
|
|
6
|
+
|
|
7
|
+
module Shuriken
|
|
8
|
+
|
|
9
|
+
class Board
|
|
10
|
+
def brd2str
|
|
11
|
+
s, empty, counter = "", 0, 0
|
|
12
|
+
80.times do |j|
|
|
13
|
+
i = 10 * (7 - j / 10) + ( j % 10 )
|
|
14
|
+
p = @brd[i]
|
|
15
|
+
if p != 0
|
|
16
|
+
if empty > 0
|
|
17
|
+
s += empty.to_s
|
|
18
|
+
empty = 0
|
|
19
|
+
end
|
|
20
|
+
s += "fcakqrbnp.PNBRQKACF"[p + 9]
|
|
21
|
+
else
|
|
22
|
+
empty += 1
|
|
23
|
+
end
|
|
24
|
+
counter += 1
|
|
25
|
+
if counter % 10 == 0
|
|
26
|
+
s += empty.to_s if empty > 0
|
|
27
|
+
s += "/" if counter < 80
|
|
28
|
+
empty = 0
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
s
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def wtm2str
|
|
35
|
+
@wtm ? "w" : "b"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def castle2str
|
|
39
|
+
return "-" if @castle == 0
|
|
40
|
+
s = ""
|
|
41
|
+
if @variant == "cabarandom"
|
|
42
|
+
a = "ABCDEFGHIJ"
|
|
43
|
+
s += a[@castle_squares[1]] if @castle & 0x1 == 0x1
|
|
44
|
+
s += a[@castle_squares[5]] if @castle & 0x2 == 0x2
|
|
45
|
+
s += a[@castle_squares[1]].downcase if @castle & 0x4 == 0x4
|
|
46
|
+
s += a[@castle_squares[5]].downcase if @castle & 0x8 == 0x8
|
|
47
|
+
else
|
|
48
|
+
s += @castle & 0x1 == 0x1 ? "K" : ""
|
|
49
|
+
s += @castle & 0x2 == 0x2 ? "Q" : ""
|
|
50
|
+
s += @castle & 0x4 == 0x4 ? "k" : ""
|
|
51
|
+
s += @castle & 0x8 == 0x8 ? "q" : ""
|
|
52
|
+
end
|
|
53
|
+
s
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def ep2str
|
|
57
|
+
return "-" if @ep == -1
|
|
58
|
+
"abcdefghijkl"[ @ep % 10 ] + (@ep / 10).to_s
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def r502str
|
|
62
|
+
@r50.to_s
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def tofen
|
|
66
|
+
"#{brd2str} #{wtm2str} #{castle2str} #{ep2str} #{r502str}"
|
|
67
|
+
end
|
|
68
|
+
end # class Board
|
|
69
|
+
|
|
70
|
+
end # module Shuriken
|
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
##
|
|
2
|
+
# Shuriken, a Ruby chess variant engine
|
|
3
|
+
# Author: Toni Helminen
|
|
4
|
+
# License: GPLv3
|
|
5
|
+
##
|
|
6
|
+
|
|
7
|
+
module Shuriken
|
|
8
|
+
|
|
9
|
+
class BoardCaparandom < Shuriken::Board
|
|
10
|
+
GOTHIC_POS = "rnbqckabnr/pppppppppp/10/10/10/10/PPPPPPPPPP/RNBQCKABNR w KQkq - 0 1"
|
|
11
|
+
CAPA_POS = "rnabqkbcnr/pppppppppp/10/10/10/10/PPPPPPPPPP/RNABQKBCNR w KQkq - 0 1"
|
|
12
|
+
FALCON_POS = "rnbfqkfbnr/pppppppppp/10/10/10/10/PPPPPPPPPP/RNBFQKFBNR w KQkq - 0 1"
|
|
13
|
+
|
|
14
|
+
PIECES = {
|
|
15
|
+
".": 0,
|
|
16
|
+
"P": 1, # Pawn
|
|
17
|
+
"p": -1,
|
|
18
|
+
"N": 2, # Knight
|
|
19
|
+
"n": -2,
|
|
20
|
+
"B": 3, # Bishop
|
|
21
|
+
"b": -3,
|
|
22
|
+
"R": 4, # Rook
|
|
23
|
+
"r": -4,
|
|
24
|
+
"Q": 5, # Queen
|
|
25
|
+
"q": -5,
|
|
26
|
+
"K": 6, # King
|
|
27
|
+
"k": -6,
|
|
28
|
+
"A": 7, # Arcbishop
|
|
29
|
+
"a": -7,
|
|
30
|
+
"C": 8, # Chancellor
|
|
31
|
+
"c": -8,
|
|
32
|
+
"F": 9, # Falcon
|
|
33
|
+
"f": -9
|
|
34
|
+
}.freeze
|
|
35
|
+
|
|
36
|
+
attr_accessor :brd, :variant, :nodetype, :hash, :ep, :wtm, :eat, :from, :to, :castle, :castle_squares, :r50, :score, :promo, :castled, :index
|
|
37
|
+
|
|
38
|
+
def initialize(variant)
|
|
39
|
+
@variant = variant
|
|
40
|
+
initme
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def initme
|
|
44
|
+
@brd = [0] * 80
|
|
45
|
+
@castle, @ep, @wtm, @from, @to, @r50, @eat = 0, -1, true, 0, 0, 0, 0
|
|
46
|
+
@score, @promo, @castled = 0, 0, 0
|
|
47
|
+
# white O-O : [ king_pos, rook_pos, castle_square, direction ]
|
|
48
|
+
# white O-O-O : [ king_pos, rook_pos, castle_square, direction ]
|
|
49
|
+
@castle_squares = [-1] * 2 * 4
|
|
50
|
+
@index = 0
|
|
51
|
+
@hash = 0
|
|
52
|
+
@nodetype = 0 # 2 draw 1 win -1 loss
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def mgen_generator
|
|
56
|
+
@wtm ? Shuriken::MgenCaparandomWhite.new(self) : Shuriken::MgenCaparandomBlack.new(self)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def create_hash
|
|
60
|
+
@hash = 0
|
|
61
|
+
80.times do | i |
|
|
62
|
+
@hash ^= Shuriken::Zobrist.get(20 * i + 8 + @brd[i])
|
|
63
|
+
end
|
|
64
|
+
@hash ^= Shuriken::Zobrist.get(20 * 80 + (@wtm ? 1 : 0))
|
|
65
|
+
@hash ^= Shuriken::Zobrist.get(20 * 81 + (@ep == -1 ? 1 : 0))
|
|
66
|
+
@hash ^= Shuriken::Zobrist.get(20 * 82 + @castle)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# TODO write castling stuff
|
|
70
|
+
def legal?
|
|
71
|
+
pieces = [0] * 20
|
|
72
|
+
@brd.each { |p| pieces[p + 9] += 1 }
|
|
73
|
+
return false if pieces[-6 + 9] == 0 || pieces[6 + 9] == 0
|
|
74
|
+
true
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def move_str
|
|
78
|
+
return "O-O" if (@castled == 1 && @variant == "caparandom")
|
|
79
|
+
return "O-O-O" if (@castled == 2 && @variant == "caparandom")
|
|
80
|
+
fromx, fromy = x_coord(@from), y_coord(@from)
|
|
81
|
+
tox, toy = x_coord(@to), y_coord(@to)
|
|
82
|
+
s = ("a".ord + fromx).chr
|
|
83
|
+
s << (fromy + 1).to_s
|
|
84
|
+
s << ("a".ord + tox).chr
|
|
85
|
+
s << (toy + 1).to_s
|
|
86
|
+
ps = @variant == "falcon" ? "nbrqkkkf" : "nbrqkac"
|
|
87
|
+
if @promo > 1
|
|
88
|
+
s << ps[@promo - 2]
|
|
89
|
+
elsif @promo < -1
|
|
90
|
+
s << ps[-@promo - 2]
|
|
91
|
+
end
|
|
92
|
+
s
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def make_move(me, from, to)
|
|
96
|
+
fail unless (good_coord?(from) && good_coord?(to))
|
|
97
|
+
@eat = @brd[to]
|
|
98
|
+
@ep = -1
|
|
99
|
+
@r50 += 1
|
|
100
|
+
@brd[to] = me
|
|
101
|
+
@brd[from] = 0
|
|
102
|
+
@r50 = 0 if @eat
|
|
103
|
+
if @wtm
|
|
104
|
+
if me == 1
|
|
105
|
+
@r50 = 0
|
|
106
|
+
@ep = from + 10 if (y_coord(from) == 1 && y_coord(to) == 3)
|
|
107
|
+
elsif me == 6
|
|
108
|
+
@castle &= 0x4 | 0x8
|
|
109
|
+
end
|
|
110
|
+
else
|
|
111
|
+
if me == -1
|
|
112
|
+
@r50 = 0
|
|
113
|
+
@ep = from - 10 if (y_coord(from) == 8 - 2 && y_coord(to) == 8 - 4)
|
|
114
|
+
elsif me == -6
|
|
115
|
+
@castle &= 0x1 | 0x2
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
handle_castle_rights
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def find_white_king
|
|
122
|
+
#80.times do |i|
|
|
123
|
+
# return i if @brd[i] == 6
|
|
124
|
+
#end
|
|
125
|
+
#fail
|
|
126
|
+
@brd.index { | x | x == 6 }
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def find_black_king
|
|
130
|
+
#80.times do |i|
|
|
131
|
+
# return i if @brd[i] == -6
|
|
132
|
+
#end
|
|
133
|
+
#fail
|
|
134
|
+
@brd.index { | x | x == -6 }
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def find_piece_all(piece)
|
|
138
|
+
@brd.index { | x | x == piece }
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# scans ->
|
|
142
|
+
def find_piece(start_square, end_square, me, diff = 1)
|
|
143
|
+
i = start_square
|
|
144
|
+
loop do
|
|
145
|
+
return i if @brd[i] == me
|
|
146
|
+
fail "Shuriken Error: Couldn't Find: '#{me}'" if i == end_square
|
|
147
|
+
i += diff
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# scans ->
|
|
152
|
+
def just_kings?
|
|
153
|
+
80.times do |i|
|
|
154
|
+
return false if (@brd[i] != 6 && @brd[i] != -6)
|
|
155
|
+
end
|
|
156
|
+
true
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def material_draw?
|
|
160
|
+
80.times do |i|
|
|
161
|
+
return false if (@brd[i] != 6 && @brd[i] != -6 && @brd[i] != 0)
|
|
162
|
+
end
|
|
163
|
+
true
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def handle_castle_rights
|
|
167
|
+
if @castle & 0x1 == 0x1
|
|
168
|
+
@castle &= (0x2 | 0x4 | 0x8) if @brd[@castle_squares[1]] != 4
|
|
169
|
+
end
|
|
170
|
+
if @castle & 0x2 == 0x2
|
|
171
|
+
@castle &= (0x1 | 0x4 | 0x8) if @brd[@castle_squares[1 + 4]] != 4
|
|
172
|
+
end
|
|
173
|
+
if @castle & 0x4 == 0x4
|
|
174
|
+
@castle &= (0x1 | 0x2 | 0x8) if @brd[70 + @castle_squares[1]] != -4
|
|
175
|
+
end
|
|
176
|
+
if @castle & 0x8 == 0x8
|
|
177
|
+
@castle &= (0x1 | 0x2 | 0x4) if @brd[70 + @castle_squares[1 + 4]] != -4
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def make_castle_squares
|
|
182
|
+
if @castle & 0x1 == 0x1
|
|
183
|
+
king = find_piece(0, 10 - 1, 6, 1)
|
|
184
|
+
rook_r = find_piece(king, 10 - 1, 4, 1)
|
|
185
|
+
castle_square = 10 - 2
|
|
186
|
+
@castle_squares[0] = king
|
|
187
|
+
@castle_squares[1] = rook_r
|
|
188
|
+
@castle_squares[2] = castle_square
|
|
189
|
+
@castle_squares[3] = king < castle_square ? 1 : -1
|
|
190
|
+
end
|
|
191
|
+
if @castle & 0x2 == 0x2
|
|
192
|
+
king = find_piece(0, 10 - 1, 6, 1)
|
|
193
|
+
rook_l = find_piece(king, 0, 4, -1)
|
|
194
|
+
castle_square = 2
|
|
195
|
+
@castle_squares[4] = king
|
|
196
|
+
@castle_squares[5] = rook_l
|
|
197
|
+
@castle_squares[6] = castle_square
|
|
198
|
+
@castle_squares[7] = king < castle_square ? 1 : -1
|
|
199
|
+
end
|
|
200
|
+
if @castle & 0x4 == 0x4
|
|
201
|
+
king = find_piece(10 * 8 - 10, 10 * 8 - 1, -6, 1)
|
|
202
|
+
rook_r = find_piece(king, 10 * 8 - 1, -4, 1)
|
|
203
|
+
castle_square = 10 * 8 - 2
|
|
204
|
+
pos = 10 * 8 - 10
|
|
205
|
+
@castle_squares[0] = king - pos
|
|
206
|
+
@castle_squares[1] = rook_r - pos
|
|
207
|
+
@castle_squares[2] = castle_square - pos
|
|
208
|
+
@castle_squares[3] = king < castle_square ? 1 : -1
|
|
209
|
+
end
|
|
210
|
+
if @castle & 0x8 == 0x8
|
|
211
|
+
king = find_piece(10 * 8 - 10, 10 * 8 - 1, -6, 1)
|
|
212
|
+
rook_l = find_piece(king, 10 * 8 - 10, -4, -1)
|
|
213
|
+
castle_square = 10 * 8 - 10 + 2
|
|
214
|
+
pos = 10 * 8 - 10
|
|
215
|
+
@castle_squares[4] = king - pos
|
|
216
|
+
@castle_squares[5] = rook_l - pos
|
|
217
|
+
@castle_squares[6] = castle_square - pos
|
|
218
|
+
@castle_squares[7] = king < castle_square ? 1 : -1
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def copy_me()
|
|
223
|
+
copy = Shuriken::BoardCaparandom.new(@variant)
|
|
224
|
+
copy.brd = @brd.dup
|
|
225
|
+
copy.castle_squares = @castle_squares.dup
|
|
226
|
+
copy.castle = @castle
|
|
227
|
+
copy.ep = @ep
|
|
228
|
+
copy.wtm = @wtm
|
|
229
|
+
copy.from = @from
|
|
230
|
+
copy.to = @to
|
|
231
|
+
copy
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def startpos(spos)
|
|
235
|
+
pos = case spos
|
|
236
|
+
when "gothic"
|
|
237
|
+
GOTHIC_POS
|
|
238
|
+
when "capablanca"
|
|
239
|
+
CAPA_POS
|
|
240
|
+
when "falcon"
|
|
241
|
+
FALCON_POS
|
|
242
|
+
else
|
|
243
|
+
CAPA_POS
|
|
244
|
+
end
|
|
245
|
+
use_fen(pos)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def use_fen(pos)
|
|
249
|
+
initme
|
|
250
|
+
fen(pos)
|
|
251
|
+
make_castle_squares
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def y_coord(n)
|
|
255
|
+
n / 10
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def x_coord(n)
|
|
259
|
+
n % 10
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def last_rank?(square)
|
|
263
|
+
y_coord(square) == 7 ? true : false
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def first_rank?(x)
|
|
267
|
+
y_coord(x) == 0 ? true : false
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def empty?(i)
|
|
271
|
+
@brd[i] == 0 ? true : false
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def walkable_w?(square)
|
|
275
|
+
@brd[square] < 1 ? true : false
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def walkable_b?(square)
|
|
279
|
+
@brd[square] > -1 ? true : false
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def black?(square)
|
|
283
|
+
@brd[square] < 0 ? true : false
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def white?(square)
|
|
287
|
+
@brd[square] > 0 ? true : false
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def is_on_board?(x, y)
|
|
291
|
+
(x >= 0 && x < 10 && y >= 0 && y < 8) ? true : false
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def good_coord?(i)
|
|
295
|
+
(i >= 0 && i < 80) ? true : false
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def mirror_board
|
|
299
|
+
half = ((10 * 8) / 2 - 1).to_i
|
|
300
|
+
(0..half).each do | i |
|
|
301
|
+
x, y = x_coord(i), y_coord(i)
|
|
302
|
+
flip_y = x + (8 - 1 - y) * 10
|
|
303
|
+
p1 = @brd[i]
|
|
304
|
+
p2 = @brd[flip_y]
|
|
305
|
+
@brd[i] = p2
|
|
306
|
+
@brd[flip_y] = p1
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def flip_coord(coord)
|
|
311
|
+
(8 - 1 - y_coord(coord)) * 10 + x_coord(coord)
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def fen_board(s)
|
|
315
|
+
i = 0
|
|
316
|
+
s.gsub(/\d+/) { | m | "_" * m.to_i }
|
|
317
|
+
.gsub(/\//) { | m | "" }
|
|
318
|
+
.each_char do | c |
|
|
319
|
+
PIECES.each do | pie, num |
|
|
320
|
+
if c == pie.to_s
|
|
321
|
+
@brd[i] = num
|
|
322
|
+
break
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
i += 1
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def fen_wtm(s)
|
|
330
|
+
@wtm = s == "w" ? true : false
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def fen_KQkq(s)
|
|
334
|
+
found = false
|
|
335
|
+
s.each_char do | c |
|
|
336
|
+
{0x1 => "K", 0x2 => "Q", 0x4 => "k", 0x8 => "q"}.each do | a, b |
|
|
337
|
+
if c == b
|
|
338
|
+
@castle |= a
|
|
339
|
+
found = true
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
return if found
|
|
344
|
+
# caparandom castling
|
|
345
|
+
# setboard 3rkcnrbb/pppn1ppppp/3p6/4p5/7P1P/6CB2/PPPPPPPP1B/RNAQK2R2 w HAh - 1 8
|
|
346
|
+
wking, bking = find_piece_all(6) - 70, find_piece_all(-6)
|
|
347
|
+
s.each_char do | c |
|
|
348
|
+
if ("A".."J").include? c
|
|
349
|
+
num = c.ord - "A".ord
|
|
350
|
+
@castle |= num > wking ? 0x1 : 0x2
|
|
351
|
+
elsif ("a".."j").include? c
|
|
352
|
+
num = c.ord - "a".ord
|
|
353
|
+
@castle |= num > bking ? 0x4 : 0x8
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
def fen_ep(s)
|
|
359
|
+
return if (s == "-" or s.length < 2)
|
|
360
|
+
@ep = (s[0].ord - "a".ord) + 10 * s[1].to_i
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def fen_r50(s)
|
|
364
|
+
@r50 = s.to_i
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
def fen(str)
|
|
368
|
+
initme
|
|
369
|
+
s = str.strip.split(" ")
|
|
370
|
+
fen_board(s[0]) if s.length >= 0
|
|
371
|
+
fen_wtm(s[1]) if s.length >= 1
|
|
372
|
+
fen_KQkq(s[2]) if s.length >= 2
|
|
373
|
+
fen_ep(s[3]) if s.length >= 3
|
|
374
|
+
fen_r50(s[4]) if s.length >= 4
|
|
375
|
+
mirror_board
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
def str_castle
|
|
379
|
+
s = ""
|
|
380
|
+
{"K" => 0x1, "Q" => 0x2, "k" => 0x4, "q" => 0x8}.each do |a, b|
|
|
381
|
+
s += a if @castle.to_i & b == b
|
|
382
|
+
end
|
|
383
|
+
s.empty? ? "-" : s
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
def eval
|
|
387
|
+
Shuriken::EvalCaparandom.eval(self)
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
def material
|
|
391
|
+
Shuriken::EvalCaparandom.material(self)
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
def print_board
|
|
395
|
+
s =""
|
|
396
|
+
flip_it = false
|
|
397
|
+
80.times do | i |
|
|
398
|
+
x, y = x_coord(i), y_coord(i)
|
|
399
|
+
p = @brd[x + (8 - y - 1) * 10]
|
|
400
|
+
if flip_it
|
|
401
|
+
p = -@brd[x + y * 10]
|
|
402
|
+
end
|
|
403
|
+
ch = "."
|
|
404
|
+
PIECES.each do |pie, num|
|
|
405
|
+
if num.to_s == p.to_s
|
|
406
|
+
ch = pie.to_s
|
|
407
|
+
end
|
|
408
|
+
end
|
|
409
|
+
s << ch
|
|
410
|
+
if (i + 1) % 10 == 0
|
|
411
|
+
s << " " + ((8 - i / 10).to_i).to_s + "\n"
|
|
412
|
+
end
|
|
413
|
+
end
|
|
414
|
+
10.times { |i| s << ("a".ord + i).chr }
|
|
415
|
+
s << "\n[ wtm: #{@wtm} ]\n"
|
|
416
|
+
s << "[ castle: #{str_castle} ]\n"
|
|
417
|
+
s << "[ ep: #{@ep} ]\n\n"
|
|
418
|
+
puts s
|
|
419
|
+
end
|
|
420
|
+
end # class BoardCaparandom
|
|
421
|
+
|
|
422
|
+
end # module Shuriken
|