aboutsummaryrefslogtreecommitdiff
path: root/include/actions.c
diff options
context:
space:
mode:
Diffstat (limited to 'include/actions.c')
-rw-r--r--include/actions.c67
1 files changed, 31 insertions, 36 deletions
diff --git a/include/actions.c b/include/actions.c
index 547024a..9b2ae0d 100644
--- a/include/actions.c
+++ b/include/actions.c
@@ -1,5 +1,5 @@
/*
- This file is part of ct.
+ This file is part of ctak.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -12,16 +12,22 @@
General Public License for more details.
You should have received a copy of the GNU General Public License
- along with ct. If not, see <https://www.gnu.org/licenses/>.
+ along with ctak. If not, see <https://www.gnu.org/licenses/>.
*/
#include "actions.h"
#include "tak.h"
#include <stdio.h>
+#include <stdlib.h>
static uint8_t al_board_size;
-static uint32_t upper_bound_moves;
+
+// Scratch move lists, one per recursion level. AL_MAX_ACTIONS is
+// sized above the worst case for a 6x6 board (3269 moves).
+#define AL_MAX_LEVELS 8
+#define AL_MAX_ACTIONS 4096
+static action_t al_scratch[AL_MAX_LEVELS][AL_MAX_ACTIONS];
// ===================================================================
// Helper method declarations
@@ -44,8 +50,6 @@ static inline uint8_t check_no_overflow(tak_state_p state, const uint8_t loc,
// Exported method implementations
// ===================================================================
-inline void actions_free(action_t *actions) { free(actions); }
-
// Keep track of move offsets
int8_t move_deltas[4];
@@ -55,27 +59,6 @@ void actions_init(const uint8_t board_size) {
move_deltas[1] = -board_size;
move_deltas[2] = -1;
move_deltas[3] = +1;
-
- const uint32_t five_cumulative_partitions = 7 + 5 + 3 + 2 + 1; // 18
- const uint32_t six_cumulative_partitions =
- 11 + five_cumulative_partitions; // 29
- if (board_size == 5) {
- // 26 = 3*3 + 4*3 + 1
-
- // which means central squares (4 dirs), sides (3 dirs), one corner (2 dirs)
- upper_bound_moves = 4 * 3 * 3 + 3 * 4 * 3 + 2 * 1;
- upper_bound_moves *= five_cumulative_partitions;
- } else {
- // 31 = 4*4 + 3*4 + 3
-
- // which means central squares (4 dirs), three sides (3 dirs) and an extra
- // three squares on the last side (1 dir)
- upper_bound_moves = 4 * 4 * 4 + 3 * 3 * 4 + 3 * 3;
- upper_bound_moves *= six_cumulative_partitions;
- }
- // In summary, using typedef uint32_t action_t
- // 74 * 18 = 1332 for 5x5, ~5.2 Kb
- // 109 * 29 = 3161 for 6x6, ~12.3 Kb
}
inline char action_in_list(action_t action, action_t *actions, const uint32_t num_actions) {
@@ -84,22 +67,31 @@ inline char action_in_list(action_t action, action_t *actions, const uint32_t nu
return idx < num_actions;
}
-void action_move_to_front(action_t action, action_t *actions,
- const uint32_t num_actions) {
- (void) num_actions; // yolo
+int action_move_to_front(action_t action, action_t *actions,
+ const uint32_t num_actions) {
uint32_t idx;
action_t prev = action, temp;
- for (idx = 0; actions[idx] != action; idx++) {
- temp = actions[idx];
- actions[idx] = prev;
+ for (idx = 0; idx < num_actions && actions[idx] != action; idx++)
+ ;
+ if (idx == num_actions)
+ return EXIT_FAILURE; // action not in list; nothing to do
+ for (uint32_t j = 0; j < idx; j++) {
+ temp = actions[j];
+ actions[j] = prev;
prev = temp;
}
actions[idx] = prev;
+ return EXIT_SUCCESS;
+}
+
+action_t *actions_generate(tak_state_p state, uint32_t *num_actions) {
+ return actions_generate_at(state, num_actions, 0);
}
// We bias place over move by prepending place actions and appending
// move actions to the generated list
-action_t *actions_generate(tak_state_p state, uint32_t *num_actions) {
+action_t *actions_generate_at(tak_state_p state, uint32_t *num_actions,
+ const uint32_t level) {
/*
* The check for whether it's a black piece to be played is actually
* black = (ply < 2) ? (ply==1) : (ply & 1),
@@ -124,9 +116,12 @@ action_t *actions_generate(tak_state_p state, uint32_t *num_actions) {
}
}
- // TODO: trap errno
- action_t *actions =
- malloc(sizeof(action_t) * (placements + upper_bound_moves));
+ if (level >= AL_MAX_LEVELS) {
+ fprintf(stderr, "actions_generate_at: level %u exceeds AL_MAX_LEVELS\n",
+ level);
+ abort();
+ }
+ action_t *actions = al_scratch[level];
uint32_t total = 0, move_idx = placements, place_idx = placements;
// Step across the board