41
Flirting With The Dark Side Domain Specific Languages and AI

Flirting With The Dark Side Domain Specific Languages and AI

Embed Size (px)

Citation preview

Flirting With The Dark Side

Domain Specific Languages and AI

Flirting With The Dark Side

• What is a Domain Specific Language?• Why are DSLs useful for AI?• How do we build and deploy a DSL?• Who benefits from this?• Concluding wisdom

What is a DSL?

A Domain-Specific Language is simply a language designed to be highly adept at solving a specific class of problems

The Continuum

Generic SpecificC

C++Mathematica

Java Lua SQL

Ruby UnrealScript

XSLT

Python Regular Expressions

JavaScript

LispYACC

Erlang Verilog

What Do DSLs Look Like?if $Aim -> is of class Huge Ship if $distance > 3500 AND $distance < 20000 if [THIS] -> fire missile $Missile on $Aim $Missilesfired.strength = $Missilesfired.strength + $Damage [THIS] -> set fire missile time difference to 16 ms $defend = random value from $Value.def2.min to $Value.def2.max - 1 [THIS] -> interrupt with script '!plugin.fightcommand.defmove' and prio $Prio: arg1=$defend arg2=$Aim arg3=null arg4=null gosub Defensive.Definitions end endend

What Do DSLs Look Like?<sequence name="ManualDemoSequence" start="0"> <shot name="test1" environment="mainsector" duration="10000"> <camera_find fillspace="50" lookat_reference="@playership“ position_reference="@playership"> <begin distance="1000" pitch="-60" yaw="110" /> <end distance="1000" pitch="-50" yaw="-90" /> </camera_find> </shot></sequence>

Language or File Format?•DSLs resemble declarative file formats•However, DSLs are typically imperative•Nothing wrong with a declarative DSL•Can think of DSLs as “smart files”

Why Use DSLs for AI?

Program code will be cleanest when implemented in the same terms that domain specialists use when thinking about problems in the domain

Principle #1

Why Use DSLs for AI?

We can minimize bugs by eliminating low-level concerns that do not directly apply to the problem we wish to solve

Principle #2

Why Use DSLs for AI?

We can maximize productivity by removing details and features that do not pertain to solving the problem

Principle #3

Why Use DSLs for AI?

AI work typically consists of solving a limited set of problems using a handful of well-known techniques

Key Observation

Why Use DSLs for AI?

• Expresses concepts in domain terms• Eliminates irrelevant lower-level concerns• Limited features keep code focused• Specialized tools are easier to develop

Avoiding Low Level Issues

Escaping from C++/etc. gives us several perks

• No manual memory management• No complex syntax• No complications like undefined behavior

Avoiding Low Level Issues

Escaping from C++/etc. gives us several perks

• Accessible for designers and junior coders• Less likely to cause severe bugs in core code• Can be radically more productive

Making Languages is Hard!

• Compilers are complicated!• What about interpreters? Virtual machines?• Garbage collection?• Concurrency?• Lexers?• Parsers?• Semantic analyzers? Abstract syntax trees? AST decoration? Optimization? Native code generation? The problems are endless!

Making Languages is Hard!

• Compilers are complicated!• What about interpreters? Virtual machines?• Garbage collection?• Concurrency?• Lexers?• Parsers?• Semantic analyzers? Abstract syntax trees? AST decoration? Optimization? Native code generation? The problems are endless!

DSLs Should Be Easy!

We can put away the Dragon Book. We don’t need complex parsers, compilers, or virtual machines

(We probably don’t even need regular expressions…)

Compilers, Be Gone!

• Syntax is often very simple• Therefore, we don’t need complex parsing• We can use existing file formats

• XML• JSON• Plain delimited text

Compilers, Be Gone!

• Execution of code need not be complex• After all, the problem space is limited• We can leverage existing data-driven code

Building a DSL for AI

Hoist configuration data and logic out of core engine code and into the DSL

This is essentially just data-driven programming taken to the next logical step

Fundamental Goal

Building a DSL for AI

We always want to do the simplest thing that can possibly work

Guiding Principle

A DSL From Scratch

• Identify the core problems our AI must solve• Select algorithms and solutions for each• Break down solutions into discrete chunks• Implement DSL concepts for each chunk

Identifying Core Problems

• Pathfinding• Responding to dynamic game situations• Anticipating dynamic game situations• Planning/behavior selection• Achieving specific game design goals

Selecting Solutions

Choose the options that we would normally implement directly, as the design and specifications require

Guiding Principle

Breaking Down the Solutions

• Identify common concerns and issues• Determine required decision-making logic• Look for branch points• Branches are ideal spots for DSL placement

Concepts and Languages

Typically, when control flow can branch in AI code, this represents a point where a domain-specific concept has come into play; therefore the presence of branches tends to suggest the application of domain-specific logic

Control Branches

Concepts as Syntax

• Pathfinding: find_path• Reading state: get_player_shields• Reasoning: select_enemy_target • Changing state: set_unit_armor• Computation: calculate_damage

Granularity

• It is important to get granularity right• Too fine and we have a general language• Too coarse and we don’t accomplish much• This depends a lot on the individual game

Granularity

Many concepts can be implicitly constructed• Behavior trees• State machines (simple and hierarchical)• Utility-based decision making• Smart objects• Blackboards

Implementation

• Keep syntax simple and clean• Or use existing file formats like XML or JSON• Deploy simple code (or library) for parsing• Map syntax elements to constants or classes• Execute the DSL code in some fashion

Clean Syntax

• Should be able to parse very, very easily• No complex grammars/regular expressions• If we need rich syntax, consider XML/JSON• Comma or space delimited fields work great• Prefer specific operations to generic ones

Clean Syntax

Bad: player.health -= weapon.get_damage();Good: damage player with weapon

• Vastly easier to parse• Maps directly to the appropriate concept• Minimizes potential for bugs due to focus

Minimal Syntax, Maximum Power<move_to object="this.ship" avoid="$target"> <position min="1km" max="3km" /> <interrupt> <conditions> <event_object_attacked object="this.ship" /> </conditions> <actions> <set_value name="$doevade" exact="1" /> </actions> </interrupt></move_to>

Executing DSL Logic

• Build a miniature interpreter• Embed the DSL in C++, Lua, etc.• Compile to another language• Compile to native code (scary!)

Various Options

Embedded DSLs

• Implement using underlying language• DSL concepts become functions or classes• Benefit: doesn’t require custom tool chain• Cost: reintroduces low-level concerns• Cost: doesn’t separate AI logic from core

Converting Existing AI Code

• Start by making implementation data-driven• Identify logic that can be grouped into DSL• Factor out existing logic temporarily• Implement chunks of DSL to replace code

So Who Benefits?

• Programmers have a safer environment• Junior team members can do critical AI work• Designers can write logic directly• Code reviewers have a much simpler job• Fast turnaround from QA/automatic testing

So Who Benefits?

Basically everyone wins when DSLs are done carefully

Some Brief Tips

• We can’t depend on realtime execution• Splitting AI DSL onto a thread is usually best• Minimize direct interaction with game state• Respond to events and queue tasks instead

Some Brief Tips

• Put low-level logic in low-level code• Design the DSL for non-realtime execution• Excess flow control in the DSL is risky• It may make sense to deploy multiple DSLs

Flirting With The Dark Side

• Code is cleanest when it maps directly to the problem• DSLs are a superb way to achieve this• Implementing a DSL can be easy and rewarding

http://members.gamedev.net/bag-of-holding/gdc.html