RubyShogi 0.2 → 0.22

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 436d061edb50eee96d957a656caab3673b93183494b33d67324d68a4c006dd4e
4
- data.tar.gz: 18a2ad1204d24f8f17cd099ae48f08530ebabdc18fca03c984cd754e462d3c92
3
+ metadata.gz: 6701c33167fe944ca928ebd9bcf6ffccda09f294a416f6dafc8730b9f668a879
4
+ data.tar.gz: b8ea182ba133ac2e99f0da4d0434c7227a6f13abd2331178f179350c6c21e639
5
5
  SHA512:
6
- metadata.gz: b5319bc2ea8d8368b22f94afd7869b25462c139d04ba34e8bc576fe562a258465a00512e3b117d913f3b6d9a9f794c4ac94b97e65cd89cf3625dc83e4e925e86
7
- data.tar.gz: ef8812338d72cce94172439336f356b78fab48a21133aa2a1f819142c87331af40b36c17011575c5073284e6e147203bdc701d32992339c3268c59178b1c6165
6
+ metadata.gz: f24bf303d7e6fd9f2dd76559673bbf2eed9dff4dfe6e0a14eb6fd1e4311ea9a929522baf23b538752928047d86f641f4384f5834d14a7949f1f7641dd14169a5
7
+ data.tar.gz: 4f249d08e78e8adc31476e12bdeafd49a5269739cfea6e9ff785a6ecf46cac9362986bfde156be498478af9b05bb060c88d955e04316baccdbf5be09ec7eb6ad
@@ -43,9 +43,8 @@ class Board
43
43
 
44
44
  attr_accessor :brd, :wking, :bking, :white_pocket, :black_pocket, :variant, :nodetype, :r50, :drop, :hash, :fullmoves, :wtm, :eat, :from, :to, :score, :promo, :index
45
45
 
46
- def initialize(pos = nil)
46
+ def initialize
47
47
  initme
48
- fen(pos)
49
48
  end
50
49
 
51
50
  def initme
@@ -88,6 +87,11 @@ class Board
88
87
  s
89
88
  end
90
89
 
90
+ def mustbeok
91
+ fail if find_white_king != @wking
92
+ fail if find_black_king != @bking
93
+ end
94
+
91
95
  def wtm2str
92
96
  @wtm ? "w" : "b"
93
97
  end
@@ -114,7 +118,6 @@ class Board
114
118
  end
115
119
 
116
120
  def make_move(me, from, to)
117
- #fail unless (good_coord?(from) && good_coord?(to))
118
121
  @eat = @brd[to]
119
122
  @brd[to] = me
120
123
  @brd[from] = 0
@@ -184,15 +187,15 @@ class Board
184
187
  end
185
188
 
186
189
  def empty?(i)
187
- @brd[i] == 0
190
+ @brd[i].zero?
188
191
  end
189
192
 
190
193
  def walkable_w?(square)
191
- @brd[square] < 1
194
+ @brd[square] <= 0
192
195
  end
193
196
 
194
197
  def walkable_b?(square)
195
- @brd[square] > -1
198
+ @brd[square] >= 0
196
199
  end
197
200
 
198
201
  def is_on_board?(x, y)
@@ -358,8 +361,15 @@ class Board
358
361
  @wtm = s == "w" ? true : false
359
362
  end
360
363
 
364
+ def fen2(s = nil)
365
+ if s.nil?
366
+ fen(START_POS)
367
+ else
368
+ fen(s)
369
+ end
370
+ end
371
+
361
372
  def fen(str)
362
- return if str.nil?
363
373
  initme
364
374
  s = str.strip.split(" ")
365
375
  fail if s.length < 3
@@ -389,6 +399,10 @@ class Board
389
399
  s.strip.length == 0 ? "-" : s
390
400
  end
391
401
 
402
+ def move2str
403
+ move_str
404
+ end
405
+
392
406
  def move_str
393
407
  if @drop != 0
394
408
  s = "#{number2piece(@drop).upcase}@"
@@ -411,16 +425,32 @@ class Board
411
425
  s
412
426
  end
413
427
 
414
- def randpos
428
+ def randpos2
415
429
  copy = RubyShogi::Board.new
