179 lines
4.0 KiB
Plaintext
179 lines
4.0 KiB
Plaintext
--- todo make it parse the input unmodified
|
|
|
|
fmod OBJECT is
|
|
sort Object .
|
|
ops ore clay obsidian geode : -> Object [ctor] .
|
|
endfm
|
|
|
|
view Object from TRIV to OBJECT is sort Elt to Object . endv
|
|
|
|
|
|
fmod INV is
|
|
pr NAT + OBJECT .
|
|
|
|
sorts Item Inv .
|
|
subsort Item < Inv .
|
|
op nil : -> Inv [ctor] .
|
|
op __ : Nat Object -> Item [ctor prec 10] .
|
|
op _and_ : Inv Inv -> Inv
|
|
[ctor comm assoc id: nil prec 11] .
|
|
|
|
vars A B : Object .
|
|
vars I J : Nat .
|
|
|
|
eq 0 A = nil .
|
|
eq (I A) and (J A) = (I + J) A .
|
|
|
|
vars X Y : Inv .
|
|
|
|
op _-_ : Inv Inv -> [Inv] [prec 20] .
|
|
eq Y - nil = Y .
|
|
ceq I A and X - J A and Y = sd(I, J) A and (X - Y) if J <= I .
|
|
|
|
op count : Object Inv -> Nat .
|
|
eq count(A, I A and X) = I .
|
|
eq count(A, X) = 0 [owise] .
|
|
endfm
|
|
|
|
|
|
fmod BP-ITEM is
|
|
pr OBJECT + INV .
|
|
|
|
sort BpItem .
|
|
op item : Object Inv -> BpItem [ctor] .
|
|
|
|
var A : Object . var Xs : Inv .
|
|
|
|
op (Each _ robot costs _ .) : Object Inv -> BpItem [prec 20] .
|
|
eq (Each A robot costs Xs .) = item(A, Xs) .
|
|
endfm
|
|
|
|
view BpItem from TRIV to BP-ITEM is sort Elt to BpItem . endv
|
|
|
|
|
|
fmod BP is
|
|
pr SET{BpItem} * (sort Set{BpItem} to Items, op _,_ to __ [prec 21]) .
|
|
|
|
sort Bp .
|
|
op bp : Nat Items -> Bp [ctor] .
|
|
|
|
var I : Nat .
|
|
var Rs : Items .
|
|
|
|
op (Blueprint _ : _) : Nat Items -> Bp [prec 30] .
|
|
eq (Blueprint I : Rs) = bp(I, Rs) .
|
|
|
|
op index : Bp -> Nat .
|
|
eq index(bp(I, Rs)) = I .
|
|
|
|
op items : Bp -> Items .
|
|
eq items(bp(I, Rs)) = Rs .
|
|
endfm
|
|
|
|
view Bp from TRIV to BP is sort Elt to Bp . endv
|
|
|
|
|
|
fmod MAYBE{T :: TRIV} is
|
|
sort Maybe{T} .
|
|
subsort T$Elt < Maybe{T} .
|
|
op nothing : -> Maybe{T} [ctor] .
|
|
endfm
|
|
|
|
fmod BAG{T :: TRIV} is
|
|
sort Bag{T} .
|
|
subsort T$Elt < Bag{T} .
|
|
|
|
op nil : -> Bag{T} [ctor] .
|
|
op __ : Bag{T} Bag{T} -> Bag{T} [ctor assoc comm id: nil] .
|
|
endfm
|
|
|
|
fmod STATE is
|
|
pr NAT .
|
|
pr LIST{Bp} * (sort List{Bp} to Bps,
|
|
op __ : Bps Bps -> Bps to __ [prec 31]) .
|
|
pr MAYBE{Object} * (sort Maybe{Object} to Making) .
|
|
pr BAG{Object} * (sort Bag{Object} to Robots) .
|
|
|
|
sort State .
|
|
op running : Bp Making Robots Inv -> State [ctor] .
|
|
subsort Nat < State .
|
|
|
|
var Bp : Bp .
|
|
var Rs : Robots .
|
|
var X : Object .
|
|
var Y : Making .
|
|
var Xs : Inv .
|
|
|
|
op new : Bp -> State .
|
|
eq new(Bp) = running(Bp, nothing, ore, nil).
|
|
|
|
op count : Object State -> Nat .
|
|
eq count(X, running(Bp, Y, Rs, Xs)) = count(X, Xs) .
|
|
endfm
|
|
|
|
view State from TRIV to STATE is sort Elt to State . endv
|
|
|
|
|
|
mod RULES is
|
|
pr STATE .
|
|
|
|
var Bp : Bp .
|
|
var Is : Items .
|
|
var Rs : Robots .
|
|
var X : Object .
|
|
var Y : Making .
|
|
vars Xs Ys : Inv .
|
|
|
|
op collect : Robots -> Inv .
|
|
eq collect(nil) = nil .
|
|
eq collect(X Rs) = 1 X and collect(Rs) .
|
|
|
|
op qual : Bps Inv -> Nat .
|
|
eq qual(Bp, Xs) = index(Bp) * count(geode, Xs) .
|
|
|
|
rl [collect] : running(Bp, Y, Rs, Xs) =>
|
|
running(Bp, Y, Rs, Xs and collect(Rs)) .
|
|
|
|
crl [startBuild] : running(Bp, nothing, Rs, Xs) =>
|
|
running(Bp, X, Rs, Xs - Ys)
|
|
if item(X, Ys) Is := items(Bp)
|
|
/\ Xs - Ys :: Inv .
|
|
|
|
rl [finishBuild] : running(Bp, X, Rs, Ys) =>
|
|
running(Bp, nothing, X Rs, Ys) .
|
|
|
|
rl [done] : running(Bp, Y, Rs, Xs) => qual(Bp, Xs) .
|
|
endm
|
|
|
|
|
|
smod RUN is
|
|
pr LIST{State} .
|
|
pr RULES .
|
|
|
|
var N : Nat .
|
|
var X : Object .
|
|
var S : State .
|
|
var Ss : List{State} .
|
|
|
|
--- this won't work because e.g. in example 1 it will just keep making a
|
|
--- million clay guys forever and never get enough ore for an obsidian guy
|
|
strat buildBest : @ State .
|
|
sd buildBest := startBuild[X <- geode]
|
|
or-else startBuild[X <- obsidian]
|
|
or-else startBuild[X <- clay]
|
|
or-else startBuild[X <- ore] .
|
|
|
|
strat step1 : @ State .
|
|
sd step1 := try(buildBest) ; collect ; try(finishBuild) .
|
|
|
|
strat stepAll : @ List{State} .
|
|
sd stepAll := try(matchrew S Ss by S using step1, Ss using stepAll) .
|
|
|
|
strat stepsOnly : Nat @ List{State} .
|
|
sd stepsOnly(0) := idle .
|
|
sd stepsOnly(s(N)) := stepAll ; stepsOnly(N) .
|
|
|
|
strat steps : Nat @ List{State} .
|
|
sd steps(N) := stepsOnly(N) ; done ! .
|
|
endsm
|