// group must be base of a group inline static bool try_delete_group(board_t *b, index_t group) { if (b->pseudo_liberties[group] != 0) { maybe_in_atari_now(b, group); return false; } index_t ptr = group; index_swap(b, b->list_pos[ptr], b->group_ptr++); do { clear_atari_bits_3x3(b->nbr3x3[ptr]); index_swap(b, b->list_pos[ptr], b->empty_ptr++); b->hash -= (hash_t)b->stones[ptr] * p4423[ptr]; b->stones[ptr] = STONE_EMPTY; delete_stone_update_liberties(b, ptr); delete_stone_update_3x3(b, ptr); ptr = b->next_in_group[ptr]; } while (ptr != group); do { if (IS_STONE(b->stones[N(b, ptr)])) { maybe_not_in_atari_now(b, b->base_of_group[N(b, ptr)]); } if (IS_STONE(b->stones[S(b, ptr)])) { maybe_not_in_atari_now(b, b->base_of_group[S(b, ptr)]); } if (IS_STONE(b->stones[W(b, ptr)])) { maybe_not_in_atari_now(b, b->base_of_group[W(b, ptr)]); } if (IS_STONE(b->stones[E(b, ptr)])) { maybe_not_in_atari_now(b, b->base_of_group[E(b, ptr)]); } ptr = b->next_in_group[ptr]; } while (ptr != group); return true; }
int32_t hfile_swap(hfile_t *fp) { int32_t fd; meta_t *o; int8_t *ptr; int32_t len; if (!fp) return(-1); len = strlen(fp->name); ptr = fp->name + len; umask(0); do { fp->trailer->timestamp = time(NULL); snprintf(ptr,PATH_MAX - len,"%ld",fp->trailer->timestamp); fd = open(fp->name,O_WRONLY|O_APPEND|O_CREAT|O_EXCL,0644); } while (fd < 0); for (o = index_head(fp->metas); o != NULL; o = meta_next(o)) { o->offset = lseek(fd,0,SEEK_CUR); o->blocksize = block_swap(fd,o->offset,fp->blocks[o->id]); } fp->trailer->indexoffset = lseek(fd,0,SEEK_CUR); fp->trailer->indexsize = index_swap(fd,fp->trailer->indexoffset,fp->metas); fp->trailer->bloomoffset = lseek(fd,0,SEEK_CUR); fp->trailer->bloomsize = bloom_swap(fd,fp->trailer->bloomoffset,fp->bloom); fp->trailer->infooffset = lseek(fd,0,SEEK_CUR); fp->trailer->infosize = hinfo_swap(fd,fp->trailer->infooffset,fp->fileinfo); fp->trailer->version = hfile_version(NULL); htail_swap(fd,lseek(fd,0,SEEK_CUR),fp->trailer); close(fd); return(0); }
STATIC void link_group(board_t *b, index_t p, index_t q) { //link q into p index_swap(b, b->list_pos[q], b->group_ptr++); b->group_size[p] += b->group_size[q]; b->pseudo_liberties[p] += b->pseudo_liberties[q]; b->group_liberties_sum[p] += b->group_liberties_sum[q]; b->group_liberties_sum_squared[p] += b->group_liberties_sum_squared[q]; index_t ptr = q; do { b->base_of_group[ptr] = p; ptr = b->next_in_group[ptr]; } while (ptr != q); }
void put_stone(board_t *b, index_t pos, stone_t color) { // basic checks if (pos < 0 || pos >= b->len || b->stones[pos] != STONE_EMPTY) return; stone_t oppocolor = OTHER_C(color); // records some variable b->vis_cnt ++; b->nbr3x3_cnt = 0; if (b->ko_pos >= 0) { touch_nbr3x3(b, b->ko_pos); } b->ko_pos = detect_ko(b, pos); if (b->ko_pos >= 0 && b->stones[b->ko_pos] == color) b->ko_pos = -1; if (b->last_move >= 0) { touch_nbr3x3(b, b->last_move); } // put a stone b->stones[pos] = color; b->next_in_group[pos] = pos; b->base_of_group[pos] = pos; b->group_size[pos] = 1; b->pseudo_liberties[pos] = 0; b->group_liberties_sum[pos] = 0; b->group_liberties_sum_squared[pos] = 0; b->atari_of_group[pos] = -1; index_swap(b, b->list_pos[pos], --b->empty_ptr); index_swap(b, b->list_pos[pos], --b->group_ptr); b->hash += p4423[pos] * (hash_t)color; update_empty_neighbour(b, pos); // update neighbour group's pseudo_liberties add_stone_update_liberties(b, pos); add_stone_update_3x3(b, pos); clear_atari_bits_3x3(b->nbr3x3[pos]); // try to capture others if (b->stones[N(b, pos)] == oppocolor) { try_delete_group(b, b->base_of_group[N(b, pos)]); } if (b->stones[S(b, pos)] == oppocolor) { try_delete_group(b, b->base_of_group[S(b, pos)]); } if (b->stones[W(b, pos)] == oppocolor) { try_delete_group(b, b->base_of_group[W(b, pos)]); } if (b->stones[E(b, pos)] == oppocolor) { try_delete_group(b, b->base_of_group[E(b, pos)]); } // merge with friendly neighbours' group if (b->stones[N(b, pos)] == color) { try_merge_group(b, b->base_of_group[N(b, pos)], b->base_of_group[pos]); } if (b->stones[S(b, pos)] == color) { try_merge_group(b, b->base_of_group[S(b, pos)], b->base_of_group[pos]); } if (b->stones[W(b, pos)] == color) { try_merge_group(b, b->base_of_group[W(b, pos)], b->base_of_group[pos]); } if (b->stones[E(b, pos)] == color) { try_merge_group(b, b->base_of_group[E(b, pos)], b->base_of_group[pos]); } // check suicide if (!try_delete_group(b, b->base_of_group[pos])) { if (b->ko_pos >= 0 && ( b->next_in_group[pos] != pos || find_atari(b, pos) < 0 || b->atari_of_group[pos] != b->ko_pos)) { b->ko_pos = -1; } else { b->ko_color = oppocolor; } } else b -> ko_pos = -1; if (b->ko_pos >= 0) { touch_nbr3x3(b, b->ko_pos); } b->last_move = pos; for (index_t i = 0; i < b->nbr3x3_cnt; i++) { index_t p = b->nbr3x3_changed[i]; update_prob(b, p, STONE_BLACK); update_prob(b, p, STONE_WHITE); } }