Werewolves and Wanderer

2023-07-19

This blog post is also available as a video. Would you prefer to watch/listen to me tell you about the video game that had the biggest impact on my life?

Of all of the videogames I've ever played, perhaps the one that's had the biggest impact on my life (The game that had the biggest impact on my life, it might surprise you to hear, is not among the "top ten videogames that stole my life" that I wrote about almost exactly 16 years ago nor the follow-up list I published in its incomplete form three years later. Turns out that time and impact are not interchangable. Who knew?) was: Werewolves and (the) Wanderer. (The game is variously known as Werewolves and Wanderer, Werewolves and Wanderers, or Werewolves and the Wanderer. Or, on any system I've been on, WERE.BAS, WEREWOLF.BAS, or WEREWOLV.BAS, thanks to the CPC's eight-point-three filename limit.)



This simple text-based adventure was originally written by Tim Hartnell for use in his 1983 book Creating Adventure Games on your Computer. At the time, it was common for computing books and magazines to come with printed copies of program source code which you'd need to re-type on your own computer, printing being significantly many orders of magnitude cheaper than computer media. (Additionally, it was thought that having to undertake the (painstakingly tiresome) process of manually re-entering the source code for a program might help teach you a little about the code and how it worked, although this depended very much on how readable the code and its comments were. Tragically, the more comprehensible some code is, the more long-winded the re-entry process.)

Front cover of The Amazing Amstrad Omnibus, by Martin Fairbanks, with its bright yellow text on a red background.

I'd been working my way through the operating manual for our microcomputer, trying to understand it all. (One of my favourite features of home microcomputers was that seconds after you turned them on, you could start programming. Your prompt was an interface to a programming language. That magic had begun to fade by the time DOS came to dominate (sure, you can program using batch files, but they're neither as elegant nor sophisticated as any BASIC dialect) and was completely lost by the era of booting directly into graphical operating systems. One of my favourite features about the Web is that it gives you some of that magic back again: thanks to the debugger in a modern browser, you can "tinker" with other people's code once more, right from the same tool you load up every time. (Unfortunately, mobile devices - which have fast become the dominant way for people to use the Internet - have reversed this trend again. Try to View Source on your mobile - if you don't already know how, it's not an easy job!))

Scan of a ring-bound page from a technical manual. The page describes the use of the "INPUT" command, saying "This command is used to let the computer know that it is expecting something to be typed in, for example, the answer to a question". The page goes on to provide a code example of a program which requests the user's age and then says "you look younger than [age] years old.", substituting in their age. The page then explains how it was the use of a variable that allowed this transaction to occur.

In particular, I found myself comparing Werewolves to my first attempt at a text-based adventure. Using what little I'd grokked of programming so far, I'd put together a series of passages (blocks of PRINT statements (In particular, one frustration I remember from my first text-based adventure was that I'd been unable to work around Locomotive BASIC's lack of string escape sequences - not that I yet knew what such a thing would be called - in order to put quote marks inside a quoted string!)) with choices (INPUT statements) that sent the player elsewhere in the story (using, of course, the long-considered-harmful GOTO statement), Choose-Your-Own-Adventure style.

Werewolves was... better.

Photograph of Dan in his mid-teens, with shoulder-length bleached-blonde hair and wearing a t-shirt with a picture of a snarling wolf, sits in front of a running PC (with its beige case open) on which an external modem is precariously balanced.

Werewolves and Wanderer was my first lesson in how to structure a program.

Let's take a look at a couple of segments of code that help illustrate what I mean (here's the full code, if you're interested):

10 REM WEREWOLVES AND WANDERER

20 GOSUB 2600:REM INTIALISE

30 GOSUB 160

40 IF RO<>11 THEN 30

50 PEN 1:SOUND 5,100:PRINT:PRINT "YOU'VE DONE IT!!!":GOSUB 3520:SOUND 5,80:PRINT "THAT WAS THE EXIT FROM THE CASTLE!":SOUND 5,200

60 GOSUB 3520

70 PRINT:PRINT "YOU HAVE SUCCEEDED, ";N$;"!":SOUND 5,100

80 PRINT:PRINT "YOU MANAGED TO GET OUT OF THE CASTLE"

