The Elegance of the ASCII Table

Duration

Podcast Version

This post is also available as a podcast. Listen here, download for later, or subscribe wherever you consume podcasts.

If you’ve been a programmer or programming-adjacent nerd1 for a while, you’ll have doubtless come across an ASCII table.

An ASCII table is useful. But did you know it’s also beautiful and elegant.

Frames from the scene in The Martian where Mark Watney discovers Beth Johanssen's ASCII table.
Even non-programmer-adjacent nerds may have a cultural awareness of ASCII thanks to books and films like The Martian2.
ASCII‘s still very-much around; even if you’re transmitting modern Unicode3 the most-popular encoding format UTF-8 is specifically-designed to be backwards-compatible with ASCII! If you decoded this page as ASCII you’d get the gist of it… so long as you ignored the garbage characters at the end of this sentence! 😁

History

ASCII was initially standardised in X3.4-1963 (which just rolls off the tongue, doesn’t it?) which assigned meanings to 100 of the potential 128 codepoints presented by a 7-bit4 binary representation: that is, binary values 0000000 through 1111111:

Scan of a X3.4-1963 ASCII table.
Notably absent characters in this first implementation include… the entire lowercase alphabet! There’s also a few quirks that modern ASCII fans might spot, like the curious “up” and “left” arrows at the bottom of column 101____ and the ACK and ESC control codes in column 111____.

If you’ve already guessed where I’m going with this, you might be interested to look at the X3.4-1963 table and see that yes, many of the same elegant design choices I’ll be talking about later already existed back in 1963. That’s really cool!

Table

In case you’re not yet intimately familiar with it, let’s take a look at an ASCII table. I’ve colour-coded some of the bits I think are most-beautiful:

ASCII table with Decimal, Hex, and Character columns.That table only shows decimal and hexadecimal values for each character, but we’re going to need some binary too, to really appreciate some of the things that make ASCII sublime and clever.

Control codes

The first 32 “characters” (and, arguably, the final one) aren’t things that you can see, but commands sent between machines to provide additional instructions. You might be familiar with carriage return (0D) and line feed (0A) which mean “go back to the beginning of this line” and “advance to the next line”, respectively5. Many of the others don’t see widespread use any more – they were designed for very different kinds of computer systems than we routinely use today – but they’re all still there.

32 is a power of two, which means that you’d rightly expect these control codes to mathematically share a particular “pattern” in their binary representation with one another, distinct from the rest of the table. And they do! All of the control codes follow the pattern 00_____: that is, they begin with two zeroes. So when you’re reading 7-bit ASCII6, if it starts with 00, it’s a non-printing character. Otherwise it’s a printing character.

Not only does this pattern make it easy for humans to read (and, with it, makes the code less-arbitrary and more-beautiful); it also helps if you’re an ancient slow computer system comparing one bit of information at a time. In this case, you can use a decision tree to make shortcuts.

Two rolls of punched paper tape.
That there’s one exception in the control codes: DEL is the last character in the table, represented by the binary number 1111111. This is a historical throwback to paper tape, where the keyboard would punch some permutation of seven holes to represent the ones and zeros of each character. You can’t delete holes once they’ve been punched, so the only way to mark a character as invalid was to rewind the tape and punch out all the holes in that position: i.e. all 1s.

Space

The first printing character is space; it’s an invisible character, but it’s still one that has meaning to humans, so it’s not a control character (this sounds obvious today, but it was actually the source of some semantic argument when the ASCII standard was first being discussed).

Putting it numerically before any other printing character was a very carefully-considered and deliberate choice. The reason: sorting. For a computer to sort a list (of files, strings, or whatever) it’s easiest if it can do so numerically, using the same character conversion table as it uses for all other purposes7. The space character must naturally come before other characters, or else John Smith won’t appear before Johnny Five in a computer-sorted list as you’d expect him to.

Being the first printing character, space also enjoys a beautiful and memorable binary representation that a human can easily recognise: 0100000.

Numbers

The position of the Arabic numbers 0-9 is no coincidence, either. Their position means that they start with zero at the nice round binary value 0110000 (and similarly round hex value 30) and continue sequentially, giving:

Binary Hex Decimal digit (character)
011 0000 30 0
011 0001 31 1
011 0010 32 2
011 0011 33 3
011 0100 34 4
011 0101 35 5
011 0110 36 6
011 0111 37 7
011 1000 38 8
011 1001 39 9

The last four digits of the binary are a representation of the value of the decimal digit depicted. And the last digit of the hexadecimal representation is the decimal digit. That’s just brilliant!

If you’re using this post as a way to teach yourself to “read” binary-formatted ASCII in your head, the rule to take away here is: if it begins 011, treat the remainder as a binary representation of an actual number. You’ll probably be right: if the number you get is above 9, it’s probably some kind of punctuation instead.

Shifted Numbers

Subtract 0010000 from each of the numbers and you get the shifted numbers. The first one’s occupied by the space character already, which is a shame, but for the rest of them, the characters are what you get if you press the shift key and that number key at the same time.

“No it’s not!” I hear you cry. Okay, you’re probably right. I’m using a 105-key ISO/UK QWERTY keyboard and… only four of the nine digits 1-9 have their shifted variants properly represented in ASCII.

That, I’m afraid, is because ASCII was based not on modern computer keyboards but on the shifted positions of a Remington No. 2 mechanical typewriter – whose shifted layout was the closest compromise we could find as a standard at the time, I imagine. But hey, you got to learn something about typewriters today, if that’s any consolation.

A Remington Portable No. 3 typewriter.
Bonus fun fact: early mechanical typewriters omitted a number 1: it was expected that you’d use the letter I. That’s fine for printed work, but not much help for computer-readable data.

Letters

Like the numbers, the letters get a pattern. After the @-symbol at 1000000, the uppercase letters all begin 10, followed by the binary representation of their position in the alphabet. 1 = A = 1000001, 2 = B = 1000010, and so on up to 26 = Z = 1011010. If you can learn the numbers of the positions of the letters in the alphabet, and you can count in binary, you now know enough to be able to read any ASCII uppercase letter that’s been encoded as binary8.

And once you know the uppercase letters, the lowercase ones are easy too. Their position in the table means that they’re all exactly 0100000 higher than the uppercase variants; i.e. all the lowercase letters begin 11! 1 = a = 1100001, 2 = b = 1100010, and 26 = z = 1111010.

If you’re wondering why the uppercase letters come first, the answer again is sorting: also the fact that the first implementation of ASCII, which we saw above, was put together before it was certain that computer systems would need separate character codes for upper and lowercase letters (you could conceive of an alternative implementation that instead sent control codes to instruct the recipient to switch case, for example). Given the ways in which the technology is now used, I’m glad they eventually made the decision they did.

Beauty

There’s a strange and subtle charm to ASCII. Given that we all use it (or things derived from it) literally all the time in our modern lives and our everyday devices, it’s easy to think of it as just some arbitrary encoding.

But the choices made in deciding what streams of ones and zeroes would represent which characters expose a refined logic. It’s aesthetically pleasing, and littered with historical artefacts that teach us a hidden history of computing. And it’s built atop patterns that are sufficiently sophisticated to facilitate powerful processing while being coherent enough for a human to memorise, learn, and understand.

Footnotes

1 Programming-adjacent? Yeah. For example, geocachers who’ve ever had to decode a puzzle-geocache where the coordinates were presented in binary (by which I mean: a binary representation of ASCII) are “programming-adjacent nerds” for the purposes of this discussion.

2 In both the book and the film, Mark Watney divides a circle around the recovered Pathfinder lander into segments corresponding to hexadecimal digits 0 through F to allow the rotation of its camera (by operators on Earth) to transmit pairs of 4-bit words. Two 4-bit words makes an 8-bit byte that he can decode as ASCII, thereby effecting a means to re-establish communication with Earth.

3 Y’know, so that you can type all those emoji you love so much.

