mirror of https://github.com/dnomd343/klotski.git
Dnomd343
2 years ago
8 changed files with 238 additions and 17 deletions
@ -0,0 +1,3 @@ |
|||
cmake_minimum_required(VERSION 3.0) |
|||
|
|||
add_library(core core.cc) |
@ -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) |
@ -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 <iostream> |
|||
|
|||
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;
|
|||
} |
|||
} |
|||
} |
|||
|
|||
|
@ -0,0 +1,43 @@ |
|||
#pragma once |
|||
|
|||
#include <cstdint> |
|||
|
|||
#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); |
|||
|
|||
}; |
|||
|
|||
|
Loading…
Reference in new issue