src/ai/squirrel/squirrel.cpp
author truelight
Tue, 13 Mar 2007 22:55:44 +0000
branchnoai
changeset 9367 f8f43e231acf
parent 9366 d30036300fe7
child 9368 55bdc4215a68
permissions -rw-r--r--
(svn r9154) [NoAI] -Fix: print compile-time errors too
/* $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);
}