Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

removalBasedOnMillCounts: Removel bits count is not enough #890

Open
calcitem opened this issue Dec 29, 2024 · 1 comment
Open

removalBasedOnMillCounts: Removel bits count is not enough #890

calcitem opened this issue Dec 29, 2024 · 1 comment
Labels
bug Something isn't working

Comments

@calcitem
Copy link
Owner

  void _updateKeyMisc() {
    st.key = st.key << _Zobrist.keyMiscBit >> _Zobrist.keyMiscBit;

    // TODO: pieceToRemoveCount[sideToMove] or
    // abs(pieceToRemoveCount[sideToMove] - pieceToRemoveCount[~sideToMove])?
    // TODO: If pieceToRemoveCount[sideToMove]! <= 3,
    //  the top 2 bits can store its value correctly;
    //  if it is greater than 3, since only 2 bits are left,
    //  the storage will be truncated or directly get 0,
    //  and the original value cannot be completely retained.
    st.key |= pieceToRemoveCount[sideToMove]! << (32 - _Zobrist.keyMiscBit);
  }
@calcitem calcitem added the bug Something isn't working label Dec 29, 2024
@calcitem
Copy link
Owner Author

In this code, pieceToRemoveCount[sideToMove] itself can be negative or positive. In Dart, when shifting a negative number left (<<) or right (>>), an arithmetic shift is used instead of a logical shift. That is, if pieceToRemoveCount[sideToMove] is negative, the high bits after the shift will be filled with the sign bit instead of simply padding the high bits with zeros.

If you just want the "sign difference" of pieceToRemoveCount[sideToMove] to be included in the hash calculation, then you can just shift it directly without any additional processing. Negative numbers will produce completely different shift results from positive numbers, making the high bits of the final st.key completely different, which is feasible for hashing.

If you only want to keep its absolute value (i.e. store it as a positive number regardless of whether it is positive or negative), then you have to manually take the absolute value and then shift it, for example:

st.key |= pieceToRemoveCount[sideToMove]!.abs() << (32 - _Zobrist.keyMiscBit);

But please note that if you only use _Zobrist.keyMiscBit = 2 bits to store, then there are 7 states from -3 to +3, and only 2 bits (4 states) are not enough to represent the entire range. If this is just "taking a few random bits as some extra states" to interfere with the hash, and no one stipulates that all numerical ranges must be covered, then it doesn't matter. Anyway, the extra values ​​may be truncated or only take the lower two bits after shifting or taking the mask.

So whether to "change it to a positive number if it is a negative number and then |" depends on the semantics you want:

• If it is for hashing purposes, negative numbers and positive numbers produce different high-bit characteristics, and usually do not need to be specifically changed to positive numbers.
• If you want to represent a certain range (for example, 0~3), and pieceToRemoveCount[sideToMove] may have negative numbers, but you don't want them to interfere with the high-order bits, you can manually take the absolute value and then shift it, or do further logical processing on the value (for example, & 0x03, or do a range clipping).

In short, it works without special processing; if you want to "only keep the absolute value" or "only take a few bits" and then participate in the hash, additional explicit processing is required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant