/*
 * Prelude for the interpreter-facing fragments in docs/20: the boot sequence,
 * the ADDEM proof and the rebind-call-reset protocol, shown as runs of CATCH
 * calls. The statics are the ones examples/galaga/script.c keeps; the locals
 * are the superset every fragment draws from, void-cast in the postlude so an
 * unused one is not a warning.
 */
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include <SDL3/SDL.h>

#include <akerror.h>
#include <akstdlib.h>

#include <akgl/actor.h>

#include <akbasic/environment.h>
#include <akbasic/error.h>
#include <akbasic/host.h>
#include <akbasic/runtime.h>
#include <akbasic/sink.h>

typedef struct galaga_docs_Enemy
{
    int32_t  kind;
    int32_t  state;
    float    homex;
    float    homey;
    float    t;
    int32_t  hp;
    int32_t  fire;
    float    rnd;
} galaga_docs_Enemy;

typedef struct galaga_docs_Shared
{
    float    playerx;
    float    playery;
    int32_t  wave;
    float    rnd;
} galaga_docs_Shared;

static akbasic_Runtime SCRIPT;
static akbasic_TextSink SINK;
static akbasic_StdioSink SINKSTATE;
static char SOURCE[16384];

static galaga_docs_Enemy SCRATCH_ENEMY;
static akgl_Actor SCRATCH_ACTOR;
static galaga_docs_Shared galaga_shared;

static const akbasic_HostField ENEMY_FIELDS[] = {
    AKBASIC_HOST_FIELD( galaga_docs_Enemy, kind, "KIND#", AKBASIC_HOSTFIELD_INT32 )
};
static const akbasic_HostType ENEMY_TYPE = {
    "ENEMY", sizeof(galaga_docs_Enemy), ENEMY_FIELDS, 1
};
static const akbasic_HostField ACTOR_FIELDS[] = {
    AKBASIC_HOST_FIELD( akgl_Actor, x, "X%", AKBASIC_HOSTFIELD_FLOAT )
};
static const akbasic_HostType ACTOR_TYPE = {
    "ACTOR", sizeof(akgl_Actor), ACTOR_FIELDS, 1
};
static const akbasic_HostField GAME_FIELDS[] = {
    AKBASIC_HOST_FIELD( galaga_docs_Shared, wave, "WAVE#", AKBASIC_HOSTFIELD_INT32 )
};
static const akbasic_HostType GAME_TYPE = {
    "GAME", sizeof(galaga_docs_Shared), GAME_FIELDS, 1
};

akerr_ErrorContext AKERR_NOIGNORE *galaga_docs_fragment(galaga_docs_Enemy *enemy, akgl_Actor *actor, float dt);
akerr_ErrorContext AKERR_NOIGNORE *galaga_docs_fragment(galaga_docs_Enemy *enemy, akgl_Actor *actor, float dt)
{
    PREPARE_ERROR(errctx);
    akbasic_Value args[2];
    akbasic_Value *argp[2];
    akbasic_Value dtval;
    akbasic_Value *result = NULL;

    ATTEMPT {