4 ASCII is often thought of as an 8-bit code, but it’s not: it’s 7-bit. That’s why virtually every ASCII message you see starts every octet with a zero. 8-bits is a convenient number for transmission purposes (thanks mostly to being a power of two), but early 8-bit systems would be far more-likely to use the 8th bit as a parity check, to help detect transmission errors. Of course, there’s also nothing to say you can’t just transmit a stream of 7-bit characters back to back!

5 Back when data was sent to teletype printers these two characters had a distinct different meaning, and sometimes they were so slow at returning their heads to the left-hand-side of the paper that you’d also need to send a few null bytes e.g. 0D 0A 00 00 00 00 to make sure that the print head had gotten settled into the right place before you sent more data: printers didn’t have memory buffers at this point! For compatibility with teletypes, early minicomputers followed the same carriage return plus line feed convention, even when outputting text to screens. Then to maintain backwards compatibility with those systems, the next generation of computers would also use both a carriage return and a line feed character to mean “next line”. And so, in the modern day, many computer systems (including Windows most of the time, and many Internet protocols) still continue to use the combination of a carriage return and a line feed character every time they want to say “next line”; a redundancy build for a chain of backwards-compatibility that ceased to be relevant decades ago but which remains with us forever as part of our digital heritage.

6 Got 8 binary digits in front of you? The first digit is probably zero. Drop it. Now you’ve got 7-bit ASCII. Sorted.

7 I’m hugely grateful to section 13.8 of Coded Character Sets, History and Development by Charles E. Mackenzie (1980), the entire text of which is available freely online, for helping me to understand the importance of the position of the space character within the ASCII character set. While most of what I’ve written in this blog post were things I already knew, I’d never fully grasped its significance of the space character’s location until today!

8 I’m sure you know this already, but in case you’re one of today’s lucky 10,000 to discover that the reason we call the majuscule and minuscule letters “uppercase” and “lowercase”, respectively, dates to 19th century printing, when moveable type would be stored in a box (a “type case”) corresponding to its character type. The “upper” case was where the capital letters would typically be stored.

× × × × ×

Good Food, Bad Authorisation

I was browsing (BBC) Good Food today when I noticed something I’d not seen before: a “premium” recipe, available on their “app only”:

Screenshot showing recipes, one of which is labelled "App only" and "Premium".

I clicked on the “premium” recipe and… it looked just like any other recipe. I guess it’s not actually restricted after all?

Just out of curiosity, I fired up a more-vanilla web browser and tried to visit the same page. Now I saw an overlay and modal attempting1 to restrict access to the content:

Overlay attempting to block content to the page beneath, saying "Try 1 year for just £9.99 and save 81%".

It turns out their entire effort to restrict access to their premium content… is implemented in client-side JavaScript. Even when I did see the overlay and not get access to the recipe, all I needed to do was open my browser’s debugger and run document.body.classList.remove('tp-modal-open'); for(el of document.querySelectorAll('.tp-modal, .tp-backdrop')) el.remove(); and all the restrictions were lifted.

What a complete joke.

Why didn’t I even have to write my JavaScript two-liner to get past the restriction in my primary browser? Because I’m running privacy-protector Ghostery, and one of the services Ghostery blocks by-default is one called Piano. Good Food uses Piano to segment their audience in your browser, but they haven’t backed that by any, y’know, actual security so all of their content, “premium” or not, is available to anybody.

I’m guessing that Immediate Media (who bought the BBC Good Food brand a while back and have only just gotten around to stripping “BBC” out of the name) have decided that an ad-supported model isn’t working and have decided to monetise the site a little differently2. Unfortunately, their attempt to differentiate premium from regular content was sufficiently half-hearted that I barely noticed that, too, gliding through the paywall without even noticing were it not for the fact that I wondered why there was a “premium” badge on some of their recipes.

Screenshot from OpenSourceFood.com, circa 2007.
You know what website I miss? OpenSourceFood.com. It went downhill and then died around 2016, but for a while it was excellent.

Recipes probably aren’t considered a high-value target, of course. But I can tell you from experience that sometimes companies make basically this same mistake with much more-sensitive systems. The other year, for example, I discovered (and ethically disclosed) a fault in the implementation of the login forms of a major UK mobile network that meant that two-factor authentication could be bypassed entirely from the client-side.

These kinds of security mistakes are increasingly common on the Web as we train developers to think about the front-end first (and sometimes, exclusively). We need to do better.

Footnotes

1 The fact that I could literally see the original content behind the modal was a bit of a giveaway that they’d only hidden it, not actually protected it in any way.

2 I can see why they’d think that: personally, I didn’t even know there were ads on the site until I did the experiment above: turns out I was already blocking them, too, along with any anti-ad-blocking scripts that might have been running alongside.

× × ×

Vmail via FreshRSS

It’s time for… Dan Shares Yet Another FreshRSS XPath Scraping Recipe!

Vmail

I’m a huge fan of the XPath scraping feature of FreshRSS, my favourite feed reader (and one of the most important applications in my digital ecosystem). I’ve previously demonstrated how to use the feature to subscribe to Forward, reruns of The Far Side, and new The Far Side content, despite none of those sites having “official” feeds.

Signup form for VMail from Vole.WTF
Sure, I could have used my selfhosted OpenTrashMail server to convert email into RSS, but I figured XPath scraping would be more-elegant…

Vmail is cool. It’s vole.wtf’s (of ARCC etc. fame) community newsletter, and it’s as batshit crazy as you’d expect if you were to get the kinds of people who enjoy that site and asked them all to chip in on a newsletter.

Totes bonkers.

But email’s not how I like to consume this kind of media. So obviously, I scraped it.

Screenshot showing VMail subscription in FreshRSS
I’m not a monster: I want Vmail’s stats to be accurate. So I signed up with an unmonitored OpenTrashMail account as well. I just don’t read it (except for the confirmation link email). It actually took me a few attempts because there seems to be some kind of arbitrary maximum length validation on the signup form. But I got there in the end.

Recipe

Want to subscribe to Vmail using your own copy of FreshRSS? Here’s the settings you’re looking for –

  • Type of feed source: HTML + XPath (Web scraping)
  • XPath for finding news items: //table/tbody/tr
    It’s just a table with each row being a newsletter; simple!
  • XPath for item title: descendant::a
  • XPath for item content: .
  • XPath for item link (URL): descendant::a/@href
  • XPath for item date: descendant::td[1]
  • Custom date/time format: d M *y
    The dates are in a format that’s like 01 May ’24 – two-digit days with leading zeros, three-letter months, and a two-digit year preceded by a curly quote, separated by spaces. That curl quote screws up PHP’s date parser, so we have to give it a hint.
  • XPath for unique item ID: descendant::th
    Optional, but each issue’s got its own unique ID already anyway; we might as well use it!
  • Article CSS selector on original website: #vmail
    Optional, but recommended: this option lets you read the entire content of each newsletter without leaving FreshRSS.

So yeah, FreshRSS continues to be amazing. And lately it’s helped me keep on top of the amazing/crazy of vole.wtf too.

× ×

A Pressure Cooker for Tea

Duration

Podcast Version

This post is also available as a podcast. Listen here, download for later, or subscribe wherever you consume podcasts.

I’m not a tea-drinker1. But while making a cuppa for Ruth this morning, a thought occurred to me and I can’t for a moment believe that I’m the first person to think of it:

What about a pressure-cooker, but for tea?2

Hear me out.

A pressure cooker whose digital display reads 'tea'.
Modern digital pressure cookers have a lot of different settings and modes, but ‘tea’ is somehow absent?

It’s been stressed how important it is that the water used to brew the tea is 100℃, or close to it possible. That’s the boiling point of water at sea level, so you can’t really boil your kettle hotter than that or else the water runs away to pursue a new life as a cloud.

That temperature is needed to extract the flavours, apparently3. And that’s why you can’t get a good cup of tea at high altitudes, I’m told: by the time you’re 3000 metres above sea level, water boils at around 90℃ and most British people wilt at their inability to make a decent cuppa4.

It’s a question of pressure, right? Increase the pressure, and you increase the boiling point, allowing water to reach a higher temperature before it stops being a liquid and starts being a gas. Sooo… let’s invent something!

