SC2L

A commitment language for StarCraft II — authors declare what game states must hold by certain times, how to react to events, and how to orchestrate concurrent behaviors.

Compiles to playbook that runs on a fixed runtime across desktop, mobile, and web.

Grammar

// Program structure
program      ::= block*
block        ::= world | belief | economy | plan | tactics

// World — map topology
world        ::= 'world' '{' world_decl* '}'
world_decl   ::= 'base' IDENT '=' 'base' '(' STRING ')'
             |   'ramp' IDENT '=' 'ramp' '(' IDENT '->' IDENT ')'
             |   'region' IDENT '=' ('choke' | 'open') '(' region_params ')'

// Belief — partial information
belief       ::= 'belief' IDENT '{' belief_decl* '}'
belief_decl  ::= 'track' IDENT '=' expr
             |   'hypothesis' IDENT 'when' expr
             |   'infer' IDENT 'from' '{' infer_fields '}'
infer_fields ::= ('rule' ':' expr)? ('quality' ':' IDENT)? ('decay' ':' expr)?

// Economy — continuous invariants
economy      ::= 'economy' '{' invariant* '}'
invariant    ::= 'invariant' 'never' expr
             |   'invariant' 'keep' expr ('when' expr)?

// Plan — milestones and commitments
plan         ::= 'plan' '{' plan_stmt* '}'
plan_stmt    ::= 'commit' STRING ('confidence' expr)?
             |   'milestone' STRING time_spec 'require' requirements
             |   'on_miss' STRING '{' tactics_stmt* '}'
             |   'pivot_to' STRING 'when' expr '{' plan_stmt* '}'
             |   'cancel_milestone' STRING
time_spec    ::= 'around' expr ('±' expr)? | 'asap'
requirements ::= '{' requirement* '}'
requirement  ::= 'units' '{' type_counts '}' | 'building' '{' type_counts '}' | expr
type_counts  ::= (IDENT ':' expr (',' IDENT ':' expr)*)?

// Tactics — groups, actions, events
tactics      ::= 'tactics' '{' tactics_decl* '}'
tactics_decl ::= 'group' IDENT '=' expr
             |   'on' 'event' IDENT args? '{' tactics_stmt* '}'
             |   'every' expr ('while' expr)? '{' tactics_stmt* '}'

tactics_stmt ::= 'until' expr 'timeout' expr '{' tactics_stmt* '}'
             |   'await' 'act' IDENT expr ('->' expr)?
             |   'await' 'sleep' expr
             |   IDENT '=' 'try' 'act' IDENT expr ('->' expr)?
             |   'match' expr '{' match_arm* '}'
             |   'if' expr '{' tactics_stmt* '}' ('else' '{' tactics_stmt* '}')?
             |   'race' '{' ('{' tactics_stmt* '}')+ '}'
             |   'select' '{' (expr '->' '{' tactics_stmt* '}')+ '}'
             |   'deviation' 'severity' IDENT expr
             |   expr
match_arm    ::= ('ok' | 'failed' IDENT? | 'timeout') '->' '{' tactics_stmt* '}'

// Expressions
expr         ::= or_expr
or_expr      ::= and_expr ('or' and_expr)*
and_expr     ::= cmp_expr ('and' cmp_expr)*
cmp_expr     ::= add_expr (('==' | '!=' | '<' | '<=' | '>' | '>=') add_expr)?
add_expr     ::= mul_expr (('+' | '-' | '±') mul_expr)*
mul_expr     ::= unary_expr (('*' | '/' | '%') unary_expr)*
unary_expr   ::= ('-' | 'not') unary_expr | postfix_expr
postfix_expr ::= primary ('.' IDENT args? | 'where' expr | 'within' expr 'of' expr)*
primary      ::= INT | FLOAT | TIME | STRING | 'true' | 'false' | IDENT args? | '(' expr ')'
args         ::= '(' (expr (',' expr)*)? ')'

// Tokens
INT          ::= [0-9]+
FLOAT        ::= [0-9]+ '.' [0-9]+
TIME         ::= [0-9]+ ':' [0-9][0-9]              // e.g., 2:30, 0:15
STRING       ::= '"' [^"]* '"'
IDENT        ::= [a-zA-Z_][a-zA-Z0-9_]*

Example

example.sc2l
world {
  base main    = base("main")
  base natural = base("natural")
  ramp main_ramp = ramp(main -> natural)
}

economy {
  invariant never supply_blocked
  invariant keep workers_building when minerals >= 50
}

plan {
  milestone "expand" around 2:30 ± 0:15 require {
    base_count >= 2
  }

  on_miss "expand" {
    deviation severity high "Missed expansion timing"
  }
}

tactics {
  group defenders = owned.units where type == Stalker

  on event EnemyNear(natural) {
    until threat == 0 timeout 1:00 {
      await act attack_move defenders -> natural
      await sleep 0:02
    }
  }
}
← Back to home