Page 1 of 2

fixing CPW-engine

Posted: Tue Dec 30, 2014 9:02 pm
by PK
In 2008 me and Edmund Moshammer wrote a thing called CPW-Engine, attempting it to be a didactic piece of code for Chessprogramming Wiki. It succeeded only as a self-learning exercise, because at that time both of us knew next to nothing about chess programming. Nevertheless that sin against all principles of good coding has been accessible on the Chessprogramming Wiki, and sometimes even some of the code snippets were referred to on this very forum.

About a month ago I looked at that code again and decided that showing 2008 version to the public is plain wrong. Today a slightly less wrong version has been uploaded, both at the wiki and under the following link.

https://github.com/nescitus/cpw-engine

It is still wrong in many places, but at least some bad decisions were revoked and some misconceptions cleared. Changes include:

- adding late move reduction
- changing hash retrieval logic in PV nodes
- changing futility pruning logic
- adding static eval pruning
- deleting lots of garbage from eval function
- interpolating between midgame and endgame scores

Probably it does not make sense to test this engine, as its only purpose was to show a couple of chess programming techniques. It should perform a bit better than Sungorus, which makes it uninteresting from competitive standpoint. If somebody wants to improve it - fine, but IMHO the only thing that makes sense would be to make code more readable and gradually remove some more idiocies that are left in the source.

Re: fixing CPW-engine

Posted: Tue Dec 30, 2014 10:33 pm
by cdani
In the starts of Andscacs, CPW-engine was of incredible help!! Thanks for it!!

Re: fixing CPW-engine

Posted: Wed Dec 31, 2014 2:20 pm
by sedicla
Good job Pawel !
I also used CPW-Engine in the beginning, tremendous help. Keep it up!
Thanks.

Re: fixing CPW-engine

Posted: Wed Dec 31, 2014 2:22 pm
by vittyvirus
Is it a bitboard engine?

Re: fixing CPW-engine

Posted: Wed Dec 31, 2014 2:25 pm
by sedicla
vittyvirus wrote:Is it a bitboard engine?
No, it uses 0x88 board representation.

Re: fixing CPW-engine

Posted: Wed Dec 31, 2014 2:47 pm
by hgm
How is "static eval pruning" different from "futility pruning"?

Re: fixing CPW-engine

Posted: Wed Dec 31, 2014 4:37 pm
by PK
eval pruning/ static null move prunes a node without searching forcing moves. It's like a stand pat with a margin. or like a null move with search replaced by eval - margin. I must admit I am surprised that it works at mediocre depths reached by CPW-engine.

Re: fixing CPW-engine

Posted: Wed Dec 31, 2014 6:39 pm
by vittyvirus
sedicla wrote:
vittyvirus wrote:Is it a bitboard engine?
No, it uses 0x88 board representation.
You guya should then create a bitboard CPW engine. It'd help much.

Re: fixing CPW-engine

Posted: Thu Jan 01, 2015 3:55 pm
by hgm
PK wrote:eval pruning/ static null move prunes a node without searching forcing moves. It's like a stand pat with a margin. or like a null move with search replaced by eval - margin. I must admit I am surprised that it works at mediocre depths reached by CPW-engine.
But that is exactly what futility pruning does, right? Pruning a node because you already know that this node will fail high already by merely standing pat. Futilty pruning is just an efficient implemantation of standing pat.

Re: fixing CPW-engine

Posted: Thu Jan 01, 2015 6:24 pm
by Gerd Isenberg
hgm wrote:
PK wrote:eval pruning/ static null move prunes a node without searching forcing moves. It's like a stand pat with a margin. or like a null move with search replaced by eval - margin. I must admit I am surprised that it works at mediocre depths reached by CPW-engine.
But that is exactly what futility pruning does, right? Pruning a node because you already know that this node will fail high already by merely standing pat. Futilty pruning is just an efficient implemantation of standing pat.
Yep, static null move pruning (Stockfish term) is also called Reverse Futility Pruning, often implemented in conjunction with classical fultility pruning inside the move loop as pre-filter, see Texel or cpw-engine, here the relevant snippets:

Code: Select all

/************************************************************************
    * EVAL PRUNING / STATIC NULL MOVE                                       *
    ************************************************************************/
 
    if &#40;depth < 3
        && (!is_pv&#41;
        && (!flagInCheck&#41;
        && &#40;abs&#40;beta - 1&#41; > -INF+100&#41;) 
    &#123;
        int static_eval = eval&#40;alpha, beta, 1&#41;;
 
        int eval_margin = 120 * depth;
        if &#40;static_eval - eval_margin >= beta&#41;
            return static_eval - eval_margin;
    &#125;
 
    ...

    /************************************************************************
    *  Decide  if FUTILITY PRUNING  is  applicable. If we are not in check, *
    *  not searching for a checkmate and eval is below  &#40;alpha - margin&#41;,   *
    *  it  might  mean that searching non-tactical moves at  low depths     *
    *  is futile, so we set a flag allowing this pruning.                   *
    ************************************************************************/
 
    int fmargin&#91;4&#93; = &#123;0, 200, 300, 500&#125;;
 
    if ( depth <= 3
    &&   !is_pv
    &&   !flagInCheck
    &&   abs&#40;alpha&#41; < 9000
    &&   eval&#40;alpha,beta, 1&#41; + fmargin&#91;depth&#93; <= alpha )
    f_prune = 1;

    /************************************************************************
    *  Now it's time to loop through the move list.                         *
    ************************************************************************/

    for &#40;int i = 0; i < mcount; i++) &#123;
        move_make&#40;move&#41;;

        if ( f_prune
        &&  !move_iscapt&#40;move&#41;
        &&  !move_isprom&#40;move&#41; 
        &&  !isAttacked&#40; !b.stm, b.KingLoc&#91;b.stm&#93; )  ) &#123;
                move_unmake&#40;move&#41;;
                continue;
        &#125;