Illustration showing key components of a pressure-tea maker.

I’m thinking a container about the size of a medium-sized Thermos flask or a large keep-cup – you need thick walls to hold pressure, obviously – with a safety valve and a heating element, like a tiny version of a modern pressure cooker. The top half acts as the lid, and contains a compartment into which you put your teabag or loose leaves (optionally in an infuser). After being configured from the front panel, the water gets heated to a specified temperature – which can be above the ambient boiling point of water owing to the pressurisation – at which point the tea is released from the upper half. The temperature is maintained for a specified amount of time and then the user is notified so they can release the pressure, open the top, lift out the inner cup, remove the teabag, and enjoy their beverage.

This isn’t just about filling the niche market of “dissatisfied high-altitude tea drinkers”. Such a device would also be suitable for other folks who want a controlled tea experience. You could have it run on a timer and make you tea at a particular time, like a teasmade. You can set the temperature lower for a controlled brew of e.g. green tea at 70℃. But there’s one other question that a device like this might have the capacity to answer:

What is the ideal temperature for making black tea?

We’re told that it’s 100℃, but that’s probably an assumption based on the fact that that’s as hot as your kettle can get water to go, on account of physics. But if tea is bad when it’s brewed at 90℃ and good when it’s brewed at 100℃… maybe it’s even better when it’s brewed at 110℃!

A modern pressure cooker can easily maintain a liquid water temperature of 120℃, enabling excellent extraction of flavour into water (this is why a pressure cooker makes such excellent stock).

A mug of tea held by the handle.
It’s possible that the perfect cup of tea hasn’t been invented yet, owing to limitations in the boiling point of water.

I’m not the person to answer this question, because, as I said: I’m not a tea drinker. But surely somebody’s tried this5? It shouldn’t be too hard to retrofit a pressure cooker lid with a sealed compartment that releases, even if it’s just on a timer, to deposit some tea into some superheated water?

Because maybe, just maybe, superheated water makes better tea. And if so, there’s a possible market for my proposed device.

Footnotes

1 I probably ought to be careful confessing to that or they’ll strip my British citizenship.

2 Don’t worry, I know better than to suggest air-frying a cup of ta. What kind of nutter would do that?

3 Again, please not that I’m not a tea-drinker so I’m not really qualified to comment on the flavour of tea at all, let alone tea that’s been brewed at too-low a temperature.

4 Some high-altitude tea drinkers swear by switching from black tea to green tea, white tea, or oolong, which apparently release their aromatics at lower temperatures. But it feels like science, not compromise, ought to be the solution to this problem.

5 I can’t find the person who’s already tried this, if they exist, but maybe they’re out there somewhere?

× × ×

Building a Secret Cabinet

We’ve recently had the attics of our house converted, and I moved my bedroom up to one of the newly-constructed rooms.

To make the space my own, I did a little light carpentry up there: starting with a necessary reshaping of the doors, then moving on to shelving and eventually… a secret cabinet!

I’d love to tell you about how I built it: but first, a disclaimer! I am a software engineer, and with good reason. Letting me near a soldering iron is ill-advised. Letting me use a table saw is tempting fate.

Letting me teach you anything about how you should use a soldering iron or a table saw is, frankly, asking for trouble.

A spirit level on an unfinished shelf, under a window and beneath an uncarpeted floor.
Knowing that I’d been short on shelf space in my old bedroom, I started work on fitting shelves for my new bedroom before the carpet had even arrived.

Building a secret cabinet wasn’t part of my plan, but came about naturally after I got started. I’d bought a stack of pine planks and – making use of Ruth’s table saw – cut them to squarely fit beneath each of the two dormer windows1. While sanding and oiling the wood I realised that I had quite a selection of similarly-sized offcuts and found myself wondering if I could find a use for them.

Dan drinks a 0% alcohol beer in front of three upright planks of wood.
The hardest part of sanding and oiling wood on the hottest day of the year is all the beer breaks you have to take. Such a drag.

I figured I had enough lumber to insert a small cabinet into one of the bookshelves, and that got me thinking… what about if it were a secret cabinet, disguised as books unless you knew where to look. Or to go one step further: what if it had some kind of electronic locking mechanism that could be triggered from somewhere else in the room2.

Magpie decal 'perched' on a light switch.
There are other ways in which I’ve made my new room distinctly-“mine” – like the pair of magpies – but probably the secret cabinet is the most-distinctive.

Not wanting to destroy a stack of real books, which is the traditional way to get a collection of book spines for the purpose of decorating a “fake bookshelf” panel3, I looked online and discovered the company that made the fake book spines used at the shop of my former employer. They looked ideal: carefully shaped and painted panels with either an old-school or contemporary look.

Buuut, they don’t seem to be well-equipped for short runs and are doubtless pricey, so I looked elsewhere and found the eBay presence of Beatty Lockey Antiques in Loewstof. They’d acquired a stack of them second-hand from the set of Netflix’s The School for Good and Evil.4

(By the way: at time of writing they’ve still got a few panels left, if you want to make your own…)

I absolutely must sing the praises of Brad at Beatty Lockey Antiques who, after the first delivery of fake book fronts was partially-damaged in transit, was super quick about helping me find the closest-available equivalent (I’d already measured-up based on the one I’d thought I was getting) and sent a replacement.

The cabinet is just a few bits of wood glued together and reinforced with L-shaped corner braces, with a trio of thin strips – made from leftover architrave board – attached using small brass hinges. The fake book fronts are stuck to the strips using double-sided mounting tape left over from installing a bathroom mirror. A simple magnetic clasp holds the door shut when pushed closed5, and the hinges are inclined to “want” the door to stand half-open, which means it only needs a gentle push away from the magnetic catch to swing it open.

Circuit diagram showing a Raspberry Pi Zero W connected to two relays, each connecting 12V DC to a latch solenoid.
The wiring is uncomplicated enough that even I – a self-confessed software engineer – could manage it. Note the separate power supply: those solenoids can draw a full 1 amp in a “surge” that’s enough to give a little Raspberry Pi Zero a Bad Day if you try to power it directly from the computer (there might be some capacitor-based black magic that I don’t understand that could have made this easier, I suppose)!

I mounted a Raspberry Pi Zero W into a rear corner inside the cabinet6, and wired it up via a relay to what was sold to me as a “large push-pull solenoid”, then began experimenting with the position in which I’d need to mount it to allow it to “kick” open the door, against the force of the magnetic clasp7.

This was, amazingly, the hardest part of the whole project! Putting the solenoid too close to the door didn’t work: it couldn’t “push” it from a standing start. Too far away, and the natural give of the door took the strain without pushing it open. Just the right distance, and the latch had picked up enough momentum that its weight “kicked” the door away from the magnet and followed-through to ensure that it kept moving.

A second solenoid, mounted inside the top of the cabinet, slides into the “loop” part of a large bolt fitting, allowing the cabinet to be electronically “locked”.

A Raspberry Pi Zero, relay, and solenoid assembly on the bottom outside edge of the inside of the cabinet.
I seriously must’ve spent about an hour getting the position of that little “kicker” in the bottom right just right.

Next up came the software. I started with a very simple Python program8 that would run a webserver and, on particular requests, open the lock solenoid and push with the “kicker” solenoid.

#!/usr/bin/python
#
# a basic sample implementation of a web interface for a secret cabinet
#
# setup:
#   sudo apt install -y python3-flask
#   wget https://github.com/sbcshop/Zero-Relay/blob/master/pizero_2relay.py
#
# running:
#   sudo flask --app web run --host=0.0.0.0 --port 80

from flask import Flask, redirect, url_for
import pizero_2relay as pizero
from time import sleep

# set up pizero_2relay with the two relays attached to this Pi Zero:
r1 = pizero.relay("R1") # The "kicker" relay
r2 = pizero.relay("R2") # The "locking bolt" relay

app = Flask(__name__)

# GET / - nothing here
@app.route("/")
def index():
  return "Nothing to see here."

