\chapter{Game Scripting Under Linux}
\label{ch:gamescripting}

Games tend to be extremely large these days, and it is usually impractical for programmers to worry about the details of level design and character behavior. For example, the game \gametitle{Soldier of Fortune} (which has been ported to Linux) weighs in at over 700 megabytes of disk space, and only a small fraction of this data contains actual code. The bulk of this space is consumed by 3D world data, character models, and scripts.

Scripts allow game creators to control the behavior and artificial intelligence of maps and game characters without actually modifying the game's compiled code. Just as high-level languages (such as C and Java) allow programmers to accomplish tasks that would be practically impossible in pure assembly language (due to development time and complexity), game-scripting languages allow game developers to quickly implement features that would not be practical to implement directly in the game engine. Scripts are simply special-purpose programs, usually written in customized scripting languages, that tie game worlds together. Game-scripting languages are often specially designed for a particular game, but programmers sometimes opt to use off-the-shelf scripting languages for their games. Scripting also allows nonprogrammers to create game worlds, and it can add a great deal of realism to games.

In this chapter we'll use the Tcl scripting language to add a scripted opponent to Penguin Warrior. Although Tcl is neither the fastest scripting language nor the most popular, it is extremely simple to embed into a program and extend with custom commands, and the language is trivial to learn. Before we learn how to weld the Tcl library into our game engine, however, let's look at the Tcl language itself. If you're interested only in learning how to hook up a scripting engine or you happen to have a distaste for Tcl, you may wish to skim over the next section.

\section{A Crash Course in Tcl}
\index{Tcl!tutorial|(}
Tcl is an extremely simple language to learn; in fact, the single biggest problem with Tcl is that people often try to second-guess its trivial syntax. Once we've gone over the basics of Tcl syntax, we will examine the embeddable Tcl scripting library and learn how to add its functionality to \gametitle{Penguin Warrior}. We'll keep this brief; this is not a book on scripting languages, nor is it a treatise on the fine points of Tcl coding.

Tcl is based almost entirely on substitution. It has no notion of data types\index{Tcl!data}; numbers and strings are the same thing, represented internally as strings and converted as necessary.\footnote{\index{Tcl!performance concerns}Performance-minded readers need not be concerned about the implications of treating all variables as strings. Tcl does a bit of voodoo internally to avoid unnecessary conversions; for instance, if it becomes apparent to Tcl that a certain variable contains a floating-point number, it will store it in an appropriate binary format, rather than as a string. This improves memory usage and performance. However, this optimization takes place behind the scenes, and you can treat everything as a string.} Tcl programs consist of \firstterm{words}. The first word on each line is a \firstterm{command}, and the rest of the words on each line are \firstterm{arguments} to that command. Many commands are provided by Tcl, but you can also easily add your own, either as scripts or as native C code. Tcl has no keywords; everything is implemented with commands, even such high-level constructs as code{for} and code{while}.

\index{Tcl!strings}
There are two types of strings in Tcl. The first type is delimited by curly braces (\verb|{ }|). These strings are not affected by Tcl's normal substitution rules (which we discuss shortly). The second type is delimited by double quotes. These are subject to substitution and backslash escapes. (Backslash escapes work just like they do in C.) The first type of strings are processed a bit more quickly, so it is a good idea to use them whenever possible. They're also a bit more convenient for enclosing entire scripts, since you don't have to escape quotes.

Let's take a look at a simple Tcl script.
\index{Tcl!simple example|(}
\begin{codelisting}{basictcl.tcl}{code:basictcl}
\begin{verbatim}
# A very basic Tcl example.

# Print "Hello, world!" using the two string types.
puts "Hello, world! (using quotes)"
puts {Hello, world! (using braces)}

# Demonstrate simple variable substitution.
set foo {Foo!}
puts "This is the variable foo: $foo"

# This won't be substituted, since the string is in curly braces.
puts {This is not the variable foo: $foo}

# Change the value of the variable foo.
set foo {Bar!}
puts "The variable foo is now $foo."

# Read a string from the console (stdin).
puts -nonewline {Please enter your name: }
flush stdout
set name [gets stdin]
puts "You entered: $name"
\end{verbatim}
\end{codelisting}
\index{Tcl!simple example|)}

\index{Tcl!variable substitution}Give this script a try by feeding it to the Tcl shell (tclsh). \index{Tcl!tclsh}\index{tclsh}tclsh is simply a command-line utility that provides an interface to an embedded Tcl interpreter (the same interpreter library that we will build into \gametitle{Penguin Warrior}). From the script's output you can see that strings enclosed in curly braces are not scanned for substitution, whereas strings enclosed in quotes are processed. Variables are inserted into strings with the \code{\$name} notation (\code{\${name}} also works, and this notation can be useful if the name of a variable contains special characters). Variable substitution also works outside of strings.

\index{Tcl!command substitution}This script also uses \firstterm{command substitution}, which is invoked with square brackets (\mbox{\code{[ ]}}). Any text within a set of square brackets is evaluated as a separate Tcl script, and the brackets are replaced by the result of the script. Our example uses command substitution to assign a variable to the output of the \code{gets} command. Command substitution is allowed both inside and outside of quoted strings.

In case you don't have access to a Tcl interpreter, the output of the script should look something like this:

\begin{shell}
\begin{verbatim}
$ tclsh basictcl.tcl
Hello, world! (using quotes)
Hello, world! (using braces)
This is the variable foo: Foo!
This is not the variable foo: $foo
The variable foo is now Bar!.
Please enter your name: John
You entered: John
\end{verbatim}
\end{shell}

% $

\begin{note}{Commercially Maintained Free Software}
\index{Tcl!obtaining|(}
Tcl is free and open source software with almost no usage restrictions, but it is commercially supported by \index{Scriptics, Inc.}Scriptics, Inc. (recenty acquired by Ajuba and then by Interwoven). Tcl is included with most Linux distributions, and you can also download it separately from \ulink{ftp://ftp.scriptics.com}. In addition to the embeddable scripting library, the Tcl distribution comes with a command-line script loader and shell called tclsh. This shell is good for learning Tcl and for writing scripts for quick jobs. Tcl can actually serve as a powerful replacement for traditional shell scripting languages. Scriptics developed but no longer maintains a commercial Tcl development system called TclPro. It's now open source and available to the public on \website{SourceForge}{http://www.sourceforge.net}. TclPro includes a bytecode compiler, a graphical debugger, a code checker, and other utilities that might be of interest for large-scale Tcl development.
\index{Tcl!obtaining|)}
\end{note}

\subsection{Built-in Tcl Commands}
\index{Tcl!built-in commands|(}
Let's look at a few of Tcl's built-in commands. Some of these commands are essential and some are just nice to have around. In general, you should use as many built-in commands as possible, rather than write your own, since C code executes much more quickly than interpreted Tcl. Performance is very much a concern when writing scripts for real-time games, especially when working with a language that isn't remarkably fast to begin with.

\subsubsection{Recursive Evaluation}
It's sometimes nice to be able to evaluate arbitrary pieces of text as separate scripts. The \code{eval} command evaluates its argument (or arguments) as a complete script, returning the result of the script if there are not showstopping errors. In addition to providing a clean way to implement control structures, \code{eval} is useful for forcing the interpreter to perform multiple passes of substitution over a string. Tcl's power lies in the fact that it treats everything as text, and it performs substitution before execution. If a variable containing the text ``\code{\$foo}'' is substituted into a string and the string is evaluated again (with \code{eval}), Tcl will try to substitute the value of the variable \code{foo} into the final string. Consider the following:

\begin{shell}
\begin{verbatim}
$ tclsh
% set foo {$bar}
$bar
% set bar {Hello, world!}
Hello, world!
% eval puts $foo
Hello, world!
\end{verbatim}
\end{shell}

Tcl automatically performs substitution on each line of code before it actually evaluates the code, and this immediately transforms the last line of input in the example into \code{eval puts \$bar}. The explicit call to \code{eval} forces another substitution pass, which transforms the code into \code{puts Hello, world!}. This trick is quite useful for game scripting; Tcl has very weak array support, and it is often more practical to create variable names (such as \code{missile3} and \code{ship5}) on the fly. You can abuse \code{eval} in any number of ways. You'll see how to use \code{eval} to create control structures shortly.


\subsubsection{Evaluating Mathematical Expressions}
Tcl itself has no support for mathematical operations; instead, mathematical expressions are passed as input to the \code{expr} command, which returns its result as a string. \code{expr} introduces a mini-language of its own (documented in its manpage), and it can handle just about any expression you would expect a command-line calculator to understand. You can use normal Tcl substitution to introduce variables into mathematical expressions. For example, \code{set bar [expr \$foo + sin(\$angle)]} adds the sine of the \code{angle} variable to \code{foo}, and saves the result in the variable \code{bar}. You could then use this value by substituting it into a statement as \code{\$bar}.

If you just need to increment or decrement a variable, the \code{incr} command is much more efficient than \code{expr}. For instance, \code{incr foo -2} is equivalent to \code{set foo [expr \$foo - 2]}, but a bit faster.

\code{expr} is not as slow as you might think, but it's certainly a good idea to avoid it when you can. Tcl is designed for flexibility and simplicity, not speed. It is much better at string processing than number crunching; keep this in mind if you decide to use Tcl for your own projects.


\subsubsection{Lists}
Tcl does not have built-in support for lists or arrays. Instead, it provides a set of functions for treating specially formatted strings as lists. This is clearly not the most efficient way to manage large sets of data, but it is fairly elegant, and it fits well with Tcl's philosophy of simplicity and consistency. Tcl does perform a certain amount of runtime optimization on its data storage mechanisms, but don't count on this optimization to do very much. If you need to store a large amount of data in your script, consider using associative arrays (which we won't cover here) or storing the data in your C program.

A Tcl list is simply a string of space-separated elements. For instance, the string \code{foo bar baz qux} can be considered a four-element list. If an individual element contains spaces, enclose it in braces to prevent it from being treated as multiple elements. For instance, \code{foo \{Hello, world!\} bar} is a three-element list. You can create lists by hand or with Tcl's \code{list} command. For instance, \code{list foo \{Hello, world\} bar} would return a three-element list. However, since Tcl lists are just strings, \code{list} is really just a command for quickly assembling a bunch of strings into one. This is handy for strange constructs involving multiple passes of substitution.

The \code{lindex} command retrieves an element of a Tcl list by index, starting with zero. For instance, \code{lindex \{foo bar baz qux\} 2} returns \code{baz}, the third element of the list. The \code{lreplace} command allows you to edit elements in a list, and the \code{linsert} command allows you to insert elements into a list. See the Tcl manpages for more information about these commands.


\subsubsection{Control Commands}
Tcl doesn't have an \code{if} statement (a feature of just about every other language out there), but it does have an \code{if} \emph{command}. This distinction is really only a technicality; the command works exactly as you might expect. It takes an expression (of the same format expected by the \code{expr} command) and one or two pieces of code. If the expression evaluates to a value that is considered ``true'' (nonzero), the first piece of code is executed recursively. If the expression evaluates to ``false'' (zero) and a second piece of code is provided, preceded by the token \code{else}, it is executed instead. These pieces of code are simply strings contained in curly braces.

Likewise, Tcl provides a \code{while} command that executes a piece of code while an expression holds true. This is self-explanatory. It would be extremely simple to implement the \code{while} command in Tcl yourself (but rather pointless).

\longpage
The last Tcl control command we'll discuss is the \code{switch} command, which allows a program to quickly compare a string against several other strings and execute a piece of code as soon as one of the strings matches. This matching can be done with exact comparison (code{strcmp}), globbing (the type of matching most UNIX shells use for comparing filenames, allowing asterisks and question marks for wildcards), and regular expressions. For example, the following \code{switch} command compares the string in the variable \code{foo} against the strings \code{bar}, \code{baz}, and \code{qux}:

\begin{codesegment}
\begin{verbatim}
switch $foo {
  bar     { puts "Bar!" }
  baz     { puts "Baz!" }
  qux     { puts "Qux!" }
  default { puts "Nothing!" }
}
\end{verbatim}
\end{codesegment}

% $

The \code{switch} command's other matching modes are even more powerful. To use globbing or regex matching, add \code{-glob} or \code{-regexp} as the first argument to \code{switch}. These modes are not likely to be useful in a game script, however, and they aren't nearly as fast as normal string matching.


\subsubsection{Procedures}
Tcl procedures are commands that are implemented in Tcl rather than in C. They can take any number of arguments, and they can optionally return a single value. Tcl provides a \code{proc} command for creating procedures. Once you have created a procedure, you can invoke it by name, just as you can any other Tcl command. For instance, the following script creates an \code{avg} command for averaging two numbers:

\begin{codesegment}
\begin{verbatim}
proc avg { a b } {
  return [expr ($a + $b) / 2]
}
\end{verbatim}
\end{codesegment}

\code{proc} takes three arguments: the name of the command to define, a list of the parameters it takes, and a script to associate with the command (as a string). Since all Tcl variables (except for associative arrays, which we won't discuss here) are strings, there is no need to specify anything about the parameters, other than the names. When the command is executed, the arguments passed to the command will be available as variables with these names.

Tcl handles local and global variables a bit differently than most other languages. All variable names are assumed to be \emph{local} unless you specify otherwise; that is, global variables are not normally visible from procedure bodies. For example, the following code is incorrect:

\begin{codesegment}
\begin{verbatim}
set status {Ok}

proc printstatus { } {
  puts "Status: $status"
}
\end{verbatim}
\end{codesegment}

% $

\longpage
Here, \code{status} is a global variable, and so by default it is not available to \code{printstatus}. To remedy this, use the \code{global} command to bring in the global variables you need to access:

\begin{codesegment}
\begin{verbatim}
set status {Ok}

proc printstatus { } {
  global status
  puts "Status: $status"
}
\end{verbatim}
\end{codesegment}

% $

This is annoying, but it does allow Tcl to optimize its variable namespace searching a bit. It is a good idea to avoid excessive use of global variables, since they often lead to unwanted side effects and sloppy programming.

Tcl also provides two other commands, \code{upvar} and \code{uplevel}, which allow you to link variables between stack frames. This is important for implementing control structures (for instance, a pure Tcl implementation of the \code{while} command would most likely rely on \code{uplevel} to keep variables from disappearing), but we'll leave these commands to Tcl's online documentation.


\subsubsection{Error Handling}
Tcl commands can fail for a number of reasons, and it's a good idea to be ready to handle this when it happens. Error conditions normally stop the interpreter, but you can use the \code{catch} command to trap errors and keep them from bringing your script down. This command is extremely simple; if you enclose a block of code in a \code{catch} block, it won't be able to crash the interpreter. The \code{catch} command returns zero if nothing disastrous happens and nonzero if something failed. You can even nest \code{catch} blocks for fine-grained error detection. Keep in mind that \code{catch} is just another Tcl command, rather than special syntax.

\index{Tcl!built-in commands|)}
\index{Tcl!tutorial|)}

\section{Interfacing Tcl with C}
\index{Tcl!extension language@as extension language|(}
Enough about the Tcl language; our main interest is to add a scripting engine to our game. \gametitle{Penguin Warrior} is pretty boring at the moment. There's really nothing to do except fly around. It's now time to add a computer-controlled opponent, scripted in Tcl, of course, and some heavy weaponry for doing battle.  To do this we'll need to link the Tcl library into our program and use its C interface to create a few \gametitle{Penguin Warrior}--specific commands.

\subsection{Linking Against Tcl}
\index{Tcl!linking against|(}
First things first: we need access to the Tcl library before we can use it as an extension language. Fortunately, this is pretty easy. Once you've installed the library and C headers on your system, you can include \filename{tcl.h} and link your programs against \filename{libtcl.so} (with the \cmdline{-ltcl} flag). You'll also need to link in the standard math library (\cmdline{-lm}). Beware that some distributions try to be clever by renaming their Tcl libraries to reflect a particular version number, so you may have to look around a bit. Try compiling a simple ``Hello, world!'' program with the Tcl library. If this works, you're ready to go. For the purposes of this chapter, we'll assume that your system has an appropriate \filename{libtcl.so} and that you know where to find it. You may have to modify \gametitle{Penguin Warrior}'s makefile accordingly.

If your Linux distribution didn't come with a working Tcl library, you can download one from \ulink{ftp://ftp.scriptics.com}. Follow the installation instructions included with the package. The current version at the time of this writing is 8.3, but later versions will probably work just as well.
\index{Tcl!linking against|)}

\subsection{Executing Scripts}
\index{Tcl!interpreter object}Each Tcl session is represented internally by a \code{Tcl\_Interp} structure. This structure keeps track of the script's text, its activation stack, and its variables. Everything in Tcl is dynamically allocated, so there's no harm in creating as many of these structures as you might find useful. (One will usually suffice, however.) \code{Tcl\_CreateInterp} returns a pointer to a new \code{Tcl\_Interp} structure, and \code{Tcl\_DeleteInterp} gets rid of an interpreter that's no longer needed. \gametitle{Penguin Warrior} is a simple game, and it will run all of its scripting out of one interpreter.

\longpage
\index{Tcl!executing code}Once you have a \code{Tcl\_Interp} to play with, you can feed it a script. There are two ways to get Tcl code into an interpreter: you can load the script file ahead of time and pass it to Tcl (as a string) with the \code{Tcl\_Eval} function, or you can use the \code{Tcl\_EvalFile} function to run a script directly from a file. The choice is really just a matter of convenience; Tcl doesn't care how it gets its input. Once Tcl has a script to chew on, it will rip through the script as quickly as possible, adding any newly defined commands or variable assignments to its repertoire and executing anything else it finds. \code{Tcl\_Eval} saves the result of the last command it executed for later use (it's the return value of the script, in a sense).

Let's see exactly how this is done.

\begin{codelisting}{tclshell.c}{code:tclshell}
\begin{verbatim}
/* A simple but functional Tcl shell. */

#include <stdio.h>
#include <stdlib.h>
#include <tcl.h>

int main()
{
    Tcl_Interp *interp;
    char input[16384];

    /* Create an interpreter structure. */
    interp = Tcl_CreateInterp();
    if (interp == NULL) {
        printf("Unable to create interpreter.\n");
        return 1;
    }

    /* Add custom commands here. */

    /* Loop indefinitely (we'll break on end-of-file). */
    for (;;) {
        int result;
        char *message;

        /* Print a prompt and make it appear immediately. */
        printf("> ");
        fflush(stdout);

        /* Read up to 16k of input. */
        if (fgets(input, 16383, stdin) == NULL) {
            printf("End of input.\n");
            break;
        }

        /* Evaluate the input as a script. */
        result = Tcl_Eval(interp, input);

        /* Print the return code and the result. */
        switch (result) {
        case TCL_OK:
            message = " OK ";
            break;
        case TCL_ERROR:
            message = "ERR ";
            break;
        case TCL_CONTINUE:
            message = "CONT";
            break;
        default:
            message = " ?? ";
            break;
        }

        printf("[%s] %s\n", message, Tcl_GetStringResult(interp));
    }

    /* Delete the interpreter. */
    Tcl_DeleteInterp(interp);

    return 0;
}
\end{verbatim}
\end{codelisting}

This program implements a very simple command-line Tcl shell. It collects input from standard input (up to 16K of it), evaluates it with \code{Tcl\_Eval}, and prints the result, along with any errors that occurred.

\index{Tcl!linking against}To compile this Tcl shell, you'll need the Tcl library and the floating-point math library:

\begin{shell}
\begin{verbatim}
$ gcc -W -Wall -pedantic tclshell.c -o tclshell -ltcl -lm
\end{verbatim}
\end{shell}

% $

Your Tcl library may be named differently; if it refuses to link with \cmdline{-ltcl}, try \cmdline{-ltcl8.2} or \cmdline{-ltcl8.3}. Failing these, look for something starting with \filename{libtcl} in \filename{/usr/lib} or \filename{/usr/local/lib} and use that name. (This is the kind of situation in which Autoconf would be handy; more on this in Chapter \ref{ch:gameinstall}.)

Go ahead and give this program a try. Feed it some of the scripts from earlier in the chapter or anything else you can think of. Remember that this simple shell can't handle partial statements; for instance, you can't enter \code{proc foo \{ \} \{} on one line and expect to continue it on the next. You can exit with an end-of-file character (Ctrl-D) or with the built-in \code{exit} command.

\begin{apiref}
\indexc{Tcl\_Interp}
\structname{Tcl\_Interp}
\structsynopsis{Encapsulates a Tcl interpreter's stack, variables, and script. \code{Tcl\_Interp} is a large structure, but most of it is meant to be internal to Tcl.}
\structfirstmember{result}{Most recently set result, as a string. (You may retrieve a Tcl interpreter's most recent result as a Tcl object with \code{Tcl\_GetObjResult}.)}
\structnextmember{freeProc}{Function to call if \code{Tcl\_DeleteInterp} is ever invoked on this interpreter. You only need to use this if you've set the result pointer to memory that you own and you'd like a chance to free it before the pointer is lost.}
\structnextmember{errorLine}{If \code{Tcl\_Eval} returns \code{TCL\_ERROR}, this will contain the line number of the error. \emph{Read-only.}}
\structendmembers
\end{apiref}

\begin{apiref}
\indexc{Tcl\_CreateInterp}
\apifunction{Tcl\_CreateInterp()}
\apisynopsis{Allocates a new \code{Tcl\_Interp} structure and prepares it to receive a script.}
\apireturns{Pointer to a new \code{Tcl\_Interp}, or \code{NULL} on error.}
\end{apiref}

\begin{apiref}
\indexc{Tcl\_DeleteInterp}
\apifunction{Tcl\_DeleteInterp(interp)}
\apisynopsis{Shuts down and deletes a Tcl interpreter.}
\apifirstparm{interp}{Pointer to the \code{Tcl\_Interp} to delete.}
\apiendparms
\end{apiref}

\begin{apiref}
\indexc{Tcl\_Eval}
\apifunction{Tcl\_Eval(interp, script)}
\apisynopsis{Evaluates a string in the given interpreter.}
\apireturns{One of several codes on success (usually \code{TCL\_OK}), and \code{TCL\_ERROR} on failure.}
\apifirstparm{interp}{Tcl interpreter to evaluate \code{script} in.}
\apinextparm{script}{String containing a complete Tcl script to evaluate.}
\apiendparms
\end{apiref}

\begin{apiref}
\indexc{Tcl\_EvalFile}
\apifunction{Tcl\_EvalFile(interp, filename)}
\apisynopsis{Evaluates a script file in the given interpreter.}
\apireturns{One of several codes on success (usually \code{TCL\_OK}), and \code{TCL\_ERROR} on failure.}
\apifirstparm{interp}{Tcl interpreter to evaluate the script file in.}
\apinextparm{filename}{Filename of the script to execute.}
\apiendparms
\end{apiref}

\subsection{Understanding Commands and Objects}
\index{Tcl!objects}Tcl represents data as \firstterm{objects} (of type \code{Tcl\_Obj}). This abstract structure allows Tcl to deal with strings, integers, and floating-point numbers without having to convert between types more than necessary. \code{Tcl\_Obj} is an abstract datatype, and you should avoid touching it directly. Tcl supplies functions for creating and accessing \code{Tcl\_Obj} variables as strings, integers, and doubles. The library can convert \code{Tcl\_Obj} objects between variable types whenever it needs to; for instance, if you create a variable as an integer and then try to access it as a string, Tcl will perform this conversion behind the scenes. There is no real limit to the number of variables you can create, but you should probably think twice about creating more than a few hundred (it's rarely necessary and performance could suffer).

\newpage
\code{Tcl\_CreateObjCommand} creates a new command and adds it to a given interpreter.\footnote{There is also a \code{Tcl\_CreateCommand} function, but this interface is obsolete for performance reasons. In fact, you'll notice that a lot of Tcl library functions are obsolete. The entire library was given a serious overhaul a while back, which improved performance drastically but left a mound of obsolete interfaces behind. They still work, but it's better to avoid them.} It takes a pointer to a \code{Tcl\_Interp}, a command name, a pointer to a handler function, an optional piece of ``client data'' (an integer), and a pointer to a cleanup function. Whenever the new command is called from within Tcl, the interpreter will give control to the handler function and await a result. It also passes the client data for the particular command to the handler; this data serves no defined purpose, so you can use it for just about anything. For instance, you could implement several distinct commands in one handler function, and use the client data to decide which body of code to execute. The cleanup function is optional. Tcl calls it when it's time to delete a command from the interpreter, but it is useful in only a few cases. We'll generally set this to \code{NULL}.

\begin{apiref}
\indexc{Tcl\_CreateObjCommand}
\apifunction{Tcl\_CreateObjCommand(interp, name, proc, clientdata, deleteproc)}
\apisynopsis{Adds a new command to the given Tcl interpreter. See Listing \ref{code:pwscripting} for the exact usage of this function.}
\apireturns{Command handle of type \code{Tcl\_Command}.}
\apifirstparm{interp}{Interpreter to receive the new command.}
\apinextparm{name}{Name of the new command, as a string.}
\apinextparm{proc}{Command handler procedure. See Listing \ref{code:pwscripting} for an example of a command handler.}
\apinextparm{clientdata}{Data of type \code{ClientData} (integer) for your own usage. Tcl will pass this integer value to \code{proc} each time it is called. You can use this to ``multi-home'' commands (serve several commands with the same handler).}
\apinextparm{deleteproc}{Function to call when this command is deleted (or the interpreter containing this command is deleted). This function should return \code{void} and accept one argument of type \code{ClientData} (the same \code{clientdata} listed above). If this command doesn't require any particular cleanup, just pass \code{NULL}.}
\apiendparms
\end{apiref}

Pretty easy, huh? Don't worry about the details; they'll become apparent when we implement \gametitle{Penguin Warrior}'s scripting engine. Let's do it!


\section{A Simple Scripting Engine}

It's time for some results. We know enough about Tcl and its library to create a simple but practical scripting interface for our game. We'll then be able to implement the computer player's brain as an easily modifiable script.

\begin{note}{Source Files}
We will add three files to \gametitle{Penguin Warrior} in this chapter: \filename{scripting.c}, \filename{scripting.h}, and \filename{pw.tcl}. The first is the C source code that embeds the Tcl library, the second is a header file that declares our scripting interface, and the third is the Tcl script that our scripting engine will execute automatically. In addition, we will link \gametitle{Penguin Warrior} against the \filename{libtcl.so} shared library.
\end{note}

\index{scripting engine!task}The basic job of the scripting engine is to provide an interface between the game engine and a script. Ideally, the script will act just like any other player, from the game engine's perspective. It will observe its surroundings, formulate a plan, provide the game engine with input for controlling a ship, and eventually destroy its target. We'll talk more about writing the Tcl side of this project in the next section. For now we'll concentrate on building the Tcl library interface.

Our script will need several pieces of information, as well as the ability to cause changes in the game world. First, we'll need to give it the positions of the two players in the world, as well as their headings and velocities. This will give the script enough information to figure out where the opponent ship is relative to the human player. The script also needs a way to control the opponent ship's throttle, heading, and weapons. There are several possible ways to make this control available to the script.

\index{scripting engine!data exchange}We could define Tcl commands for getting this information and controlling the opponent ship. Tcl commands are easy to create, they provide decent performance, and we can have them return information in any format we desire. However, handler functions can get a bit messy, especially if we want one handler function to process more than one Tcl command. Instead, we'll communicate using global variables. Our scripting engine will define variables with the information about each ship, and it will update these each time the script is called. Our script will be able to make modifications to some of these variables (its throttle and angle, for instance), and the scripting engine will give these back to the main game engine at each frame. Tcl makes this simple with the \code{Tcl\_LinkVar} command.\index{Tcl!variable linking}

\begin{apiref}
\indexc{Tcl\_LinkVar}
\apifunction{Tcl\_LinkVar(interp, name, addr, type)}
\apisynopsis{Links a Tcl variable to a C variable, so that any accesses to the Tcl variable will result in accesses to the C variable. This is a convenient way to share data between scripts and C programs.}
\apireturns{\code{TCL\_OK} on success, \code{TCL\_ERROR} on failure.}
\apifirstparm{interp}{Tcl interpreter to perform the link in.}
\apinextparm{name}{Name of the Tcl variable to create.}
\apinextparm{addr}{Pointer to the C variable that \code{name} should reference.}
\apinextparm{type}{Data type of the C variable. Valid types are \code{TCL\_LINK\_INT}, \code{TCL\_LINK\_DOUBLE}, \code{TCL\_LINK\_BOOLEAN} (int), and \code{TCL\_LINK\_STRING}.}
\apiendparms
\end{apiref}

To demonstrate a custom Tcl command, we'll create a command for controlling the opponent ship's weapons. It'll be called \code{fireComputerWeapons}, and it will have to respect the same firing limitations as the human player. This function won't actually do anything until we add weapons (in Chapter \ref{ch:finishingpw}).

Thanks to the Tcl library, none of this is too hard to implement. Here's our scripting system (\filename{scripting.c}) in its entirety:

\begin{codelisting}{scripting.c}{code:pwscripting}
\begin{verbatim}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tcl.h>
#include "scripting.h"

/* Our interpreter. This will be initialized by InitScripting. */
static Tcl_Interp *interp = NULL;

/* Prototype for the "fireWeapon" command handler. */
static int HandleFireWeaponCmd(ClientData client_data,
                               Tcl_Interp * interp,
                               int objc, Tcl_Obj * CONST objv[]);

/* Ship data structures (from main.c). */
extern player_t player, opponent;

/* Sets up a Tcl interpreter for the game. Adds commands
   to implement our scripting interface. */
void InitScripting(void)
{

    /* First, create an interpreter and make sure it's valid. */
    interp = Tcl_CreateInterp();
    if (interp == NULL) {
        fprintf(stderr, "Unable to initialize Tcl.\n");
        exit(1);
    }

    /* Add the "fireWeapon" command. */
    if (Tcl_CreateObjCommand(interp, "fireWeapon",
                             HandleFireWeaponCmd, (ClientData) 0,
                             NULL) == NULL) {
        fprintf(stderr, "Error creating Tcl command.\n");
        exit(1);
    }

    /* Link the important parts of our player data structures
       to global variables in Tcl. (Ignore the char * typecast;
       Tcl will treat the data as the requested type, in this
       case double.) */
    Tcl_LinkVar(interp, "player_x", (char *) &player.world_x,
                TCL_LINK_DOUBLE);
    Tcl_LinkVar(interp, "player_y", (char *) &player.world_y,
                TCL_LINK_DOUBLE);
    Tcl_LinkVar(interp, "player_angle", (char *) &player.angle,
                TCL_LINK_DOUBLE);
    Tcl_LinkVar(interp, "player_accel", (char *) &player.accel,
                TCL_LINK_DOUBLE);
    Tcl_LinkVar(interp, "computer_x", (char *) &opponent.world_x,
                TCL_LINK_DOUBLE);
    Tcl_LinkVar(interp, "computer_y", (char *) &opponent.world_y,
                TCL_LINK_DOUBLE);
    Tcl_LinkVar(interp, "computer_angle", (char *) &opponent.angle,
                TCL_LINK_DOUBLE);
    Tcl_LinkVar(interp, "computer_accel", (char *) &opponent.accel,
                TCL_LINK_DOUBLE);

    /* Make the constants in gamedefs.h available to the script.
       The script should play by the game's rules, just like the
       human player.
       
       Tcl_SetVar2Ex is part of the Tcl_SetVar family of functions,
       which you can read about in the manpage. It simply sets a
       variable to a new value given by a Tcl_Obj structure. */
    Tcl_SetVar2Ex(interp, "world_width", NULL,
                  Tcl_NewIntObj(WORLD_WIDTH), 0);
    Tcl_SetVar2Ex(interp, "world_height", NULL,
                  Tcl_NewIntObj(WORLD_HEIGHT), 0);
    Tcl_SetVar2Ex(interp, "player_forward_thrust", NULL,
                  Tcl_NewIntObj(PLAYER_FORWARD_THRUST), 0);
    Tcl_SetVar2Ex(interp, "player_reverse_thrust", NULL,
                  Tcl_NewIntObj(PLAYER_REVERSE_THRUST), 0);
}

/* Cleans up after our scripting system. */
void CleanupScripting(void)
{
    if (interp != NULL) {
        Tcl_DeleteInterp(interp);
    }
}

/* Executes a script in our customized interpreter. Returns 0
   on success. Returns -1 and prints a message on standard error
   on failure.

   We'll use this to preload the procedures in the script. The
   interpreter's state is maintained after Tcl_EvalFile. We will
   NOT call Tcl_EvalFile after each frame - that would be
   hideously slow. */
int LoadGameScript(char *filename)
{
    int status;

    status = Tcl_EvalFile(interp, filename);
    if (status != TCL_OK) {
        fprintf(stderr, "Error executing %s: %s\n", filename,
                Tcl_GetStringResult(interp));
        return -1;
    }

    return 0;
}

/* Handles "fireWeapon" commands from the Tcl script. */
static int HandleFireWeaponCmd(ClientData client_data,
                               Tcl_Interp * interp,
                               int objc, Tcl_Obj * CONST objv[])
{
    /* Do nothing for now. We'll add weapons to the game later on. */
    fprintf(stderr, "Computer is firing weapon. Not implemented.\n");

    /* Return nothing (but make sure it's a valid nothing). */
    Tcl_ResetResult(interp);

    /* Succeed. On failure we would set a result with Tcl_SetResult
       and return TCL_ERROR. */
    return TCL_OK;
}

/* Runs the game script's update function (named "playComputer").
   Returns 0 on success, -1 on failure. */
int RunGameScript()
{
    int status;

    /* Call the script's update procedure. */
    status = Tcl_Eval(interp, "playComputer");
    if (status != TCL_OK) {
        fprintf(stderr, "Error in script: %s\n",
                Tcl_GetStringResult(interp));
        return -1;
    }

    /* Enforce limits on the script. It can still "cheat" by turning
       its ship more quickly than the player or by directly modifying
       its position variables, but that's not too much of a problem.
       We can more or less trust the script (it's part of the game). */
    if (opponent.accel > PLAYER_FORWARD_THRUST)
        opponent.accel = PLAYER_FORWARD_THRUST;
    if (opponent.accel < PLAYER_REVERSE_THRUST)
        opponent.accel = PLAYER_REVERSE_THRUST;
    while (opponent.angle >= 360)
        opponent.angle -= 360;
    while (opponent.angle < 0)
        opponent.angle += 360;

    return 0;
}
\end{verbatim}
\end{codelisting}

In addition to this code, we'll need to add some fairly obvious hooks into \filename{main.c} (to initialize the scripting engine and call \code{RunGameScript} at each frame) and create a \filename{pw.tcl} script. We'll talk about the script shortly. Let's break this code down.

\code{InitScripting} sets up a fresh Tcl interpreter and adds our game's interface to the interpreter. At this point our interface consists of only one function (which is empty for now) and a few variables. We take advantage of Tcl's variable linking feature, which causes a Tcl variable to track a C variable. Every access to a linked variable within a Tcl script translates into an access to the corresponding C variable.

The next function of interest is \code{LoadGameScript}. Our game uses this function to load the script in \filename{pw.tcl} at startup. \code{Tcl\_EvalFile} works just like \code{Tcl\_Eval}, except that it reads its input from a file instead of a string. If it returns anything but \code{TCL\_OK}, \code{LoadGameScript} prints an error message and reports failure.

\code{RunGameScript} is the heart of our scripting engine. This function is responsible for giving control to the script once each frame to let the enemy ship steer itself and fire its weapons. To do this, \code{RunGameScript} calls \code{Tcl\_Eval} to invoke the \code{playComputer} script command. If there are no errors, \code{RunGameScript} performs some basic checks on the script's actions and then returns. \code{Tcl\_Eval} takes care of the rest.

Finally, the \code{CleanupScripting} function frees the Tcl interpreter. No surprises here.

We now have a working scripting engine. If you want to see it run, you can find this version of the \gametitle{Penguin Warrior} code in the \filename{ph-ch6} subdirectory of the source archive.

Now let's talk about creating a decent game script. We won't quite reach a \othertitle{Star Trek} level of artificial intelligence, but hopefully we can make life difficult for the (human) player.

\index{Tcl!extension language@as extension language|)}

\section{Designing a Game Script}
\index{scripts!designing|(}
Our game script is charged with one simple mission: to track down and blow up the player. It has the ability to steer a ship, control its thrust, and activate its weapons. It also has access to the player's current position in the world. At a glance, our script should look something like this:

\begin{enumerate}
        \item Figure out where the player is with respect to our script's ship, and find the angle that will point us in that direction.
        \item Decide whether a clockwise or counterclockwise turn would reach that angle the fastest.
        \item If the player is in front of us, fire our weapons.
        \item Lather, rinse, repeat.
\end{enumerate}


These steps shouldn't be too difficult to implement in Tcl. Let's give it a try.

\begin{codelisting}{pwscript-firsttry.tcl}{code:pwscriptfirsttry}
\begin{verbatim}
# Penguin Warrior game script (Tcl).
# A first attempt.

proc playComputer { } {
    global computer_x computer_y computer_angle computer_accel
    global player_x player_y player_angle player_accel

    # Global constants. These are initially set by InitScripting().
    global world_width world_height
    global player_forward_thrust player_reverse_thrust

    # Find our distance from the player.
    set distance [getDistanceToPlayer]

    # If we're close enough to the player, fire away!
    if {$distance < 200} {
        fireWeapon
    }

    # Figure out the quickest way to aim at the player.
    set target_angle [getAngleToPlayer]
    set arc [expr {$target_angle - $computer_angle}]
    if {$arc < 0} {
        set arc [expr {$arc + 360}]
    }

    # Turn 15 degrees at a time, same as the player.
    if {$arc < 180} {
        set computer_angle [expr {$computer_angle + 15}]
    } else {
        set computer_angle [expr {$computer_angle - 15}]
    }

    # Apply a reasonable amount of thrust.
    set computer_accel 5

    # That's it! Exit from Tcl_Eval and go back to the C-based engine.
}


# Returns the distance (in pixels) between the player and the opponent.
# This is just the Pythagorean formula.
proc getDistanceToPlayer { } {
    global computer_x computer_y player_x player_y

    set xdiff [expr {$computer_x - $player_x}]
    set ydiff [expr {$computer_y - $player_y}]

    return [expr {sqrt($xdiff * $xdiff + $ydiff * $ydiff)}]
}

# Returns the angle (in degrees) to the player from
# the opponent. Uses basic trig (arctangent).
proc getAngleToPlayer { } {
    global computer_x computer_y player_x player_y

    set x [expr {$player_x - $computer_x}]
    set y [expr {$player_y - $computer_y}]

    set theta [expr {atan2(-$y,$x)}]
    if {$theta < 0} {
        set theta [expr {2*3.141592654 + $theta}]
    }
    
    return [expr {$theta * 180/3.141592654}]
}
\end{verbatim}
\end{codelisting}

% $

Give this script a go. (It's in the \filename{pw-chapter6} directory as \filename{pwscript-firsttry.tcl}; you'll need to symlink or copy it to \filename{pw.tcl} for the game to find it.) As you can guess by the name, it's not quite what we're looking for. Yes, the computer's ship does follow the player around, and with weapons it would probably win pretty quickly. The problem is that the script is \emph{too} good---it doesn't give the player a fair chance. The computer's ship is basically impossible to avoid. Once it manages to get behind the player, it's very difficult to get rid of. This would make for a very boring game (aside from the fact that the weapons don't work yet).

So we need to make the computer a little bit worse at the game. A few things come to mind. We could limit its speed or rate of turning, but that would be cheesy (and probably very easy to notice). It would be better to give the computer's AI a bit more depth, so that it would act more like a human and less like a machine with a one-track mind. A human player makes a conscious effort to avoid the enemy's line of fire and periodically seizes an opportunity to attack. Our script would be more interesting if it were to follow this behavior.

\index{scripts!state machines}\index{state machines}To accomplish this, we'll use a simple \firstterm{state machine}. The computer's ship will always be in either \emph{attack} or \emph{evade} mode, and it might switch between these two states at any time based on its position in the world and the position of the player's ship. In attack mode it will steer in the direction of the player, firing its weapons if it gets close enough, and in evade mode it will home in on a random target (other than the player) somewhere in the game world. It will switch into evade mode whenever it gets too close to the player, and it will switch back into attack mode whenever it reaches a randomly chosen point in the world. From the player's point of view, the computer-controlled ship will seem to dive in for an attack and then quickly run off. Properly tuned, this looks surprisingly similar to what a human player would do.

\extfigure{figures/pw-script-states}{fig:pwscriptstates}{State diagram for Penguin Warrior's improved script}

Here's the code to make it happen:

\begin{codelisting}{pwscript-improved.tcl}{code:pwscriptimproved}
\begin{verbatim}
# Penguin Warrior game script (Tcl).
# This version of the script implements two states:
# attack and evade. In the attack state, the opponent
# homes in on the player and fires its weapons. After it
# gets within a certain proximity of the player, it switches
# to the evade state, in which it aims at a random point in the
# world.

# The name of our current state, attack or evade.
set state attack

# Coordinates to aim towards. In the attack state these will
# be set to the player's position. In the evade state these
# will be set to random values.
set target_x 0
set target_y 0

proc playComputer { } {
    global computer_x computer_y computer_angle computer_accel
    global player_x player_y player_angle player_accel
    global target_x target_y state

    # Global constants. These are initially set by InitScripting().
    global world_width world_height
    global player_forward_thrust player_reverse_thrust

    if {[string equal $state attack]} {
        #
        # Code for the attack state
        #

        # In attack mode, our target is the player.
        set target_x $player_x
        set target_y $player_y

        # If we're too close to the player, switch to evade.
        set distance [getDistanceToTarget]
        if {$distance < 30} {
            set state evade

            # Set an invalid target so the evade state will
            # come up with a new one.
            set target_x -1

            return
        }

        # If we're far away, speed up. If we're close, lay off
        #the throttle.
        if {$distance > 100} {
            set computer_accel $player_forward_thrust
        } elseif {$distance > 50} {
            set computer_accel [expr {$player_forward_thrust/3}]
        } else {
            set computer_accel 0
        }

        # If we're close enough to the player, fire away!
        if {$distance < 200} {
            fireWeapon
        }

    } else {
        #
        # Code for the evade state
        #

        # Have we hit our target yet?
        #(within a reasonable tolerance)
        if {abs($target_x - $computer_x) < 10 &&
            abs($target_y - $computer_y) < 10} {
            puts "Going back into ATTACK mode."
            set state attack
            return
        }

        # Do we need to find a new target?
        if {$target_x < 0} {
            # Select a random point in the world
            #as our target.
            set target_x [expr {int(rand()*$world_width)}]
            set target_y [expr {int(rand()*$world_height)}]

            puts "Selected new EVADE target."
        }

        set computer_accel $player_forward_thrust
    }

    #
    # State-independent code
    #

    # Figure out the quickest way to aim at our destination.
    set target_angle [getAngleToTarget]
    set arc [expr {$target_angle - $computer_angle}]
    if {$arc < 0} {
        set arc [expr {$arc + 360}]
    }

    if {$arc < 180} {
        set computer_angle [expr {$computer_angle + 3}]
    } else {
        set computer_angle [expr {$computer_angle - 3}]
    }

}

# Returns the distance (in pixels) between the target
# coordinate and the opponent.
proc getDistanceToTarget { } {
    global computer_x computer_y target_x target_y

    set xdiff [expr {$computer_x - $target_x}]
    set ydiff [expr {$computer_y - $target_y}]

    return [expr {sqrt($xdiff * $xdiff + $ydiff * $ydiff)}]
}

# Returns the angle (in degrees) to the target coordinate from
# the opponent. Uses basic trig (arctangent).
proc getAngleToTarget { } {
    global computer_x computer_y target_x target_y

    set x [expr {$target_x - $computer_x}]
    set y [expr {$target_y - $computer_y}]

    set theta [expr {atan2(-$y,$x)}]
    if {$theta < 0} {
        set theta [expr {2*3.141592654 + $theta}]
    }
    
    return [expr {$theta * 180/3.141592654}]
}
\end{verbatim}
\end{codelisting}

% $

We use a global variable to keep track of the state we're currently in, and we test the current state with a simple conditional. It would be a simple matter to add more states to make for a more realistic opponent. (This might make for an interesting project.) Note that our script no longer causes the opponent to run after the player, per se, but rather has it move toward a target coordinate. In attack mode, the target coordinate is changed each time the script is called to reflect the player's current position, so it's all the same.

Most games would employ much more complex state machines (also known as \index{automatons}\index{scripts!automatons}\firstterm{automatons}) to give life to computer-controlled characters; indeed, \gametitle{Penguin Warrior}'s state machine is very simple. It's also quite effective, however. If you haven't done so already, give this new script a try (rename \filename{pw-improved.tcl} to \filename{pw.tcl}), and observe the opponent's behavior. Much better! Now if there were some weapons, it would be a worthy fight. Don't worry; we'll add this when we finish off \gametitle{Penguin Warrior} in Chapter \ref{ch:finishingpw}.

\index{scripts!designing|)}

\section{Applying Scripting to the Real World}
\gametitle{Penguin Warrior} is a bit of a pedagogical example. Sure, it's a playable game (or will be soon enough), but it's not something you'd expect to find on the shelf at a computer store or given a good review on a gaming site. But the ingredients we've used to create Penguin Warrior are industrial grade, and this book would be pointless if we couldn't apply them in the ``real world.'' To that end, let's look at some of the problems involved in implementing a scripting system in larger projects. Bear in mind that this discussion applies to any scripting language: Tcl, Scheme, Perl, Python, librep, or anything else you can grab \website{Freshmeat}{http://www.freshmeat.net}.


\subsection{Single Versus Multiple Contexts}
\index{scripting engine!contexts|(}
Suppose that you are making a game similar to \gametitle{StarCraft} (a real-time strategy game with hundreds of computer-controlled opponents in the world simultaneously), and that you want to implement the scripting with Tcl. You'll obviously want to call \code{Tcl\_Eval} on part of the script at least once each frame. The question is, do you create a separate \code{Tcl\_Interp} for each character in the game, or do you run all of them through the same interpreter? In the latter case, do you invoke the interpreter once for each character or once for the entire group? (For lack of a better term, we'll call an interpreter with a loaded script a \firstterm{context}.)

In the case of something like \gametitle{StarCraft}, it would probably be a bad idea to use a separate interpreter for each character in the game; that would be a horrendous waste of memory and script loading time, even though it might make the scripting system a bit easier to organize. In cases with only a few characters, though, it might be desirable to use multiple scripting contexts.

\extfigure{figures/scripting-contexts}{fig:scriptingcontexts}{Several possible scripting models}

If you decide to use a single interpreter for the whole thing, you still need to decide whether you'll make a single call to it at each frame and let it sort out all of the different characters (through a loop of some sort, probably) or call the script once for each game character. The former has the advantage of fewer calls to the scripting library (which can be expensive, depending on the language), and the latter has the advantage of potentially simpler scripting. It's hard to predict how well either scenario will perform; if you're faced with this question, you might want to write some timing code to measure the total amount of time spent in the scripting engine per frame.
\index{scripting engine!contexts|)}

\subsection{Can We Trust the Script?}
\index{scripting engine!security|(}
Security really doesn't matter for a single-player game; if a player wants to cheat, so what? For that matter, you might as well publish a list of cheat codes. But it is a huge problem in multiplayer games. You can pretty much count on a few lamers trying to mess up the game for everyone else. If the game depends on an interpreted (rather than compiled) script for its rules, there's a problem. Someone \emph{will} figure out how to change the code, and without proper safeguards, this can make the game unfair for the rest of the players.

This problem becomes even worse in open source software. Everyone has access to all of the code, and anyone can change it to their liking. Unless the other players have some way of telling when someone's copy of the game has been modified, there's no hope of preventing cheaters from spoiling the fun, unless the players trust one other from the start.

\gametitle{Penguin Warrior} is wide open to script abuse. The script can essentially take direct control of either ship, and no limits are imposed. If security were an issue, we would have to add a limit-checking system to prevent the script from making illegal moves. Even then, the source code to the game would be available for all to see and modify. Multiplayer games can avoid this problem by having all players connect to a trusted central server. We'll touch on multiplayer security in the next chapter.
\index{scripting engine!security|)}

\subsection{Script Performance}
\index{scripting engine!performance|(}
Script interpreters are usually pretty well optimized, but unless scripts are compiled, they are always separated from the processor by at least one layer of code. The exact speed ratio of interpreted code to native code varies among languages, but don't be surprised if a script runs at about a tenth the speed of equivalent C code. (Again, it could be better or worse, depending on a lot of factors; if you're concerned, benchmark it.) To achieve decent performance, you'll need to take the properties of your chosen language into account. Tcl, for instance, isn't very fast at list processing (though this has gotten much better of late), while Scheme excels at lists. It probably wouldn't be a good idea to use the ``one interpreter, one call'' model mentioned previously with Tcl, but this model would be quite natural in Scheme. Also, don't be fooled by the ``compilation'' modes of most scripting systems; TclPro and MzScheme can both ``compile'' programs, but this does little more than hide the source. The code is still interpreted in the same way it normally would be, except for the initial parsing stage. (However, TclPro's \filename{.tbc} or MzScheme's \filename{.zo} bytecode formats might be useful if you want to hide the source to your scripts.)

Another performance issue has to do with memory management. Tcl uses reference counting to know when it can safely reclaim unused variable memory, while Scheme and most other Lisp-like languages use much more complicated ``garbage collection'' techniques. Scheme has plenty of reasons to use garbage collection, but it means that a Scheme program will typically use more memory than it really needs at any given time. Garbage collection often takes place very suddenly, and it can cause noticeable delays in your program. There are ways to avoid this problem (such as running the scripting system in a separate thread or scheduling garbage collection yourself at safe times), but you would do well to become informed about these quirks before you try to use one of these libraries.
\index{scripting engine!performance|)}

\subsection{Who's Writing the Script?}
\index{scripts!skill level of writers}
\longpage
As a final thought, it's important to note that the people who write game scripts often aren't programmers. Scripting is part of creating maps and characters, and this task often falls to artists and game designers. These are smart people, no doubt, but they might not be up to speed on programming. This is actually one of the main reasons for using scripting languages in games: they allow nonprogrammers to make minor changes to the way a game behaves without actually messing with the main source code. Scripting languages are usually much simpler than C and \cplusplus{}. But even with a well-designed scripting system, some people might have trouble grokking the language or the interface. The only real solution is to document your scripting interface well, pick an intuitive language, and be prepared to teach it to your scripters. Almost anyone can pick up something like Tcl without too much effort, so be patient.

We've covered a lot in this chapter, but there's a lot more to game scripting than we've mentioned here. If game scripting systems interest you, point your browser to \website{Gamasutra}{http://www.gamasutra.com} and search for articles on scripting. Gamasutra frequently publishes retrospective accounts from game teams after the release of major products, and one can glean a lot of insight from the experiences of these professionals.
