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!

× × × ×

Ranking Every Elevator in the Myst Series

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

Dustin Garner

Part of the joy of the collaborative Internet is that people can share their passion. Today’s example comes from this YouTuber who’s made an hour long video demonstrating and ranking the 35 elevators in the first five games in the Myst series.

Starting with a discussion of what defines an elevator, the video goes on to show off some of the worst of the lifts in the series of games (mostly those that are uninspired, pointless, or which have confusing interfaces) before moving on to the well-liked majority.

I only ever played the first two Myst games (and certainly haven’t played the first since, what, the mid-1990s?) and I don’t think I finished either. But that didn’t stop me watching the entirety of this video and revelling in the sheer level of dedication and focus it’ll have taken on the part of the creator. When I made my (mere 15-minute!) video describing my favourite video game Easter Egg I spent tens of hours over the prior weeks researching the quirk and its background, configuring a copy of the (elderly) game so that it’d play and record in the way I wanted, and of course playing through the game far enough to be able to fully demonstrate the Easter Egg. Dustin’s video, which doubtless involved replaying (possibly multiple times) five different games released over a 12-year window is mindblowing by comparison.

I don’t really care about the Myst series. I care even less about its elevators. But I really enjoyed this video, if only for its creator’s enthusiasm.

Information Trajectory

Humans invented Wikipedia, which made accessing information highly-convenient, at the risk of questions about its authenticity1.

Then humans invented GPTs, which made accessing information even more-convenient2 at the expense of introducing hallucinations that can be even harder to verify and check.

Is humanity’s long-term plan to invent something that spews complete nonsense that’s simultaneously impossible to conclusively deny?3

Shonky MSPaint-grade graph showing ease of access increasing as ease of verification decreases, with a trend line going through Wikipedia (2001) through ChatGPT (2022) to an unknown future in 2043.

Footnotes

1 I’m well aware that in many subject areas Wikipedia routinely outranks many other sources for accuracy. But the point remains, because you’ve no idea what the bias of randomuser123 is; even if you check the sources they cite, you don’t know what sources they omitted to include. I love Wikipedia, but I can’t deny its weaknesses.

2 Sure, ChatGPT and friends aren’t always more-convenient. But if you need to summarise information from several sources, you might find them a more-suitable tool than those which came before. Why do I feel the need to add so many footnotes to what should have been a throwaway comment?

3 Actually, now I think about it, I’m confident that I can name some politicians who are ahead of the machines, for 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!

× × × ×

Canine commuters chase dog travel season tickets

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

Dog aboard a train at the Ravenglass and Eskdale Railway

Dogs are being offered boat and rail season tickets to ease their path to walkies in the Lake District.

Ullswater Steamers and the Ravenglass and Eskdale Railway have introduced £20 annual “Rover” season tickets, which include a 10% donation to animal charities.

The cost for a standard doggie day ticket is £2.50 for the railway and £1 for a boat trip.

In a world where the news is dominated by war, cyber attacks, or imminent elections, it’s nice to be distracted by a nonsense bit of news. And this one’s just delightful.

For a fee of £1 – £2.50, dogs can travel on the boats and railways of Ravenglass and Eskdale Railway and Ullswater Steamers. So far, so good.

And now they’ve introduced a season pass for people who take their canines on the ferries or railways more often. Also good.

And they’ve called the season pass for dogs… a “Rover” ticket.

Excellent.

Screenshot of the page selling Ravenglass Railway 'Rover' tickets for dogs.
Yes. This. 😘🤌
× ×

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.

×