aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Duncan <pabs@pablotron.org>2019-01-08 15:55:22 -0500
committerPaul Duncan <pabs@pablotron.org>2019-01-08 15:55:22 -0500
commite15f396ef55e190502ee7603c8e5e3d8f31ad3ea (patch)
treec384d398f3b545a9939037a55951308bec277c55
parent1bc7126d48bd09c9b8d69593d4a48e9cd394a79f (diff)
downloadsok-e15f396ef55e190502ee7603c8e5e3d8f31ad3ea.tar.bz2
sok-e15f396ef55e190502ee7603c8e5e3d8f31ad3ea.zip
speed up sok_ctx_is_done()
-rw-r--r--src/libsok/sok-ctx.c66
-rw-r--r--src/libsok/sok.h4
2 files changed, 47 insertions, 23 deletions
diff --git a/src/libsok/sok-ctx.c b/src/libsok/sok-ctx.c
index d9985d7..d19682a 100644
--- a/src/libsok/sok-ctx.c
+++ b/src/libsok/sok-ctx.c
@@ -145,6 +145,40 @@ LEVEL_PARSER_CBS = {
.on_junk = on_junk,
};
+static size_t
+pos_find(
+ const sok_pos_t pos,
+ const sok_pos_t * const set,
+ const size_t len
+) {
+ for (size_t i = 0; i < len; i++) {
+ if (POINTS_EQUAL(pos, set[i])) {
+ return i;
+ }
+ }
+
+ return len;
+}
+
+static size_t
+sok_ctx_count_goals_left(
+ sok_ctx_t * const ctx
+) {
+ const size_t num_boxes = ctx->level.num_boxes;
+ size_t r = 0;
+
+ for (size_t i = 0; i < ctx->level.num_goals; i++) {
+ r += pos_find(
+ ctx->level.goals[i],
+ ctx->boxes,
+ num_boxes
+ ) < num_boxes ? 0 : 1;
+ }
+
+ return r;
+}
+
+
void
sok_ctx_init(sok_ctx_t * const ctx, void *user_data) {
memset(ctx, 0, sizeof(sok_ctx_t));
@@ -175,6 +209,9 @@ sok_ctx_set_level(
ctx->home = ctx->level.home;
memcpy(ctx->boxes, ctx->level.boxes, ctx->level.num_boxes * sizeof(sok_pos_t));
+ // count number of goals left
+ ctx->num_goals_left = sok_ctx_count_goals_left(ctx);
+
// return success
return true;
}
@@ -191,21 +228,6 @@ tile_is_floor(
);
}
-static size_t
-pos_find(
- const sok_pos_t pos,
- const sok_pos_t * const set,
- const size_t len
-) {
- for (size_t i = 0; i < len; i++) {
- if (POINTS_EQUAL(pos, set[i])) {
- return i;
- }
- }
-
- return len;
-}
-
static bool
tile_is_box(
const sok_ctx_t * const ctx,
@@ -274,10 +296,15 @@ sok_ctx_move_box(
box_ofs = pos_find(old_pos, ctx->boxes, num_boxes);
if (box_ofs < num_boxes) {
+ // update box and goal count
ctx->boxes[box_ofs] = new_pos;
+ ctx->num_goals_left = sok_ctx_count_goals_left(ctx);
+
+ // return success
return true;
}
+ // return failure
return false;
}
@@ -285,14 +312,7 @@ bool
sok_ctx_is_done(
sok_ctx_t * const ctx
) {
- for (size_t i = 0; i < ctx->level.num_goals; i++) {
- if (!tile_is_box(ctx, ctx->level.goals[i])) {
- return false;
- }
- }
-
- // return success
- return true;
+ return ctx->num_goals_left == 0;
}
bool
diff --git a/src/libsok/sok.h b/src/libsok/sok.h
index 54e6c93..3e64afd 100644
--- a/src/libsok/sok.h
+++ b/src/libsok/sok.h
@@ -107,9 +107,13 @@ typedef struct {
typedef struct {
sok_level_t level;
+ // moves
sok_move_t moves[SOK_CTX_MAX_MOVES];
size_t num_moves;
+ // number of open goals
+ size_t num_goals_left;
+
// player position
sok_pos_t home;