App idea: Game of QR

Imagine this: You’re outside, standing in line of your favorite bakery, and spot a QR code in the window of the store. You don’t care about the code itself, but pull out your phone anyway, open the Game of QR app and point your phone’s camera at the QR code. On the screen, it switches from the camera view to a 2D/flat version of the code, which starts animating using the rules of Conway’s Game of Life

  1. Any live cell with fewer than two live neighbours dies, as if by underpopulation.
  2. Any live cell with two or three live neighbours lives on to the next generation.
  3. Any live cell with more than three live neighbours dies, as if by overpopulation.
  4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.

If you’re not familiar with this zero-player game, here’s a sample from Wikipedia:

By Lucas Vieira – Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=101736

And a screenshot of my own implementation from 2020, which I called “Game of Ghosts”:

Two still lifes, two oscillators, one glider (bottom right)

Now imagine the AR (augmented reality) version: Still pointing the camera at the QR code, but now the animation happens in place, with the same perspective, instead of a reproduced 2D copy.

To make it more interesting, QR codes and their Game of Life states are collected in a gallery with geolocation. That way users of the app can collect QR codes, sharing the ones with interesting lifeforms.

Technical considerations

Wikipedia has a nice overview of QR codes, including all 7 variants. I had no idea so many exist – some even have color.

I’m still interested in learning more about React Native, so that’s where I’d start. The camera access should be possible with Expo, which would allow for a very low barrier to get started with development and testing. That also makes it easy to do beta testing, since there’s no need to upload and install apk files.

Implementing Game of Life itself is rather easy, which is probably why its a popular programming exercise. My CLI version implemented with node.js runs on replit.com.

I expect the difficult part to implement for Game of QR is to read the raw QR code as a 2D data structure, without decoding it. I assume QR code scanner libraries will include the decoding. At least the documentation for https://github.com/moaazsidat/react-native-qrcode-scanner doesn’t show how to access the raw data. Maybe the decoded data can be turned into a new QR code, which is then used to seed the Game of Life.

Let me know if you’re interested in collaborating with me on this idea!

Tools for playing D&D 5e online

My groups have used the following tools for playing D&D 5e, AD&D 2e and Maze Rats online.

Owlbear

This is it! If we had known about Owlbear in April 2020, our early attempts at playing online would’ve been a lot smoother. This is the perfect virtual tabletop for us. It works really well and does what we need (about 80% of all its features), and its free. It doesn’t embed any RPG systems or character management (unlike Roll20, see below), and this helps a lot in keeping it light and focused on the virtual table. All the improvements they made since we started using it were welcome and useful, and didn’t disturb anything we gotten used to.

To give you an idea how Owlbear works for the game master, I’ll show an example from one of my Maze Rats sessions. For that session I planned a scene with the player characters visiting a shady tavern. I sketched that tavern in Excalidraw (a bit more on that tool at the end):

From Excalidraw I exported the sketch as a PNG file and uploaded that as a map in Owlbear. There I adjusted the Columns and Rows and Grid Scale to roughly match the desired scale of this building. This affects how large the tokens will be shown by default (more on tokens below).

I did that for two other maps as well, one a map of the Dock District, another for a warehouse that the player characters had to explore.

For the tavern, I wanted to initially hide the back room, so I used Owlbear’s fog tool (the cloud icon) to draw a rectangular fog over the whole room. For players joining the session, they’d only see the main room, with a black rectangle hiding the rest. So other characters (as tokens) could hide back there. I didn’t really use it for this session, but its great when exploring dungeons, where you can use the eraser during the session to gradually reveal the full map.

To turn this from a static map into a virtual tabletop, add some tokens and name them:

Here I placed some of the default tokens that Owlbear provides. Players should create a custom token for their characters and upload them. As a game master, important non-player characters (NPCs) also deserve their own token.

To create custom tokens, Token Stamp is a neat little tool. My usual workflow there looks like this: Click on “Choose Image” to upload an image; scale it up and move it so that the person’s face is well visible in the preview on the right, then click on “Download” and save the token as “[name]_token.png”. Then upload that token in Owlbear: First the “plus” icon at the bottom right (disable fullscreen if this is hidden), then the “Import tokens” plus icon in the “Edit or import a token” modal.

With custom maps and custom tokens you’re ready to play your custom campaign. Which brings us to the last important feature of Owlbear: Rolling dice! For that, Owlbear provides a dice tray via the tiny icon at the top left, next to the party list. The palette icon let’s you choose from different style of dice. The next group of buttons are all for rolling dice. For example, to roll 2d6, click twice on the [6]. The rolls are somewhat physical, so sometimes you’ll end up with a perfect throw that turns to a failure in the last millisecond, as the dice topples over. Adding more dice to the tray might even change the result of dice that you threw earlier.

The last two buttons allow you to increase the size of the tray and to share your dice throws with the rest of the party (the globe icon). This last setting should be on for all players! For game masters, it depends if you prefer to hide (and fudge) your rolls or not.

There’s a few more features worth exploring, but these I consider the essentials.

Before Owlbear, we tried Roll20, but that didn’t really work for us. It has a loooooot of features and the virtual tabletop isn’t nearly as polished and accessible as in Owlbear. It might still be interesting if you prefer an integrated setup with the game system (like D&D 5e) and the virtual tabletop in one tool.

A battle scene in Roll20 from a past D&D 5e campaign

Zoom Pro

For the video call we use Zoom, with a paid account since our sessions are longer than the free plan’s 40 minute limit.

We’ve tried out various options like Discord, Jitsi and Google Meet. Zoom has the most consistent and reliable performance across operating systems, with the lowest processor load. In contrast, when we tried it, Discord’s performance on macOS was horrible, generating 100% CPU load non-stop, with crashes and freezes in every session for one participant.

Zoom generally works with “meetings” that you schedule or start ad-hoc. When playing with a fixed group, it can be useful to set up a permanent “room” instead.

Here’s how (at least in December 2021 this works, Zoom is likely changing their UI again in the future): Schedule a new meeting, give it a Topic, then set it to “Recurring meeting” with “No Fixed Time”. Use a Generated ID and Passcode, both should be set by default. Finally under Options (expand first) enable “Allow participants to join anytime”, that way you (as host) don’t have to be there before the others. The screenshots should help find each UI element:

Then Save that new meeting and share the meeting URL with your group. As long as the URL contains the Passcode, they don’t need to enter it.

We also use Zoom to share audio, usually atmospheric background music. I’ve never done that myself, but in this case Zoom has a decent explanation.

If Zoom isn’t an option, I recommend testing Discord. By creating your own server, you also get text chat rooms and you can have multiple video rooms (e.g. to have quick private chat between GM and a player). With the Dice Maiden bot you can also throw dice, especially useful for dice-based character creation or generating dungeons for Maze Rats (for which you need unsorted rolls, like !roll ul 6 2d6). Discord also used to have a nice audio sharing option via the Rythmbot, but that got shut down in September 2021.

D&D Beyond

Specifically for playing Dungeons and Dragons 5th edition (D&D 5e), D&D Beyond is great. Creating a character can be pretty quick, but will still take a lot of time if you pay for extra source books with access to all kinds of extra races, classes, backgrounds and whatnot. Here’s a Human Fighter character I created:

If D&D Beyond isn’t an option, an alternative editable character sheet for D&D 5e could be this Google Docs spreadsheet. You’ll have to copy it, then fill it out with your character. Its more fragile than D&D Beyond and won’t help you with character creation. But once created, it works well for leveling up and maintaining your inventory. Here’s my level 5 Barbarian from a past campaign:

Bonus: Artbreeder

