Created
June 2, 2014 18:53
-
-
Save rndmcnlly/cc801233012df3cb0883 to your computer and use it in GitHub Desktop.
ASP model of space trading simulation game (gringo 3 w/ lua)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#begin_lua function min(a,b) return math.min(a,b) end #end_lua. | |
%% Adam's minimal event calculus formalism: | |
%% - only true holds/happens are tracked | |
%% - all fluents are always inertial | |
%% - time is a totally ordered contiguous integer sequence | |
%% - events and fluents are self-contained terms | |
%% - T variables always come first for easy sorting | |
initiated(T,F) :- happens(T,E), initiates(T,E,F). | |
terminated(T,F) :- happens(T,E), terminates(T,E,F). | |
holds(T+1,F) :- time(T), holds(T,F), not terminated(T,F). | |
holds(T+1,F) :- time(T), happens(T,E), initiates(T,E,F). | |
%% static structures in the authored universe | |
% links between star systems form digraph | |
jumpgate(sol,eta_ravioli). | |
jumpgate(eta_ravioli,sol). | |
jumpgate(sol,corea). | |
% stars may have many planets, indexed by integer to simplify fluent | |
orbit(sol,1,earth). | |
orbit(sol,2,mars). | |
orbit(sol,3,belt). | |
orbit(sol,4,jupiter). | |
orbit(eta_ravioli,1,meatball_one). | |
orbit(eta_ravioli,2,cloud). | |
orbit(corea,1,ring). | |
% extract systems, orbital ids, and planet names form facts above | |
system(S) :- orbit(S,N,P). | |
orbital(N) :- orbit(S,N,P). | |
planet(P) :- orbit(S,N,P). | |
% named places the main character can be | |
location(surface(P)) :- planet(P). | |
location(orbit(P)) :- planet(P). | |
location(adrift(S)) :- system(S). | |
% a production/consumption network to support trade | |
produces(earth,surface,trinkets). | |
produces(earth,surface,water). | |
produces(jupiter,orbit,hydrogen). | |
produces(belt,orbit,rocks). | |
produces(mars,orbit,rustbuckets). | |
produces(meatball_one,surface,urnoxen). | |
transduces(meatball_one,surface,urnoxen,urnox_hides). | |
consumes(ring,surface,urnox_hides). | |
consumes(earth,surface,rustbuckets). | |
consumes(belt,orbit,hydrogen). | |
consumes(jupiter,orbit,rocks). | |
% extract commodities mentioned anywhere in authored network | |
commodity(C) :- produces(_,_,C). | |
commodity(C) :- consumes(_,_,C). | |
commodity(C) :- transduces(_,_,C,_). | |
commodity(C) :- transduces(_,_,_,C). | |
% non-commodity items | |
sells(belt,jumpdrive,3). | |
equipment(E) :- sells(_,E,_). | |
% instead of finely grained interstellar credits, track quantized wealth class | |
wealth_class(1..4). | |
wealth_max(WMax) :- WMax = #max[wealth_class(W)=W]. % calculate vs. hard-code | |
%% EC fluents | |
% Normally, I would write ... | |
% fluent(loc(L)) :- location(L). | |
% ..., but, because I know locations, commodities, and wealth classes use | |
% disjoint sets of identifiers, I use the raw identifiers as fluents instead of | |
% wrapping them. If locations and commodities were abstract elements identified | |
% only by integers, I'd have to wrap them to distinguish them later. Unwrapped | |
% fluents save a few keystrokes later on, | |
fluent(L) :- location(L). | |
fluent(C) :- commodity(C). | |
fluent(wealth(W)) :- wealth_class(W). % loose integers are scary | |
fluent(E) :- equipment(E). | |
% holds(1,jumpdrive) means "my ship has a jumpdrive installed at T=1" | |
%% EC events (just declaring a space of terms here, no trigger logic) | |
event(enter_orbit(N)) :- orbital(N). | |
event(leave_orbit). | |
event(shuttle). | |
event(jump(S)) :- system(S). | |
event(gather(C)) :- commodity(C). | |
event(trade(C)) :- commodity(C). | |
event(transduce(C)) :- commodity(C). | |
event(buy(E)) :- equipment(E). | |
%% Preconditions (not officially part of EC, but a common idiom nonetheless) | |
possible(T,enter_orbit(N)) :- holds(T,adrift(S)), orbit(S,N,_). | |
possible(T,leave_orbit) :- holds(T,orbit(P)). | |
possible(T,shuttle) :- holds(T,orbit(P)). | |
possible(T,shuttle) :- holds(T,surface(P)). | |
possible(T,jump(S2)) :- holds(T,jumpdrive), holds(T,adrift(S1)), jumpgate(S1,S2). | |
possible(T,gather(C)) :- holds(T,surface(P)), produces(P,surface,C). | |
possible(T,gather(C)) :- holds(T,orbit(P)), produces(P,orbit,C). | |
possible(T,trade(C)) :- holds(T,C), holds(T,surface(P)), consumes(P,surface,C). | |
possible(T,trade(C)) :- holds(T,C), holds(T,orbit(P)), consumes(P,orbit,C). | |
possible(T,transduce(C1)) :- holds(T,C1), holds(T,surface(P)), transduces(P,surface,C1,C2). | |
possible(T,buy(E)) :- holds(T,wealth(W)), holds(T,orbit(P)), sells(P,E,W). | |
%% EC initiates rules | |
initiates(T,enter_orbit(N),orbit(P)) :- holds(T,adrift(S)), orbit(S,N,P). | |
initiates(T,leave_orbit,adrift(S)) :- holds(T,orbit(P)), orbit(S,N,P). | |
initiates(T,shuttle,surface(P)) :- holds(T,orbit(P)). | |
initiates(T,shuttle,orbit(P)) :- holds(T,surface(P)). | |
initiates(T,jump(S2),adrift(S2)) :- time(T), jumpgate(S1,S2). | |
initiates(T,gather(C),C) :- time(T), event(gather(C)). | |
initiates(T,trade(C),wealth(@min(WMax,W+1))) :- % had to invent Lua helper "min" | |
commodity(C), | |
holds(T,wealth(W)), | |
wealth_max(WMax). | |
initiates(T,transduce(C1),C2) :- holds(T,surface(P)), transduces(P,surface,C1,C2). | |
initiates(T,buy(E),E) :- time(T), event(buy(E)). | |
%% EC terminates rules | |
terminates(T,enter_orbit(N),adrift(S)) :- holds(T,adrift(S)), orbit(S,N,P). | |
terminates(T,leave_orbit,orbit(P)) :- holds(T,orbit(P)). | |
terminates(T,shuttle,orbit(P)) :- holds(T,orbit(P)). | |
terminates(T,shuttle,surface(P)) :- holds(T,surface(P)). | |
terminates(T,jump(S2),adrift(S1)) :- holds(T,adrift(S1)), jumpgate(S1,S2). | |
% gather(C) doesn't termiante anything | |
terminates(T,trade(C),wealth(W)) :- event(trade(C)), holds(T,wealth(W)). | |
terminates(T,trade(C),C) :- event(trade(C)), holds(T,C). | |
terminates(T,transduce(C),C) :- event(transduce(C)), holds(T,C). | |
%% Initial conditions and time points | |
holds(0,surface(earth)). % location | |
holds(0,wealth(1)). % wealth_class | |
#const t_max=24. | |
time(0..t_max). | |
%% Event occurence | |
{ happens(T,E) } :- time(T), possible(T,E). | |
:- time(T), not 1 { happens(T,E) } 1. | |
%% Planning goals | |
space_cowboy :- happens(T,trade(urnox_hides)). | |
:- not space_cowboy. | |
#hide. | |
#show happens/2. | |
#show initiated/2. | |
#show terminated/2. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
One solution rendered in text: