Tenliner Cave Adventure in R: Miniature Text Adventure Ported From the ZX81

[This article was first published on Having Fun and Creating Value With the R Language on Lucid Manager, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Computing has come a long way in the past 75 years. I learned how to write code in the 1980s on my tiny 1 kilobyte ZX81 home computer. With only 1 kilobyte of memory, capabilities were limited, but this machine set me off on an adventure writing code in the BASIC language. An active subculture of computer enthusiasts still develops new code and keeps these old machines alive. I recently stumbled across the fantastic Tenliner Cave Adventure (2016) by Einar Saukas from Brazil. This tiny ZX81 program provides a fully functional classical text adventure using some cunning techniques. This article contains a port of this game to the R language to explore its inner workings.

Interactive Fiction

Text adventures, or interactive fiction, were trendy in the 1980s. The basic premise is that the computer shows a text and the player responds with a text command. The computer parses the command, calculates the new state of play and progresses the game with a new bit of prose. Last year I wrote an article about writing interactive fiction using the R language with a translation of Secret of Landusia. The Tenliner Cave Adventure provides a minimalist approach by squashing the basic principles of a text adventure into 1024 bytes of memory. The backstory of this Saukas' mini-adventure is a typical fantasy setting:

As a young warrior apprentice, you have been chosen by the village elders to seek out the evil menace that lurks in some nearby caves. Once found, use any means at your disposal to defeat it… Good luck on your quest!

ZX81 Screenshot of the Tenliner Cave Adventure
ZX81 Screenshot of the Tenliner Cave Adventure.

Tenliner Cave Adventure in R

The Tenliner Cave Adventure is a jewel of efficient programming. The game is simple, but it has all typical elements of a text adventure. As I no longer own a ZX81, I could not resist translating this code to R to be able to play and reverse-engineer the game.

The game recognises the following commands:

  • north, south, east, west (move)

  • inventory

  • look

  • look

  • get

  • open

  • kill

    Most advanced games understand abbreviations and synonyms, but in this simple version, you have to provide precise commands. Can you rid the village of the evil menace?

      ## Tenliner Cace Adventure by Einar Saukas
      ## Ported from ZX81 BASIC to R by Peter Prevos
    
      ## Helper functions to keep syntax close to ZX81
      val <- function(p) as.numeric(p)
      x <- function(p, q = p) substr(X, p, q)
    
      ## Ported ZX81 code
      X <- "100cannot doyou walk opened   closed   a sword  a key    nothing  a chest  a dragon a corpse taken    you died you won. "
      repeat {
          cat(paste("You are in a", substr("cavepit halllake", val(x(1)) * 4 - 3, val(x(1)) * 4), "\n"))
          u <- tolower(readline(prompt = "What would you like to do? "))
          m <- 2 * (u == "north") * (x(1) < "3") -
            2 * (u == "south") * (x(1) > "2") +
            (x(1) == "2" & u == "west") -
            (x(1) == "3" & u == "east")
          a <- (3 * val(x(2)) + 2 * (x(3) == "2")) * (x(1) == 2 & u == "look chest") +
            (11 + (x(3) == "2")) * (x(1) == "3" & u == "kill dragon") +
            (m != 0) +
            (5 + val(x(1))) * (u == "look") +
            (6 - val(x(3))) * (u == "inventory") +
            (6 - (x(3) == "0")) * (x(1) == 4 & u == "look corpse") +
            10 * (x(1, 3) == "400" & u == "get key") +
            2 * (x(1, 3) == "201" & u == "open chest") +
            10 * (x(1, 3) == "211" & u == "get sword")
          X <- paste0(val(x(1)) + m, val(x(2)) + (a == 2), val(x(3)) + (a == 10), substring(X, 4))
          cat(paste(substr(X, a * 9 + 4, a * 9 + 12), "\n"))
          if (a >= 11) break
      }

    This port of the Ten-liner Text Adventure stay as close as possible to the original code by creating two helper functions, `val()` and `x()`. In ZX81 basic, you can subset a string with parenthesis, which is mimicked in this code with the `x()` function. The `val()` function in ZX81 BASIC converts a string to a value. The rest of the code is almost literally the same as the ZX81 version.

    The workings of the game are ingenious and minimise memory usage on the ZX81 to a minimum. All numeric values are stored in the `X` string to save memory, which also contains all game responses. The first number is the room number the player is in, the second number records whether the chest is closed or open and the third number records the objects held by the player (the inventory). The responses in the `X` variable are all nine characters long.

    In ZX81 BASIC, all lines have numbers to control sequencing. This version uses a `repeat{}` loop that keeps running until the game ends.

    The game opens with displaying the room the player is in. Next, the player is asked to provide a response.

    The variable `m` determines the movement of the player depending on their direction. The result is a number between -2 and 2, which indicates the difference between the current and new room. The code uses a complex boolean expression to work this out.

    The variable `a` determines the outcome after the command if it is not a change in direction. This is the most sophisticated line in the game. In the original listing, it took three lines to determine the new game state due to line-length restrictions. In this code, I concatenated it into one line in line with the games minimalism philosophy. This line combines the input of the player with the current game state to determine the new situation.

    In the next step, the code changes the state of the game by updating the three numbers in `X`. The game displays a response, depending on the content of `a`.

    It takes much more space to describe how this game works than the size of the code itself.

    Have fun!

    To leave a comment for the author, please follow the link and comment on their blog: Having Fun and Creating Value With the R Language on Lucid Manager.

    R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
    Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

    Never miss an update!
    Subscribe to R-bloggers to receive
    e-mails with the latest R posts.
    (You will not see this message again.)

    Click here to close (This popup will not appear again)