Author: Dann Corbit
Date: 17:53:50 06/05/03
Go up one level in this thread
On June 05, 2003 at 20:11:27, Geoff wrote:
>Hi Dan
>
>>> /* NULL_R = 2 */
>>> nullScore = -search(-beta, -beta+1, depth-NULL_R-1, FALSE);
>>
>>In the above:
>>No adjustment to ply depth during null move?
>
>Not sure what you mean ? The Null move search is called with param (depth - 3)
>so reducing the search depth for the null move.
>
>>The takeback does not seem to have enough information restored to me, but I
>>don't know your data structures.
>
>Data structures are pretty much as TSCP, I think it is ok as it is because it
>vastly speeds up my search and doesnt make any obviously buggy or totally stupid
>moves with the null move code enabled. However if I play a number of games
>against earlier versions of the program prior to Null move, they older code
>quite easily wins !
Here is the code from some version of Beowulf:
/* -----------==== PROBE TRANSPOSITION TABLE ====------------ */
/* See if this position is in the hash table */
Entry = HashProbe(B);
/* ------------==== GET INFORMATION FROM HASH TABLE ====------------- */
/* See what we can learn from the hash table entry (if any exists) */
if (USE_HASH && Entry) {
/* Get the suggested best move from the hash entry (if there is one) */
hashmove = Entry->move;
EntryType = GetHashType(Entry->flags);
EntryScore = (int) Entry->score;
/* Only accept this hash entry if the level to which it was initially
* searched was greater than or equal to the current depth. Don't
* check at ply==0 so that we're sure we can get a return value. */
if (ply > 0 && ((int) Entry->depth >= depth || (EntryType == HASH_EXACT
&& IsCM(EntryScore) == 1))) {
/* This was an exact entry so return it */
switch (EntryType) {
case (HASH_EXACT):
return EntryScore;
/* This was an upper bound, but still isn't greater than
* alpha, so return a fail-low */
case (HASH_UPPER):
if (EntryScore <= talpha)
return EntryScore;
/* This was an upper bound, but was greater than alpha, so
* adjust beta if necessary */
if (EntryScore < tbeta)
tbeta = EntryScore;
break;
/* This was a lower bound, but was still greater than beta,
* so return a fail-high */
case (HASH_LOWER):
if (EntryScore >= tbeta)
return EntryScore;
/* This was a lower bound, but was not greater than beta, so
* adjust alpha if necessary */
if (EntryScore > talpha)
talpha = EntryScore;
break;
/* Check to see if we should avoid null moves */
case (HASH_NULL):
DoNull = FALSE;
break;
}
}
}
/* -----------==== TRY A NULL MOVE ====------------- */
/* Perform a NULL move if; (1) We're not on the first 2 plies (2) We are
* OK to NULL move at this position (from the hash table) (3) We haven't
* done more than one NULL move consecutively (The 'Double Null Move'
* algorithm) (4) We're not in check (5) There are enough pieces left to
* avoid high risk of zugzwang (6) We're on skill level 5 or higher */
if (USE_NULL && ply > 1 && DoNull && NullDepth < 2 && !inchk &&
(nullreduction = NullOK(B, depth)) && Skill > 4) {
/* Increase the NULL reduction by one ply to account for the fact
* that we've passed on this move. */
nullreduction += ONEPLY;
/* Set up temporary flags to store the board position */
ep_carry = B->ep;
B->ep = -1;
/* Do the null move reduced-depth search */
B->side = Opponent(B->side);
if (depth - nullreduction < ONEPLY)
score = -Quiesce(B, -tbeta, -tbeta + 1, ply + 1, 0, 0);
else
score = -Search(B, -tbeta, -tbeta + 1, depth - nullreduction, ply +
1, 0, 0, NullDepth + 1, NO_MOVE);
/* Put things back */
B->side = Opponent(B->side);
/* Verification Search. Here we re-search this node at a shallower
* depth if the score is >= beta. The reason we do this is simple:
* we want to make sure that this really is a strong node, and
* therefore worth chopping. This time, instead of actually making a
* NULL move, we play a proper move. Note that we don't bother doing
* this when close to the frontier nodes (this would take us into the
* qsearch). We only fail high if this second search ALSO fails
* high. */
if (USE_VERIFICATION && score >= tbeta && depth - nullreduction >=
ONEPLY)
score = Search(B, tbeta - 1, tbeta, depth - nullreduction, ply + 1,
0, fifty, NullDepth + 1, LastMove);
/* Replace the En-Passant flag */
B->ep = ep_carry;
/* If this move returned CM then we must be careful because there is
* a CM threat dangerously close! Only do this on highest skill
* level. */
if (IsCM(score) == -1 && Skill == 10)
threat = TRUE;
/* A fail high means that the positional score here is so high that
* even if the opponent is given a 'free move' then he still can't
* improve his position enough to increase the value of alpha. If
* this is the case then clearly the current position is very strong.
* In fact it is so strong that the opponent would never let it occur
* in the first place, so we should cause a cut off. */
if (score >= tbeta) {
HashUpdate(B, score, BestMoveRet, depth + ONEPLY - nullreduction,
HASH_LOWER, FALSE, ply);
return score;
}
}
Yours might be a bit simpler since you are not hashing.
I can't really see what's wrong with your code, to tell the truth.
You might set up some board with an obvious set of really 3-4 bad moves and one
good one and trace it to see what is happening.
For instance, here:
[D]r3k3/2ppp3/Qp6/np6/8/8/8/3K4 w - -
Most of the really dumb moves should obvously be trimmed by null move.
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.