# GET /relay - show a page with "open" and "lock" links
@app.route("/relay")
def relay():
  return "<html><head><meta name='viewport' content='width=device-width, initial-scale=1'></head><body><ul><li><a href='/relay/open'>Open</a></li><li><a href='/relay/lock'>Lock</a></li></ul>"

# GET /relay/open - open the secret cabinet then return to /relay
# This ought to be a POST request in your implementation, and you probably
# want to add some security e.g. a 
@app.route("/relay/open")
def open():
  # Retract the lock:
  r2.off()
  sleep(0.5)
  # Fire the kicker twice:
  r1.on()
  sleep(0.25)
  r1.off()
  sleep(0.25)
  r1.on()
  sleep(0.25)
  r1.off()
  # Redirect back:
  return redirect(url_for('relay'))

@app.route("/relay/lock")
def lock():
  # Engage the lock:
  r2.on()
  return redirect(url_for('relay'))
Don’t use this code as-is on any kind of open network, obviously. Follow the comments for some tips on what you’ll need to change.

Once I had something I could trigger from a web browser or with curl, I could start experimenting with trigger mechanisms. I had a few ideas (and prototyped a couple of them), including:

  • A mercury tilt switch behind a different book, so you pull it to release the cabinet in the style of a classic movie secret door.
  • A microphone that listens for a specific pattern of knocks on a nearby surface.
I had far too much fun playing about with crappy prototypes.
  • An RFID reader mounted underneath another surface, and a tag on the underside of an ornament: moving the ornament to the “right” place on the surface triggers the cabinet (elsewhere in the room).
  • The current design, shown in the video above, where a code9 is transmitted to the cabinet for verification.

I think I’m happy with what I’ve got going on with it now. And it’s been a good opportunity to improve my carpentry, electronics, and Python.

Footnotes

1 The two dormer windows, wouldn’t you guarantee it, were significantly different widths despite each housing a window of the same width. Such are the quirks of extending a building that the previous occupier had previously half-heartedly tried to extend, I guess.

2 Why yes, I am a big fan of escape rooms. Why do you ask?

3 For one thing, I live with JTA, and I’m confident that he’d somehow be able to hear the silent screams of whatever trashy novels I opted to sacrifice for the good of the project.

4 As a bonus, my 10-year-old is a big fan of the book series that inspired the film (and a more-muted fan of the film itself) and she was ever-so excited at my project using real-life parts of the set of the movie… that she’s asked me to make a similar secret cabinet for her, when we get around to redecorating her room later in the year!

5 If I did it again, I might consider using a low-powered electromagnetic lock to hold the door shut. In this design, I used a permanent magnet and a pair of latch solenoids: one to operate a bolt, the second to “kick” the door open against the pull of the magnet, and… it feels a little clumsier than a magnetic lock might’ve.

6 That double-sided mounting tape really came in handy for this project!

7 Props to vlogger Technology Connections, one of whose excellent videos on the functionality of 1970s pinball tables – maybe this one? – taught me what a latch solenoid was in the first place, last year, which probably saved me from the embarrassment of trying to do this kind of thing with, I don’t know, a stepper motor or something.

8 I’m not a big fan of Python normally, but the people who made my relays had some up with a convenience library for them that was written in it, so I figured it would do.

9 Obviously the code isn’t A-B; I changed it temporarily for the video.

× × × × ×

Ladybird Browser

I’ve been playing with the (pre-Alpha version of) Ladybird, and it fills me with such joy and excitement.

This page, as rendered by Ladybird.
As you can see, Ladybird does a perfectly adequate job of rendering this page, including most of its CSS and virtually all of its JavaScript.

Browser diversity

Back in 2018, while other Web developers were celebrating, I expressed my dismay at the news that Microsoft Edge was on the cusp of switching from using Microsoft’s own browser engine EdgeHTML to using Blink. Blink is the engine that powers almost all other mainstream browsers; all but Firefox, which continues to stand atop Gecko.

The developers who celebrated this loss of rendering engine diversity were, I suppose, happy to have one fewer browser in which they must necessarily test their work. I guess these are the same developers who don’t test the sites they develop for accessibility (does your site work if you can’t see the images? what about with a keyboard but without a pointing device? how about if you’re colourblind?), or consider what might happen if a part of their site fails (what if the third-party CDN that hosts your JavaScript libraries goes down or is blocked by the user’s security software or their ISP?).

This blog post viewed in Lynx.
When was the last time you tested your site in a text-mode browser?

But I was sad, because – as I observed after Andre Alves Garzia succinctly spelled it outbrowser engines are an endangered species. Building a new browser that supports the myriad complexities of the modern Web is such a huge endeavour that it’s unlikely to occur from scratch: from this point on, all “new” browsers are likely to be based upon an existing browser engine.

Engine diversity is important. Last time we had a lull in engine diversity, the Web got stuck, stagnating in the shadow of Internet Explorer 6’s dominance and under the thumb of Microsoft’s interests. I don’t want those days to come back; that’s a big part of why Firefox is my primary web browser.

A Ladybird book browser

Spoof cover for "The Ladybird Book of The Browser"
I actually still own a copy of the book from which I adapted this cover!

Ladybird is a genuine new browser engine. Y’know, that thing I said that we might never see happen again! So how’ve they made it happen?

It helps that it’s not quite starting from scratch. It’s starting point is the HTML viewer component from SerenityOS. And… it’s pretty good. It’s DOM processing’s solid, it seems to support enough JavaScript and CSS that the modern Web is usable, even if it’s not beautiful 100% of the time.

Acid3 test score of 97/100 in Ladybird.
I’ve certainly seen browsers do worse than this at Acid3 and related tests…

They’re not even expecting to make an Alpha release until next year! Right now if you want to use it at all, you’re going to need to compile the code for yourself and fight with a plethora of bugs, but it works and that, all by itself, is really exciting.

They’ve got four full-time engineers, funded off donations, with three more expected to join, plus a stack of volunteer contributors on Github. I’ve raised my first issue against the repo; sadly my C++ probably isn’t strong enough to be able to help more-directly, even if I somehow did have enough free time, which I don’t. But I’ll be watching-from-afar this wonderful, ambitious, and ideologically-sound initiative.

#100DaysToOffload

Woop! This is my 100th post of the year (stats), even using my more-conservative/pedant-friendly “don’t count checkins/reposts/etc. rule. If you’re not a pedant, I achieved #100DaysToOffload when I found a geocache alongside Regents Canal while changing trains to go to Amsterdam where I played games with my new work team, looked at windows and learned about how they’ve been taxed, and got nerdsniped by a bus depot. In any case: whether you’re a pedant or not you’ve got to agree I’ve achieved it now!

× × × ×

Science Weekend

This weekend was full of science.

Research

String of large electromagnets used for steering an electron beam.
If you wanna bend a stream of electrons travelling at nearly the speed of light, you’re gonna need a lot of big magnets.

This started on Saturday with a trip to the Harwell Campus, whose first open day in eight years provided a rare opportunity for us to get up close with cutting edge science (plus some very kid-friendly and accessible displays) as well as visit the synchrotron at Diamond Light Source.

Dan with a child in front of beamlines coming out of the Diamond Light Synchrotron ring.
It’s hard to convey the scale of the thing; turns out you need a big ol’ ring if you want to spin electrons fast enough to generate a meaningful amount of magnetobremsstrahlung radiation.

The whole thing’s highly-recommended if you’re able to get to one of their open days in the future, give it a look. I was particularly pleased to see how enthused about science it made the kids, and what clever questions they asked.

For example: the 7-year-old spent a long time cracking a variety of ciphers in the computing tent (and even spotted a flaw in one of the challenge questions that the exhibitors then had to hand-correct on all their handouts!); the 10-year-old enjoyed quizzing a researcher who’d been using x-ray crystallography of proteins.

Medicine

And then on Sunday I finally got a long-overdue visit to my nearest spirometry specialist for a suite of experiments to try to work out what exactly is wrong with my lungs, which continue to be a minor medical mystery.

