Blog to 5K

This is my 5,000th post on this blog.

Okay, we’re gonna need a whole lot of caveats on the “this is 5,000” claim:

Engage pedantry mode

First, there’s a Ship of Theseus consideration. By “this blog”, I’m referring to what I feel is a continuation (with short breaks) of my personal diary-style writing online from the original “Avatar Diary” on castle.onza.net in the 1990s via “Dan’s Pages” on avangel.com in the 2000s through the relaunch on scatmania.org in 2003 through migrating to danq.me in 2012. If you feel that a change of domain precludes continuation, you might disagree with me. Although you’d be a fool to do so: clearly a blog can change its domain and still be the same blog, right? Back in 2018 I celebrated the 20th anniversary of my first blog post by revisiting how my blog had looked, felt, and changed over the decades, if you’re looking for further reading.

Castle of the Four Winds in early 1999.
These posts were from the 1990s (in case the design didn’t give that away), and despite a change in domain name, I’m counting them. They’re still accessible, via this domain, today!1
Similarly, one might ask if retroactively republishing something that originally went out via a different medium “counts”2.

In late 1999 I ran “Cool Thing of the Day (to do at the University of Wales, Aberystwyth)” as a way of staying connected to my friends back in Preston as we all went our separate ways to study. Initially sent out by email, I later maintained a web page with a log of the entries I’d sent out, but the address wasn’t publicly-circulated. I consider this to be a continuation of the Avatar Diary before it and the predecessor to Dan’s Pages on avangel.com after it, but a pedant might argue that because the content wasn’t born as a blog post, perhaps it’s invalid.

Pedants might also bring up the issue of contemporaneity. In 2004 a server fault resulted in the loss of a significant number of 149 blog posts, of which only 85 have been fully-recovered. Some were resurrected from backups as late as 2012, and some didn’t recover their lost images until later still – this one had some content recovered as late as 2017! If you consider the absence of a pre-2004 post until 2012 a sequence-breaker, that’s an issue. It’s theoretically possible, of course, that other old posts might be recovered and injected, and this post might before the 5,001st, 5,002nd, or later post, in terms of chronological post-date. Who knows!

Then there’s the posts injected retroactively. I’ve written software that, since 2018, has ensured that my geocaching logs get syndicated via my blog when I publish them to one of the other logging sites I use, and I retroactively imported all of my previous logs. These never appeared on my blog when they were written: should they count? What about more egregious examples of necroposting, like this post dated long before I ever touched a keyboard? I’m counting them all.

I’m also counting other kinds of less-public content too. Did you know that I sometimes make posts that don’t appear on my front page, and you have to subscribe e.g. by RSS to get them? They have web addresses – although search engines are discouraged from indexing them – and people find them with or without subscribing. Maybe you should subscribe if you haven’t already?

Note that I’m not counting my comments on my own blog, even though many of them are very long, like this 2,700-word exploration of a jigsaw puzzle geocache, or this 1,000-word analogy for cookie theft via cross-site scripting. I’d like to think that for any post that you’d prefer to rule out, given the issues already described, you’d find a comment that could justifiably have been a post in its own right.[/footnote]

Back to celebration mode

Generating a chart...
If this message doesn't go away, the JavaScript that makes this magic work probably isn't doing its job right: please tell Dan so he can fix it.

I’ve only recently started actively keeping stats on my blogging activity, without which I probably wouldn’t even have noticed that my “5K” milestone was coming up!

Let’s take a look at some of those previous milestone posts:

It takes a pretty special geocache for me to make a video about it (unlike my geohashing expeditions, for which videos aren’t uncommon). The only other one I can think of was one of my own

I absolutely count this as the 5,000th post on this blog.

Dan with a champagne flute, fireworks in the background, points to a screen showing this blog post.
Here’s to the next 5,000!

Footnotes

1 Don’t go look at them. Just don’t. I was a teenager.

2 Via a bit of POSSE and a bit of PESOS I do a lot of crossposting (the diagram in that post is a little out-of-date now, though).

3 Bird & Moon, of course, doesn’t have a subscription feed that I’m aware of, but FreshRSS‘s “killer feature” of XPath scraping makes the same kind of thing possible.

× ×

If you’ve ever found yourself missing the “good old days” of the web, what is it that you miss?

Jason Weill said:

Molly White said:

If you’ve ever found yourself missing the “good old days” of the #web, what is it that you miss? (Interpret “it” broadly: specific websites? types of activities? feelings? etc.) And approximately when were those good old days?