416
- copy.brd[rand(0.. 32)] = 14
417
- copy.brd[rand((81-32)..80)] = -14
418
- 32.times { |i| copy.brd[32 + i] = rand(-14..14) if rand < 0.3 }
419
- 3.times { |i| copy.white_pocket.push([1, 3, 5, 7, 9].sample) }
420
- 3.times { |i| copy.black_pocket.push([-1, -3, -5, -7, -9].sample) }
430
+ copy.brd[rand(0..9)] = 14
431
+ copy.brd[rand(71..80)] = -14
432
+ 8.times { |i| copy.brd[32 + i] = rand(-13..13) if rand < 0.3 }
433
+ 3.times { |i| copy.white_pocket.push([1, 3, 5, 7, 9].sample) if rand < 0.3 }
434
+ 3.times { |i| copy.black_pocket.push([-1, -3, -5, -7, -9].sample) if rand < 0.3 }
435
+ copy.wking = copy.find_white_king
436
+ copy.bking = copy.find_black_king
421
437
  copy
422
438
  end
423
439
 
440
+
441
+ def randpos
442
+ brd = nil
443
+ loop do
444
+ brd = randpos2
445
+ brd2 = brd
446
+ mgen = brd.mgen_generator
447
+ next if mgen.checks_b? || mgen.checks_w?
448
+ break
449
+ end
450
+ brd.mustbeok
451
+ brd
452
+ end
453
+
424
454
  def print_board
425
455
  s =""
426
456
  81.times do | i |
@@ -8,7 +8,7 @@ module RubyShogi
8
8
 
9
9
  class Cmd
10
10
  attr_accessor :engine, :random_mode
11
-
11
+
12
12
  def initialize
13
13
  @random_mode = false
14
14
  @tokens = RubyShogi::Tokens.new(ARGV)
@@ -33,26 +33,29 @@ class Cmd
33
33
  end
34
34
 
35
35
  def mbench
36
- suite(peek_argint(4))
36
+ p = RubyShogi::Perft.new
37
+ p.suite(peek_argint(4))
37
38
  end
38
39
 
39
40
  def perft
41
+ n = peek_argint(5)
42
+ puts "~~~ perft( #{n} ) ~~~"
40
43
  p = RubyShogi::Perft.new(@fen)
41
- p.perft(peek_argint(5))
44
+ p.perft(n)
42
45
  end
43
46
 
44
47
  def randperft
45
- n = peek_argint(3)
48
+ n = peek_argint(10)
49
+ puts "~~~ randperft( #{n} ) ~~~"
46
50
  n.times do |i|
47
51
  p = RubyShogi::Perft.new
48
- puts "#{i} / ..."
49
- p.randperft(2)
52
+ p.randperft(2, i, n)
50
53
  end
51
54
  end
52
55
 
53
56
  def suite
54
57
  p = RubyShogi::Perft.new
55
- p.suite(peek_argint(5))
58
+ p.suite(peek_argint(4))
56
59
  end
57
60
 
58
61
  def bench
@@ -61,14 +64,9 @@ class Cmd
61
64
  end
62
65
 
63
66
  def stats
64
- n, val = 100, @tokens.peek(1)
65
- if val != nil && val.match(/\d+/)
66
- @tokens.forward
67
- n = val.to_i
68
- end
69
- e = RubyShogi::Engine.new("falcon", random_mode: @random_mode)
70
- e.board.use_fen(@fen) if @fen != nil
71
- e.stats(n)
67
+ e = RubyShogi::Engine.new(random_mode: @random_mode)
68
+ e.board.fen(@fen) if @fen != nil
69
+ e.stats(peek_argint(100))
72
70
  end
73
71
 
74
72
  def tactics
@@ -82,25 +80,62 @@ class Cmd
82
80
 
83
81
  def list
84
82
  board = RubyShogi::Board.new
85
- board.fen(@fen)
83
+ board.fen2(@fen)
86
84
  mgen = board.mgen_generator
87
85
  moves = mgen.generate_moves
88
- moves.each_with_index { |b, i| puts "> #{i}: #{b.move_str}" }
86
+ mgen.print_move_list
87
+ puts "= #{moves.length} moves"
89
88
  end
