Game Scripting

coordinatedcapableSoftware and s/w Development

Nov 4, 2013 (3 years and 9 months ago)

75 views

Game Scripting

By: Nicholas Haines

Aurora Neverwinter Toolset

What is Scripting?


Interpreted Language


As the game runs

Advantages


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

Disadvantages


Performance


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


Speed


don’t slow down the game


Size


Lua executable is ~ 160kb


Well Documented


Lua documentation is lacking


Flexible


Clean and flexible interface

Falko Poiker

Jobs

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
arguments


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
predicted


A
Jump Table

can be used to
decrease decode time during
execution


Contains the offset of native
opcode executing specific script
opcode


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]

;get contents of vm register 1 into ebx


mov ebx, [ecx+4]

;solve indirection


mov [eax], ebx

;increment vm instruction pointer


add edx, 4

;transfer program control to next opcode


jump [edx]

~3 cycles


~3 cycles


~3 cycles


~1 cycles


~3 cycles

Branched into Non
-
Branched


Monster::PlayerSpotted(bool hear_player, bool see_player, float* pos)

{


if(!see_player)


{


if(hear_player)


{


//we have heard something..check out


//situation..keep an eye on the place


FocusAttention(pos); //native function


}


else


{


//someone told us about the


//player (monster friend or so)


//let's help our friends


WalkTo(pos); //native function


}


}


else


{


//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)


{


FocusAttention(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

Virtual

Machine

Debugger

breakpoint hit

access violation

update breakpoints

Useful Features


Debug information


Handling Breakpoints


Variable Watch


Call Stack


Step
-
by
-
Step
Execution


Step
-
by
-
Step
Assembly Execution


Register Watch


Memory Watch


Step
-
by
-
Step High
-
Level 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
messages.

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
functions


Undeclared and Redeclared Variables


Parser must check variable table to see if the
variable has been previously declared

References


AI Game Programming WISDOM 2


Sections 9.1
-
9.3


Game Dev Articles:




Scripting by Falko Poiker


http://www.relic.com/industry/articles/scripting.php


The Secret Life of Game Scripting

By Brian Hook


http://www.bookofhook.com/Article/GameDevelopme
nt/TheSecretLifeofGameScript.html