No wrong answers — I’m working on an article and wanted to get some outside thoughts.

I miss the era of personal web sites started out of genuine admiration for something, rather than out of a desire to farm a few advertising pennies

This. You wanted to identify a song? Type some of the lyrics into a search engine and hope that somebody transcribed the same lyrics onto their fansite. You needed to know a fact? Better hope some guru had taken the time to share it, or it’d be time for a trip to the library

Not having information instantly easy to find meant that you really treasured your online discoveries. You’d bookmark the best sites on whatever topics you cared about and feel no awkwardness about emailing a fellow netizen (or signing their guestbook to tell them) about a resource they might like. And then you’d check back, manually, from time to time to see what was new.

The young Web was still magical and powerful, but the effort to payoff ratio was harder, and that made you appreciate your own and other people’s efforts more.

Aberystwyth 1984

This article is a repost promoting content originally published elsewhere. See more things Dan's reposted.

Nigel Lowrie

This promotional video for Aberystwyth University has been kindly archived onto YouTube by one of the undergraduate students who features in it. It was produced in 1984; approximately the same time I first visited Aberystwyth, although it would take until fifteen years later in 1999 for me to become a student there myself.

But the thing is… this 1984 video, shot on VHS in 1984, could absolutely be mistaken at-a-glance for a video shot on an early digital video camera a decade and a half later. The pace of change in Aberystwyth was and is glacial; somehow even the fashion and music seen in Pier Pressure in the video could pass for late-90s!

Anyway: I found the entire video amazingly nostalgic in spite of how far it predates my attendance of the University! Amazing.

Oldest Digital Photo… of Me

Some younger/hipper friends tell me that there was a thing going around on Instagram this week where people post photos of themselves aged 21.

I might not have any photos of myself aged 21! I certainly can’t find any digital ones…

Dan, aged 22, stands in a cluttered flat with his partner Claire and several members of Dan's family.
The closest I can manage is this photo from 23 April 2003, when I was 22 years old.

It must sound weird to young folks nowadays, but prior to digital photography going mainstream in the 2000s (thanks in big part to the explosion of popularity of mobile phones), taking a photo took effort:

  • Most folks didn’t carry their cameras everywhere with them, ready-to-go, so photography was much more-intentional.
  • The capacity of a film only allowed you to take around 24 photos before you’d need to buy a new one and swap it out (which took much longer than swapping a memory card).
  • You couldn’t even look at the photos you’d taken until they were developed, which you couldn’t do until you finished the roll of film and which took at least hours – more-realistically days – and incurred an additional cost.

I didn’t routinely take digital photos until after Claire and I got together in 2002 (she had a digital camera, with which the photo above was taken). My first cameraphone – I was a relatively early-adopter – was a Nokia 7650, bought late that same year.

It occurs to me that I take more photos in a typical week nowadays, than I took in a typical year circa 2000.

Monochrome photo of a toddler, smiling broadly, pointing at the camera.
The oldest analogue photo of me that I own was taken on 2 October 1982, when I was 22 months old.

This got me thinking: what’s the oldest digital photo that exists, of me. So I went digging.

I might not have owned a digital camera in the 1990s, but my dad’s company owned one with which to collect pictures when working on-site. It was a Sony MVC-FD7, a camera most-famous for its quirky use of 3½” floppy disks as media (this was cheap and effective, but meant the camera was about the size and weight of a brick and took about 10 seconds to write each photo from RAM to the disk, during which it couldn’t do anything else).

In Spring 1998, almost 26 years ago, I borrowed it and took, among others, this photo:

Dan aged 17 - a young white man with platinum blonde shoulder-length hair - stands in front of a pink wall, holding up a large, boxy digital camera.
I’m aged 17 in what’s probably the oldest surviving digital photo of me, looking like a refugee from Legoland in 640×480 glorious pixels.

I’m confident a picture of me was taken by a Connectix QuickCam (an early webcam) in around 1996, but I can’t imagine it still exists.

So unless you’re about to comment to tell me know you differently and have an older picture of me: that snap of me taking my own photo with a bathroom mirror is the oldest digital photo of me that exists.

× × ×

[Bloganuary] Road Trip!

This post1 is part of my attempt at Bloganuary 2024.2Today’s prompt is:

Think back on your most memorable road trip.

Runners-up