89
+
90
+ #def list
91
+ # board = RubyShogi::Board.new
92
+ # board.fen(@fen)
93
+ # mgen = board.mgen_generator
94
+ # moves = mgen.generate_moves
95
+ # moves.each_with_index { |b, i| puts "> #{i}: #{b.move_str}" }
96
+ #end
90
97
 
98
+ def perft_by_moves
99
+ #b = RubyShogi::Board.new
100
+ #b.startpos
101
+ #b.fen("lnsgkgsnl/2r4b1/ppppp+Pp1p/7p1/9/9/PPPPP1PPP/1B5R1/LNSGKGSNL[P] w 1 5")
102
+ #b.fen("9/3k5/7+P1/8P/9/9/6P2/R3K4/1NSG1GSNL[PPPPPPPPPNNBRLLSSGGppppppbl] w 19 100")
103
+ # +P8/9/8L/L3k3R/1KP6/9/3s5/2S6/1+n1g4+B[PPPPPPPPPNBRLLSGpppppppnnsgg] b
104
+ # b.fen("5K3/2+P6/6+P2/9/4k4/9/9/9/9[PPPPPPPPPNNBRLLSSGGpppppppnnbrllssgg] w 67 185")
105
+ #b.fen("8+r/5K3/9/9/9/9/k8/9/9[-] w 24 1")
106
+ #b.fen("9/+l4k3/+P1+r2L1+l1/+l3+B2S1/1n5rR/5+l+l2/9/9/1K7[LGNpgl] w 0 1")
107
+ #b.print_board
108
+ #mgen = b.mgen_generator
109
+ #mgen.generate_moves
110
+
111
+ # 5k3/+n8/1G5R1/2+s+P3b1/n+s2l+B+N2/5s+prp/9/7K1/9 w
112
+ #p = RubyShogi::Perft.new("5k3/+n8/1G5R1/2+s+P3b1/n+s2l+B+N2/5s+prp/9/7K1/9[SPGnpn] w 0 1")
113
+ p = RubyShogi::Perft.new("5k3/+n8/1G5R1/2+s+P3b1/n+s2l+B+N2/5s+prp/9/8K/9[PSGpnn] b 0 1")
114
+
115
+ p.perft_by_moves(peek_argint(1))
116
+ end
117
+
91
118
  def test
92
- b = RubyShogi::Board.new
119
+ #b = RubyShogi::Board.new
93
120
  #b.startpos
94
121
  #b.fen("lnsgkgsnl/2r4b1/ppppp+Pp1p/7p1/9/9/PPPPP1PPP/1B5R1/LNSGKGSNL[P] w 1 5")
95
122
  #b.fen("9/3k5/7+P1/8P/9/9/6P2/R3K4/1NSG1GSNL[PPPPPPPPPNNBRLLSSGGppppppbl] w 19 100")
96
123
  # +P8/9/8L/L3k3R/1KP6/9/3s5/2S6/1+n1g4+B[PPPPPPPPPNBRLLSGpppppppnnsgg] b
97
124
  # b.fen("5K3/2+P6/6+P2/9/4k4/9/9/9/9[PPPPPPPPPNNBRLLSSGGpppppppnnbrllssgg] w 67 185")
98
125
  #b.fen("8+r/5K3/9/9/9/9/k8/9/9[-] w 24 1")
99
- b.fen("2+P+P+P4/8P/3k3+P1/1+b2P1p2/3p2Pp1/2p5l/+p3+p3p/1p+l+p5/+p4K2+p[NNRSSGGnnbrllssgg] b 1 ")
100
- b.print_board
101
- mgen = b.mgen_generator
102
- mgen.generate_moves
103
- mgen.print_move_list
126
+ #b.fen("9/+l4k3/+P1+r2L1+l1/+l3+B2S1/1n5rR/5+l+l2/9/9/1K7[LGNpgl] w 0 1")
127
+ #b.print_board
128
+ #mgen = b.mgen_generator
129
+ #mgen.generate_moves
130
+ # 5k3/+n8/1G5R1/2+s+P3b1/n+s2l+B+N2/5s+prp/9/7K1/9 w
131
+ p = RubyShogi::Perft.new("5k3/+n8/1G5R1/2+s+P3b1/n+s2l+B+N2/5s+prp/9/7K1/9[SPGnpn] w 0 1")
132
+
133
+ p = RubyShogi::Perft.new("7lk/9/8S/9/9/9/9/7L1/8K[P] w 0 1")
134
+
135
+
136
+ p.board.print_board
137
+ p.perft_by_moves(peek_argint(1))
138
+ #p.perft(peek_argint(5))
104
139
  end
105
140
 
106
141
  def print_numbers
@@ -147,6 +182,7 @@ class Cmd
147
182
  puts "-bench: Benchmark ShurikenShogi Engine"
148
183
  puts "-mbench: Benchmark ShurikenShogi Movegen"
149
184
  puts "-perft [NUM]: Run Perft"
185
+ puts "-perft_by_moves [NUM]: Run Perft By Moves"
150
186
  puts "-profile: Profile ShurikenShogi"
151
187
  puts "-randommode: Activate Random Mode"
152
188
  puts "-fen [FEN]: Set Fen"
@@ -170,10 +206,12 @@ class Cmd
170
206
  when "-test" then test
171
207
  when "-name" then name
172
208
  when "-fen" then fen
209
+ when "-list" then list
173
210
  when "-profile" then profile
174
211
  when "-perft" then perft
175
212
  when "-randperft" then randperft
176
213
  when "-suite" then suite
214
+ when "-perft_by_moves" then perft_by_moves
177
215
  when "-numbers" then print_numbers
178
216
  when "-help" then help
179
217
  else
@@ -228,7 +228,6 @@ class Engine
228
228
  else
229
229
  search(moves)
230
230
  moves = func.call
231
- #print_move_list(moves)
232
231
  @board = moves[0]
233
232
  end
234
233
  print_move_list(moves) if @debug
@@ -84,6 +84,28 @@ module Eval
84
84
  end
85
85
 
86
86
  def Eval.material(board)
87
+ board.print_board
88
+ puts Eval.material2(board)
89
+ puts Eval.material3(board)
90
+ fail if Eval.material2(board) != Eval.material3(board)
91
+ 0
92
+ end
93
+
94
+ def Eval.material3(board)
95
+ score = board.brd.inject do |sum, p|
96
+ sum += case p
97
+ when 1..14 then MATERIAL_SCORE[p]
98
+ when -14..-1 then -MATERIAL_SCORE[-p]
99
+ else
100
+ 0
101
+ end
102
+ end
103
+ board.white_pocket.each { |p| score += MATERIAL_HAND_SCORE[p] }
104
+ board.black_pocket.each { |p| score -= MATERIAL_HAND_SCORE[-p] }
105
+ score
106
+ end
107
+
108
+ def Eval.material2(board)
87
109
  score = 0
88
110
  board.brd.each do |p|
89
111
  score += case p
@@ -54,17 +54,8 @@ class Mgen
54
54
  end
55
55
 
56
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
57
+ array.delete_at(array.index(x) || array.length)
58
+ array
68
59
  end
69
60
 
70
61
  def good_coord?(i)
@@ -112,15 +103,16 @@ class Mgen
112
103
  def jump_checks_to?(jumps, here)
113
104
  jumps.each do |jmp|
114
105
  px, py = @x_checks + jmp[0], @y_checks + jmp[1]
115
- return true if px + py * 9 == here
106
+ return true if is_on_board?(px, py) && px + py * 9 == here
116
107
  end
117
108
  false
118
109
  end
119
110
 
120
- def checks_w?#(here)
121
- here = @board.bking
111
+ def checks_w?(here = nil, useking = true)
112
+ here = here == nil ? @board.bking : here
113
+ #fail if @board.find_black_king != here
122
114
  81.times do |i|
123
- @x_checks, @y_checks = i % 9, i / 9
115
+ @x_checks, @y_checks = i % 9, (i / 9).to_i
124
116
  case @board.brd[i]
125
117
  when 1 then return true if pawn_checks_w?(here)
126
118
  when 2 then return true if jump_checks_to?(WHITE_GOLD_GENERAL_MOVES, here)
