Revitalizing Castlequest, Part 2: NOW WITHOUT SHOUTING
Tags: fortran, legacy, refactoring, adventure
Published: 2021-09-03 21:56:20

---
title: Revitalizing Castlequest, Part 2: NOW WITHOUT SHOUTING
published: true
description: A discussion of unfortunate input and output formats in legacy scientific code, origins, and solutions.
series: Revitalizing Castlequest
tags: #fortran #legacy #refactoring #adventure
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0dqluoojlcre511o1vmk.png
---

In the [previous installment](https://dev.to/arclight/revitalizing-castlequest-part-1-museums-and-garages-4mhc), I discussed several motivations for embarking on this modernization effort. It's important to be honest about why you are changing a code, whether you're modernizing, rewriting, or even retiring software.

*Shall we play a game?*

I've been writing about Castlequest but I haven't really shown it in action:

```
$ .\cquest.exe
- Welcome to CASTLEQUEST!! Would you like instructions?
 
Y
0  You are in a remote castle somewhere in Eastern Europe.
   I will be your eyes and hands.  Direct me with words such
   as "LOOK", "TAKE", or "DROP".  To move, enter compass points
   (N,NE,E,SE,S,SW,W,NW), UP, or DOWN.  To get a list of what
   you are carrying, say "INVENTORY".  To save the current game
   so it can be finished later say "SAVE".  Say "RESTORE" as
   your first command to finish a game that had been saved.
0  The object of the game is to find the master of the castle
   and kill him, while accumulating as many treasures as possible.
   You get maximum points for depositing the treasures in the
   vault.  Notice that the descriptions of treasures have an
   exclamation point.  Be wary, as many dangers await you in
   in the castle.
0  Would you like more detailed instructions?
 
N
0  You are in a large, tarnished brass bed in an old, musty bedroom.
   cobwebs hang from the ceiling.  A few rays of light filter through
   the shutters.  There is a nightstand nearby with a single wooden
   drawer.  The door west creaks in the breeze.  A macabre portrait
   hangs to the left of an empty fireplace.
0  The shutters are closed.
0  There is a silver bullet here.
 
OPEN SHUTTERS
0  The shutter is open, but there are bars over the window.
0  Something on the ground outside is glistening brightly.
 
TAKE BULLET
0  OK
 
INVENTORY
0  You are carrying the following object:
      Silver bullet   
 
QUIT
0  You scored    0 out of  300 points.
0  You are a GREENHORN at this game!!

$
```

It's a basic text adventure with a verb-noun command form. It recognizes only a few words (80 verbs and 76 nouns) and not every combination makes sense. Even fewer combinations do anything useful. Still, Castlequest's vocabulary is reasonable for the game's size and era.

Two aspects of the game transcript are worth further discussion: why all my commands are in UPPER CASE and why there are all those zeroes at the beginning of a line.

## The Case of the Upper Case ##

The upper case user input is maybe easiest to explain, and no, it's not that the cat stepped on caps-lock while I was distracted. F66 has almost no support for character data. The language has no string types and there are no functions for changing case or otherwise manipulating text. About all you can do is print text.

Here's a fragment of the input routine (creatively named `INPUT`, located in the file `input.f`):

```fortran
C-----------------------------------------------------
      SUBROUTINE INPUT(ACTION)
      IMPLICIT INTEGER (A - Z)
      INTEGER ACTION(2), VERBS(2,80), NOUNS(2,76),
     2        BLANK, N, V, NVERBS /80/,
     3        NNOUNS /76/
C
      INTEGER NOUN(3), VERB(3)
C
      EQUIVALENCE (VERB(1), V), (NOUN(1), N)
C
      DATA VERBS  /4hATTA, 15, 4hBACK, 40, 4hBREA, 37, 4hBRIE, 61,
     2             4hCHOP, 37, 4hCLIM,  9, 4hCLOS, 28, 4hCROS, 43,
     3             4hD   , 10, 4hDEBU, 59, 4hDOWN, 10, 4hDRIN, 24,
     4             4hDROP, 12, 4hE   ,  3, 4hEAST,  3, 4hEAT , 23,
     5             4hENTE, 13, 4hEXIT, 14, 4hEXTI, 34, 4hFEED, 22,
     6             4hFILL, 49, 4hFIRE, 54, 4hFUCK, 19, 4hGOTO, 51,
     7             4hHELP, 50, 4hHINT, 50, 4hHONK, 45, 4hIN  , 13,
     8             4hINVE, 26, 4hJUMP, 25, 4hKILL, 16, 4hL   , 52,
     9             4hLEAV, 14, 4hLEFT, 52, 4hLIGH, 32, 4hLOAD, 18,
     X             4hLOCK, 29, 4hLONG, 60, 4hLOOK, 35, 4hMELT, 42,
     1             4hN   ,  1, 4hNE  ,  2, 4hNORT,  1, 4hNW  ,  8,
     2             4hOFF , 33, 4hON  , 31, 4hOPEN, 27, 4hOUT , 14,
     3             4hPOOF, 56, 4hPOUR, 39, 4hQUIT, 44, 4hR   , 53,
     4             4hREAD, 48, 4hREST, 58, 4hRIGH, 53, 4hS   ,  5,
     5             4hSAVE, 57, 4hSCOR, 36, 4hSE  ,  4, 4hSHOO, 54,
     6             4hSHOW, 20, 4hSOUT,  5, 4hSTAB, 21, 4hSUSP, 57,
     7             4hSW  ,  6, 4hSWIM, 41, 4hT   , 11, 4hTAKE, 11,
     8             4hTHRO, 17, 4hTIE , 46, 4hU   ,  9, 4hUNLO, 30,
     9             4hUNTI, 47, 4hUP  ,  9, 4hVERB, 60, 4hW   ,  7,
     X             4hWAKE, 55, 4hWATE, 38, 4hWAVE, 20, 4hWEST,  7/
```

The code takes advantage of the fact that integer variables are stored as 4 consecutive bytes, characters can be represented with one byte, and most F66 compilers did not check type. So all the variables that look like they're holding nouns and verbs are actually integers. Here the big list of verbs is represented in Hollerith format ([named after Herman Hollerith](https://www.ibm.com/ibm/history/ibm100/us/en/icons/tabulator/), famed inventor of [punchcard](http://www.quadibloc.com/comp/cardint.htm) tabulating machines in the 1890s). [Hollerith format](https://en.wikipedia.org/wiki/Hollerith_constant) consists of the number of characters in the string followed by the letter `'H'` followed by the actual characters in the string. The first verb in the list, `4hATTA` is just the four characters `ATTA`. Why not just put text between quotes like a normal person?

There aren't any quotes in standard F66.

*Seriously.*

This is the entire F66 character set:

```
ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 =+-*/(),.$
```

Compiler vendors could support other characters as unofficial extensions to the language. For portability however, you're limited to those 47 characters. So per the language standard the text `ATTA` should be written as `4HATTA`. The upshot is all the game commands are upper case essentially because the language isn't guaranteed to support lower case and there's no good way to normalize text case in F66.

##Zeroes for Heroes##

Remember the gameplay from before? With all the leading zeroes sprinkled through the text? This?

```
- Welcome to CASTLEQUEST!! Would you like instructions?
 
Y
0  You are in a remote castle somewhere in Eastern Europe.
   I will be your eyes and hands.  Direct me with words such
   as "LOOK", "TAKE", or "DROP".  To move, enter compass points
```

The first character on each line is an [ASA carriage control code](https://en.wikipedia.org/wiki/ASA_carriage_control_characters) used to format text sent to a [(weird, ancient) printer](https://en.wikipedia.org/wiki/Carriage_control_tape). `' '` (a space) is single-space, `'0'` is double-space, `'-'` is triple-space, `'+'` is overstrike (zero-space?), and `'1'` is form-feed. This is how the original gameplay looks when run through an ASA format converter:

```
$ .\cquest.exe | .\asa.ex
 Welcome to CASTLEQUEST!! Would you like instructions?
Y


  You are in a remote castle somewhere in Eastern Europe.
  I will be your eyes and hands.  Direct me with words such
  as "LOOK", "TAKE", or "DROP".  To move, enter compass points
  (N,NE,E,SE,S,SW,W,NW), UP, or DOWN.  To get a list of what
  you are carrying, say "INVENTORY".  To save the current game
  so it can be finished later say "SAVE".  Say "RESTORE" as
  your first command to finish a game that had been saved.

  The object of the game is to find the master of the castle
  and kill him, while accumulating as many treasures as possible.
  You get maximum points for depositing the treasures in the
  vault.  Notice that the descriptions of treasures have an
  exclamation point.  Be wary, as many dangers await you in
  in the castle.

  Would you like more detailed instructions?
N


  You are in a large, tarnished brass bed in an old, musty bedroom.
  cobwebs hang from the ceiling.  A few rays of light filter through
  the shutters.  There is a nightstand nearby with a single wooden
  drawer.  The door west creaks in the breeze.  A macabre portrait
  hangs to the left of an empty fireplace.

  The shutters are closed.

  There is a silver bullet here.
OPEN SHUTTERS


  The shutter is open, but there are bars over the window.

  Something on the ground outside is glistening brightly.
TAKE BULLET


  OK
INVENTORY


  You are carrying the following object:
     Silver bullet
QUIT


  You scored    0 out of  300 points.

  You are a GREENHORN at this game!!

$
```

Much better but still not great. But that's what you get with a language that dates to the early 60s. Escaped notation such as `"\n"` wouldn't be invented until 1972 with C and wouldn't be a *de facto* standard until much later.

## Why Do We Care? ##

So that's the explanation for SHOUTED COMMANDS and the Mystery Zeroes in the original game output.

Why does this matter? Two reasons: user experience and testing. The game is a lot less fun to play IF YOU HAVE TO SHOUT ALL YOUR COMMANDS. Recognizing commands in upper case only is authentic and there's an argument to be made for preserving that behavior. My counter-argument is that it doesn't add anything to game play, it strains the eyes, and the caps-lock key is stupid. When modernizing Castlequest, I made it a top priority to change the game to accept lower case.

This also leads to issues when testing. In its original form, Castlequest can only be tested interactively. The game logic is tangled up in an immense monolithic main program. By definition, unit testing only works on discrete program units, not the whole code at once -- that's integral testing. I did all the coding and testing so I wound up playing a lot of Castlequest.

**So. Much. Castlequest.**

To preserve my eyesight and my remaining sanity, I rewrote the input routines to ignore case. Replacing the long-deprecated Hollerith format with actual quotes was next, mainly because it was an easy change. Conversely, one of my very last changes was making ASA carriage control optional. That change was complex and miserable even after cleaning up the rest of the code.

Beyond that, I made very few changes to the user experience. All the original typos are preserved; the game just crashes less and is easier on the eyes. But the innards of the code? Very little was left untouched.

If you really want that authentic Castlequest experience, it's still in there. If you just want to play the game and find out what's in the drawer of the nightstand without fiddling about with `asa`, you can do that too. NOW WITHOUT SHOUTING.