Dan holds a piece of medical apparatus to his mouth.
“Once you’ve got your breath back, let’s fill you with drugs and do those experiments again…”

It was… surprisingly knackering. Though perhaps that’s mostly because once I was full of drugs I felt briefly superpowered and went running around the grounds of the wonderfully-named Brill Hill Windmill with the dog until was panting in pretty much the way that I might normally have been, absent an unusually-high dose of medication.

Computer screen graphs showing peak respiratory flow under a series of different experiments.
It’s got a graph; that makes it science, right? (I’m ignoring those party political histograms that outright lie about how narrow the margins are…)

For amusement purposes alone, I’d be more-likely to recommend the first day’s science activities than the second, but I can’t deny that it’s cool to collect a load of data about your own body and how it works in a monitorable, replicable way. And maybe, just maybe, start to get to the bottom of why my breathing’s getting so much worse these last few years!

× × × ×

A Stupid Joke About Elephants

Duration

Podcast Version

This post is also available as a podcast. Listen here, download for later, or subscribe wherever you consume podcasts.

You’ve probably been taught that you can tell the difference between African Elephants and Indian Elephants by looking at their head and ears. The larger African Elephants have a rounded cranium and big ears (with a shape somewhat like the continent of Africa itself!), whereas the smaller Indian Elephants have a two-lobed skull and diminutive ears that tuck tidily alongside their heads.

An African Elephant and an Indian Elephant, with the different head & ear shape clearly visible.
If you’re inside the elephant or have access to an extraordinarily-large X-ray machine, you can also differentiate by counting the ribs: African Elephants tend to have 21 pairs, Indian Elephants only 20.

But suppose you don’t manage to get a glimpse at the front end of the elephant as it passes you. What hope is there of identifying the species? Well: you can look at its back!

Concave back of an African Elephant.
Never forget: this back belongs to an African Elephant.

African Elephants, it turns out, have a concave back, whereas Indian elephants have a convex back (a bit like a hump)!

Convex back of an Indian Elephant.
You could probably come up with some kind of mnemonic if you wanted, like “African Elephants back down when Indian Elephants back up.” But perhaps a better one than that.

I was having difficulty sleeping one night during the UK‘s current heatwave, so naturally I opted to practice my newfound ability to distinguish elephant species by their spines. Indian, Indian, African, Indian, African, African… etc.

And then I came across this one:

A flat elephant back, neither concave nor convex.
What is this thing?

African Elephant backs are concave. Indian Elephant backs are convex. But what does it mean when you see a flat elephant’s back?

It turns out…

…that’s a grey area.

Dan with a stuffed toy (African) elephant.
You’re welcome/I’m sorry. Delete as applicable.
× × × × ×

Special Roads

Duration

Podcast Version

This post is also available as a podcast. Listen here, download for later, or subscribe wherever you consume podcasts.

Sometimes I’ve seen signs on dual carriageways and motorways that seem to specify a speed limit that’s the same as the national speed limit (i.e. 60 or 70 mph for most vehicles, depending on the type of road), which seem a bit… pointless? Today I learned why they’re there, and figured I’d share with you!

Google Street View photo from the A1 East of Edinburgh, showing a blue "No motor cycles under 50cc, moped,s invalid carriages and animals" sign alongside a 70mph sign.
The first time I saw this sign, on the A1 near Edinburgh, I wondered why it wasn’t just a national speed limit/derestriction sign. Now I know.

To get there, we need a history lesson.

As early as the 1930s, it was becoming clear that Britain might one day need a network of high-speed, motor-vehicle-only roads: motorways. The first experimental part of this network would be the Preston By-pass1.

Monochome photograph showing construction of bridge support pillars.
Construction halted on several occasions owing to heavy rain, and only six weeks after opening the road needed to be closed for resurfacing after the discovery that water had penetrated the material.

Construction wouldn’t actually begin until the 1950s, and it wasn’t just the Second World War that got in the way: there was a legislative challenge too.

When the Preston By-pass was first conceived, there was no legal recognition for roads that restricted the types of traffic that were permitted to drive on them. If a public highway were built, it would have to allow pedestrians, cyclists, and equestrians, which would doubtless undermine the point of the exercise! Before it could be built, the government needed to pass the Special Roads Act 1949, which enabled the designation of public roads as “special roads”, to which entry could be limited to certain classes of vehicles2.

Monochrome photograph showing a sign at the entrance to the Preston By-pass, reading: 'Motorway. NO L-drivers, mopeds, motorcycles under 50cc., invalid-carriages, pedal-cycles, pedestrians, animals'.
The original motorways had to spell out the regulations at their junctions.

If you don’t check your sources carefully when you research the history of special roads, you might be taken in by articles that state that special roads are “now known as motorways”, which isn’t quite true. All motorways are special roads, by definition, but not all special roads are motorways.

There’s maybe a dozen or more non-motorway special roads, based on research by Pathetic Motorways (whose site was amazingly informative on this entire subject). They tend to be used in places where something is like a motorway, but can’t quite be a motorway. In Manchester, a couple of the A57(M)’s sliproads have pedestrian crossings and so have to be designated special roads rather than motorways, for example3.

1968 Manchester City Council planning document showing their proposed new special roads.
“…is hereby varied by adding Class IX of the Classes of Traffic set out in Schedule 4 to the Highways Act 1980 as a class of traffic permitted to use those lengths of the special roads described in the Schedule to this Scheme and which…” /snoring sounds intensify/

Now we know what special roads are, that we might find them all over the place, and that they can superficially look like motorways, let’s talk about speed limits.

The Road Traffic Act 1934 introduced the concept of a 30mph “national speed limit” in built-up areas, which is still in force today. But outside of urban areas there was no speed limit. Perhaps there didn’t need to be, while cars were still relatively slow, but automobiles became increasingly powerful. The fastest speed ever legally achieved on a British motorway came in 1964 during a test by AC Cars, when driver Jack Sears reached 185mph.

Cyclists alongside a 'motorway' river bridge lane.
The “M48” Severn Bridge is another example of a special road that appears to be part of a motorway. The cycle lane and footpath (which is not separated from the main carriageway by more than a fence) is the giveaway that it’s not truly a “motorway” but a general-case special road.

In the late 1960s an experiment was run in setting a speed limit on motorways of 70mph. Then the experiment was extended. Then the regulation was made permanent.

There’ve been changes since then, e.g. to prohibit HGVs from going faster than 60mph, but fundamentally this is where Britain’s national speed limit on motorways comes from.

The Motorways Traffic (Speed Limit) (England) Regulations 1967, highlighting "3. No person shall drive a motor vehicle on a motorway at a speed greater than 70 miles per hour".
I assume that it relates to the devolution of transport policy or to the separation of legislation that it replaces, but separate-but-fundamentally-identical acts were passed for Scotland and Northern Ireland.

You’ve probably spotted the quirk already. When “special roads” were created, they didn’t have a speed limit. Some “special roads” were categorised as “motorways”, and “motorways” later had a speed limit imposed. But there are still a few non-motorway “special roads”!

Putting a national speed limit sign on a special road would be meaningless, because these roads have no centrally-legislated speed limit. So they need a speed limit sign, even if that sign, confusingly, might specify a speed limit that matches what you’d have expected on such a road4. That’s the (usual) reason why you sometimes see these surprising signs.

As to why this kind of road are much more-common in Scotland and Wales than they are anywhere else in the UK: that’s a much deeper-dive that I’ll leave as an exercise for the reader.

Footnotes

1 The Preston By-pass lives on, broadly speaking, as the M6 junctions 29 through 32.

2 There’s little to stop a local authority using the powers of the Special Roads Act and its successors to declare a special road accessible to some strange and exotic permutation of vehicle classes if they really wanted: e.g. a road could be designated for cyclists and horses but forbidden to motor vehicles and pedestrians, for example! (I’m moderately confident this has never happened.)

3 There’s a statutory instrument that makes those Mancunian sliproads possible, if you’re having trouble getting to sleep on a night and need some incredibly dry reading.

