line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#! /bin/false |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# Copyright (C) 2021 Guido Flohr , |
4
|
|
|
|
|
|
|
# all rights reserved. |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
# This program is free software. It comes without any warranty, to |
7
|
|
|
|
|
|
|
# the extent permitted by applicable law. You can redistribute it |
8
|
|
|
|
|
|
|
# and/or modify it under the terms of the Do What the Fuck You Want |
9
|
|
|
|
|
|
|
# to Public License, Version 2, as published by Sam Hocevar. See |
10
|
|
|
|
|
|
|
# http://www.wtfpl.net/ for more details. |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
package Chess::Plisco::Engine::TranspositionTable; |
13
|
|
|
|
|
|
|
$Chess::Plisco::Engine::TranspositionTable::VERSION = '0.4'; |
14
|
11
|
|
|
11
|
|
57535
|
use strict; |
|
11
|
|
|
|
|
30
|
|
|
11
|
|
|
|
|
322
|
|
15
|
11
|
|
|
11
|
|
472
|
use integer; |
|
11
|
|
|
|
|
31
|
|
|
11
|
|
|
|
|
64
|
|
16
|
|
|
|
|
|
|
|
17
|
11
|
|
|
11
|
|
607
|
use Chess::Plisco::Engine::Tree; |
|
11
|
|
|
|
|
28
|
|
|
11
|
|
|
|
|
252
|
|
18
|
|
|
|
|
|
|
|
19
|
11
|
|
|
11
|
|
49
|
use constant TT_ENTRY_SIZE => 16; |
|
11
|
|
|
|
|
21
|
|
|
11
|
|
|
|
|
506
|
|
20
|
|
|
|
|
|
|
|
21
|
11
|
|
|
11
|
|
54
|
use constant TT_SCORE_EXACT => 0; |
|
11
|
|
|
|
|
22
|
|
|
11
|
|
|
|
|
413
|
|
22
|
11
|
|
|
11
|
|
56
|
use constant TT_SCORE_ALPHA => 1; |
|
11
|
|
|
|
|
20
|
|
|
11
|
|
|
|
|
448
|
|
23
|
11
|
|
|
11
|
|
48
|
use constant TT_SCORE_BETA => 2; |
|
11
|
|
|
|
|
27
|
|
|
11
|
|
|
|
|
620
|
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
our @EXPORT = qw(TT_SCORE_EXACT TT_SCORE_ALPHA TT_SCORE_BETA); |
26
|
|
|
|
|
|
|
|
27
|
11
|
|
|
11
|
|
66
|
use base qw(Exporter); |
|
11
|
|
|
|
|
20
|
|
|
11
|
|
|
|
|
4645
|
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
sub new { |
30
|
308
|
|
|
308
|
0
|
5989
|
my ($class, $size) = @_; |
31
|
|
|
|
|
|
|
|
32
|
308
|
|
|
|
|
723
|
my $self = []; |
33
|
308
|
|
|
|
|
779
|
bless $self, $class; |
34
|
|
|
|
|
|
|
|
35
|
308
|
|
|
|
|
1106
|
return $self->resize($size); |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
sub clear { |
39
|
310
|
|
|
310
|
0
|
650
|
my ($self) = @_; |
40
|
|
|
|
|
|
|
|
41
|
310
|
|
|
|
|
644
|
my $size = @$self; |
42
|
|
|
|
|
|
|
|
43
|
310
|
|
|
|
|
1280
|
$#$self = 0; |
44
|
310
|
|
|
|
|
828
|
$#$self = $size; |
45
|
|
|
|
|
|
|
|
46
|
310
|
|
|
|
|
541
|
return $self; |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
sub resize { |
50
|
309
|
|
|
309
|
0
|
1809
|
my ($self, $size) = @_; |
51
|
|
|
|
|
|
|
|
52
|
309
|
|
|
|
|
1215
|
$self->clear; |
53
|
309
|
|
|
|
|
27103
|
$#$self = (1024 * 1024 / TT_ENTRY_SIZE) - 1; |
54
|
|
|
|
|
|
|
|
55
|
309
|
|
|
|
|
3328
|
return $self; |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
sub probe { |
59
|
1482449
|
|
|
1482449
|
0
|
2462751
|
my ($self, $lookup_key, $depth, $alpha, $beta, $bestmove) = @_; |
60
|
|
|
|
|
|
|
|
61
|
1482449
|
100
|
|
|
|
3889211
|
my $entry = $self->[$lookup_key % scalar @$self] or return; |
62
|
|
|
|
|
|
|
|
63
|
569325
|
|
|
|
|
1232803
|
my ($stored_key, $payload) = @$entry; |
64
|
569325
|
100
|
|
|
|
1338293
|
return if $stored_key != $lookup_key; |
65
|
|
|
|
|
|
|
|
66
|
174685
|
|
|
|
|
507418
|
my ($edepth, $flags, $value, $move) = unpack 's4', $payload; |
67
|
174685
|
100
|
|
|
|
359057
|
$$bestmove = $move if $move; |
68
|
|
|
|
|
|
|
|
69
|
174685
|
100
|
|
|
|
329973
|
if ($edepth >= $depth) { |
70
|
161005
|
100
|
|
|
|
299219
|
if ($flags == TT_SCORE_EXACT) { |
71
|
108555
|
100
|
|
|
|
254177
|
if ($value <= Chess::Plisco::Engine::Tree::MATE |
|
|
100
|
|
|
|
|
|
72
|
|
|
|
|
|
|
+ Chess::Plisco::Engine::Tree::MAX_PLY) { |
73
|
18
|
|
|
|
|
40
|
$value += ($edepth - $depth); |
74
|
|
|
|
|
|
|
} elsif ($value >= -Chess::Plisco::Engine::Tree::MATE |
75
|
|
|
|
|
|
|
- Chess::Plisco::Engine::Tree::MAX_PLY) { |
76
|
31
|
|
|
|
|
64
|
$value -= ($edepth - $depth); |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
108555
|
|
|
|
|
251567
|
return $value; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
52450
|
100
|
100
|
|
|
145958
|
if (($flags == TT_SCORE_ALPHA) && ($value <= $alpha)) { |
83
|
7992
|
|
|
|
|
22289
|
return $alpha; |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
44458
|
100
|
100
|
|
|
134322
|
if (($flags == TT_SCORE_BETA) && ($value >= $beta)) { |
87
|
14392
|
|
|
|
|
38227
|
return $beta; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
43746
|
|
|
|
|
95176
|
return; |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub store { |
95
|
895588
|
|
|
895588
|
0
|
1426637
|
my ($self, $key, $depth, $flags, $value, $move) = @_; |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
# Replacement scheme is currently replace-always. We must make sure that |
98
|
|
|
|
|
|
|
# only the significant bits of the best move are stored. |
99
|
895588
|
|
|
|
|
2389541
|
my $payload = pack 's4', $depth, $flags, $value, $move & 0x7fff; |
100
|
|
|
|
|
|
|
|
101
|
895588
|
|
|
|
|
2750202
|
$self->[$key % scalar @$self] = [$key, $payload]; |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
1; |