It didn’t take me long to choose a most-memorable road trip, but first: here’s a trio of runners-up that I considered3:

  1. A midwinter ascent
    On the last day of 2018, Ruth‘s brother Robin and I made a winter ascent of Ben Nevis, the highest mountain in the British Isles. But amazing as the experience was, it perhaps wasn’t as memorable as the endless car journey up there, especially for Robin who was sandwiched between our two children in the back of the car and spent the entire 12-hour journey listening to Little Baby Bum songs on loop.4 Surely a quick route to insanity.
Dan and Robin atop Ben Nevis
Probably should have wiped the snow off the lens.
  1. A childhood move
    Shortly after starting primary school my family and I moved from Aberdeen, Scotland to the North-West of England. At my young age, long car journeys – such as those we’d had to make to view prospective new houses – always seemed interminably boring, but this one was unusually full of excitement and anticipation. The car was filled to the brim with everything we needed most-imminently to start our new lives5, while the removals lorry followed a full day behind us with everything less-essential6. I’m sure that to my parents it was incredibly stressful, but for me it was the beginning of an amazing voyage into the unknown.
A partially-pebbledashed house, number 7, with an old white Ford Escort parked in the driveway.
To this house. In this car.
  1. Live on Earth
    Back in 1999 I bought tickets for myself and two friends for Craig Charles’ appearance in Aberystwyth as part of his Live on Earth tour. My two friends shared a birthday at around the date of the show and had expressed an interest in visiting me, so this seemed like a perfect opportunity. Unfortunately I hadn’t realised that at that very moment one of them was preparing to have their birthday party… 240 miles away in London. In the end all three of us (plus a fourth friend who volunteered to be and overnight/early morning post-nightclub driver) attended both events back to back! A particular highlight came at around 4am we returned from a London nightclub to the suburb where we’d left the car to discover it was boxed in by some inconsiderate parking: we were stuck! So we gathered some strong-looking fellow partygoers… and carried the culprit’s car out of the way7. By that point we decided to go one step further and get back at its owner by moving their car around the corner from where they’d parked it. I reflected on parts of this anecdote back in 2010.

The winner

At somewhere between 500 and 600 road miles each way, perhaps the single longest road journey I’ve ever made without an overnight break was to attend a wedding.

A white couple, bride and groom; she's wearing a white dress and flowers in her hair; he's in a suit with a grey waistcoat and a thistle buttonhole.
The wedding of this lovely couple, whose courtship I expressed joy over the previous year.

The wedding was of my friends Kit and Fi, and took place a long, long way up into Scotland. At the time I (and a few other wedding guests) lived on the West coast of Wales. The journey options between the two might be characterised as follows:

  • the fastest option: a train, followed by a ludicrously expensive plane, followed by a taxi
  • the public transport option: about 16 hours of travel via a variety of circuitous train routes, but at least you get to sleep some of the way
  • drive along a hundred miles of picturesque narrow roads, then three hundred of boring motorways, then another hundred and fifty of picturesque narrow roads

Guess which approach this idiot went for?

Despite having just graduated, I was still living very-much on a student-grade budget. I wasn’t confident that we could afford both the travel to and from the wedding and more than a single night’s accommodation at the other end.

But there were four of us who wanted to attend: me, my partner Claire, and our friends Bryn and Paul. Two of the four were qualified to drive and could be insured on Claire’s car8. This provided an opportunity: we’d make the entire 11-or-so-hour journey by car, with a pair of people sleeping in the back while the other pair drove or navigated!

It was long, and it was arduous, but we chatted and we sang and we saw a frankly ludicrous amount of the A9 trunk road and we made it to and from what was a wonderful wedding on our shoestring budget. It’s almost a shame that the party was so good that the memories of the road trip itself pale, or else this might be a better anecdote! But altogether, entirely a worthwhile, if crazy, exercise.

Footnotes

1 Participating in Bloganuary has now put me into my fifth-longest “daily streak” of blog posts! C-c-c-combo continues!

2 Also, wow: thanks to staying up late with my friend John drinking and mucking about with the baby grand piano in the lobby of the hotel we’re staying at, I might be first to publish a post for today’s Bloganuary!

3 Strangely, all three of the four journeys I’ve considered seem to involve Scotland. Which I suppose shouldn’t be too much of a surprise, given its distance from many of the other places I’ve lived and of course its size (and sometimes-sparse road network).

4 Okay, probably not for the entire journey, but I’m certain it must’ve felt like it.

5 Our cargo included several cats who almost-immediately escaped from their cardboard enclosures and vomited throughout the vehicle.

6 This included, for example, our beds: we spent our first night in our new house camped together in sleeping bags on the floor of what would later become my bedroom, which only added to the sense of adventure in the whole enterprise.