@@ -135,16 +127,17 @@ class Mgen
135
127
  when 11 then return true if slider_checks_to?(BISHOP_MOVES, here) || jump_checks_to?(PROMOTED_BISHOP_MOVES, here)
136
128
  when 12 then return true if slider_checks_to?(ROOK_MOVES, here)
137
129
  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)
130
+ when 14 then return true if useking && jump_checks_to?(KING_MOVES, here)
139
131
  end
140
132
  end
141
133
  false
142
134
  end
143
-
144
- def checks_b?#(here)
145
- here = @board.wking
135
+
136
+ def checks_b?(here = nil, useking = true)
137
+ here = here == nil ? @board.wking : here
138
+ #fail if @board.find_white_king != here
146
139
  81.times do |i|
147
- @x_checks, @y_checks = i % 9, i / 9
140
+ @x_checks, @y_checks = i % 9, (i / 9).to_i
148
141
  case @board.brd[i]
149
142
  when -1 then return true if pawn_checks_b?(here)
150
143
  when -2 then return true if jump_checks_to?(BLACK_GOLD_GENERAL_MOVES, here)
@@ -159,7 +152,7 @@ class Mgen
159
152
  when -11 then return true if slider_checks_to?(BISHOP_MOVES, here) || jump_checks_to?(PROMOTED_BISHOP_MOVES, here)
160
153
  when -12 then return true if slider_checks_to?(ROOK_MOVES, here)
161
154
  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)
155
+ when -14 then return true if useking && jump_checks_to?(KING_MOVES, here)
163
156
  end
164
157
  end
165
158
  false
@@ -44,14 +44,24 @@ class MgenBlack < RubyShogi::Mgen
44
44
  copy.brd[@from_gen] = 0
45
45
  copy.brd[to] = me
46
46
  copy.bking = to if me == -14
47
- #fail if copy.find_black_king != copy.bking
47
+ copy.mustbeok
48
48
  @board = copy
49
49
  @moves.push << copy if !checks_w?
50
50
  @board = board2
51
51
  end
52
52
 
53
+ def can_white_king_run?(to2)
54
+ x, y = to2 % 9, to2 / 9
55
+ KING_MOVES.each do |jmp|
56
+ px, py = x + jmp[0], y + jmp[1]
57
+ to = px + 9 * py
58
+ return true if is_on_board?(px, py) && @board.walkable_w?(to) && !checks_b?(to, false)
59
+ end
60
+ false
61
+ end
62
+
53
63
  def pawn_drop_checkmate?(to)
54
- @board.brd[to - 9] == 14 && !checks_w?(to - 9) ? true : false
64
+ @board.brd[to - 9] == 14 && (!checks_w?(to, false) && !can_white_king_run?(to - 9)) ? true : false
55
65
  end
56
66
 
57
67
  def add_new_drop_move(me, to)
@@ -59,19 +69,18 @@ class MgenBlack < RubyShogi::Mgen
59
69
  return if me == -5 && to / 9 <= 1
60
70
  board2 = @board
61
71
  copy = @board.copy_me
62
- copy.from = @from_gen
72
+ copy.from = -1
63
73
  copy.to = to
64
74
  copy.drop = me
65
75
  copy.r50 += 1
66
76
  copy.fullmoves += 1
67
77
  copy.eat = 0
68
- copy.wtm = ! copy.wtm
69
- copy.brd[@from_gen] = 0
78
+ copy.wtm = !copy.wtm
70
79
  copy.brd[to] = me
71
80
  copy.black_pocket = remove_from_array(copy.black_pocket, me)
72
- #fail if copy.find_black_king != copy.bking
81
+ copy.mustbeok
73
82
  @board = copy
74
- if !checks_w? && !(me == 1 && pawn_drop_checkmate?(to))
83
+ if !checks_w? && !(me == -1 && pawn_drop_checkmate?(to))
75
84
  @moves.push << copy
76
85
  end
77
86
  @board = board2
@@ -79,7 +88,7 @@ class MgenBlack < RubyShogi::Mgen
79
88
 
80
89
  def handle_promotion?(me, to)
81
90
  return true if must_promote?(me, to)
82
- return false if to / 9 > 2 && @from_gen / 9 > 2
91
+ return false if to / 9 >= 3 && @from_gen / 9 >= 3
83
92
  case me
84
93
  when -1
85
94
  push_move(-1, to, PROMO_STAY)
@@ -163,34 +172,31 @@ class MgenBlack < RubyShogi::Mgen
163
172
  end
164
173
 
165
174
  def pawn_on_column?(c)
166
- ret = false
167
175
  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
176
+ to = 9 * i + c
177
+ return true if to != @from_gen && @board.brd[to] == -1
173
178
  end
174
- ret
179
+ false
175
180
  end
176
181
 
177
182
  def put_pawn_drops
178
183
  (9*8).times do |i2|
179
184
  i = i2 + 9
180
185
  @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
186
+ add_new_drop_move(-1, i) if (!pawn_on_column?(i % 9 ) && @board.brd[i].zero?)
182
187
  end
183
188
  end
184
189
 
185
190
  def put_drops(piece)
186
191
  81.times do |i|
187
192
  @x_gen, @y_gen, @from_gen = i % 9, i / 9, i
188
- add_new_drop_move(piece, i) if @board.brd[i] == 0
193
+ add_new_drop_move(piece, i) if @board.brd[i].zero?
189
194
  end
190
195
  end
191
196
 
192
197
  def generate_drops
193
- @board.black_pocket.each do |piece|
198
+ nodub = @board.black_pocket.dup.uniq
199
+ nodub.each do |piece|
194
200
  case piece
195
201
  when -1 then put_pawn_drops
196
202
  when -3 then put_drops(-3)
@@ -209,7 +215,6 @@ class MgenBlack < RubyShogi::Mgen
209
215
  @moves = []
210
216
  81.times do |i|
211
217
  @x_gen, @y_gen, @from_gen = i % 9, i / 9, i
212
- #puts @board.brd[i]
213
218
  case @board.brd[i]
214
219
  when -1 then generate_pawn_moves
215
220
  when -2 then generate_jump_moves(BLACK_GOLD_GENERAL_MOVES, -2)
@@ -26,34 +26,43 @@ class MgenWhite < RubyShogi::Mgen
26
26
  copy.brd[@from_gen] = 0
27
27
  copy.brd[to] = me
28
28
  copy.wking = to if me == 14
29
- #fail if copy.find_white_king != copy.wking
29
+ copy.mustbeok
30
30
  @board = copy
31
31
  @moves.push << copy if !checks_b?
32
32
  @board = board2
33
33
  end
34
34
 
35
+ def can_black_king_run?(to2)
36
+ x, y = to2 % 9, to2 / 9
37
+ KING_MOVES.each do |jmp|
38
+ px, py = x + jmp[0], y + jmp[1]
39
+ return true if is_on_board?(px, py) && @board.walkable_b?(px + 9 * py) && !checks_w?(px + 9 * py, false)
40
+ end
41
+ false
42
+ end
43
+
35
44
  def pawn_drop_checkmate?(to)
36
- @board.brd[to + 9] == -14 && !checks_b?(to + 9) ? true : false
45
+ @board.brd[to + 9] == -14 && (!checks_b?(to, false) && !can_black_king_run?(to + 9)) ? true : false
37
46
  end
38
47
 
39
48
  def add_new_drop_move(me, to)
40
49
  return if me == 3 && to / 9 == 8
41
50
  return if me == 5 && to / 9 >= 7
51
+ fail if !@board.brd[to].zero?
42
52
  board2 = @board
43
53
  copy = @board.copy_me
44
- copy.from = @from_gen
54
+ copy.from = -1
45
55
  copy.to = to
46
56
  copy.drop = me
47
57
  copy.eat = 0
48
58
  copy.r50 += 1
49
59
  copy.fullmoves += 1
50
- copy.wtm = ! copy.wtm
51
- copy.brd[@from_gen] = 0
60
+ copy.wtm = !copy.wtm
52
61
  copy.brd[to] = me
53
62
  copy.white_pocket = remove_from_array(copy.white_pocket, me)
54
- #fail if copy.find_white_king != copy.wking
63
+ copy.mustbeok
55
64
  @board = copy
56
- if !checks_b? && !(me == -1 && pawn_drop_checkmate?(to))
65
+ if !checks_b? && !(me == 1 && pawn_drop_checkmate?(to))
57
66
  @moves.push << copy
58
67
  end
59
68
  @board = board2
@@ -164,33 +173,30 @@ class MgenWhite < RubyShogi::Mgen
164
173
  end
165
174
 
166
175
  def pawn_on_column?(c)
167
- ret = false
168
176
  9.times do |i|
169
177
  to = 9 * i + c
170
- if to != @from_gen && @board.brd[to] == 1
171
- ret = true
172
- break
173
- end
178
+ return true if to != @from_gen && @board.brd[to] == 1
174
179
  end
175
- ret
180
+ false
176
181
  end
177
182
 
178
183
  def put_pawn_drops
179
184
  (9*8).times do |i|
180
185
  @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
186
+ add_new_drop_move(1, i) if !pawn_on_column?(i % 9 ) && @board.brd[i].zero?
182
187
  end
183
188
  end
184
189
 
185
190
  def put_drops(piece)
186
191
  81.times do |i|
187
192
  @x_gen, @y_gen, @from_gen = i % 9, i / 9, i
188
- add_new_drop_move(piece, i) if @board.brd[i] == 0
193
+ add_new_drop_move(piece, i) if @board.brd[i].zero?
189
194
  end
190
195
  end
191
196
 
192
197
  def generate_drops
193
- @board.white_pocket.each do |piece|
198
+ nodub = @board.white_pocket.dup.uniq
199
+ nodub.each do |piece|
194
200
  case piece
195
201
  when 1 then put_pawn_drops
196
202
  when 3 then put_drops(3)
@@ -200,6 +206,8 @@ class MgenWhite < RubyShogi::Mgen
200
206
  when 10 then put_drops(10)
201
207
  when 11 then put_drops(11)
202
208
  when 12 then put_drops(12)
209
+ else
210
+ fail
203
211
  end
204
212
  end
205
213
  @moves
@@ -9,18 +9,50 @@ module RubyShogi
9
9
  class Perft
10
10
  attr_accessor :board
11
11
 
12
- NUMS = { # https://groups.google.com/forum/#!topic/shogi-l/U7hmtThbk1k
13
- 0 => 1,
14
- 1 => 30,
15
- 2 => 900,
16
- 3 => 25470,
17
- 4 => 719731,
18
- 5 => 19861490,
19
- 6 => 547581517
20
- }
12
+ SUITE = [
13
+
14
+ {
15
+ # https://groups.google.com/forum/#!topic/shogi-l/U7hmtThbk1k
16
+ "fen" => "lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL[-] w 0 1",
17
+ "numbers" => [
18
+ 1,
19
+ 30,
20
+ 900,
21
+ 25470,
22
+ 719731,
23
+ 19861490,
24
+ 547581517
25
+ ]
26
+ },
27
+ {
28
+ # http://talkchess.com/forum3/viewtopic.php?f=7&t=32014
29
+ "fen" => "7lk/9/8S/9/9/9/9/7L1/8K[P] w 0 1",
30
+ "numbers" => [
31
+ 1,
32
+ 85,
33
+ 639,
34
+ 10786,
35
+ 167089,
36
+ 3458811
37
+ ]
38
+ },
39
+ {
40
+ "fen" => "2k6/L8/+b6p1/+b1+b2+n2P/5P1s+N/9/9/7K1/9[LPPpsn] w 0 1",
41
+ "numbers" => [
42
+ 1,
43
+ 122,
44
+ 26689,
45
+ 0,#2308091,
46
+ 0,
47
+ 0,
48
+ 0
49
+ ]
50
+ }
51
+ ]
21
52
 
22
53
  def initialize(fen = nil)
23
- @board = RubyShogi::Board.new(fen)
54
+ @board = RubyShogi::Board.new
55
+ @board.fen2(fen)
24
56
  end
25
57
 
26
58
  def perft_number(depth)
@@ -37,13 +69,36 @@ class Perft
37
69
  n
38
70
  end
39
71
 
40
- def randperft(depth)
72
+ def randperft(depth, i, n)
41
73
  @board = @board.randpos
