these force values in a list and add them together at the end of the effect phase.

Most of the time, game developers use the state-effect pattern to manually design high-performance algorithms for very specific cases. That is because it has several properties that allow them to significantly enhance the performance of the simulation loop. The effect phase can be parallelized since the effect assignments do not influence each other. The update phase can also be parallelized since it consists only of the aggregation of effects and updates to state variables. This does not need to be done by hand; if the scripting language knew which attributes were state attributes and which were effect attributes, it could perform much of this parallelization automatically, even in scripts written by inexperienced designers. This is similar to what Google achieves with its Sawzall language and the MapReduce pattern; special aggregate variables perform much the same function as effect attributes, and the language allows programmers at Google to process data without any knowledge of how the program is being parallelized. 2

Automatic parallelization is an example of an alternative execution model; the game runs the script using a control flow that is different from the one specified by the programmer. Since the simulation loop logically processes all of the game objects simultaneously, we can process them in any order, provided that we always produce the same outcome. Thus, alternative execution models are among the easiest ways of optimizing game scripts. Another unusual execution model is used by the SGL scripting language, which is being developed at Cornell University.1 This language is based on the observation that game 3 scripts written in the state-effect pattern can often be optimized and processed with database techniques.

FIGURE

The script compiler gathers all of the scripts together and converts them into a single in-memory query plan. Instead of using explicit threads, it constructs a data pipeline that allows the code to be parallelized in natural ways. Many of these data pipelines are similar to the

ones that game programmers create when they program on the graphics processing unit, except that these are generated automatically.

THE RES TRIC TED I TERA TION PAT TERN

Iteration is another common source of problems in game development. Allowing arbitrary iteration can quickly lead to significant performance degradation of the simulation loop. Iteration can be even more dangerous in the hands of inexperienced designers. During the development of City of Heroes, Cryptic Studios discovered that many of the scripts had interdependencies that produced hard-to-find infinite loops. To prevent this, the developers removed unbounded iteration from the scripting language.

Although this was a fairly drastic solution, most games do not need arbitrary iteration in their scripts. The scripts just need to perform a computation over a finite set of objects; such scripts follow the restricted iteration pattern, which obviously guarantees termination on all loops. In addition, it may enable code analysis and compile-time code transformations that improve performance. For example, SGL can take nested loops that produce quadratic behavior and generate an index structure from them1; it then replaces the nested loops with a single loop that performs lookups into that index.

Examples of the restricted iteration pattern appear throughout the scripts in Warcraft III, a realtime strategy game that has to process armies of individual units. The NudgeObjectsInRect script in figure 3 appears in the

Example of the Restricted Iteration Pattern

//===================================================================== // Nudge items and units within a given rect, so that they can find

// locations where they can peacefully coexist function NudgeObjectsInRect takes rect nudgeArea returns nothing local group g

set g = CreateGroup() call GroupEnumUnitsInRect(g, nudgeArea, null) call ForGroup(g, function NudgeUnitsInRectEnum) call DestroyGroup(g)

call EnumItemsInRect(nudgeArea, null, function NudgeItemsInRectEnum) endfunction

more queue: www.acmqueue.com

ACM QUEUE November/December 2008 23

References:

http://www.acmqueue.com

Archives