4 An interesting side-effect of these roads might be that speed restrictions based on the class of your vehicle and the type of road, e.g. 60mph for lorries on motorways, might not be enforceable on special roads. If you wanna try driving your lorry at 70mph on a motorway-like special road with “70” signs, though, you should do your own research first; don’t rely on some idiot from the Internet. I Am Not A Lawyer etc. etc.

× × × × × ×

ARCC

In the late ’70s, a shadowy group of British technologists concluded that nuclear war was inevitable and secretly started work on a cutting-edge system designed to help rebuild society. And thanks to Matt Round-and-friends at vole.wtf (who I might have mentioned before), the system they created – ARCC – can now be emulated in your browser.

3D rendering of an ARCC system, by HappyToast.

I’ve been playing with it on-and-off all year, and I’ve (finally) managed to finish exploring pretty-much everything the platform currently has to offer, which makes it pretty damn good value for money for the £6.52 I paid for my ticket (the price started at £2.56 and increases by 2p for every ticket sold). But you can get it cheaper than I did if you score 25+ on one of the emulated games.

ARCC system showing a high score table for M1, with DAN50 (score 13012) at the top.
It gives me more pride than it ought to that I hold the high score for a mostly-unheard-of game for an almost-as-unheard-of computer system.

Most of what I just told you is true. Everything… except the premise. There never was a secretive cabal of engineers who made this whackballs computer system. What vole.wtf emulates is an imaginary system, and playing with that system is like stepping into a bizarre alternate timeline or a weird world. Over several separate days of visits you’ll explore more and more of a beautifully-realised fiction that draws from retrocomputing, Cold War fearmongering, early multi-user networks with dumb terminal interfaces, and aesthetics that straddle the tripoint between VHS, Teletext, and BBS systems. Oh yeah, and it’s also a lot like being in a cult.

Needless to say, therefore, it presses all the right buttons for me.

ARCC terminal in which an email is being written to DAN50.
If you make it onto ARCC – or are already there! – drop me a message. My handle is DAN50.

If you enjoy any of those things, maybe you’d like this too. I can’t begin to explain the amount of work that’s gone into it. If you’re looking for anything more-specific in a recommendation, suffice to say: this is a piece of art worth seeing.

× ×

Somewhat-Effective Spam Filters

I’ve tried a variety of unusual strategies to combat email spam over the years.

Here are some of them (each rated in terms the geekiness of its implementation and its efficacy), in case you’d like to try any yourself. They’re all still in use in some form or another:

Spam filters

Geekiness: 1/10
Efficacy: 5/10

A colander filters spam email out of a stream of emails.

Your email provider or your email software probably provides some spam filters, and they’re probably pretty good. I use Proton‘s and, when I’m at my desk, Thunderbird‘s. Double-bagging your spam filter only slightly reduces the amount of spam that gets through, but increases your false-positive rate and some non-spam gets mis-filed.

A particular problem is people who email me for help after changing their name on FreeDeedPoll.org.uk, probably because they’re not only “new” unsolicited contacts to me but because by definition many of them have strange and unusual names (which is why they’re emailing me for help in the first place).

Frankly, spam filters are probably enough for many people. Spam filtering is in general much better today than it was a decade or two ago. But skim the other suggestions in case they’re of interest to you.

Unique email addresses

Geekiness: 3/10
Efficacy: 8/10

If you give a different email address to every service you deal with, then if one of them misuses it (starts spamming you, sells your data, gets hacked, whatever), you can just block that one address. All the addresses come to the same inbox, for your convenience. Using a catch-all means that you can come up with addresses on-the-fly: you can even fill a paper form with a unique email address associated with the company whose form it is.

On many email providers, including the ever-popular GMail, you can do this using plus-sign notation. But if you want to take your unique addresses to the next level and you have your own domain name (which you should), then you can simply redirect all email addresses on that domain to the same inbox. If Bob’s Building Supplies wants your email address, give them bobs@yourname.com, which works even if Bob’s website erroneously doesn’t accept email addresses with plus signs in them.

This method actually works for catching people misusing your details. On one occasion, I helped a band identify that their mailing list had been hacked. On another, I caught a dodgy entrepreneur who used the email address I gave to one of his businesses without my consent to send marketing information of a different one of his businesses. As a bonus, you can set up your filtering/tagging/whatever based on the incoming address, rather than the sender, for the most accurate finding, prioritisation, and blocking.

Emails to multiple email addresses reach the same inbox. Spam emails are blocked based on the addresses they're sent to.

Also, it makes it easy to have multiple accounts with any of those services that try to use the uniqueness of email addresses to prevent you from doing so. That’s great if, like me, you want to be in each of three different Facebook groups but don’t want to give Facebook any information (not even that you exist at the intersection of those groups).

Signed unique email addresses

Geekiness: 10/10
Efficacy: 2/10

Unique email addresses introduce two new issues: (1) if an attacker discovers that your Dreamwidth account has the email address dreamwidth@yourname.com, they can probably guess your LinkedIn email, and (2) attackers will shotgun “likely” addresses at your domain anyway, e.g. admin@yourname.com, management@yourname.com, etc., which can mean that when something gets through you get a dozen copies of it before your spam filter sits up and takes notice.

What if you could assign unique email addresses to companies but append a signature to each that verified that it was legitimate? I came up with a way to do this and implemented it as a spam filter, and made a mobile-friendly webapp to help generate the necessary signatures. Here’s what it looked like:

  1. The domain directs all emails at that domain to the same inbox.
  2. If the email address is on a pre-established list of valid addresses, that’s fine.
  3. Otherwise, the email address must match the form of:
    • A string (the company name), followed by
    • A hyphen, followed by
    • A hash generated using the mechanism described below, then
    • The @-sign and domain name as usual

The hashing algorithm is as follows: concatenate a secret password that only you know with a colon then the “company name” string, run it through SHA1, and truncate to the first eight characters. So if my password were swordfish1 and I were generating a password for Facebook, I’d go:

  1. SHA1 ( swordfish1 : facebook) [ 0 ... 8 ] = 977046ce
  2. Therefore, the email address is facebook-977046ce@myname.com
  3. If any character of that email address is modified, it becomes invalid, preventing an attacker from deriving your other email addresses from a single point (and making it hard to derive them given multiple points)

I implemented the code, but it soon became apparent that this was overkill and I was targeting the wrong behaviours. It was a fun exercise, but ultimately pointless. This is the one method on this page that I don’t still use.

Honeypots

Geekiness: 8/10
Efficacy: ?/10

Emails to multiple email addresses reach an inbox, but senders who reach a "honeypot" inbox are blocked from reaching the real inbox.

A honeypot is a “trap” email address. Anybody who emails it get aggressively marked as a spammer to help ensure that any other messages they send – even to valid email addresses – also get marked as spam.

I litter honeypots all over the place (you might find hidden email addresses on my web pages, along with text telling humans not to use them), but my biggest source of honeypots is formerly-valid unique addresses, or “guessed” catch-all addresses, which already attract spam or are otherwise compromised!

I couldn’t tell you how effective it is without looking at my spam filter’s logs, and since the most-effective of my filters is now outsourced to Proton, I don’t have easy access to that. But it certainly feels very satisfying on the occasions that I get to add a new address to the honeypot list.

Instant throwaways

Geekiness: 5/10
Efficacy: 6/10

OpenTrashmail is an excellent throwaway email server that you can deploy in seconds with Docker, point some MX records at, and be all set! A throwaway email server gives you an infinite number of unique email addresses, like other solutions described above, but with the benefit that you never have to see what gets sent to them.

Emails are delivered to an inbox and to a trash can, depending on the address they're sent to. The inbox subscribes to the trash can using RSS.

If you offer me a coupon in exchange for my email address, it’s a throwaway email address I’ll give you. I’ll make one up on the spot with one of my (several) trashmail domains at the end of it, like justgivemethedamncoupon@danstrashmailserver.com. I can just type that email address into OpenTrashmail to see what you sent me, but then I’ll never check it again so you can spam it to your heart’s content.

