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