|
|
@ -2,16 +2,16 @@ |
|
|
|
#include "common.h" |
|
|
|
|
|
|
|
/// block move direction
|
|
|
|
#define UP (-4 * 3) |
|
|
|
#define LEFT (-1 * 3) |
|
|
|
#define DOWN (+4 * 3) |
|
|
|
#define RIGHT (+1 * 3) |
|
|
|
#define DIR_UP (-4 * 3) |
|
|
|
#define DIR_LEFT (-1 * 3) |
|
|
|
#define DIR_DOWN (+4 * 3) |
|
|
|
#define DIR_RIGHT (+1 * 3) |
|
|
|
|
|
|
|
/// block direction limit
|
|
|
|
#define ALLOW_UP (filter != -UP) |
|
|
|
#define ALLOW_DOWN (filter != -DOWN) |
|
|
|
#define ALLOW_LEFT (filter != -LEFT) |
|
|
|
#define ALLOW_RIGHT (filter != -RIGHT) |
|
|
|
#define ALLOW_UP (filter != -DIR_UP) |
|
|
|
#define ALLOW_DOWN (filter != -DIR_DOWN) |
|
|
|
#define ALLOW_LEFT (filter != -DIR_LEFT) |
|
|
|
#define ALLOW_RIGHT (filter != -DIR_RIGHT) |
|
|
|
|
|
|
|
/// horizontal restraints
|
|
|
|
#define NOT_COLUMN_0 ((addr & 3) != 0b00) |
|
|
@ -19,10 +19,10 @@ |
|
|
|
#define NOT_COLUMN_3 ((addr & 3) != 0b01) |
|
|
|
|
|
|
|
/// try to move block
|
|
|
|
#define MOVE_UP (next_addr = addr + UP) |
|
|
|
#define MOVE_DOWN (next_addr = addr + DOWN) |
|
|
|
#define MOVE_LEFT (next_addr = addr + LEFT) |
|
|
|
#define MOVE_RIGHT (next_addr = addr + RIGHT) |
|
|
|
#define MOVE_UP (next_addr = addr + DIR_UP) |
|
|
|
#define MOVE_DOWN (next_addr = addr + DIR_DOWN) |
|
|
|
#define MOVE_LEFT (next_addr = addr + DIR_LEFT) |
|
|
|
#define MOVE_RIGHT (next_addr = addr + DIR_RIGHT) |
|
|
|
|
|
|
|
/// vertical restraints
|
|
|
|
#define TOP_LIMIT(ADDR) (addr >= ADDR * 3) |
|
|
@ -61,28 +61,28 @@ cache_insert(cache_t { \ |
|
|
|
#define BFS_INIT \ |
|
|
|
int next_addr; \ |
|
|
|
int current = 0; \ |
|
|
|
cache[0].addr = addr; |
|
|
|
cache_[0].addr = addr; |
|
|
|
|
|
|
|
#define BFS_LOAD \ |
|
|
|
code = cache[current].code; \ |
|
|
|
addr = cache[current].addr; \ |
|
|
|
int filter = cache[current++].filter; |
|
|
|
code = cache_[current].code; \ |
|
|
|
addr = cache_[current].addr; \ |
|
|
|
int filter = cache_[current++].filter; |
|
|
|
|
|
|
|
#define BFS_STOP (current == cache_size) |
|
|
|
#define BFS_STOP (current == cache_size_) |
|
|
|
|
|
|
|
///////////////////////////////////////////////
|
|
|
|
|
|
|
|
using klotski::Core; |
|
|
|
|
|
|
|
inline void Core::cache_insert(cache_t next_case) { // try to insert into cache
|
|
|
|
auto *cache_ptr = cache; |
|
|
|
for (; cache_ptr < cache + cache_size; ++cache_ptr) { |
|
|
|
auto *cache_ptr = cache_; |
|
|
|
for (; cache_ptr < cache_ + cache_size_; ++cache_ptr) { |
|
|
|
if (cache_ptr->code == next_case.code) { |
|
|
|
return; // already exist -> insert failed
|
|
|
|
} |
|
|
|
} |
|
|
|
*cache_ptr = next_case; // cache push back
|
|
|
|
++cache_size; |
|
|
|
++cache_size_; |
|
|
|
} |
|
|
|
|
|
|
|
void Core::move_1x1(uint64_t code, int addr) { // try to move target 1x1 block
|
|
|
@ -90,16 +90,16 @@ void Core::move_1x1(uint64_t code, int addr) { // try to move target 1x1 block |
|
|
|
while (!BFS_STOP) { // bfs search process
|
|
|
|
BFS_LOAD |
|
|
|
if (ALLOW_UP && TOP_LIMIT(4) && CHECK_UP(F_1x1)) { |
|
|
|
RELEASE_1x1(UP) // 1x1 block move up
|
|
|
|
RELEASE_1x1(DIR_UP) // 1x1 block move up
|
|
|
|
} |
|
|
|
if (ALLOW_DOWN && BOTTOM_LIMIT(15) && CHECK_DOWN(F_1x1)) { |
|
|
|
RELEASE_1x1(DOWN) // 1x1 block move down
|
|
|
|
RELEASE_1x1(DIR_DOWN) // 1x1 block move down
|
|
|
|
} |
|
|
|
if (ALLOW_LEFT && NOT_COLUMN_0 && CHECK_LEFT(F_1x1)) { |
|
|
|
RELEASE_1x1(LEFT) // 1x1 block move left
|
|
|
|
RELEASE_1x1(DIR_LEFT) // 1x1 block move left
|
|
|
|
} |
|
|
|
if (ALLOW_RIGHT && NOT_COLUMN_3 && CHECK_RIGHT(F_1x1)) { |
|
|
|
RELEASE_1x1(RIGHT) // 1x1 block move right
|
|
|
|
RELEASE_1x1(DIR_RIGHT) // 1x1 block move right
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -109,16 +109,16 @@ void Core::move_1x2(uint64_t code, int addr) { // try to move target 1x2 block |
|
|
|
while (!BFS_STOP) { // bfs search process
|
|
|
|
BFS_LOAD |
|
|
|
if (ALLOW_UP && TOP_LIMIT(4) && CHECK_UP(F_1x2)) { |
|
|
|
RELEASE_1x2(UP) // 1x2 block move up
|
|
|
|
RELEASE_1x2(DIR_UP) // 1x2 block move up
|
|
|
|
} |
|
|
|
if (ALLOW_DOWN && BOTTOM_LIMIT(14) && CHECK_DOWN(F_1x2)) { |
|
|
|
RELEASE_1x2(DOWN) // 1x2 block move down
|
|
|
|
RELEASE_1x2(DIR_DOWN) // 1x2 block move down
|
|
|
|
} |
|
|
|
if (ALLOW_LEFT && NOT_COLUMN_0 && CHECK_LEFT(F_1x1)) { |
|
|
|
RELEASE_1x2(LEFT) // 1x2 block move left
|
|
|
|
RELEASE_1x2(DIR_LEFT) // 1x2 block move left
|
|
|
|
} |
|
|
|
if (ALLOW_RIGHT && NOT_COLUMN_2 && CHECK_RIGHT(F_1x1_R)) { |
|
|
|
RELEASE_1x2(RIGHT) // 1x2 block move right
|
|
|
|
RELEASE_1x2(DIR_RIGHT) // 1x2 block move right
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -128,16 +128,16 @@ void Core::move_2x1(uint64_t code, int addr) { // try to move target 2x1 block |
|
|
|
while (!BFS_STOP) { // bfs search process
|
|
|
|
BFS_LOAD |
|
|
|
if (ALLOW_UP && TOP_LIMIT(4) && CHECK_UP(F_1x1)) { |
|
|
|
RELEASE_2x1(UP) // 2x1 block move up
|
|
|
|
RELEASE_2x1(DIR_UP) // 2x1 block move up
|
|
|
|
} |
|
|
|
if (ALLOW_DOWN && BOTTOM_LIMIT(11) && CHECK_DOWN(F_1x1_D)) { |
|
|
|
RELEASE_2x1(DOWN) // 2x1 block move down
|
|
|
|
RELEASE_2x1(DIR_DOWN) // 2x1 block move down
|
|
|
|
} |
|
|
|
if (ALLOW_LEFT && NOT_COLUMN_0 && CHECK_LEFT(F_2x1)) { |
|
|
|
RELEASE_2x1(LEFT) // 2x1 block move left
|
|
|
|
RELEASE_2x1(DIR_LEFT) // 2x1 block move left
|
|
|
|
} |
|
|
|
if (ALLOW_RIGHT && NOT_COLUMN_3 && CHECK_RIGHT(F_2x1)) { |
|
|
|
RELEASE_2x1(RIGHT) // 2x1 block move right
|
|
|
|
RELEASE_2x1(DIR_RIGHT) // 2x1 block move right
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -147,23 +147,23 @@ void Core::move_2x2(uint64_t code, int addr) { // try to move target 2x2 block |
|
|
|
while (!BFS_STOP) { // bfs search process
|
|
|
|
BFS_LOAD |
|
|
|
if (ALLOW_UP && TOP_LIMIT(4) && CHECK_UP(F_1x2)) { |
|
|
|
RELEASE_2x2(UP) // 2x2 block move up
|
|
|
|
RELEASE_2x2(DIR_UP) // 2x2 block move up
|
|
|
|
} |
|
|
|
if (ALLOW_DOWN && BOTTOM_LIMIT(10) && CHECK_DOWN(F_1x2_D)) { |
|
|
|
RELEASE_2x2(DOWN) // 2x2 block move down
|
|
|
|
RELEASE_2x2(DIR_DOWN) // 2x2 block move down
|
|
|
|
} |
|
|
|
if (ALLOW_LEFT && NOT_COLUMN_0 && CHECK_LEFT(F_2x1)) { |
|
|
|
RELEASE_2x2(LEFT) // 2x2 block move left
|
|
|
|
RELEASE_2x2(DIR_LEFT) // 2x2 block move left
|
|
|
|
} |
|
|
|
if (ALLOW_RIGHT && NOT_COLUMN_2 && CHECK_RIGHT(F_2x1_R)) { |
|
|
|
RELEASE_2x2(RIGHT) // 2x2 block move right
|
|
|
|
RELEASE_2x2(DIR_RIGHT) // 2x2 block move right
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void Core::next_cases(uint64_t code, uint64_t mask) { // search next step cases
|
|
|
|
cache[0].filter = 0; // without filter
|
|
|
|
cache[0].code = code; // bfs root code
|
|
|
|
cache_[0].filter = 0; // without filter
|
|
|
|
cache_[0].code = code; // bfs root code
|
|
|
|
auto range = code | mask; |
|
|
|
|
|
|
|
for (int addr = 0; range; addr += 3, range >>= 3) { // traverse every 3-bits
|
|
|
@ -183,11 +183,11 @@ void Core::next_cases(uint64_t code, uint64_t mask) { // search next step cases |
|
|
|
default: |
|
|
|
continue; // B_space or B_fill
|
|
|
|
} |
|
|
|
if (cache_size != 1) { // found one or more next cases
|
|
|
|
for (int i = 1; i < cache_size; ++i) { |
|
|
|
Core::release(cache[i].code, cache[i].mask); // release next cases
|
|
|
|
if (cache_size_ != 1) { // found one or more next cases
|
|
|
|
for (int i = 1; i < cache_size_; ++i) { |
|
|
|
Core::release_(cache_[i].code, cache_[i].mask); // release next cases
|
|
|
|
} |
|
|
|
cache_size = 1; // reset cache size
|
|
|
|
cache_size_ = 1; // reset cache size
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|