diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8cd5289..abf1a68 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,6 @@ cmake_minimum_required(VERSION 3.0) +include_directories(core) include_directories(common) include_directories(all_cases) @@ -7,6 +8,7 @@ include_directories(raw_code) include_directories(short_code) include_directories(common_code) +add_subdirectory(core) add_subdirectory(common) add_subdirectory(all_cases) @@ -14,8 +16,11 @@ add_subdirectory(raw_code) add_subdirectory(short_code) add_subdirectory(common_code) -#add_executable(klotski main.cc) -add_executable(klotski main.cc core_demo.cc) +add_executable(klotski main.cc) +#add_executable(klotski main.cc core_demo.cc) + +target_link_libraries(klotski core) +target_link_libraries(klotski common) target_link_libraries(klotski all_cases) target_link_libraries(klotski raw_code) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt new file mode 100644 index 0000000..fae268d --- /dev/null +++ b/src/core/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.0) + +add_library(core core.cc) diff --git a/src/core/bfs.h b/src/core/bfs.h new file mode 100644 index 0000000..d925f60 --- /dev/null +++ b/src/core/bfs.h @@ -0,0 +1,16 @@ +#pragma once + +#define BFS_INIT \ +int next_addr; \ +cache_size = 1; \ +int current = 0; \ +cache[0].code = code; \ +cache[0].addr = addr; \ +cache[0].filter = 0; + +#define BFS_LOAD \ +code = cache[current].code; \ +addr = cache[current].addr; \ +int filter = cache[current++].filter; + +#define BFS_STOP (current == cache_size) diff --git a/src/core/core.cc b/src/core/core.cc new file mode 100644 index 0000000..35b4bd6 --- /dev/null +++ b/src/core/core.cc @@ -0,0 +1,162 @@ +#include "bfs.h" +#include "core.h" +#include "raw_code.h" + +#define ALLOW_UP (filter != -UP) +#define ALLOW_DOWN (filter != -DOWN) +#define ALLOW_LEFT (filter != -LEFT) +#define ALLOW_RIGHT (filter != -RIGHT) + +#define NOT_COLUMN_0 ((addr & 3) != 0) +#define NOT_COLUMN_2 ((addr & 3) != 2) +#define NOT_COLUMN_3 ((addr & 3) != 1) + +#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 TOP_LIMIT(ADDR) (addr >= ADDR * 3) +#define BOTTOM_LIMIT(ADDR) (addr <= ADDR * 3) + +#define RELEASE(NEXT_CODE, FILTER) { \ + cache_t next_case = { \ + .code = NEXT_CODE, \ + .mask = F_1x1 << next_addr, \ + .filter = FILTER, \ + .addr = next_addr \ + }; \ + cache_insert(next_case); \ +} + +#define release_1x1(FILTER) RELEASE(NEXT_CODE_1x1, FILTER) +#define release_1x2(FILTER) RELEASE(NEXT_CODE_1x2, FILTER) +#define release_2x1(FILTER) RELEASE(NEXT_CODE_2x1, FILTER) +#define release_2x2(FILTER) RELEASE(NEXT_CODE_2x2, FILTER) + +#define NEXT_CODE_1x1 (code & ~(F_1x1 << addr) | (C_1x1 << next_addr)) +#define NEXT_CODE_1x2 (code & ~(F_1x2 << addr) | (C_1x2 << next_addr)) +#define NEXT_CODE_2x1 (code & ~(F_2x1 << addr) | (C_2x1 << next_addr)) +#define NEXT_CODE_2x2 (code & ~(F_2x2 << addr) | (C_2x2 << next_addr)) + +inline void Core::cache_insert(Core::cache_t &next_case) { // try to insert into cache + auto *p = cache; + for (; p < cache + cache_size; ++p) { + if (p->code == next_case.code) { + return; // already exist -> insert failed + } + } + *p = next_case; + ++cache_size; +} + +void Core::move_1x1(uint64_t code, int addr) { // try to move target 1x1 block + BFS_INIT + while (!BFS_STOP) { // bfs search process + BFS_LOAD + if (ALLOW_UP && TOP_LIMIT(4) && !(code >> MOVE_UP & F_1x1)) { + release_1x1(UP) // 1x1 block move up + } + if (ALLOW_DOWN && BOTTOM_LIMIT(15) && !(code >> MOVE_DOWN & F_1x1)) { + release_1x1(DOWN) // 1x1 block move down + } + if (ALLOW_LEFT && NOT_COLUMN_0 && !(code >> MOVE_LEFT & F_1x1)) { + release_1x1(LEFT) // 1x1 block move left + } + if (ALLOW_RIGHT && NOT_COLUMN_3 && !(code >> MOVE_RIGHT & F_1x1)) { + release_1x1(RIGHT) // 1x1 block move right + } + } +} + +void Core::move_1x2(uint64_t code, int addr) { // try to move target 1x2 block + BFS_INIT + while (!BFS_STOP) { // bfs search process + BFS_LOAD + if (ALLOW_UP && TOP_LIMIT(4) && !(code >> MOVE_UP & F_1x2)) { + release_1x2(UP) // 1x2 block move up + } + if (ALLOW_DOWN && BOTTOM_LIMIT(14) && !(code >> MOVE_DOWN & F_1x2)) { + release_1x2(DOWN) // 1x2 block move down + } + if (ALLOW_LEFT && NOT_COLUMN_0 && !(code >> MOVE_LEFT & F_1x1)) { + release_1x2(LEFT) // 1x2 block move left + } + if (ALLOW_RIGHT && NOT_COLUMN_2 && !(code >> MOVE_RIGHT & F_1x1_R)) { + release_1x2(RIGHT) // 1x2 block move right + } + } +} + +void Core::move_2x1(uint64_t code, int addr) { // try to move target 2x1 block + BFS_INIT + while (!BFS_STOP) { // bfs search process + BFS_LOAD + if (ALLOW_UP && TOP_LIMIT(4) && !(code >> MOVE_UP & F_1x1)) { + release_2x1(UP) // 2x1 block move up + } + if (ALLOW_DOWN && BOTTOM_LIMIT(11) && !(code >> MOVE_DOWN & F_1x1_D)) { + release_2x1(DOWN) // 2x1 block move down + } + if (ALLOW_LEFT && NOT_COLUMN_0 && !(code >> MOVE_LEFT & F_2x1)) { + release_2x1(LEFT) // 2x1 block move left + } + if (ALLOW_RIGHT && NOT_COLUMN_3 && !(code >> MOVE_RIGHT & F_2x1)) { + release_2x1(RIGHT) // 2x1 block move right + } + } +} + +void Core::move_2x2(uint64_t code, int addr) { // try to move target 2x2 block + BFS_INIT + while (!BFS_STOP) { // bfs search process + BFS_LOAD + if (ALLOW_UP && TOP_LIMIT(4) && !(code >> MOVE_UP & F_1x2)) { + release_2x2(UP) // 2x2 block move up + } + if (ALLOW_DOWN && BOTTOM_LIMIT(10) && !(code >> MOVE_DOWN & F_1x2_D)) { + release_2x2(DOWN) // 2x2 block move down + } + if (ALLOW_LEFT && NOT_COLUMN_0 && !(code >> MOVE_LEFT & F_2x1)) { + release_2x2(LEFT) // 2x2 block move left + } + if (ALLOW_RIGHT && NOT_COLUMN_2 && !(code >> MOVE_RIGHT & F_2x1_R)) { + release_2x2(RIGHT) // 2x2 block move right + } + } +} + +#include + +void Core::next_step(uint64_t raw_code) { + + auto temp_code = raw_code; + for (int addr = 0; temp_code; addr += 3, temp_code >>= 3) { + + switch (temp_code & 0b111) { + case B_1x1: + move_1x1(raw_code, addr); + break; + case B_1x2: + move_1x2(raw_code, addr); + break; + case B_2x1: + move_2x1(raw_code, addr); + break; + case B_2x2: + move_2x2(raw_code, addr); + break; + default: + continue; // B_space or B_fill + } + if (cache_size != 1) { + for (int i = 1; i < cache_size; ++i) { + std::cout << RawCode(cache[i].code).dump_case(); + printf("MASK -> %016lX\n", cache[i].mask); + } +// std::cout << "found: " << cache_size - 1 << std::endl; + } + } +} + + diff --git a/src/core/core.h b/src/core/core.h new file mode 100644 index 0000000..7341bdf --- /dev/null +++ b/src/core/core.h @@ -0,0 +1,43 @@ +#pragma once + +#include + +#define UP (-12) // -4 * 3-bits +#define LEFT (-3) // +1 * 3-bits +#define DOWN (+12) // +4 * 3-bits +#define RIGHT (+3) // +1 * 3-bits + +#define F_1x1 (uint64_t)0x7 // 111 +#define F_1x2 (uint64_t)0x3F // 111 111 +#define F_2x1 (uint64_t)0x7007 // 111 000 000 000 111 +#define F_2x2 (uint64_t)0x3F03F // 111 111 000 000 111 111 + +#define F_1x1_R (uint64_t)0x38 // 111 000 +#define F_1x1_D (uint64_t)0x7000 // 111 000 000 000 000 +#define F_2x1_R (uint64_t)0x38038 // 111 000 000 000 111 000 +#define F_1x2_D (uint64_t)0x3F000 // 111 111 000 000 000 000 + +class Core { +public: + struct cache_t { + uint64_t code; // raw code + uint64_t mask; // only 000 or 111 + int filter; + int addr; + }; + + int cache_size; + cache_t cache[16]; + + inline void cache_insert(Core::cache_t &next_case); + + void move_1x1(uint64_t code, int addr); + void move_1x2(uint64_t code, int addr); + void move_2x1(uint64_t code, int addr); + void move_2x2(uint64_t code, int addr); + + void next_step(uint64_t raw_code); + +}; + + diff --git a/src/core_demo.cc b/src/core_demo.cc index 442b546..673fe6e 100644 --- a/src/core_demo.cc +++ b/src/core_demo.cc @@ -191,8 +191,8 @@ void next_step(uint64_t raw_code) { } if (cache_size != 1) { for (int i = 1; i < cache_size; ++i) { - std::cout << RawCode(cache[i].code).dump_case(); - printf("MASK -> %016lX\n", cache[i].mask); +// std::cout << RawCode(cache[i].code).dump_case(); +// printf("MASK -> %016lX\n", cache[i].mask); } // std::cout << "found: " << cache_size - 1 << std::endl; } diff --git a/src/main.cc b/src/main.cc index c32997e..5c47f61 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,11 +1,12 @@ #include +#include "core.h" #include "all_cases.h" #include "basic_ranges.h" #include "common_code.h" #include "short_code.h" #include "raw_code.h" -#include "core_demo.h" +//#include "core_demo.h" #include @@ -145,8 +146,9 @@ int main() { // next_step(CommonCode("4FEA134").to_raw_code().unwrap(), 0); // mask unset auto raw_code = RawCode(CommonCode("4fea134")).unwrap(); -// for (int i = 0; i < 1000000000; ++i) { - next_step(raw_code); + auto c = Core(); +// for (int i = 0; i < 100000000; ++i) { + c.next_step(raw_code); // } return 0; diff --git a/src/raw_code/raw_code.h b/src/raw_code/raw_code.h index 7272c31..eec1f47 100644 --- a/src/raw_code/raw_code.h +++ b/src/raw_code/raw_code.h @@ -15,16 +15,6 @@ #define C_2x1 (uint64_t)0x7002 // 111 000 000 000 010 #define C_2x2 (uint64_t)0x3F03C // 111 111 000 000 111 100 -#define F_1x1 (uint64_t)0x7 // 111 -#define F_1x2 (uint64_t)0x3F // 111 111 -#define F_2x1 (uint64_t)0x7007 // 111 000 000 000 111 -#define F_2x2 (uint64_t)0x3F03F // 111 111 000 000 111 111 - -#define F_1x1_R (uint64_t)0x38 // 111 000 -#define F_1x1_D (uint64_t)0x7000 // 111 000 000 000 000 -#define F_2x1_R (uint64_t)0x38038 // 111 000 000 000 111 000 -#define F_1x2_D (uint64_t)0x3F000 // 111 111 000 000 000 000 - class CommonCode; class RawCode {