7 It was, fortunately, only a light vehicle, plus our designated driver was at this point so pumped-up on energy drinks he might have been able to lift it by himself!

8 It wasn’t a big car, and in hindsight cramming four people into it for such a long journey might not have been the most-comfortable choice!

× × ×

[Bloganuary] Nostalgia vs Futurism

This post is part of my attempt at Bloganuary 2024. Today’s prompt is:

Do you spend more time thinking about the future or the past? Why?

I probably spend similar amounts of time and energy on both. And that is: a lot!

Thinking about the past

I’m nostalgic as anything. I play retro video games (or even reverse-engineer them and vlog about it). I revisit old blog posts on their anniversary, years later. I recreate old interactive advertisements using modern technologies. When I’m not reading about how the Internet used to be, I’m bringing it back to life by reimagining old protocols in modern spaces and sharing the experience with others1.

Hardware turtle and microcomputer.
Would a nostalgic person reimplement this set-up but in a modern browser? Why yes, yes I would.

Thinking about the future

But I’m also keenly-focussed on the future. I apply a hacker mindset to every new toy that comes my way, asking not “what does it do?” but “what can it be made to do?”. I’ve spent over a decade writing about the future of (tele)working, which faces new challenges today unlike any before. I’m much more-cautious than I was in my youth about jumping on every new tech bandwagon2, but I still try to keep abreast and ahead of developments in my field.

But I also necessarily find myself thinking about the future of our world: the future that our children will grow up in. It’s a scary time, but I’m sure you don’t need me to spell that out for you!

Either way: a real mixture of thinking about the past and the future. It’s possible that I neglect the present?

Footnotes

