truelight@9365: /* $Id$ */ truelight@9365: truelight@9365: /** @file squirrel.cpp allows loading squirrel scripts to control an AI */ truelight@9365: truelight@9365: #include "squirrel.hpp" truelight@9365: #include truelight@9365: #include truelight@9365: #include truelight@9365: #include "../../debug.h" truelight@9365: truelight@9365: /** truelight@9365: * Here we handle errors that come from squirrel. truelight@9365: */ truelight@9367: static void Squirrel_CompileError(HSQUIRRELVM vm, const SQChar *desc, const SQChar *source, SQInteger line, SQInteger column) truelight@9365: { truelight@9365: #ifdef _SQ64 truelight@9365: printf("Error %s:%ld/%ld: %s\n", source, line, column, desc); truelight@9365: #else truelight@9365: printf("Error %s:%d/%d: %s\n", source, line, column, desc); truelight@9365: #endif truelight@9365: } truelight@9365: truelight@9365: /** truelight@9367: * Here we handle run-time errors that come from squirrel. truelight@9367: */ truelight@9367: static SQInteger Squirrel_RunError(HSQUIRRELVM vm) truelight@9367: { truelight@9367: const SQChar *sErr = 0; truelight@9367: truelight@9367: if (sq_gettop(vm) >= 1) { truelight@9367: if (SQ_SUCCEEDED(sq_getstring(vm, -1, &sErr))) { truelight@9367: printf("%s\n", sErr); truelight@9367: } else { truelight@9367: printf("Unknown error\n"); truelight@9367: } truelight@9367: } truelight@9367: truelight@9367: return 0; truelight@9367: } truelight@9367: truelight@9367: /** truelight@9365: * Here we handle 'print' command within squirrel script. truelight@9365: */ truelight@9365: static void Squirrel_PrintFunc(HSQUIRRELVM vm, const SQChar *s, ...) truelight@9365: { truelight@9365: va_list arglist; truelight@9365: va_start(arglist, s); truelight@9365: vprintf(s, arglist); truelight@9365: va_end(arglist); truelight@9365: printf("\n"); truelight@9365: } truelight@9365: truelight@9365: Squirrel::Squirrel(const char *script_dir) truelight@9365: { truelight@9365: char filename[1024]; truelight@9365: truelight@9365: this->vm = sq_open(1024); truelight@9365: truelight@9365: /* Handle compile-errors ourself, so we can display it nicely */ truelight@9367: sq_setcompilererrorhandler(this->vm, Squirrel_CompileError); truelight@9365: sq_notifyallexceptions(this->vm, SQTrue); truelight@9365: /* Set a good print-function */ truelight@9365: sq_setprintfunc(this->vm, Squirrel_PrintFunc); truelight@9365: truelight@9367: sq_newclosure(this->vm, &Squirrel_RunError, 0); truelight@9367: sq_seterrorhandler(this->vm); truelight@9367: truelight@9365: /* TODO -- This is ugly! */ truelight@9365: strcpy(filename, "ai/"); truelight@9365: strcat(filename, script_dir); truelight@9365: strcat(filename, PATHSEP); truelight@9365: strcat(filename, "main.sq"); truelight@9365: truelight@9365: DEBUG(ai, 1, "[squirrel] Starting AI with script in '%s'", filename); truelight@9365: truelight@9365: /* Load and run the script */ truelight@9365: sq_pushroottable(this->vm); truelight@9365: if (!SQ_SUCCEEDED(sqstd_dofile(this->vm, filename, SQFalse, SQTrue))) { truelight@9365: DEBUG(ai, 0, "[squirrel] Failed to compile '%s'", filename); truelight@9365: return; truelight@9365: } truelight@9365: } truelight@9365: truelight@9365: Squirrel::~Squirrel() truelight@9365: { truelight@9365: /* Clean up the stuff */ truelight@9365: sq_pop(this->vm, 1); truelight@9365: sq_close(this->vm); truelight@9365: } truelight@9365: truelight@9365: /* virtual */ void Squirrel::GameLoop() truelight@9365: { truelight@9365: /* Store the current top */ truelight@9365: int top = sq_gettop(this->vm); truelight@9365: /* Go back to root-table */ truelight@9365: sq_pushroottable(this->vm); truelight@9365: /* Find the function-name inside the script */ truelight@9366: sq_pushstring(this->vm,_SC("GameLoop"), -1); truelight@9365: if (!SQ_SUCCEEDED(sq_get(this->vm, -2))) { truelight@9366: DEBUG(ai, 0, "[squirrel] Failed to run GameLoop"); truelight@9365: sq_settop(this->vm, top); truelight@9365: return; truelight@9365: } truelight@9365: /* Call the function */ truelight@9365: sq_pushroottable(this->vm); truelight@9365: sq_call(this->vm, 1, 0, 0); truelight@9365: /* Reset the top */ truelight@9365: sq_settop(this->vm, top); truelight@9365: }