aboutsummaryrefslogtreecommitdiff
path: root/include/zobrist.c
diff options
context:
space:
mode:
authortslil clingman <tslil@posteo.de>2021-01-26 23:54:46 -0500
committertslil <tslil@posteo.de>2026-08-28 19:37:41 +0100
commit8f15c1131342376ab3de2c6ce50d1ca5f20ec32a (patch)
tree7f6a165878ab3a43bb0f5203d20db5e0979a1933 /include/zobrist.c
parent6b48baaf6b67cc7364d5945eb6d9b25ea9683bd9 (diff)
I don't have the presence of mind to debug this right now
Diffstat (limited to 'include/zobrist.c')
-rw-r--r--include/zobrist.c75
1 files changed, 52 insertions, 23 deletions
diff --git a/include/zobrist.c b/include/zobrist.c
index 8eeb758..6208339 100644
--- a/include/zobrist.c
+++ b/include/zobrist.c
@@ -60,8 +60,9 @@ zobrist_apply(const action_t action, uint64_t hash) {
const enum A_TYPE type = GET_TYPE(action);
const int8_t loc = GET_LOC(action);
if (type == A_PLACE) {
+ enum COLOUR c = (current_colour == C_BLACK) ? C_WHITE : C_BLACK;
hash ^= zobrist[0][loc*(2*3+1)
- +current_colour*3
+ +c*3
+GET_DATA0(action)];
} else {
const uint8_t gaps = GET_DATA0(action) & 0x7F,
@@ -70,35 +71,63 @@ zobrist_apply(const action_t action, uint64_t hash) {
dir = GET_DATA1(action) >> 4;
const int8_t delta = move_deltas[dir];
- // TODO: adapt this
int8_t steps = 1;
- uint8_t gap_bit = 1, total = 1;
- for (int8_t d = 1; d < num; d++, total++, gap_bit <<= 1) {
+ uint8_t gap_bit = 1, num_dropped = 1, total = COUNT_AT(loc);
+ for (int8_t d = 1; d < num; d++, num_dropped++, gap_bit <<= 1) {
if (gaps & gap_bit) {
- colours[loc] <<= total;
- colours[loc] |= colours[loc+steps*delta] & ((1 << total) - 1);
- colours[loc+steps*delta] >>= total;
- celldat[loc] += total*NUM_INC;
- celldat[loc+steps*delta] -= total*NUM_INC;
- total = 0;
+ const int8_t target = loc+steps*delta, th = COUNT_AT(target);
+ // Stash these stones to offset for the height at source
+ total += num_dropped;
+ // Apply XOR for stones at source and current target
+ uint8_t point = 1;
+ for (int k = 0, ht = th-1, hs = total-1; k < num_dropped;
+ k++, ht--, hs--, point<<=1) {
+ hash ^= zobrist[ht][target*(2*3+1)
+ +(point & colours[target])*3
+ +STONE_FLAT];
+ hash ^= zobrist[hs][loc*(2*3+1)
+ +(point & colours[target])*3
+ +STONE_FLAT];
+ }
+ // Continue processing gap sequence
+ num_dropped = 0;
steps++;
}
}
- colours[loc] <<= total;
- colours[loc] |= colours[loc+steps*delta] & ((1 << total) - 1);
- colours[loc+steps*delta] >>= total;
-
- celldat[loc] += total*NUM_INC;
- // celldat[loc] &= CLR_STONE; is not necessary, as STONE_FLAT == 0
- celldat[loc] |= STONE_AT(loc+steps*delta);
- celldat[loc+steps*delta] -= total*NUM_INC;
- celldat[loc+steps*delta] &= CLR_STONE;
+ total += num_dropped;
+ const int8_t target = loc+steps*delta, th = COUNT_AT(target);
+ const enum STONE_VARIANT top_stone = STONE_AT(target);
+ // Stash these stones to offset for the height at source
+ // Apply XOR for stones at source and end target. After this
+ // source will be correct, but we must account for crush @ target.
+ uint8_t point = 1;
+ for (int k = 0, ht = th-1, hs = total-1; k < num_dropped;
+ k++, ht--, hs--, point<<=1) {
+ if (k == 0) {
+ hash ^= zobrist[ht][target*(2*3+1)
+ +(point & colours[target])*3
+ +top_stone];
+ hash ^= zobrist[hs][loc*(2*3+1)
+ +(point & colours[target])*3
+ +top_stone];
+ } else {
+ hash ^= zobrist[ht][target*(2*3+1)
+ +(point & colours[target])*3
+ +STONE_FLAT];
+ hash ^= zobrist[hs][loc*(2*3+1)
+ +(point & colours[target])*3
+ +STONE_FLAT];
+ }
+ }
+ // Correct for crush
if (crush) {
- celldat[loc+steps*delta] |= STONE_STANDING;
- } else {
- celldat[loc+steps*delta] |= STONE_FLAT; // should be optimised out
+ hash ^= zobrist[th-1][target*(2*3+1)
+ +(colours[target] & 1)*3
+ +STONE_FLAT];
+ hash ^= zobrist[th-1][target*(2*3+1)
+ +(colours[target] & 1)*3
+ +STONE_STANDING];
}
-
}
return hash;
}