1 By the way: did you know that much of my blog is accessible over finger (finger @danq.me), Gopher (gopher://danq.me), and Gemini (gemini://danq.me). Grab yourself a copy of Lagrange or your favourite smolweb browser and see for yourself!

2 Exactly how many new JavaScript frameworks can you learn each week, anyway?

×

Wonder Boy

There are video games that I’ve spent many years playing (sometimes on-and-off) before finally beating them for the first time. I spent three years playing Dune II before I finally beat it as every house. It took twice that to reach the end of Ultima Underworld II. But today, I can add a new contender1 to that list.

Today, over thirty-five years after I first played it, I finally completed Wonder Boy.

Entryway to "West View Leisure Centre", decorated in a bright, abstract, 80s style.
I first played Wonder Boy in 1988 at West View Leisure Centre, pictured here mostly as-I-remember-it in a photo by Keith Wright (used under CC BY-SA 2.0 license).

My first experience of the game, in the 1980s, was on a coin-op machine where I’d discovered I could get away with trading the 20p piece I’d been given by my parents to use as a deposit on a locker that week for two games on the machine. I wasn’t very good at it, but something about the cutesy graphics and catchy chip-tune music grabbed my attention and it became my favourite arcade game.

Of all the video games about skateboarding cavemen I’ve ever played, it’s my favourite.

I played it once or twice more when I found it in arcades, as an older child. I played various console ports of it and found them disappointing. I tried it a couple of times in MAME. But I didn’t really put any effort into it until a hotel we stayed at during a family holiday to Paris in October had a bank of free-to-play arcade machines rigged with Pandora’s Box clones so they could be used to play a few thousand different arcade classics. Including Wonder Boy.

A young girl in a pink leopard-print top plays Wonder Boy on an arcade cabinet.
Our eldest was particularly taken with Wonder Boy, and by the time we set off for home at the end of our holiday she’d gotten further than I ever had at it (all without spending a single tenpence).

Off the back of all the fun the kids had, it’s perhaps no surprise that I arranged for a similar machine to be delivered to us as a gift “to the family”2 this Christmas.

A large, arcade-cabinet-shaped present, wrapped in black paper and a red ribbon, stands alongside a Christmas tree.
If you look carefully, you can work out which present it it, despite the wrapping.

And so my interest in the game was awakened and I threw easily a hundred pounds worth of free-play games of Wonder Boy3 over the last few days. Until…

…today, I finally defeated the seventh ogre4, saved the kingdom, etc. It was a hell of a battle. I can’t count how many times I pressed the “insert coin” button on that final section, how many little axes I’d throw into the beast’s head while dodging his fireballs, etc.

So yeah, that’s done, now. I guess I can get back to finishing Wonder Boy: The Dragon’s Trap, the 2017 remake of a 1989 game I adored!5 It’s aged amazingly well!

Footnotes

1 This may be the final record for time spent playing a video game before beating it, unless someday I ever achieve a (non-cheating) NetHack ascension.

2 The kids have had plenty of enjoyment out of it so far, but their time on the machine is somewhat eclipsed by Owen playing Street Fighter II Turbo and Streets of Rage on it and, of course, by my rediscovered obsession with Wonder Boy.

3 The arcade cabinet still hasn’t quite paid for itself in tenpences-saved, despite my grinding of Wonder Boy. Yet.

4 I took to calling the end-of-world bosses “ogres” when my friends and I swapped tips for the game back in the late 80s, and I refuse to learn any different name for them.[footnote], saved Tina[footnote]Apparently the love interest has a name. Who knew?

5 I completed the original Wonder Boy III: The Dragon’s Trap on a Sega Master System borrowed from my friend Daniel back in around 1990, so it’s not a contender for the list either.

× ×

Incredible Doom

I just finished reading Incredible Doom volumes 1 and 2, by Matthew Bogart and Jesse Holden, and man… that was a heartwarming and nostalgic tale!

Softcover bound copies of volumes 1 and 2 of Incredible Doom, on a wooden surface.
Conveniently just-over-A5 sized, each of the two volumes is light enough to read in bed without uncomfortably clonking yourself in the face.

Set in the early-to-mid-1990s world in which the BBS is still alive and kicking, and the Internet’s gaining traction but still lacks the “killer app” that will someday be the Web (which is still new and not widely-available), the story follows a handful of teenagers trying to find their place in the world. Meeting one another in the 90s explosion of cyberspace, they find online communities that provide connections that they’re unable to make out in meatspace.

A "Geek Code Block", printed in a dot-matrix style font, light-blue on black, reads: GU D-- -P+ C+L? U E M+ S-/+ N--- H-- F--(+) !G W++ T R? X?
I loved some of the contemporary nerdy references, like the fact that each chapter page sports the “Geek Code” of the character upon which that chapter focusses.1
So yeah: the whole thing feels like a trip back into the naivety of the online world of the last millenium, where small, disparate (and often local) communities flourished and early netiquette found its feet. Reading Incredible Doom provides the same kind of nostalgia as, say, an afternoon spent on textfiles.com. But it’s got more than that, too.
Partial scan from a page of Incredible Doom, showing a character typing about "needing a solution", with fragments of an IRC chat room visible in background panels.
The user interfaces of IRC, Pine, ASCII-art-laden BBS menus etc. are all produced with a good eye for accuracy, but don’t be fooled: this is a story about humans, not computers. My 9-year-old loved it too, and she’s never even heard of IRC (I hope!).

It touches on experiences of 90s cyberspace that, for many of us, were very definitely real. And while my online “scene” at around the time that the story is set might have been different from that of the protagonists, there’s enough of an overlap that it felt startlingly real and believable. The online world in which I – like the characters in the story – hung out… but which occupied a strange limbo-space: both anonymous and separate from the real world but also interpersonal and authentic; a frontier in which we were still working out the rules but within which we still found common bonds and ideals.

A humorous comic scene from Incredible Doom in which a male character wearing glasses walks with a female character he's recently met and is somewhat intimidated by, playing-out in his mind the possibility that she might be about to stab him. Or kiss him. Or kiss him THEN stab him.
Having had times in the 90s that I met up offline with relative strangers whom I first met online, I can confirm that… yeah, the fear is real!

Anyway, this is all a long-winded way of saying that Incredible Doom is a lot of fun and if it sounds like your cup of tea, you should read it.

Also: shortly after putting the second volume down, I ended up updating my Geek Code for the first time in… ooh, well over a decade. The standards have moved on a little (not entirely in a good way, I feel; also they’ve diverged somewhat), but here’s my attempt:

----- BEGIN GEEK CODE VERSION 6.0 -----
GCS^$/SS^/FS^>AT A++ B+:+:_:+:_ C-(--) D:+ CM+++ MW+++>++
ULD++ MC+ LRu+>++/js+/php+/sql+/bash/go/j/P/py-/!vb PGP++
G:Dan-Q E H+ PS++ PE++ TBG/FF+/RM+ RPG++ BK+>++ K!D/X+ R@ he/him!
----- END GEEK CODE VERSION 6.0 -----

Footnotes

1 I was amazed to discover that I could still remember most of my Geek Code syntax and only had to look up a few components to refresh my memory.

× × × ×

Werewolves and Wanderer

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 life1 was: Werewolves and (the) Wanderer.2

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.3

Front cover of The Amazing Amstrad Omnibus, by Martin Fairbanks, with its bright yellow text on a red background.
Werewolves and Wanderer was adapted for the Amstrad CPC4 by Martin Fairbanks and published in The Amazing Amstrad Omnibus (1985), which is where I first discovered it.
When I first came across the source code to Werewolves, I’d already begun my journey into computer programming. This started alongside my mother and later – when her quantity of free time was not able to keep up with my level of enthusiasm – by myself.

I’d been working my way through the operating manual for our microcomputer, trying to understand it all.5

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.
The ring-bound 445-page A4 doorstep of a book quickly became adorned with my pencilled-in notes, the way a microcomputer manual ought to be. It’s strange to recall that there was a time that beginner programmers still needed to be reminded to press [ENTER] at the end of each line.
And even though I’d typed-in dozens of programs before, both larger and smaller, it was Werewolves that finally helped so many key concepts “click” for me.

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 statements6) 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.
By the time I was the model of a teenage hacker, I’d been writing software for years. Most of it terrible.

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 code for “what to do when you win the game” is very near the top. “Winning” is the default state. The rest of the adventure exists to obstruct that. In a language with enforced line numbering and no screen editor7, it makes sense to put fixed-length code at the top… saving space for the adventure to grow below.
  • Two subroutines are called (the GOSUB statements):
    • The first sets up the game state: initialising the screen (2610), the RNG (2620), and player characteristics (26302660). 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.8
  • A common subroutine is the “delay loop” (line 3520). It just counts to 900! On a known (slow) processor of fixed speed, this is a simpler way to put a delay in than relying on a real-time clock.

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?

  • Line 2690 defines an array (DIM) with two dimensions9 (19 by 7). This will store room data, an approach that allows code to be shared between all rooms: much cleaner than my first attempt at an adventure with each room having its own INPUT handler.
  • The two-level loop on lines 2700 through 2730 populates the room data from the DATA blocks. Nowadays you’d probably put that data in a separate file (probably JSON!). Each “row” represents a room, 1 to 19. Each “column” represents the room you end up at if you travel in a given direction: North, South, East, West, Up, or Down. The seventh column – always zero – represents whether a monster (negative number) or treasure (positive number) is found in that room. This column perhaps needn’t have been included: I imagine it’s a holdover from some previous version in which the locations of some or all of the treasures or monsters were hard-coded.
  • The loop beginning on line 2850 selects seven rooms and adds a random amount of treasure to each. The loop beginning on line 2920 places each of six monsters (numbered -1 through -6) in randomly-selected rooms. In both cases, the start and finish rooms, and any room with a treasure or monster, is ineligible. When my 8-year-old self finally deciphered what was going on I was awestruck at this simple approach to making the game dynamic.
  • Rooms 4 and 16 always receive treasure (lines 29702980), replacing any treasure or monster already there: the Private Meeting Room (always worth a diversion!) and the Treasury, respectively.
  • Curiously, room 9 (the lift) defines three exits, even though it’s impossible to take an action in this location: the player teleports to room 10 on arrival! Again, I assume this is vestigal code from an earlier implementation.
  • The “checksum” that’s tested on line 2740 is cute, and a younger me appreciated deciphering it. I’m not convinced it’s necessary (it sums all of the values in the DATA statements and expects 355 to limit tampering) though, or even useful: it certainly makes it harder to modify the rooms, which may undermine the code’s value as a teaching aid!
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.
By the time I was 10, I knew this map so well that I could draw it perfectly from memory. I almost managed the same today, aged 42. That memory’s buried deep!

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!10

