I turned 24 today. This weekend has been a bit busy and overwhelming – but perfect.
On Friday I went to Dundee for some Marioke, which was fantastic. The event itself was amazing, but it was also nice to see some Dundee friends I hadn’t met for a while. Hopefully we’ll have another Marioke in Scotland some time.
Last night we had some friends over for a flat party. My flatmate had decorated the whole place in birthday stuff while I was out during the day (at edindies, in fact). That was a lot of effort I didn’t expect anyone to take, but really appreciated. She also got me a cake!
Natalie made me a birthday card in short game form, which was incredibly sweet. I’m really grateful for her.
Today I had lunch with my mum and I’m meeting my dad for dinner. It’s nice to see them both, as usual.
I’ve been barrelled over by all the folks who have checked in and said happy birthday, over the internet or otherwise. It’s not that there’s been more than usual, it’s that I seem to be paying attention to it more. I think for a number of years I haven’t really noticed birthdays – in fact last year I thought I was turning 22, not 23 – but this year has been different for some reason. Maybe it’s just that some things kind of settled into place this year? Who knows.
Anyway, thankyou for being along for the ride. Here’s to another year of us.
I’ve added a new page to the website containing a few podcasts I regularly listen to, or have listened to in the past, that I think are good and want to share with people. At the moment there’s only a handful. I’ll update it with new ones occasionally.
I’ve written in the past about standard-library smart pointers and how they can make management of memory allocated from the heap much easier. How useful are they when working with objects allocated from elsewhere, such as objects created by a library we use?
Box2D is a popular 2D rigid-body physics engine in which the b2World is the top-level object that represents the physics ‘world’. Rigid bodies are represented by instances of b2Body and are created like so:
// world is a b2World*// bodyDef is a b2BodyDef that describes the properties of the new bodyb2Body*body=world->CreateBody(&bodyDef);
The b2World owns the b2Body and the memory it is created from, and when the world is destroyed it destroys all the bodies it contains. To remove an individual body and free its memory we call b2World::DestroyBody(b2Body*).
This creates a small challenge for us when we build our game code on top. Let’s say we have an Entity class, which has a b2Body* member.
classEntity{b2Body*body;};
In Entity’s destructor we may want to call DestroyBody, so that when an Entity goes out of scope, it tells the b2World to remove its body from the world:
Unfortunately, this is no good. By default, std::unique_ptr’s destructor calls delete on its internal pointer, which isn’t what we want. The b2World is who really owns the memory, so deleting it out from underneath it would probably cause undefined behaviour down the line, if not immediately. The memory which the b2World allocates bodies etc. from may be a pool block-allocated from the heap. It might not even come from the heap, it may be on the stack. Either way, calling delete on a bit of it would not go down well.
So we need to call b2World::DestroyBody instead of delete.
Custom Deleters
We’re in luck: std::unique_ptr has more than one template parameter.
The first is the type to which it points, and the second allows the user to define a custom deleter. A custom deleter must be a type with an operator that takes a pointer to T. The custom deleter lets us define what unique_ptr’s destructor does if its internal pointer is non-null.
Here is a pointless example of one that just does the same as std::default_delete<b2Body>:
decltype(&b2BodyDeleter) gives us the type of a pointer to the b2BodyDeleter function (which I’m not going to write, because ugh). However, when we try to instantiate BodyPtr we hit a snag – the class doesn’t have a default constructor anymore, and must be constructed with a pointer to b2BodyDeleter (or any function with a matching signature, actually – so much for safety!).
BodyPtrbody;// Doesn't compile!BodyPtrbody(nullptr,&b2BodyDeleter);// Does compile!BodyPtrbody(world->CreateBody(&bodyDef),&b2BodyDeleter);// Does compile!
Unfortunately, BodyPtr is no longer a zero-cost abstraction as it now consists of both a pointer to a b2Body and a function pointer.
If we instead use a functor like our original b2BodyDeleter then the empty base class optimization allows unique_ptr’s size to equal the size of a raw pointer. When using a function pointer our smart pointer becomes stateful, meaning it carries additional stuff along with its underlying raw pointer. This is a bit of a gotcha, and arguably things shouldn’t have to be this way (i.e. functions in C++ should be first-class types), but writing a functor or a lambda to avoid this isn’t too much bother.
We had a choice here. Instead of accessing the b2World using b2Body::GetWorld we could store a World* (or World&) in b2BodyDeleter, setting it in the constructor. That doesn’t really bring any advantages that I can think of, and I can think of two disadvantages. For one, it would force us to specify an extra argument every time we instantiate a BodyPtr. For another, it’d make the deleter stateful and increase its size. No good!
Now we can swap Entity’s raw b2Body pointer for a BodyPtr, and we never have to worry about manually calling b2World::DestroyBody for the Entity’s body again. The body will be removed from the world when the Entity goes out of scope. We get all the other benefits of unique_ptr, too.
There are limitations to doing things this way: an Entity now must go out of scope before the b2World does, otherwise b2Body->GetWorld will return a dangling pointer. We can no longer destroy the b2World before all the Entity instances who are using it unless we call release on each Entity’s BodyPtr before its destructor is called.
This example may seem like a bit of a strawman to you, but in my homebrew game engine switching from using raw b2Body pointers to smart ones has been a pleasant improvement. It fits into my RAII-based approach to just about everything.
Further Reading
Fluent C++ did a series about smart pointers recently, with a few posts dedicated to custom deleters:
Recently me and Natalie went on holiday for a week in the south of France. We stayed in an old townhouse in La Garde-Freinet, a village nestled in the hills above Saint-Tropez, with my mum and her partner.
I’ve been there a few times before but not for about five years. It was good to be back. It’s a lovely, pleasant and peaceful place; the perfect retreat. In many ways it’s just as I remember, but in October it has a rather different feel than it does in summer, during which I’d previously visited. Many of the shops and restaurants are beginning to close down for the winter when there is too little business for it to be worth opening, and generally it is a bit quieter in the absence of high-summer holiday traffic.
The surrounding countryside is densely forested and the hills are low enough to be covered all the way to their peaks in a foliage, giving them an almost fuzzy appearance. Autumn hasn’t quite arrived yet and everything is lush and verdant, if a little dry. On the plains to the north and south the forest sprawls, giving way only to roads, groves, villages and vineyards. Big umbrella pines tower over smaller deciduous trees, bushes and shrubs. The earth is the colour of rust, visible between blades of dry, brittle grass.
The region is a historic producer of silk, chestnuts and cork, and it still exports the latter two. Along the edges of paths one can find trees that have been stripped naked of all their bark up to about head height, and chestnut trees are abundant.
We spent the week going for walks in the village and the area, relaxing, eating and sleeping. It was great to spend so much time with Natalie.
We made a day trip to the Gorges du Verdon, a truly awe-inspiring landscape. Vultures circle above brilliant white crags between which, hundreds of metres below, flows a sliver of pure turquoise. Every bit of land that isn’t vertical is blanketed in foliage, now breaking out into autumn colours. We drove along the top of the gorge, taking in the vistas, then followed the road down into it, clinging to the sides.
After emerging from the gorge’s mouth, which opens onto a long ice-blue lake, we visited the village of Moustiers-Sainte-Marie. It too is a stunningly beautiful place, old and quaint and majestic all at once. Above of the village, atop a long flight of steps, perches an old chapel, which we made the climb to visit.
Then, leaving the village, we rented a pedalo and took it back into the gorge, gaping at the scale of the thing, peddling past weird rock formations and strange caves. If you ever find yourself in the region, I highly recommend checking it out.
Also, I drank multiple cups of wine every evening. It was great.
It has a lot in common with developer Big Robot’s previous game, Sir, You Are Being Hunted, a first-person stealth-em-up set in a procedurally-generated pastiche of the English countryside in which humans are pursued across bleak rural and post-industrial landscapes by aristocratic robots and their mechanical hounds. It’s like Tory Britain, but with the possibility of escape.
The planet Tölva is less Doctor Who and more Roadside Picnic. It’s had a rough time. At some point in its past debris from countless wars crashed onto its surface, leaving only traces of what was there before, and now the drones of three warring factions fight over the remaining spoils in a remote-controlled conflict, searching for something. That’s where you come in.
You’re hacking into the drone network of one of the factions, hijacking their automata so you can explore the planet and discover more about the titular Signal. That’s where the mandatory story stops and your freedom to get on with the business of playing the game begins.
Most of what you do is walk and look at things. The experience of simply traversing Tölva’s scarred hills and rubble-strewn valleys is remarkably intense. There are moments of stillness during which you warily scan the distance for threats or watch some of the planet’s wildlife sail serenely across the sky. Then a distant battle breaks the silence, as shockwaves from explosions echo off the stones, and the austere synths of the game’s soundtrack give momentum to your hike. Entering one of the map’s numerous strange places, your vision and hearing become warped and glitchy, sometimes fantastically so, and you feel a bit like the pilot of a deep sea exploration drone. It’s very reminiscent of some of the best times I had with the Stalker games.
Everything is styled after the magnificent concept art of Ian McQue, giving the feeling that you’re walking through a painting that’s been masterfully brought to life. It’s so eminently screenshot-able that I amassed a hundred or so screenshots in my playthrough. Picking out the ones to use for this post was quite a challenge.
Big Robot’s approach to bringing the McQue’s art to life is worth noting. In one video and accompanying blog post the developers discussed how they deconstructed McQue’s style, identifying the components of his ‘visual vocabulary’ from which create the modular art assets used to construct a game world. That kind of craftsmanship, attention to detail and creative pragmatism is on display all over The Signal from Tölva. It’s a fine example of how a small team of savvy and skilled-up individuals can come together to create impressive work, and absolutely worth reading about in their blog posts and various interviews.
Bots Behaving Badly
Eventually you will have to fight. In Sir combat was something to be avoided, a frantic and unfair last resort that usually ended with your death. Here combat is inevitable, necessary, and you’re much better equipped to take part in it. Your hitpoints regenerate and the price of death is low – when your current host is destroyed you just hijack a new robot body to inhabit at any strategic point controlled by your faction.
That doesn’t mean charging headlong into the fray is a valid strategy. Battles you don’t plan are usually battles you don’t win. Combat is methodical, with a high time-to-kill and tension loaded into long reload and cool-down times. Enemy and allied robots all use the same set of weapons and tools as you, so you’ll never be confronted with something you yourself can’t bring into battle.
Progression mechanics are of the sort people are probably used to from mainstream open world games, albeit limited in scope. Completing missions unlocks new weapons and powers, while the resources needed to purchase them must be salvaged from wreckages and by killing enemies. There’s not a lot of variety in the range of weapons on offer – there are five main archetypes and the arsenal is padded out with slight variations of them at different levels of effectiveness – but it’s enough to scrape by.
One of your options is the fantastically named ‘SQ-UID Phreaker’, a tool that gives you command of robots from your own faction. You have limited control here: you can tell them to follow you or move to a particular location, but not as individuals. You can’t customize the loadout of your squad members, so if you want to build the perfect team, you’ll have to assemble it by luck. Nonetheless having a squad of robo-buddies at your back as you march across the map is a comforting thing to have in what would otherwise be a very lonely, isolating game.
It’s very easy to digest. Playable in small chunks, it’s always possible to make some measurable form of progress in 15 minutes, or at least to go on a pleasant hike. Hoovering up some resources from a salvage site, searching for rarities and nuggets of story in nooks and crannies, even striking out at an enemy bunker in an attempt to capture it: all possible within a short time-frame, each its own mini-adventure with potential for surprising encounters. Dynamic, un-scripted stuff just happens without any player input: squads of robots get into scraps with one another, capturing and re-capturing territory from each others’ factions, including your own.
The planet seems to be waking up, or perhaps just turning over in its sleep. Like the irradiated and alien Zone of the Stalker games, when it is not actively hostile to your presence, it is at best merely indifferent. It appears to be a graveyard for much older things than the crashed war machines that litter its surface. It’s difficult to figure out what’s going on and why because the scraps of information you find about the world you’re in are brief and sparse. What you do uncover as the game goes on is eldritch and unsettling. Cosmic horror for the information age. If I ever do understand quite what The Signal from Tölva is about, even just on the surface, it will have taken me a while to reach those conclusions. I welcome that mystery.
Sir, You Are Being Hunted never grabbed me like this, never left such a dent. Not many games do. Actually, honestly, I think that what Big Robot have created with Tölva deserves to be celebrated as a classic in its genre. It’s smartly made and smart to play, beautiful to look at and haunting to listen to. I hope you give it a go.
As for me? Well, there’s a free expansion on the horizon and I fully expect I’ll be sucked right back into Tölva the moment it arrives.