Arcturus - a new programming language & compiler for the Z-machine

That’s because ive been there before. I made the same mistake back in 2018. At the time i was working on a new system. I made a game for introcomp called “Mothership”. The game worked, but was only part 1 of the story.

Here are some pictures.


My system at the time was a homoiconic language (called KL) with a very small set of primitives. Ideal, i thought, for bootstrapping an IF system. But there was a problem; it got messy fast. Here’s a small excerpt of the source code to Mothership.

(defobj corridor {
  room
  (at ship)
   (gx 1) (gy 0) (exits {
                        (north controlroom)
                        (west medical)
                        (east hatch)
                        (south dorm)
                        })
   (name "Central Corridor")
   (picture "images/corridor.jpg")
   (sound "sounds/hum2.ogg")
   (focus
    {
    (r-getup (fn () ((f-getup) ())))
    (r-look "You're in the central corridor. Routes leads off in all directions; north, south, east and west")
    
    (r-look2 "\n\nI know this description is a bit short, but it's a _[corridor]_ - what can I say. Use your imagination or look at the picture which we ripped off from another game. No, honestly, these pictures are just placeholders until Amy gets around to drawing the real ones. That, and the fact that it's just too hot here to do anything really _that_ creative.")

    (r-look3 (cats "Unfortunately, the [corridor] description is still"
                   (ch "bad" "poor" "terrible" "appalling" "boring" "uninspired" "dull" "lame" "a stub" "dreadful")))
    (actions
     (
      (0 getup r-getup (EV (re (re-not get-up))))
      (1 look r-look)
      (1 look r-look2 (EV (re (re-not corridor-look))))
      (1 look r-look3 (EV (rea corridor-look)))
      )
     )
    })
   })

(defobj cabins {
  container
  (at dorm)
  (is hidden)
  (name "cabins")
  (focus
   {
   (r-look1 "Now, one of these cabins must be yours?")
   (r-look2 (f-push 'cabins-found (f-puthere 'clothes "Ahah! Found it. You open the door and find your clothes inside")))
   (r-look3 "It's your dorm cabin")
   (actions
    (
     (1 look r-look1 (EV (re "[^cabins-look]*")))
     (1 look r-look2 (EV (re "[^cabins-look]*cabins-look[^cabins-look]*")))
     (1 look r-look3 (EV (re ".*cabins-found.*")))
     )
    )
   })
  })

See the problem. One missing bracket and you’re stuffed! Yes i know tools can help a lot with this kind of thing, but the basic idea was broken, and expecting clever tools to fix it, wasn’t the answer either. Your original syntax, with its brackets all over, reminded me of this.

What i did:

New Design Goal

Strand’s original mission was to achieve the, so called, 90% rule:

Do 90% of what games want really well and leave the remaining 10% to game design.

The motivation for this goal was the supposition that 9/10 features could be made simply and easy to author whilst the annoying and complicated 10% could be isolated from poisoning the main 90%.

In other words, the central goal of Strand was ease of authoring and therefore its corollary, rapid development.

Strategy

Ease of authoring was to be achieved by inventing a non-technical domain specific language (Strand). It was important that this language did not resemble programming with its inevitable collection of weird symbols and annoying syntax.

Because, whether you’re a programmer or not, this is still a development impediment.

How nice it would be to “bosh-out” whole swathes of gameplay without programming; without variables, loops, if-then-else statements and all the other rubbish programming languages force on you.

But how?

Following the 9/10 idea, it was envisaged that Strand would handle the 90% without programming and the remaining 10% would be relegated to a companion, traditional programming language.

Because, for example, if someone wanted to have a chess game coded inside their game, it would clearly require a general programming system to be implemented. Such a thing would be deemed to fall into the 10% and thus be implemented outside of Strand.

The Strand IF system would therefore consist of a complementary blend of two languages; a DSL, called Strand and a system language called KL.


What Happened

Strand easily handled 99.9% of all cases, vastly overachieving its 90% original remit. There are almost no KL bits in any game i’ve written since then. The occasional one-liner, and all those are in the library anyhow.

Yes, I think Chord is a good choice.

1 Like