src/ai/squirrel/squirrel.cpp
author truelight
Tue, 13 Mar 2007 22:39:41 +0000
branchnoai
changeset 9366 d30036300fe7
parent 9365 c3d08e0b1083
child 9367 f8f43e231acf
permissions -rw-r--r--
(svn r9153) [NoAI] -Add: added a bit more code to the script to show how classes work (and that instances stay alive)
-Fix: gameLoop -> GameLoop
/* $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_PrintError(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 '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_seterrorhandler(this->vm);
	sq_setcompilererrorhandler(this->vm, Squirrel_PrintError);
	sq_notifyallexceptions(this->vm, SQTrue);
	/* Set a good print-function */
	sq_setprintfunc(this->vm, Squirrel_PrintFunc);

	/* 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);
}