Browse Source

update: Core module

master
Dnomd343 2 years ago
parent
commit
7e4f50105e
  1. 84
      src/klotski_core/core/core.cc
  2. 50
      src/klotski_core/core/core.h

84
src/klotski_core/core/core.cc

@ -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
}
}
}

50
src/klotski_core/core/core.h

@ -47,31 +47,33 @@
#include <functional>
namespace klotski {
class Core {
public:
/// Release with code and mask
typedef std::function<void(uint64_t, uint64_t)> release_t;
/// Core interface
void next_cases(uint64_t code, uint64_t mask);
explicit Core(release_t release_func) : release(std::move(release_func)) {}
class Core {
public:
/// Release with code and mask
typedef std::function<void(uint64_t, uint64_t)> release_t;
private:
struct cache_t {
uint64_t code;
uint64_t mask; /// (000) or (111)
int filter; /// UP | DOWN | LEFT | RIGHT
int addr; /// (0 ~ 19) * 3
};
/// Core interface
void next_cases(uint64_t code, uint64_t mask);
explicit Core(release_t release_func) : release_(std::move(release_func)) {}
int cache_size = 1;
cache_t cache[16]{};
release_t release; // release function
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);
inline void cache_insert(cache_t next_case);
private:
struct cache_t {
uint64_t code;
uint64_t mask; /// (000) or (111)
int filter; /// DIR_UP | DIR_DOWN | DIR_LEFT | DIR_RIGHT
int addr; /// (0 ~ 19) * 3
};
}
int cache_size_ = 1;
cache_t cache_[16]{};
release_t release_; // release function
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);
inline void cache_insert(cache_t next_case);
};
} // namespace klotski

Loading…
Cancel
Save