3

From Gigantua, the fastest chess move generator, it says that

The same holds true for the castling squares and most importantly the current moving color becomes a compiletime template and not an if statement. No single if statement should be wasted on non existing moves or which colors move it currently is.

...

We have 6 independent boolean board state flags - and none of these will ever need a single if during runtime. The cost of having if (Color == White) or Attack[Color] compiles away into nothingness. We only need a single switch statement as an entry point

Here is the struct used for the current game state:

class BoardStatus {

public:
    const bool WhiteMove;  const bool HasEPPawn;
    const bool WCastleL; const bool WCastleR;
    const bool BCastleL; const bool BCastleR;

    constexpr BoardStatus(bool white, bool ep, bool wcast_left, 
    bool wcast_right, bool bcast_left, bool bcast_right) :
        WhiteMove(white), HasEPPawn(ep), WCastleL(wcast_left), 
        WCastleR(wcast_right), BCastleL(bcast_left), BCastleR(bcast_right)
    {

    }
}

Because of the constructor, this implies that a new BoardStatus structure will be created for every turn. How can that be efficient?

For example, how does this reduce the number of if statements, because you still have to check the value of the WhiteMove boolean?

1
  • 1
    You do not show any of the template code that is mentioned in the text.
    – Carsten S
    Commented Jul 16, 2022 at 10:25

1 Answer 1

6

Notice, that the constructor for BoardStatus is constexpr (btw, this question on SO is an interesting extra read on the topic). So, you should think of BoardStatus as a Literal Type, which allows many interesting things to be done with it during the compilation by the compiler (as opposed to runtime calculations), including the elimination of many if statements.

The particular details would depend a lot on how this class is used, but, I would say, that constexpr is the key to the understanding of the quoted explanations.

4
  • Because constexpr is evaluated at compile-time, how would this work because you cannot be certain of the states of the variables in the class? Also, how would you get around checking if (WhiteMove){ //do something} else { //do something}?
    – BanjoMan
    Commented Jul 15, 2022 at 23:29
  • 3
    @BanjoMan 1) when you are able to write if constexpr () - this is compile-time. I am certain a bunch of uses of this class is done this way. 2) when used as a template parameter 3) when it is used as synax sugar allowing to generate the necessary version of the code/code path eliminating actual branching. Commented Jul 16, 2022 at 1:52
  • 1
    @BanjoMan Afaik it's basically like Anton describes, this generates code for all different cases. So you end up with a quite large executable and a very long compile time. Once compiled it then is super fast though. (whether this is useful when writing a chess engine is up for debate)
    – koedem
    Commented Jul 16, 2022 at 3:29
  • 1
    I think your comment is the actual answer, the question does not contain the interesting parts of the code. The constexpr itself would make no difference, the optimiser will do its job without it, too.
    – Carsten S
    Commented Jul 16, 2022 at 11:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.