Files
dusk/test/rpg/cutscene/test_cutscene.c
T
YourWishesandClaude Sonnet 5 c9f098693c Wire up battle AI/scene-return, reclaim cutscene item slots, fix GOTO
- battleStateSelectionAiDecide: AI-controlled fighters now actually
  queue a basic attack against the first living enemy instead of doing
  nothing every round.
- battleStateEndingInit: disposes the battle and switches back to
  SCENE_TYPE_OVERWORLD instead of leaving the game stuck in the battle
  scene forever.
- cutsceneSystemNext now pops each finished item off the front of the
  running cutscene (cutsceneRemoveFront) instead of leaving it in place
  forever, so a long-running cutscene (many battle rounds splicing
  items in repeatedly) no longer grows scene->items unboundedly.
- cutsceneGoTo reworked to match: since consumed items are evicted, a
  marker behind the current position can't be found in the live queue
  anymore, so it now re-parses the cutscene fresh from its source file
  (cutsceneLoadParse, into a persistent scratch buffer, not the stack)
  and replaces the live queue with marker-onward from that fresh parse.
  Only supported when the running cutscene is the one
  cutsceneSystemLoad/cutsceneCutsceneResolve populated.
- Fixed a real bug this surfaced: cutsceneSystemPrepare unconditionally
  cleared loadedFile, which ran *after* cutsceneCutsceneResolve had
  just stamped it but *before* the cutscene started - wiping it out
  immediately and breaking cutsceneGoTo for any cutscene entered via a
  CUTSCENE item or cutsceneCutsceneResolve (e.g. the main menu's
  NEW_GAME/OPTIONS/QUIT navigation). Now only cleared when switching
  away from loadedScene entirely.
- Added cutsceneLoadParse, the shared "lock asset, require loaded,
  parse items, unlock" sequence, replacing four near-identical copies
  across cutsceneSystemLoad/cutsceneCutsceneResolve/
  cutsceneInsertResolveAndSplice/battleStateExecutingInit. Each call
  site handles its own fatal-error display; cutsceneLoadParse itself
  just propagates.
- Added test_cutscene.c (cutsceneRemoveFront) and a regression test for
  the loadedFile bug. Writing the zero-count RemoveFront test caught a
  real self-move bug (count == 0 passed dest == src into memoryMove).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-21 15:04:41 -05:00

85 lines
2.5 KiB
C

/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "dusktest.h"
#include "rpg/cutscene/cutscene.h"
#include "util/memory.h"
#include "util/string.h"
// ============================================================
// cutsceneRemoveFront
// ============================================================
static cutsceneitem_t MARKER_ITEM(const char_t *name) {
cutsceneitem_t item;
memoryZero(&item, sizeof(item));
item.type = CUTSCENE_ITEM_TYPE_MARKER;
stringCopy(item.marker.name, name, CUTSCENE_MARKER_NAME_MAX - 1);
return item;
}
static void test_cutsceneRemoveFrontShiftsRemainderToIndexZero(
void **state
) {
cutsceneitem_t items[4] = {
MARKER_ITEM("a"), MARKER_ITEM("b"), MARKER_ITEM("c"), MARKER_ITEM("d")
};
cutscene_t scene = { .items = items, .itemCount = 4, .itemsMax = 4 };
cutsceneRemoveFront(&scene, 2);
assert_int_equal(scene.itemCount, 2);
assert_string_equal(scene.items[0].marker.name, "c");
assert_string_equal(scene.items[1].marker.name, "d");
}
static void test_cutsceneRemoveFrontAllItemsLeavesEmptyScene(void **state) {
cutsceneitem_t items[3] = {
MARKER_ITEM("a"), MARKER_ITEM("b"), MARKER_ITEM("c")
};
cutscene_t scene = { .items = items, .itemCount = 3, .itemsMax = 3 };
cutsceneRemoveFront(&scene, 3);
assert_int_equal(scene.itemCount, 0);
}
static void test_cutsceneRemoveFrontZeroIsNoop(void **state) {
cutsceneitem_t items[2] = { MARKER_ITEM("a"), MARKER_ITEM("b") };
cutscene_t scene = { .items = items, .itemCount = 2, .itemsMax = 2 };
cutsceneRemoveFront(&scene, 0);
assert_int_equal(scene.itemCount, 2);
assert_string_equal(scene.items[0].marker.name, "a");
assert_string_equal(scene.items[1].marker.name, "b");
}
static void test_cutsceneRemoveFrontAssertsWhenCountExceedsItemCount(
void **state
) {
cutsceneitem_t items[2] = { MARKER_ITEM("a"), MARKER_ITEM("b") };
cutscene_t scene = { .items = items, .itemCount = 2, .itemsMax = 2 };
expect_assert_failure(cutsceneRemoveFront(&scene, 3));
}
int main(int argc, char** argv) {
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_cutsceneRemoveFrontShiftsRemainderToIndexZero),
cmocka_unit_test(test_cutsceneRemoveFrontAllItemsLeavesEmptyScene),
cmocka_unit_test(test_cutsceneRemoveFrontZeroIsNoop),
cmocka_unit_test(test_cutsceneRemoveFrontAssertsWhenCountExceedsItemCount),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}