90 GOSUB 3520

100 PRINT:PRINT "WELL DONE!"

110 GOSUB 3520:SOUND 5,80

120 PRINT:PRINT "YOUR SCORE IS";

130 PRINT 3*TALLY+5*STRENGTH+2*WEALTH+FOOD+30*MK:FOR J=1 TO 10:SOUND 5,RND*100+10:NEXT J

140 PRINT:PRINT:PRINT:END

...

2600 REM INTIALISE

2610 MODE 1:BORDER 1:INK 0,1:INK 1,24:INK 2,26:INK 3,18:PAPER 0:PEN 2

2620 RANDOMIZE TIME

2630 WEALTH=75:FOOD=0

2640 STRENGTH=100

2650 TALLY=0

2660 MK=0:REM NO. OF MONSTERS KILLED

...

3510 REM DELAY LOOP

3520 FOR T=1 TO 900:NEXT T

3530 RETURN

Locomotive BASIC had mandatory line numbering. The spacing and gaps (...) have been added for readability/your convenience.

What's interesting about the code above? Well...

The first sets up the game state: initialising the screen (2610), the RNG (2620), and player characteristics (2630 - 2660). This also makes it easy to call it again (e.g. if the player is given the option to "start over"). This subroutine goes on to set up the adventure map (more on that later).

The second starts on line 160: this is the "main game" logic. After it runs, each time, line 40 checks IF RO<>11 THEN 30. This tests whether the player's location (RO) is room 11: if so, they've exited the castle and won the adventure. Otherwise, flow returns to line 30 and the "main game" subroutine happens again. This broken-out loop improving the readability and maintainability of the code. (In a modern programming language, you might use while true or similar for a main game loop, but this requires pushing the "outside" position to the stack... and early BASIC dialects often had strict (and small, by modern standards) limits on stack height that would have made this a risk compared to simply calling a subroutine from one line and then jumping back to that line on the next.)

The game setup gets more interesting still when it comes to setting up the adventure map. Here's how it looks:

2680 REM SET UP CASTLE

2690 DIM A(19,7):CHECKSUM=0

2700 FOR B=1 TO 19

2710 FOR C=1 TO 7

2720 READ A(B,C):CHECKSUM=CHECKSUM+A(B,C)

2730 NEXT C:NEXT B

2740 IF CHECKSUM<>355 THEN PRINT "ERROR IN ROOM DATA":END

...

2840 REM ALLOT TREASURE

2850 FOR J=1 TO 7

2860 M=INT(RND*19)+1

2870 IF M=6 OR M=11 OR A(M,7)<>0 THEN 2860

2880 A(M,7)=INT(RND*100)+100

2890 NEXT J

2910 REM ALLOT MONSTERS

2920 FOR J=1 TO 6

2930 M=INT(RND*18)+1

2940 IF M=6 OR M=11 OR A(M,7)<>0 THEN 2930

2950 A(M,7)=-J

2960 NEXT J

2970 A(4,7)=100+INT(RND*100)

2980 A(16,7)=100+INT(RND*100)

...

3310 DATA 0, 2, 0, 0, 0, 0, 0

3320 DATA 1, 3, 3, 0, 0, 0, 0

3330 DATA 2, 0, 5, 2, 0, 0, 0

3340 DATA 0, 5, 0, 0, 0, 0, 0

3350 DATA 4, 0, 0, 3, 15, 13, 0

3360 DATA 0, 0, 1, 0, 0, 0, 0

3370 DATA 0, 8, 0, 0, 0, 0, 0

3380 DATA 7, 10, 0, 0, 0, 0, 0

3390 DATA 0, 19, 0, 8, 0, 8, 0

3400 DATA 8, 0, 11, 0, 0, 0, 0

3410 DATA 0, 0, 10, 0, 0, 0, 0

3420 DATA 0, 0, 0, 13, 0, 0, 0

3430 DATA 0, 0, 12, 0, 5, 0, 0

3440 DATA 0, 15, 17, 0, 0, 0, 0

3450 DATA 14, 0, 0, 0, 0, 5, 0

3460 DATA 17, 0, 19, 0, 0, 0, 0

3470 DATA 18, 16, 0, 14, 0, 0, 0

