first try of A* move sorting

This commit is contained in:
2022-04-05 13:20:13 +02:00
parent 49bbc2372c
commit 4dbcc30dc3

View File

@@ -60,6 +60,15 @@ typedef struct pos {
struct list_head list; struct list_head list;
} pos_t; } pos_t;
/* All possible moves between hallway and rooms
*/
typedef struct {
uint mask; /* blocking spaces */
uint dist;
} possible_move_t;
static possible_move_t moves[24][24];
typedef struct hash { typedef struct hash {
u64 zobrist; /* zobrist hash */ u64 zobrist; /* zobrist hash */
u32 amp[4]; u32 amp[4];
@@ -145,6 +154,32 @@ static s32 room_exit[4][2][6] = {
} }
}; };
static char *int2bin(u32 mask)
{
static char ret[64];
for (int i = 0; i < 32; ++i) {
ret[31-i] = mask & BIT(i)? '1': '0';
}
ret[32] = 0;
return ret;
}
static char *int2pos(u32 mask)
{
static char res[1024];
char *p = res;
for (int i = 0; i < 32; ++i) {
if (mask & BIT(i)) {
*p++ = ' ';
strcpy(p, cells[i]);
p += 2;
}
}
return res;
}
static void moves_print(move_t *moves, int nmoves) static void moves_print(move_t *moves, int nmoves)
{ {
for (int i = 0; i < nmoves; ++i) for (int i = 0; i < nmoves; ++i)
@@ -422,72 +457,77 @@ static u64 hash(pos_t *pos, int amp, u32 from, u32 to)
return zobrist; return zobrist;
} }
/* evaluate current position. /* evaluate current position :
* * eval = cost + eval_to_dest
* * cost is current cost
* eval is cost to join top of destination room
*/ */
static u32 eval(pos_t *pos, int amp, u32 from, u32 to) static int room2room_dist[][4] = {
{ 4, 4, 6, 8}, { 4, 4, 4, 6}, { 6, 4, 4, 4}, { 8, 6, 4, 4}
};
/* static u64 eval_amp(pos_t *pos, int amp, u32 cell) */
/* { */
/* u32 bit = BIT(cell); */
/* int rows = popcount32(pos->amp[0]); */
/* int dist; */
/* int left = rows - popcount32(rooms[amp] & pos->final); */
/* if (ROOM(bit)) { /\* in a room *\/ */
/* int curroom = cell / 4 - 2; */
/* dist = cell % 4; /\* distance to top of room *\/ */
/* dist += room2room_dist[curroom][amp]; */
/* dist += --left; /\* distance to final room *\/ */
/* log(1, "eval %c room(%s) = %d\n", amp + 'A', cells[cell], dist); */
/* } else { /\* in hallway *\/ */
/* int dest = (amp + 2) * 4; */
/* dist = moves[cell][dest].dist; */
/* dist += --left; /\* distance to final room *\/ */
/* log(1, "eval %c hallway(%s) = %d\n", amp + 'A', cells[cell], dist); */
/* } */
/* return cost[amp] * dist; */
/* } */
static u64 eval(pos_t *pos)
{ {
log_f(1, "pos=%p amp=%d from=%u to=%u\n", pos, amp, from, to); u32 amp, tmp;
return 1; int cell;
int rows = popcount32(pos->amp[0]);
u64 eval = 0;
for (amp = A; amp <= D; ++amp) {
u32 todo = pos->amp[amp] & ~pos->final; /* ignore finished ones */
int destroom = amp, dist;
int left = rows - popcount32(rooms[destroom] & pos->final);
printf("amp=%d %u final=%u\n", amp, pos->amp[amp], pos->final);
printf("amp=%c pos=%s\n", amp + 'A', int2bin(pos->amp[amp]));
printf("amp= tod=%s\n", int2bin(todo));
printf("amp= fin=%s\n", int2bin(pos->final));
bit_for_each32_2(cell, tmp, todo) {
u32 bit = BIT(cell);
if (ROOM(bit)) { /* in a room */
int curroom = cell / 4 - 2;
dist = cell % 4; /* distance to top of room */
dist += room2room_dist[curroom][destroom];
dist += --left; /* distance to final room */
log(1, "eval %c room(%s) = %d\n", amp + 'A', cells[cell], dist);
} else { /* in hallway */
int dest = (destroom + 2) * 4;
dist = moves[cell][dest].dist;
dist += --left; /* distance to final room */
log(1, "eval %c hallway(%s) = %d\n", amp + 'A', cells[cell], dist);
} }
//printf("eval = %lu %lu\n", cost[amp] * dist, eval_amp(pos, amp, cell));
static char *int2bin(u32 mask) eval += cost[amp] * dist;
{
static char ret[64];
for (int i = 0; i < 32; ++i) {
ret[31-i] = mask & BIT(i)? '1': '0';
}
ret[32] = 0;
return ret;
}
static char *int2pos(u32 mask)
{
static char res[1024];
char *p = res;
for (int i = 0; i < 32; ++i) {
if (mask & BIT(i)) {
*p++ = ' ';
strcpy(p, cells[i]);
p += 2;
} }
} }
return res; //log_f(1, "pos=%p amp=%d from=%u to=%u\n", pos, amp, from, to);
return eval;
} }
typedef enum {
H1 = BIT(_H1), H2 = BIT(_H2), H3 = (_H3), H4 = (_H4),
H5 = (_H5), H6 = (_H6), H7 = (_H7),
A1 = (_A1), A2 = (_A2), A3 = (_A3), A4 = (_A4),
B1 = (_B1), B2 = (_B2), B3 = (_B3), B4 = (_B4),
C1 = (_C1), C2 = (_C2), C3 = (_C3), C4 = (_C4),
D1 = (_D1), D2 = (_D2), D3 = (_D3), D4 = (_D4),
} space_t;
/* Steps to move to hallway
*/
typedef enum {
A1H = 1, A2H = 2, A3H = 3, A4H = 4
} out_t;
/* Mask which disallow moves to hallway
*/
typedef struct {
uint mask, dist;
} possible_move_t;
/* Steps to move from space outside room to hallway destination
*/
typedef enum {
AH1 = 2, AH2 = 1, AH3 = 1, AH4 = 3, AH5 = 5, AH6 = 7 , AH7 = 8,
BH1 = 4, BH2 = 3, BH3 = 1, BH4 = 1, BH5 = 3, BH6 = 5 , BH7 = 6,
CH1 = 6, CH2 = 5, CH3 = 3, CH4 = 1, CH5 = 1, CH6 = 3 , CH7 = 4,
DH1 = 8, DH2 = 7, DH3 = 5, DH4 = 3, DH5 = 1, DH6 = 1 , DH7 = 2
} steps_t;
/* /*
* ############# * #############
* #ab.c.d.e.fg# * #ab.c.d.e.fg#
@@ -529,7 +569,6 @@ static pos_t *get_pos(pos_t *from)
new->final = new->occupied = new->zobrist = 0; new->final = new->occupied = new->zobrist = 0;
new->cost = new->eval = 0; new->cost = new->eval = 0;
new->moves = 0; new->moves = 0;
new->zobrist = 0;
} else { } else {
*new = *from; *new = *from;
} }
@@ -553,12 +592,26 @@ static void free_pos(pos_t *pos)
*/ */
static void push_pos(pos_t *pos) static void push_pos(pos_t *pos)
{ {
if (pos) { pos_t *cur;
list_add(&pos->list, &pos_queue);
} else { if (!pos) {
log(1, "Fatal foo\n"); log(1, "Fatal foo\n");
exit(1); exit(1);
} }
if (!list_empty(&pos_queue)) {
//list_add_tail(&pos->list, &pos_queue);
//} else {
list_for_each_entry(cur, &pos_queue, list) {
if (cur->eval > pos->eval) {
log(1, "adding %lu before %lu\n", pos->eval, cur->eval);
list_add_tail(&pos->list, &cur->list);
return;
} else {
log(1, "not adding %lu before %lu\n", pos->eval, cur->eval);
}
}
}
list_add_tail(&pos->list, &pos_queue);
} }
/* pop a position from stack /* pop a position from stack
@@ -629,10 +682,6 @@ static void mask_print(u32 bits)
} }
/* generate possible moves between hallway and rooms
*/
static possible_move_t moves[24][24];
/* calculate distance and move mask for all possible moves /* calculate distance and move mask for all possible moves
* (room -> hallway ans hallway -> room) * (room -> hallway ans hallway -> room)
*/ */
@@ -745,15 +794,6 @@ static pos_t *newmove(pos_t *pos, amphipod_t amp, u32 from, u32 to)
} }
} }
*/ */
/*
if ((IN_HALLWAY(from) && !IN_ROOM(to)) ||
(IN_ROOM(from) && !IN_HALLWAY(to)) ||
(HALLWAY(bit_from) && !ROOM(bit_to)) ||
(ROOM(bit_from) && !HALLWAY(bit_to))) {
log(1, "BUG genmove!\n");
}
*/
zobrist = hash(&pos_tmp, amp, from, to);
//if (zobrist != zobrist_1(&pos_tmp)) { //if (zobrist != zobrist_1(&pos_tmp)) {
// printf("Zobi Fuck1\n"); // printf("Zobi Fuck1\n");
// exit(1); // exit(1);
@@ -763,6 +803,7 @@ static pos_t *newmove(pos_t *pos, amphipod_t amp, u32 from, u32 to)
// exit(1); // exit(1);
//} //}
//zobrist = hash1(pos); //zobrist = hash1(pos);
zobrist = hash(&pos_tmp, amp, from, to);
if (ok < rows * 4 - 1) { /* */ if (ok < rows * 4 - 1) { /* */
if (zobrist == HASH_SEEN) { if (zobrist == HASH_SEEN) {
log(1, "collision, skipping move : "); log(1, "collision, skipping move : ");
@@ -770,35 +811,10 @@ static pos_t *newmove(pos_t *pos, amphipod_t amp, u32 from, u32 to)
return NULL; return NULL;
} }
} }
pos_tmp.eval = eval(&pos_tmp) + pos_tmp.cost;
if (!(newpos = get_pos(&pos_tmp))) if (!(newpos = get_pos(&pos_tmp)))
return NULL; return NULL;
//newpos->zobrist = zobrist;
//log(1, "Zobi6 %lu\n", newpos->zobrist);
//newpos->moves_list[newpos->moves].from = from;
//newpos->moves_list[newpos->moves].to = to;
//newpos->moves++;
//newpos->cost = newcost;
/*
if (HALLWAY(bit_from)) {
newpos->final |= bit_to;
log(1, "Final destination %s, ok=%d, final=%s\n", cells[to],
popcount32(newpos->final), int2pos(newpos->final));
if (popcount32(newpos->final) == rows * 4) {
log(1, "found solution! cost=%lu\n", newpos->cost);
if (newpos->cost < result) {
result = newpos->cost;
log(1, "New best=%lu moves=%u List:", result, newpos->moves);
log(1, "\n");
}
free_pos(newpos);
return NULL;
}
}
*/
burrow_print_flat(newpos); burrow_print_flat(newpos);
push_pos(newpos); push_pos(newpos);
log(1, "New position: moves=%d cost=%lu\n", newpos->moves, newpos->cost); log(1, "New position: moves=%d cost=%lu\n", newpos->moves, newpos->cost);
@@ -1023,6 +1039,6 @@ int main(int ac, char **av)
printf("%s : res=%ld\n", *av, part == 1? part1(): part2()); printf("%s : res=%ld\n", *av, part == 1? part1(): part2());
exit(0); exit(0);
/* for flycheck */ /* dummy calls for flycheck */
eval(pos, 1, 1, 1); eval(pos);
} }