Skip to content

Instantly share code, notes, and snippets.

@rndmcnlly
Created June 2, 2014 18:53
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rndmcnlly/cc801233012df3cb0883 to your computer and use it in GitHub Desktop.
Save rndmcnlly/cc801233012df3cb0883 to your computer and use it in GitHub Desktop.
ASP model of space trading simulation game (gringo 3 w/ lua)
#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.
@rndmcnlly
Copy link
Author

One solution rendered in text:

Shuttle up to orbit, leave orbit of earth, enter orbit of belt, gather rocks, leave orbit of belt, enter orbit of jupiter, gather hydrogen, profit from trade of rocks, leave orbit of jupiter, enter orbit of belt, profit from trade of hydrogen, purchase and install jumpdrive, leave orbit of belt, jump to eta ravioli, enter orbit of meatball one, shuttle to surface, gather urnoxen, craft urnox hides from urnoxen, shuttle up to orbit, leave orbit of meatball one, jump to sol, jump to corea, enter orbit of ring, shuttle to surface, and profit from trade of urnox hides.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment