Game Scripting
By: Nicholas Haines
Aurora Neverwinter Toolset
What is Scripting?
Interpreted Language
– As the game runs
Ease of use
 Makes the game more data driven
– Instead of hard coding into game engine
Allows for in-game “tweaking”
– Quick results
– Does not require a recompile
Allows user modability
 Game can be patched at a later date
 Many publicly available scripting languages
– Not noticeable most of the time in
real world performance
Automatic memory management
– Can cause problems if it interrupts a
command or takes awhile to complete
Poor debugging tools
– Some languages don’t give warnings
– Tends to be very hard to find the errors
Lua In The Industry
Ease of Use
– for non-programmers
Falko Poiker
– don’t slow down the game
– Lua executable is ~ 160kb
Well Documented
– Lua documentation is lacking
– Clean and flexible interface
Optimizing Script Execution
Using Patterns
Object: Reduce the number of instructions
 Look for patterns in the opcode output
– Replace with optimized version
Check for addresses calculated multiple
times and save to a spare register
– Replace matching with reference to register
May shorten code by up to 50%
assuming decoding script is the
bottleneck of the virtual machine [VM]
Non-Branched, Constant Scripts
Native function calls can be intercepted
inside the VM
 Store as a function pointer along its
 Big list of stored functions is called an
Execute List
Will now traverse execute list instead of
having to interpret the opcode again
Branched Scripts
Conditional jumps cannot be
A Jump Table can be used to
decrease decode time during
Contains the offset of native
opcode executing specific script
Use pure jump table opcodes for
most common instructions
Combine jump table/parse for less
common instructions to reduce the
table size
Note: jump table values change whenever
the VM’s code is changed
Example to be decoded
mov [vm_reg0], vm_reg1
(using x86 asm)
;get contents of vm register 0 into eax
mov eax, [ecx+0]
~3 cycles
;get contents of vm register 1 into ebx
mov ebx, [ecx+4]
~3 cycles
;solve indirection
mov [eax], ebx
~3 cycles
;increment vm instruction pointer
add edx, 4
~1 cycles
;transfer program control to next opcode
jump [edx]
~3 cycles
Branched into Non-Branched
Monster::PlayerSpotted(bool hear_player, bool see_player, float* pos)
//we have heard something..check out
//situation..keep an eye on the place
FocusAttention(pos); //native function
//someone told us about the
//player (monster friend or so)
//let's help our friends
WalkTo(pos); //native function
//we can see the enemy..let's kill him!
ShootAt(pos); //native function
Generates each possibility
and removes branching
Code to the left becomes:
Monster::PlayerSpotted(bool hear_player=true,
bool see_player=false,
float* pos)
This can be optimized
using execution lists
Advanced Script Debugging
Exchanging Debug Information
Debugger creates a new processes that uses
the VM to execute scripts
VM sends string messages to Debugger
VM needs memory buffers for the Debugger
to write to
breakpoint hit
access violation
update breakpoints
Useful Features
Debug information
Handling Breakpoints
Variable Watch
Call Stack
Assembly Execution
Register Watch
Memory Watch
Step-by-Step HighLevel Execution
Step Over Execution
Adding Error Reporting
Create A Parser For Your Script
Use tools like Lex and Yacc
Since mostly nonprogrammers use the
scripting language, make meaningful error
A Simple Language
Example code:
int x;
int y;
y = 0;
x = SomeFunction() - 5;
if( x > OtherFunction() )
y = 3;
Possible Errors
Semicolon missing
Parentheses missing
Unrecognized characters
Unrecognized keyword
Function misspelled
Undeclared variable
Variable declared more
than once
Reporting with yyerror()
Prints “syntax error” to standard output
 Overwrite yyerror() with a useful version
 Derive a custom scanner function
 Print formatted error messages to a
specified error file
– Include line number and copy of the line
This can be stored as a log or displayed in
another application
Identifying Specific Errors
Unknown Character Errors
yyerror(“Error: Unknown character ‘%c’ “, *yytext);
Append grammar to trap missing semicolon
 Do the same to catch unrecognized
 Undeclared and Redeclared Variables
– Parser must check variable table to see if the
variable has been previously declared
AI Game Programming WISDOM 2
Sections 9.1-9.3
Game Dev Articles:
Scripting by Falko Poiker
The Secret Life of Game Scripting
By Brian Hook

Game Scripting - Lehigh University