An experimental program being run that attempts to GOSUB a variable, failing with a syntax error on the relevant line.
In hindsight, I could have tested the functionality before I refactored with a very simple program, but I was only around 10 or 11 and still had lots to learn!

Werewolves and Wanderer has many faults11. 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.

Footnotes

1 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?

2 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.

3 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.

4 The CPC’s got a fascinating history in its own right, but you can read that any time.

5 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!)

6 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!

7 “Screen editors” is what we initially called what you’d nowadays call a “text editor”: an application that lets you see a page of text at the same time, move your cursor about the place, and insert text wherever you feel like. It may also provide features like copy/paste and optional overtyping. Screen editors require more resources (and aren’t suitable for use on a teleprinter) compared to line editors, which preceeded them. Line editors only let you view and edit a single line at a time, which is how most of my first 6 years of programming was done.

8 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.

9 A neat feature of Locomotive BASIC over many contemporary and older BASIC dialects was its support for multidimensional arrays. A common feature in modern programming languages, this language feature used to be pretty rare, and programmers had to do bits of division and modulus arithmetic to work around the limitation… which, I can promise you, becomes painful the first time you have to deal with an array of three or more dimensions!

10 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.

11 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.

× × × × ×

Satoru Iwata’s first commercial game has a secret

This article is a repost promoting content originally published elsewhere. See more things Dan's reposted.