3480 DATA 0, 17, 0, 0, 0, 0, 0

3490 DATA 9, 0, 16, 0, 0, 0, 0

Again, I've tweaked this code to improve readability, including adding indention on the loops, "modern-style", and spacing to make the DATA statements form a "table".

What's this code doing?

Map showing the layout of the castle in video game "Werewolves and the Wanderer". Entering from outside the castle, to the West, the player must progress through the ground floor, up the stairwell in the Inner Hallway, into the Lift, and then East to the exit, but there are several opportunities to diverge from this path and e.g. explore the dungeons or various dead ends on the ground or first floors.

Something you might notice is missing is the room descriptions. Arrays in this language are strictly typed: this array can only contain integers and not strings. But there are other reasons: line length limitations would have required trimming some of the longer descriptions. Also, many rooms have dynamic content, usually based on random numbers, which would be challenging to implement in this way.

As a child, I did once try to refactor the code so that an eighth column of data specified the line number to which control should pass to display the room description. That's a bit of a no-no from a "mixing data and logic" perspective, but a cool example of metaprogramming before I even knew it! This didn't work, though: it turns out you can't pass a variable to a Locomotive BASIC GOTO or GOSUB. Boo! (In reality, this was rather unnecessary, because the ON x GOSUB command can - and does, in this program - accept multiple jump points and selects the one referenced by the variable x.)

An experimental program being run that attempts to GOSUB a variable, failing with a syntax error on the relevant line.

Werewolves and Wanderer has many faults (Aside from those mentioned already, other clear faults include: impenetrable controls unless you've been given instuctions (although that was the way at the time); the shopkeeper will penalise you for trying to spend money you don't have, except on food, presumably as a result of programmer laziness; you can lose your flaming torch, but you can't buy spares in advance (you can pay for more, and you lose the money, but you don't get a spare); some of the line spacing is sometimes a little wonky; combat's a bit of a drag; lack of feedback to acknowledge the command you enterted and that it was successful; WHAT'S WITH ALL THE CAPITALS; some rooms don't adequately describe their exits; the map is a bit linear; etc.). But I'm clearly not the only developer whose early skills were honed and improved by this game, or who hold a special place in their heart for it. Just while writing this post, I discovered:

A decade or so later, I'd be taking my first steps as a professional software engineer. A couple more decades later, I'm still doing it.

And perhaps that adventure -the one that's occupied my entire adult life - was facilitated by this text-based one from the 1980s.

Links

Video version of this blog post

My blog post about the top ten videogames that stole my life

My 2010 "purge" of unfinished blog posts, including an addendum to the "top ten video games that stole my life"

Wikipedia article about Tim Hartnell, original author of Werewolves and Wanderer

Complete text of the book Creating Adventure Games on your Computer by Tim Hartnell, courtest of Atari Archives

The Register article about the history of the Amstrad CPC 464 with particular focus on its BASIC implementation

My blog repost "Learn ing BASIC like its 1983" in which I praise microcomputers' feature of "dropping you into" programming as soon as they boot

Scanned copy of the Amstrad CPC 664 ringbound manual, courtesy of CPCWiki; while I started on a CPC 464, I did most of my elementary programming learning on a CPC 664

Scan of Edgar Dijkstra's iconic 1968 paper, "Go To Statement Considered Harmful"

Full source code for the Amstrad CPC version of Werewolves and Wanderer, as published in The Amazing Amstrad Omnibus

Line editors

Link to line 1010 of the program, showing use of the ON x GOSUB syntax

Inform implementation of Werewolves, on IFDB

Graphical reimplementation of Werewolves, by Brigadier Computers

A C# reimplementation with a web interface

Vimeo video showing the C# web implementation being played

SCI Programming forum thread promoting a livestreamed reimplementation as a point-and-click adventure

French blog Retroprogrammez's Applesoft BASIC implementation, with its dynamically-revealed map

A C reimplementation of Werewolves, including a high score table

Rust reimplementation of Werewolves and Wanderer

Online playable version of the Rust reimplementation, via WebAssembly

Python reimplementation, respectably faithful to the original

A Ruby/Python microservices-based implementation of Werewolves, perhaps created as an academic project?