As a bonus, OpenTrashmail provides RSS feeds of inboxes, so I can subscribe to any email-based service using my feed reader, and then unsubscribe just as easily (without even having to tell the owner).

Summary

With the exception of whatever filters your provider or software comes with, most of these options aren’t suitable for regular folks. But you’re only a domain name (assuming you don’t have one already) away from being able to give unique email addresses to everybody you deal with, and that’s genuinely a game-changer all by itself and well worth considering, in my opinion.

× × × ×

Woke Kids

The other weekend, I joined in with the parade at Witney Pride, accompanied by our 10-year-old who’d expressed an interest in coming too.

It was her first Pride but she clearly got the idea, turning up with a wonderful hand-coloured poster she’d made which, in rainbow colours, encouraged the reader to “be kind”.

A Pride parade marches down a high street: Dan and his eldest can be seen in the very background.
You’ve seen pictures of Pride parades before, possibly even ones with me in them.

You know what: our eldest is so woke it makes me embarrassed on behalf of my past self at her age. Or even at twice her age, when I still didn’t have the level of social and societal awareness and care about queer issues that she does already.

A tweeny girl and a 40-something man with rainbows painted on their faces wave flags in a Pride parade. The child has coloured-in a poster saying "be kind".
I’d equipped her with a whistle (on a rainbow lanyard) and instructions that in the event of protests from religious nuts she shouldn’t engage with them (because that’s what they want) but instead just to help ensure that our parade was louder than them! I needn’t have worried though: Witney ain’t Oxford or London and our march seemed to see nothing but joy and support from the folks we passed.

When we got to the parade’s destination, the kid found a stall selling a variety of badges, and selected for herself a “she/her/hers” pronoun pin.

“It’s not like anybody’s likely to look at me and assume that my pronouns are anything other than that,” she explained, “But I want it to be normal to talk about, and I want to show solidarity for genderqueer people.”

That’s a level of allyship that it took me until I was much, much older to attain. So proud!

× ×

Framing Device

Doors

As our house rennovations/attic conversions come to a close, I found myself up in what will soon become my en suite, fitting a mirror, towel rail, and other accessories.

Wanting to minimise how much my power tool usage disturbed the rest of the house, I went to close the door separating my new bedroom from my rest of my house, only to find that it didn’t properly fit its frame and instead jammed part-way-closed.

“Oh,” I said, as the door clearly failed to shut, “Damn.”

Somehow we’d never tested that this door closed properly before we paid the final instalment to the fitters. And while I’m sure they’d have come back to repair the problem if I asked, I figured that it’d be faster and more-satisfying to fix it for myself.

Homes

As a result of an extension – constructed long before we moved in – the house in Preston in which spent much of my childhood had not just a front and a back door but what we called the “side door”, which connected the kitchen to the driveway.

Unfortunately the door that was installed as the “side door” was really designed for interior use and it suffered for every winter it faced the biting wet North wind.

A partially-pebbledashed house.
The side door isn’t visible in this picture: it’s concealed behind the corner of the house, to the left of the car.

My father’s DIY skills could be rated as somewhere between mediocre and catastrophic, but his desire to not spend money “frivolously” was strong, and so he never repaired nor replaced the troublesome door. Over the course of each year the wood would invariably absorb more and more water and swell until it became stiff and hard to open and close.

The solution: every time my grandfather would visit us, each Christmas, my dad would have his dad take down the door, plane an eighth of an inch or so off the bottom, and re-hang it.

Sometimes, as a child, I’d help him do so.

A grey-haired white man wearing spectacles and a boiler suit leans comfortably on a railing alongside industrial machinery.
My paternal grandfather was a practical and hand-on engineer and a reasonable carpenter.

Planes

The first thing to do when repairing a badly-fitting door is work out exactly where it’s sticking. I borrowed a wax crayon from the kids’ art supplies, coloured the edge of the door, and opened and closed it a few times (as far as possible) to spot where the marks had smudged.

Fortunately my new bedroom door was only sticking along the top edge, so I could get by without unmounting it so long as I could brace it in place. I lugged a heavy fence post rammer from the garage and used it to brace the door in place, then climbed a stepladder to comfortably reach the top.

A small box plane perched atop a sloping door.
I figured I’d only need to remove a few millimetres, so I didn’t mind doing it from atop a stepladder. Hey: here’s a fun thing – when I think about planing a door with my grandfather, I think in inches; when I think about doing it myself, I think in metric!

Loss

After my paternal grandfather died, there was nobody left who would attend to the side door of our house. Each year, it became a little stiffer, until one day it wouldn’t open at all.

Surely this would be the point at which he’d pry open his wallet and pay for it to be replaced?

A middle-aged man carrying walking poles on an urban riverbank drags a car tyre that's chained to his waist.
I’m not sure there’s a more apt metaphor for my dad’s ability to be stubborn than this photo of him dragging a tyre around Gateshead as a training activity for an Arctic expedition.

Nope. Instead, he inexpertly screwed a skirting board to it and declared that it was now no-longer a door, but a wall.

I suppose from a functionalist perspective he was correct, but it still takes a special level of boldness to simply say “That door? It’s a wall now.”

Sand

Of all the important tasks a carpenter (or in this case, DIY-er) must undertake, hand sanding must surely be the least-satisfying.

Dan rubs sandpaper atop a wooden door.
You wear your fingers out rubbing a piece of wood smooth, and your only reward is getting to do it again with a slightly finer grade of paper.

But reaching the end of the process, the feel of a freshly-planed, carefully-sanded piece of wood is fantastic. This surface represented chaos, and now it represents order. Order that you yourself have brought about.

Often, you’ll be the only one to know. When my grandfather would plane and sand the bottom edge of our house’s side door, he’d give it a treatment of oil (in a doomed-to-fail attempt to keep the moisture out) and then hang it again. Nobody can see its underside once it’s hung, and so his handiwork was invisible to anybody who hadn’t spent the last couple of months swearing at the stiffness of the door.

A paintbrush applies white paint to the top of a door.
Swish, swish. Now I’m glad I sanded.

Even though the top of my door is visible – particularly visible, given its sloping face – nobody sees the result of the sanding because it’s hidden beneath a layer of paint.

A few brush strokes provide the final touch to a spot of DIY… that in provided a framing device for me to share a moment of nostalgia with you.

Sweep away the wood shavings. Keep the memories.

× × × × × ×

Multi-Phase Maps in FoundryVTT

FoundryVTT is a fantastic Web-based environment for tabletop roleplaying adventures1 and something I particularly enjoy is the freedom for virtually-unlimited scripting. Following a demonstration to a fellow DM at work last week I promised to throw together a quick tutorial into scripting simple multi-phase maps using Foundry.2

Why multi-phase maps?

Animated battlemap which organically grows into a leafy flower over six stages.
For this demonstration, I’ll be using AtraxianBear’s Growing Flower Dungeon.

You might use a multi-phase map to:

  • Allow the development and expansion of a siege camp outside the fortress where the heroes are holed-up.3
  • Rotate through day and night cycles or different times of day, perhaps with different things to interact with in each.4
  • Gradually flood a sewer with rising water… increasing the range of the monster that dwells within.5
  • Re-arrange parts of the dungeon when the characters flip certain switches, opening new paths… and closing others.

I’ll use the map above to create a simple linear flow, powered by a macro in the hotbar. Obviously, more-complex scenarios are available, and combining this approach with a plugin like Monk’s Active Tile Triggers can even be used to make the map appear to dynamically change in response to the movement or actions of player characters!

Setting the scene

Create a scene, using the final state of the map as the background. Then, in reverse-order, add the previous states as tiles above it.

Not shown, but highly-recommended: lock each tile when you’re done placing it, so that you don’t accidentally interact with it when you mean to e.g. drag-select multiple actors.

Make a note of the X-position that your tiles are in when they’re where they supposed to be: we’ll “move” the tiles off to the side when they’re hidden, to prevent their ghostly half-hidden forms getting in your way as game master. We’ll also use this X-position to detect which tiles have already been moved/hidden.