74
+ puts "\n[ Round: #{i+1} / #{n} ]"
42
75
  perft(depth)
43
76
  end
44
77
 
78
+ def perft_by_moves(depth=2)
79
+ puts "~~~ perft_by_numbers( #{depth} ) ~~~"
80
+ puts "[ fen: #{@board.pos2fen} ]"
81
+ total_time = 0
82
+ total_nodes = 0
83
+ copy = @board
84
+ mgen = @board.mgen_generator
85
+ n, moves = 0, mgen.generate_moves
86
+ moves.each_with_index do |m, i|
87
+ @board = m
88
+ start = Time.now
89
+ nn = perft_number(depth-1)
90
+ diff = Time.now - start
91
+ total_time += diff
92
+ total_nodes += nn
93
+ puts "#{i+1}: #{m.move2str}: #{nn}"
94
+ #break
95
+ end
96
+ @board = copy
97
+ puts "= #{total_nodes} | #{total_time.round(3)}s | #{(total_nodes/total_time).to_i} nps"
98
+ end
99
+
45
100
  def perft(depth)
46
- puts "~~~ perft( #{depth} ) ~~~"
101
+ #puts "~~~ perft( #{depth} ) ~~~"
47
102
  puts "[ fen: #{@board.pos2fen} ]"
48
103
  total_time = 0
49
104
  total_nodes = 0
@@ -62,25 +117,34 @@ class Perft
62
117
  puts "= #{total_nodes} | #{total_time.round(3)}s | #{(total_nodes/total_time).to_i} nps"
63
118
  end
64
119
 
65
- def suite(depth)
66
- puts "~~~ suite( #{depth} ) ~~~"
67
- total_time = 0
68
- total_nodes = 0
69
- copy = @board
120
+ def run_suite(data, i2, depth)
121
+ fen, nums = data["fen"], data["numbers"]
122
+ puts "[ round: #{i2+1} / #{SUITE.length} ]"
123
+ puts "[ fen: #{fen} ]"
124
+ total_nodes, total_time = 0, 0
125
+ @board = RubyShogi::Board.new
126
+ @board.fen2(fen)
70
127
  (depth+1).times do |i|
128
+ break if nums[i] == 0
71
129
  start = Time.now
72
- @board = copy
73
130
  n = perft_number(i)
74
131
  diff = Time.now - start
75
- total_time += diff
76
132
  total_nodes += n
133
+ total_time += diff
77
134
  nps = (diff == 0 or n == 1) ? n : (n / diff).to_i
78
- error = ["ok", "error"][NUMS[i] - n == 0 ? 0 : 1]
79
- break if i >= NUMS.length - 1
135
+ error = ["ok", "error"][nums[i] - n == 0 ? 0 : 1]
136
+ break if i >= nums.length - 1
80
137
  puts "#{i}: #{n} | #{diff.round(3)}s | #{nps} nps | #{error}"
81
138
  end
82
139
  total_time = 1 if total_time == 0
83
- puts "= #{total_nodes} | #{total_time.round(3)}s | #{(total_nodes/total_time).to_i} nps"
140
+ puts "= #{total_nodes} | #{total_time.round(3)}s | #{(total_nodes/total_time).to_i} nps\n\n"
141
+ end
142
+
143
+ def suite(depth)
144
+ puts "~~~ suite( #{depth} ) ~~~"
145
+ start = Time.now
146
+ total_nodes = 0
147
+ SUITE.each_with_index { |s, i| run_suite(s, i, depth) }
84
148
  end
85
149
  end # class Perft
86
150
 
@@ -40,7 +40,7 @@ $stderr.reopen("ruby_shogi-error.txt", "a+")
40
40
 
41
41
  module RubyShogi
42
42
  NAME = "RubyShogi"
43
- VERSION = "0.2"
43
+ VERSION = "0.22"
44
44
  AUTHOR = "Toni Helminen"
45
45
 
46
46
  def RubyShogi.init
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: RubyShogi
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.2'
4
+ version: '0.22'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Toni Helminen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-13 00:00:00.000000000 Z
11
+ date: 2019-10-15 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: RubyShogi, a Shogi Engine
14
14
  email: kalleankka1@gmail.com