aboutsummaryrefslogtreecommitdiff
path: root/src/libsok/sok-ctx.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsok/sok-ctx.c')
-rw-r--r--src/libsok/sok-ctx.c66
1 files changed, 43 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