Adderall – more appendᵒ and memberᵒ

Lets do something practical this time and design an adventure. Our adventure will be very linear in nature, it starts from one location, progresses through several location, until it reaches the conclusion. There are no loops or branches this time.

Adderall has firstᵒ, that can be used to create a goal stating “a list l, starting with element s”. For example:

(run 1 [q]
  (firstᵒ [1 2 3 4] q))

[1]

This sounds very useful for us, since our adventure has to start from somewhere. Adderall doesn’t seem to have a way to specify similar goal, but for the last item of a list, so we need to define one (lifted from xxx again):

(defn lastᵒ [s l]
  (fresh [a]
    (appendᵒ a [l] s)))

(run 1 [q]
  (lastᵒ [1 2 3 4] q))

[4]

The lastᵒ builds on top of old trusty appendᵒ: something (the fresh variable a) is appended with l, resulting s. Doesn’t look too complicated, but I couldn’t write it by myself and had to resort on checking from Object Commando. Clearly logic / relational programs aren’t as simple to write as I had assumed.

Now we have way to specify start and end of our journey. We would like to specify some parts in the middle too. Rather than specifying their exact locations, we would like to tell that “these two items are next to each other”. And for that, there’s following function:

(defn adjacentᵒ [s l sl]
  (fresh [a b]
    (condᵉ [(appendᵒ a (list* s l b) sl)]
           [(appendᵒ a (list* l s b) sl)])))

There is two ways of satisfying the goal (hence the condᵉ): s comes first, followed by l or l comes first, followed by s. Fresh variables a and b are used to specify parts of the list we are not interested.

Armed with these new functions, we can write following:

(run 3 [q]
  (firstᵒ q :start)
  (lastᵒ q :treasure)
  (adjacentᵒ :treasure :ambush q)
  (memberᵒ :inn q)
  (memberᵒ :stream q)
  (memberᵒ :forest q))

[['\ufdd0:start', '\ufdd0:inn', '\ufdd0:stream', '\ufdd0:forest', '\ufdd0:ambush', '\ufdd0:treasure'],
 ['\ufdd0:start', '\ufdd0:inn', '\ufdd0:forest', '\ufdd0:stream', '\ufdd0:ambush', '\ufdd0:treasure'], 
 ['\ufdd0:start', '\ufdd0:stream', '\ufdd0:inn', '\ufdd0:forest', '\ufdd0:ambush', '\ufdd0:treasure']]

The adventure starts from :start and ends when we reach :treasure. Along the way there is :inn, :stream and :forest. There’s also an :ambush, that is located next to :treasure.

Another example:

(run 3 [q]
  (firstᵒ q :start)
  (lastᵒ q :treasure)
  (adjacentᵒ :treasure :ambush q)
  (adjacentᵒ :inn :stream q)
  (memberᵒ :forest q))

[['\ufdd0:start', '\ufdd0:inn', '\ufdd0:stream', '\ufdd0:forest', '\ufdd0:ambush', '\ufdd0:treasure'],
 ['\ufdd0:start', '\ufdd0:forest', '\ufdd0:inn', '\ufdd0:stream', '\ufdd0:ambush', '\ufdd0:treasure'],
 ['\ufdd0:start', '\ufdd0:stream', '\ufdd0:inn', '\ufdd0:forest', '\ufdd0:ambush', '\ufdd0:treasure']]

Otherwise similar, but now :inn is located near :stream.

The adventure is very simple, very linear and not terribly interesting for the player. But this is already one step above of our previous tests and is starting to look like what I’m after. If I wanted, I could express branches as sub lists:

(run 3 [q]
  (fresh [path]
    (firstᵒ path :hidden-way)
    (memberᵒ :forest-clearing path)
    (memberᵒ :grotto path)
    (firstᵒ q :start)
    (lastᵒ q :treasure)
    (adjacentᵒ :treasure :ambush q)
    (adjacentᵒ :inn :stream q)
    (memberᵒ :forest q)
    (memberᵒ path q)))

[['\ufdd0:start', '\ufdd0:inn', '\ufdd0:stream', '\ufdd0:forest', ('\ufdd0:hidden-way' '\ufdd0:forest-clearing' '\ufdd0:grotto' . <'_.0'>), '\ufdd0:ambush', '\ufdd0:treasure'],
['\ufdd0:start', '\ufdd0:inn', '\ufdd0:stream', ('\ufdd0:hidden-way' '\ufdd0:forest-clearing' '\ufdd0:grotto' . <'_.0'>), '\ufdd0:forest', '\ufdd0:ambush', '\ufdd0:treasure'],
['\ufdd0:start', '\ufdd0:forest', '\ufdd0:inn', '\ufdd0:stream', ('\ufdd0:hidden-way' '\ufdd0:forest-clearing' '\ufdd0:grotto' . <'_.0'>), '\ufdd0:ambush', '\ufdd0:treasure']]

Now there’s a hidden path that may branch off from the main path. Since we didn’t specify the end, there’s an unbound variable that may have any value (it’s dangerous to wander around, you never know where you end up). For loops and more complex structures, lists probably won’t be enough, but we have to create a new data structure and accompanying functions.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s