Also make note of each tile’s ID, so your script can reference them. It’s easiest to do this as you go along. When you’re ready to write your macro, reverse the list, because we’ll be hiding each tile in the opposite order from the order you placed them.

Writing the script

Next, create a new script macro, e.g. by clicking an empty slot in the macro bar. When you activate this script, the map will move forward one phase (or, if it’s at the end, it’ll reset).

I find Foundry’s built-in script editor a little… small? So I write my scripts in my favourite text editor and then copy-paste.

Here’s the code you’ll need – the 👈 emoji identifies the places you’ll need to modify the code, specifically:

  1. const revealed_tiles_default_x = 250 should refer to the X-position of your tiles when they’re in the correct position.
  2. const revealed_tiles_modified_x = 2825 should refer to the X-position they’ll appear at “off to the right” of your scene. To determine this, just move one tile right until it’s sufficiently out of the way of the battlemap and then check what it’s X-position is! Or just take the default X-position, add the width of your map in pixels, and then add a tiny bit more.
  3. const revealed_tiles = [ ... ] is a list of the tile IDs of each tile what will be hidden, in turn. In my example there are five of them (the sixth and final image being the scene background).
const revealed_tiles_default_x = 250;   // 👈 X-position of tiles when displayed
const revealed_tiles_modified_x = 2825; // 👈 X-position of tiles when not displayed
const revealed_tiles = [
  '2xG7S8Yqk4x1eAdr',                   // 👈 list of tile IDs in order that they should be hidden
  'SjNQDBImHvrjAHWX',                   //     (top to bottom)
  'tuYg4FvLgIla1l21',
  'auX4sj64PWmkAteR',
  'yAL4YP0I4Cv4Sevt',
].map(t=>canvas.tiles.get(t));

/*************************************************************************************************/

// Get the topmost tile that is still visible:
const next_revealed_tile_to_move = revealed_tiles.find(t=>
  t.position.x == revealed_tiles_default_x
);

// If there are NO still-visible tiles, we must need to reset the map:
if( ! next_revealed_tile_to_move ) {
  // To reset the map, we go through each tile and put it back where it belongs -
  for(tile of revealed_tiles){
    canvas.scene.updateEmbeddedDocuments("Tile", [ {
      _id: tile.id,
      x: revealed_tiles_default_x,
      hidden: false
    } ]);
  }
} else {
  // Otherwise, hide the topmost visible tile (and move it off to the side to help the GM) -
  canvas.scene.updateEmbeddedDocuments("Tile", [ {
    _id: next_revealed_tile_to_move.id,
    x: revealed_tiles_modified_x,
    hidden: true
  } ]);
}

I hope that the rest of the code is moderately self-explanatory for anybody with a little JavaScript experience, but if you’re just following this kind of simple, linear case then you don’t need to modify it anyway. But to summarise, what it does is:

  1. Finds the first listed tile that isn’t yet hidden (by comparing its X-position to the pre-set X-position).
  2. If there aren’t any such tiles, we must have hidden them all already, so perform a reset: to do this – iterate through each tile and set its X-position to the pre-set X-position, and un-hide it.
  3. Otherwise, move the first not-hidden tile to the alternative X-position and hide it.

I hope you have fun with scripting your own multi-phase maps. Just don’t get so caught-up in your awesome scenes that you fail to give the players any agency!

Footnotes

1 Also, it’s on sale at 20% off this week to celebrate its fourth anniversary. Just sayin’.

2 I can neither confirm nor deny that a multi-phase map might be in the near future of The Levellers‘ adventure…

3 AtraxianBear has a great series of maps inspired by the 1683 siege of Vienna by the Ottomans that could be a great starting point for a “gradually advancing siege” map.

4 If you’re using Dungeon Alchemist as part of your mapmaking process you can just export orthographic or perspective outputs with different times of day and your party’s regular inn can be appropriately lit for any time of day, even if the party decides to just “wait at this table until nightfall”.

5 Balatro made a stunning map with rising water as a key feature: there’s a preview available.

×

Don’t Ask, Don’t Teach

Politics and pundits

The UK’s Conservative government, having realised that their mandate is worthless, seems to be in a panicked rush to try to get the voters to ignore any of the real issues. Instead, they say, we should be focussed on things like ludicrously-expensive and ineffective ways to handle asylum seekers and making life as hard as possible for their second-favourite scapegoat: trans and queer people.

Screengrab from Last Week Tonight with John Oliver. John Oliver is subtitled as saying: In the end, Sunak did an end-run around the ruling that Rwanda was too dangerous by simply having his government officially declare Rwanda a "safe country".
By the time John Oliver’s doing a segment about you, perhaps it’s time to realise you’ve fucked up? But our main story tonight is about sex education…

The latest move in that second category seems likely to be a plan to, among other things, discourage teachers from talking about gender identity in schools, with children of any age. From the article I linked:

The BBC has not seen the new guidelines but a government source said they included plans to ban any children being taught about gender identity.

If asked, teachers will have to be clear gender ideology is contested.

Needless to say, such guidance is not likely to be well-received by teachers:

Pepe Di’Iasio, headteacher at a school in Rotherham, told Today that he believes pupils are being used “as a political football”.

Teachers “want well informed and evidence-based decisions”, he said, and not “politicised” guidance.

Cringey political poster reading "Is this Labour's idea of a comprehensive education? Take the politics out of education, vote Conservative", alongside three books: Young gay & proud, Police: Out of School!, and The playbook for kids about sex.
I can only assume that the Tories still have a stack of this genuine 1987 billboard poster (ugh) in stock, and are hoping to save money by reusing them.

People and pupils

This shit isn’t harmless. Regardless of how strongly these kinds of regulations are enforced, they can have a devastating chilling effect in schools.

I speak from experience.

A group of teenagers stand around awkwardly.
I don’t know if this is the “most-90s” photo I own of myself, but it’s gotta be close. Taken at the afterparty from a school production of South Pacific, so probably at least a little disproportionately-queer gathering.

Most of my school years were under the shadow of Section 28. Like I predict for the new Conservative proposals, Section 28 superficially didn’t appear to have a major impact: nobody was ever successfully prosecuted under it, for example. But examining its effects in that way completely overlooks the effect it had on how teachers felt they had to work.

For example…

In around 1994, I witnessed a teacher turn a blind eye to homophobic bullying of a pupil by their peer, during a sex education class. Simultaneously, the teacher coolly dismissed the slurs of the bully, saying that we weren’t “talking about that in this class” and that the boy should “save his chatter for the playground”. I didn’t know about the regulations at the time: only in hindsight could I see that this might have been a result of Section 28. All I got to see at the time was a child who felt that his homophobic harassment of his classmate had the tacit endorsement of the teachers, so long as it didn’t take place in the classroom.

A gay friend, who will have been present but not involved in the above event, struggled with self-identity and relationships throughout his teenage years, only “coming out” as an adult. I’m confident that he could have found a happier, healthier life had he felt supported – or at the very least not-unwelcome – at school. I firmly believe that the long-running third-degree side-effects of Section 28 effectively robbed him of a decade of self-actualisation about his identity.

The long tail of those 1980s rules were felt long-after they were repealed. And for a while, it felt like things were getting better. But increasingly it feels like we’re moving backwards.

A pride rainbow painted down the back of a white person's first, held in the air.
As a country and as a society, we can do better than this.

With general elections coming up later this year, it’ll soon be time to start quizzing your candidates on the issues that matter to you. Even (perhaps especially) if your favourite isn’t the one who wins, it can be easiest to get a politicians’ ear when they and their teams are canvassing for your vote; so be sure to ask pointed questions about the things you care about.

I hope that you’ll agree that not telling teachers to conceal from teenagers the diversity of human identity and experience is something worth caring about.

Update: Only a couple of hours after I posted this, the awesome folks (whom I’ve mentioned before) at the Vagina Museum tooted a thread about the long tail of Section 28. It’s well-worth a read.

× × × ×