Codex (YouTube)

This was a delightful vlog. It really adds personality to what might otherwise have been a story only about technology and history.

I subscribed to Codex’s vlog like… four years ago? He went dark soon afterwards, but thanks to the magic of RSS, I got notified as soon as he came back from his hiatus.

Yesterday’s Internet Today! (Woo DM 2023)

The week before last I had the opportunity to deliver a “flash talk” of up to 4 minutes duration at a work meetup in Vienna, Austria. I opted to present a summary of what I’ve learned while adding support for Finger and Gopher protocols to the WordPress installation that powers DanQ.me (I also hinted at the fact that I already added Gemini and Spring ’83 support, and I’m looking at other protocols). If you’d like to see how it went, you can watch my flash talk here or on YouTube.

If you love the idea of working from wherever-you-are but ocassionally meeting your colleagues in person for fabulous in-person events with (now optional) flash talks like this, you might like to look at Automattic’s recruitment pages

The presentation is a shortened, Automattic-centric version of a talk I’ll be delivering tomorrow at Oxford Geek Nights #53; so if you’d like to see it in-person and talk protocols with me over a beer, you should come along! There’ll probably be blog posts to follow with a more-detailed look at the how-and-why of using WordPress as a CMS not only for the Web but for a variety of zany, clever, retro, and retro-inspired protocols down the line, so perhaps consider the video above a “teaser”, I guess?

Why Did Media Players Look Like That?

You don’t really see it any more, but: if you downloaded some media player software a couple of decades ago, it’d probably appear in a weird-shaped window, and I’ve never understood why.

Composite screenshot showing Sonique, Windows Media Player and BSplayer music players, among others, in a variety of windows that are either unusually-shaped, look like conventional Hi-Fis, or both.Mostly, these designs are… pretty ugly. And for what? It’s also worth noting that this kind of design can be found in all kinds of applications, in media players that it was almost ubiquitous.

You might think that they’re an overenthusiastic kind of skeuomorphic design: people trying to make these players look like their physical analogues. But hardware players were still pretty boxy-looking at this point, either because of the limitations of their data storage1. By the time flash memory-based portable MP3 players became commonplace their design was copying software players, not the other way around.

Composite screenshot showing Windows Media Player, the (old) iTunes companion widget, KMPlayer, and other media players. All of them have unusually-shaped windows, often with organic corners.

So my best guess is that these players were trying to stand out as highly-visible. Like: they were things you’d want to occupy a disproportionate amount of desktop space. Maybe other people were listening to music differently than me… but for me, back when screen real estate was at such a premium2, a music player’s job was to be small, unintrusive, and out-of-the-way.

WinAmp music player in minified mode: just a sliver of a music player, small, showing just back/forward/play/pause/stop controls, play time, and a mini-equaliser. The timer shows we're 3 seconds into a track.
I used to run Winamp in its very-smallest minified size, tucked up at the top of the screen, using the default skin or one that made it even less-obtrusive.

It’s a mystery to me why anybody would (or still does) make media player software or skins for them that eat so much screen space, frequently looking ugly while they do so, only to look like a hypothetical hardware device that wouldn’t actually become commonplace until years after this kind of player design premiered!

Maybe other people listened to music on their computer differently from me: putting it front and centre, not using their computer for other tasks at the same time. And maybe for these people the choice of player and skin was an important personalisation feature; a fashion statement or a way to show off their personal identity. But me? I didn’t get it then, and I don’t get it now. I’m glad that this particular trend seems to have died and windows are, for the most part, rounded rectangles once more… even for music player software!

Footnotes

1 A walkman, minidisc player, or hard drive-based digital music device is always going to look somewhat square because of what’s inside.

2 I “only” had 1600 × 1200 (UXGA) pixels on the very biggest monitor I owned before I went widescreen, and I spent a lot of time on monitors at lower resolutions e.g. 1024 × 768 (XGA); on such screens, wasting space on a music player when you’re mostly going to be listening “in the background” while you do something else seemed frivolous.

× × ×

Finger Portal to WordPress Blog

