University at Buffalo

The Scalable Games Language

September 28, 2015

Declarative Languages

  • SQL
  • SparQL
  • XPath/XQuery
  • Pig Latin
  • Graal+Truffle
  • Scala LMS

Declarative Languages

  • (Often) less expressive
  • Common design patterns abstracted out
  • Easier to identify and fix inefficiencies

Declarative Languages for Games

Now: You get complexity or scale, but not both.

Challenges

  • Computing resources are limited
  • AI Devs work at the unit-scale
  • Gameplay designers work at the effect scale
  • More units/effects = more compute

The Setting

Compute What Happens Next Update State Render the Scene One Tick

The Setting

Compute What Happens Next Update State Render the Scene One Tick

The State/Effect Pattern

Produced by OmniGraffle 6.3.2 2015-09-28 03:46:30 +0000Canvas 1Layer 1StateEffects… is queried to compute… are combined to update
StateEffects
Persistent across ticksComputed once per tick
Queried for potential effectsMerged into state
Have an initial valueHave a combiner function
Read+Update onlyMerge only

Benefits of Limiting Expressiveness

  • Update phase guaranteed to be $O(1)$.
  • Query phase can be reduced to one or more aggregate queries. Opportunities for...
    • ... work-sharing: Merge scans over same data
    • ... parallelism: Safe to parallelize scans over same data
    • ... pre-computation: Index data for multiple scans

State/effect similar to barrier-based programming

Example


class Unit {

state:
    number player = 0;       number type = 0;
    number x = 0;            number y = 0;
    number health = 0;       Unit target = null;
effects:
    number vx : avg;         number vy : avg;
    number damage : sum;     number healing : max;
    Unit acquired : priority;
update:
    x = x + vx;              y = y + vy;
    health = health - damage;
    target = (acquired != null ? acquired : target);
}
					

Example AI


let (number dist = (x-target.x)*(x-target.x)+
                   (y-target.y)*(y-target.y)) in {
   if (dist < ATTACK_RANGE) {
      // If in range, attack.
      target.damage <- DMG_AMOUNT;
   } else {
      // Else move closer (use unit velocity)
      vx <- (target.x-x)/dist;
      vx <- (target.y-y)/dist;
} }
					

Merging = Aggregation

target.damage <- DMG_AMOUNT;

Damage is an effect. How is damage merged?

The total damage can be expressed as: SUM(DMG_AMOUNT). ... over what data?

Example Relational Plan

Example Relational Plan

Example Relational Plan

Group Exercise

There are two types of units: Soldiers and Skeletons

Design an AI for a soldier who attacks the nearest skeleton if there are at more soldiers than skeletons within 50 ft.

Making Repeated Aggregation Fast

Given 8 numbers...

Produced by OmniGraffle 6.3.2 2015-09-28 04:45:59 +0000Canvas 1Layer 3Layer 436 - 12 = 24Layer 1247610611Layer 226191229353637

Precompute $index_j = \sum_{i \leq j} data_i$ for each j (... is $O(N)$).

For a summation query on (3,7]... (... is normally $O(|Q|)$)

...use $index_7 - index_{3}$ (... is now $O(1)$).

Does this work for Min/Max?

Max Tree

Max Tree

Max Tree

At most $O(\log N)$ lookups.

Linear Sweep

Linear Sweep

Linear Sweep

Linear Sweep

Linear Sweep

Linear Sweep

Linear Sweep

  • Language restrictions can help optimizers.
  • Computer Games are Data-Intensive.
  • Relational-Algebra can be used to find opportunities for...
    • work-sharing
    • pre-computation
    • parallelization