Custom avatars as Owlbear tokens or on character sheets are pretty nice, but sometimes its hard to find the right image. When you need a custom picture, but suck at drawing, Artbreeder might be an option. You can upload a (limited) number of images, then change “genes” or “breed” multiple images to create something new. That’s how “Finn” was born:

There’s also an angry Finn:

And a happy Finn:

Changing one setting often heavily influences others, like angry Finn’s hair, beard and jawline changing a lot. Its still pretty impressive what you can create.

What else?

I’ve mentioned Excalidraw above for sketching custom maps. Before our groups started using Owlbear, we also used Excalidraw for shared scribbles, using their “Live collaboration” feature. We’d then draw maps, notes or memes together – something like this:

I have to mention DriveThruRPG here. That’s where I bought Maze Rats and Knave, as well as The Alchemist’s Repose and The Waking of Willowby Hall (yes, I’m into OSR this year). I’d go back there anytime if I need maps for a campaign.

Perchance is a great tool to create text-based random generators for anything. I’ve used this to create generators for Maze Rats magic items and NPCs. With some custom HTML and CSS, generators can also look much better, like this Maze Rats Spell Generator.

Another tool worth mentioning, but never actively used in our campaigns: Miro. This could work as a virtual tabletop where you can also look at pages from PDF rulebooks together. I’ve only used it at work – it works great as a virtual whiteboard for remote retrospectives.

From when we tried out Miro as an alternative to Excalidraw

Credits

Special thanks to Marcus, who did most of the research and testing for these tools. Lars was running a D&D 5e campaign since April 2020 for 18 months, where we had to and got to experiment a lot. Hermann introduced us to the invaluable Owlbear.

Maintenance Intervals

I’ve been using “Remember the Milk” as a Todo App for a really long time. At some point years ago I started using it to track repeating tasks, usually for things happening rarely enough that its important for the app to remind me. Gradually I’ve set up more reminders with shorter intervals, both for maintaining our apartment, and myself. While this is just my personal preference of organizing parts of my life, I figured it might be interesting for others, too.

A sketch of what my Todo app looks like on a given day, with a mix of recurring and one-off tasks, ordered by priority

At the time of writing, these are all the maintenance intervals I currently have in the app:

  • Daily: Back, shoulder and wrists exercises
  • Every two days: Workout
  • Every other two days: practice and play guitar
  • Weekly, Sunday: Clean cat water fountain
  • Weekly, Wednesday: Change water in cat water fountain
  • Every 3 weeks: Change bed sheets on all 3 beds and the cover on the changing table; if its the first time in a quarter, also turn the mattresses around
  • Monthly, on Sunday: Change the cat water fountain filter
  • Monthly: Check and fix tire pressure on our bicycles
  • Monthly: change the water filter (Brita) filter and put everything in the dishwasher
  • Monthly, first day of each month: Turn all 3 calendars in the apartment
  • Every 2 months: Clean the grease trap of the kitchen exhaust hood (Fettfilter der Dunstabzugshaube)
  • Every 2 months: Clean the cleaning robot and check if a part needs to be replaced 
  • Every 3 months: Review monthly costs+budget spreadsheet
  • Every 3 months: Clean the fridge
  • Every 3 months: Clean the shower curtain in the washing machine
  • Every 4 months: Clean dishwasher and washing machine
  • Every 6 months: Clean microwave
  • Every 6 months: Perform manual backups of files on PC (Dropbox, photos, music) and laptops (via Time Machine)
  • Every 8 months: Change the kitchen exhaust hood coal filter (Geruchsfilter der Dunstabzugshaube)
  • Every year: Export Telegram data (via Telegram Desktop)
  • Every year: Check ETFs, rebalance if necessary
  • Every year: Order special “urinary” cat food in bulk

I didn’t even realize how many of these I have until I wrote this list down. Its not exhaustive – there’s more maintenance we do, but some tasks have their own reminder (like the oven showing “PYR” when its time to burn some dirt), others their own processes (the dish washer is full) or habits.

Some of these intervals I have fine-tuned several times, some I still adjust every now and then. For example, when we discovered how dirty the microwave actually is, we’ve cleaned it once properly, then set up a reminder to clean it every month. At the same time, we also paid more attention to covering food we put inside, so the need for cleaning got a lot less. That’s how we ended up with the current interval of 6 months.

The two newest intervals are the two day interleaved workout and practice guitar tasks. Doing these every day is just too much, but every two days works pretty well for me. I started the regular workouts in September and have been pretty consistent since then. I focused on something you might call calisthenics for a while, then spend some time with elastic bands and heavier dumbbells. In the last few weeks, its been mostly Ring Fit on the Switch.

I bought an electric guitar early October, and tried practicing every two days since then. With 10+ years playing bass I had a good head start, though chords are still a big challenge (for my big fingers). I’ve played much more Rocksmith 2014 than I did with the bass – by itself its rather limited for learning, but it provides a lot of options and is very well-balanced gamified, similar to Ring Fit.

My daily, roughly 5 minutes back, shoulder and wrists exercises I’ve been doing for some months now, too. Along with the workouts, I haven’t had any issues with shoulders or neck, after some weeks of pain in the spring and last year. Maybe optimizing my desk setup (external monitor with camera on top) has also helped keeping those issues away.

I wonder which of these reminders I’ll keep in the next years, and which I add on top. I’m also interested to hear how you’ve approached these.

Three of a Perfect Pair

This post is about three approaches for remote pair programming that I recently learned to value a lot. They’re not perfect, but I like the King Crimson reference.

Come Prepared

Do all set up, check out, scaffolding or other basics, before you start pairing. If you’re debugging a complicated issue that needs a standalone reproduction, build that first, than use your pairing time to debug. If you’re continuing work on a feature, check out the existing or new branch first, start your development server, open the relevant files, start your unit test watcher, open the app, log in, or whatever else might be needed. Everything that is boring, where your pairing partner likely has nothing to contribute, should be done before hand. If you’re starting something from scratch, create the project (from a template first), initialize git and so on. Unless the point of the pairing session is to pick a framework or library, make sure that the new dependency is already installed and imported.

Use a Collaborative Editor

Use an editor experience where you can edit code at the same time. Something online like Glitch or repl.it, or some desktop setup like VS Code with Live Share. Use this to quickly change driver/co-pilot or suggesting single lines, not so much to work on different parts of the code in parallel. If you end up working in parallel, there’s a good risk you both make mistakes that are harder to find later, ruining the benefit of pairing.

Don’t be like me a week ago, thinking that Live Share doesn’t work for web development without a shared browser. Instead use the shared server feature and do (exploratory) testing in parallel.

When you’re exploring solutions to a problem you don’t yet understand well, consider using other collaborative tools, outside of code editors. With Excalidraw, Google Drawing or Miro you can sketch or scribble together (probably all more effective than sketching on paper and holding that in front of the camera).

Keep an ‘Improv’ Mindset

In improv (as in, improvisational, live theater/comedy), the “Yes, and…” rule encourages a positive attitude, accepting suggestions from others and building on top of them. When your pairing partner suggests something that sounds wrong, refrain from pointing out the mistake and try to roll with it. If it really is a mistake, they should realize that quickly enough. If its costly to try out, probe gently instead. There’s also a good chance that the suggestion is great, and you just didn’t quite understand it, yet.

In a recent pairing session, we were working on an image sampling task, trying to detect overexposure in video frames. At one point my pairing partner suggested to split the image into sectors and run the detection in each sector individually. At first I didn’t understand the point of that suggestion, but managed to refrain from rejecting it. After a bit more exploration we realized that these sectors would also provide much better feedback to the user – instead of saying “this frame is overexposed”, we could instead point to a specific sector. This improved the solution greatly, with very little code and runtime overhead.