Finger Primer

The finger protocol, first standardised way back in 1977, is a lightweight directory system for querying resources on a local or remote shared system. Despite barely being used today, it’s so well-established that virtually every modern desktop operating system – Windows, MacOS, Linux etc. – comes with a copy of finger, giving it a similar ubiquity to web browsers! (If you haven’t yet, give it a go.)

If you were using a shared UNIX-like system in the 1970s through 1990s, you might run finger to see who else was logged on at the same time as you, finger chris to get more information about Chris, or finger alice@example.net to look up the details of Alice on the server example.net. Its ability to transcend the boundaries of different systems meant that it was, after a fashion, an example of an early decentralised social network!

I first actively used finger when I was a student at Aberystwyth University. The shared central computers osfa and osfb supported it in what was a pretty typical way: users could add a .plan and/or .project file to their home directory and the contents of these would be output to anybody using finger to look up that user, along with other information like what department they belonged to. I’m simulating from memory so this won’t be remotely accurate, but broadly speaking it looked a little like this –

$ finger dlq9@aber.ac.uk
Login: dlq9                           Name: Dan Q
Directory: /users/9/d/dlq9      Department: Computer Science

Project:
Working on my BEng Software Engineering.

Plan:
    _______
---'   ____)____
          ______)  Finger me!
       _____)
      (____)
---.__(___)

It’s not just about a directory of people, though: you could finger printers to see what their queues were like, finger a time server to ask what time it was, finger a vending machine to see what drinks it had available… even finger for a weather forecast where you are (this one still works as shown below; try it for your own location!) –

$ finger oxford@graph.no
        -= Meteogram for Oxford, Oxfordshire, England, United Kingdom =-
 'C                                                                   Rain (mm)
 12
 11
 10                                                         ^^^=--=--
  9^^^                                                   ===
  8   ^^^===      ======                              ^^^
  7         ======      ===============^^^         =--
  6                                       =--=-----
  5
  4
  3        |  |  |  |  |  |  |                                        1 mm
    17 18 19 20 21 22 23 18/11 02 03 04 05 06 07_08_09_10_11_12_13_14 Hour

     W  W  W  W  W  W  W  W  W  W  W  W  W  W  W  W  W  W  W  W  W  W Wind dir.
     6  6  7  7  7  7  7  7  6  6  6  5  5  4  4  4  4  5  6  6  5  5 Wind(m/s)

Legend left axis:   - Sunny   ^ Scattered   = Clouded   =V= Thunder   # Fog
Legend right axis:  | Rain    ! Sleet       * Snow

If you’d just like to play with finger, then finger.farm is a great starting point. They provide free finger hosting and they’re easy to use (try finger dan@finger.farm to find me!). But I had something bigger in mind…

Fingering WordPress

What if you could finger my blog. I.e. if you ran finger blog@danq.me you’d see a summary of some of my recent posts, along with additional addresses you could finger to read the full content of each. This could be the world’s first finger-to-WordPress gateway; y’know, for if you thought the world needed such a thing. Here’s how I did it:

  1. Installed efingerd; I’m using the Debian binaries.
  2. Opened a hole in the firewall on port 79 so the outside world could access it (ufw allow 1965; utf reload).
  3. The default configuration for efingerd acts like a “typical” finger server, but it’s highly programmable to make it “smarter”. I:
    1. Blanked /etc/efingerd/list to prevent any output from “listing” the server (finger @danq.me).
    2. Replaced the contents of /etc/efingerd/list and /etc/efingerd/nouser(which are run when a request matches, or doesn’t match, a user account name) with a call to my script: /usr/local/bin/finger-to-wordpress "$3". $3 holds the username that was requested, so we can act on it.
    3. Created /usr/local/bin/finger-to-wordpressa Ruby program that either (a) lists a selection of posts or (b) returns a specific post (stripping the HTML tags)

Screenshot showing this blog rendered as plain text as the result of running finger blog@danq.me at a Linux terminal.

In future, I might use some extra tags or metadata to enhance finger-friendly WordPress posts. The infrastructure’s in place already (I already have tags that I use to make certain kinds of content available only via certain media – shh!). You might rightly as what the point is of this entire enterprise, of course, and you’d be well within your rights to ask such a question. But I think the best answer available is “because Dan”.

Screenshot showing this blog post rendered as plain text as the result of running finger wp-finger@danq.me at a Linux terminal.

If you want to see my blog in a whole new way, give it a go: run finger blog@danq.me on your computer and follow the instructions.

× ×