Author Archives: david

Programmer at Large: Are you serious?

Note: The previous chapter had a rather critical misplaced decimal point. Ship launch was 9.7 gigaseconds ago (about 300 years), not 0.97 gigaseconds ago (about 30 years).

Once the initial problem had been tracked down and verified as trivial I had to time to think about it some more.

Which is when I started to get angry.

There’s a lesson we all learn at early age: What do you do when you find something that’s wrong? You make sure it gets fixed. Then, once it is fixed, you make sure the thing that allowed it to previously go unnoticed also gets fixed.

I couldn’t entirely blame Tulela. Launching a ship is a gruelling and unforgiving task, adapting the trade operating system for a new set of hardware and trying to get everything stabilised enough for thousands of people to live in for hundreds of gigaseconds. I hope I’m dead long before the Eschaton Arbitrage forks, because I do not want to have to be a part of that.

But it was still gross negligence, and we were very lucky this hadn’t lead to a more serious problem.

“The relevant systems all seem to be working fine”. Are you serious? Who even does that? Do you know what happens when plumbing crashes on an interstellar voyage? Drainage backs up, heat regulation destabilises, cooling systems fail, and if the problem cascades then the cryostasis systems hard abort and anyone who is too deeply asleep undergoes an emergency thaw and if they’re really lucky they get away from it with little more than minor brain damage.

When you leave problems to go unfixed until they become serious people die.

Of course that doesn’t happen often. It’s happened twice in the recorded history of our lineage, one time after heavy battle damage. But do you know why it doesn’t happen often? It’s because the plumbing system has hundreds of interlocking and mutually supporting checks and balances that actively work to keep the system in a stable state. And those keep working and making sure that nobody gets brain damage because when you find problems you make sure they get fixed.

My HUD was making increasingly insistent notifications that my heart rate up was up and my stress levels were elevated. It recommended that I stop what I was doing and meditate for a kilosecond until I calmed down. I dismissed it and settled for a few calming breaths.

I knew I was being a bit unfair. Zombies are among the most harmless of problems, and every system is full of its weird little eccentricities. Ship launch is where you look hard at those eccentricities, but it can’t be the place where you fix all of them or you’d still be trying to get that ship launched when the local civilisation finally went the way of all grounders and nuked itself back into the stone age.

But but but argh.

I stopped, took a few more calming breaths and resolved to just fix things instead of getting angry about them.

So, there was a problem. I had fixed the problem. Step one was complete.

Which meant it was time to fix the thing that let the problem to escape detection.

“Ide, what fraction of process categories have not received any human attention since, say, 10 megaseconds after ship launch?”

“About 63%”

“Well, waste that idea.”

“Excuse me?”

“Never mind”.

I shouldn’t really have been surprised. There is a lot of software running aboard a ship, most of which has been heavily debugged over a period of hundreds of gigaseconds. Most of it should just work, and if it’s working you probably won’t notice it given how much there is of it.

“Of those, how many were last touched by Tulela?”

“Zero”

“What? How is that possible?”

“Tulela was not born until after the time period in question”

I sighed.

“Of those, how many were last touched by nod-sid 1?”

“A hundred and three”

“OK. Put those on the medium priority review queue with a note that nod-sid 1 may have been an unreliable maintainer.”

One of the nice things about dead crew is that you don’t have to mince words – something that would have been a political bombshell with a live crew member was just a simple administrative note.

Now to the rest of it.

“Ide, how many processes use this buffer style of logging?”

“I don’t know how to answer that.”

I hadn’t really expected that to work. If it had worked then the answer should have been zero. But you’ve got to try these things – it’s almost impossible to know the capabilities of the ship systems until you’ve tested them experimentally.

Or unless you’d written those capabilities yourself. It was time to get to work.

And emerged seven kiloseconds later with my work alarm going off. My wake time utilization for the last megasecond had hit 25%. No more work allowed for me until it dropped back down.

Which was annoying. I like work. It’s interesting, fun, and I’m good at it. Recreation is hard in comparison.

But the sociology was clear: All work and no play makes the Eschaton Arbitrage a dysfunctional crew, regardless of individual preferences.

I quickly reviewed what I’d done and made notes for when I resumed later.

The logging problem had been relatively easy to solve: You watch for processes which crash when they’d tried to write past the end of some on-disk buffer and capture the trace of what they were doing when they crashed. You run the trace through a bunch of clever translation heuristics that I’m very happy I didn’t have to write myself, and if a word meaning ‘log’ appears in the crash site you stick the process on a review queue marked “Possible Archaic Logging Practices”.

The statsd thing was harder. You can’t just look for processes trying to create connections they’re not allowed to because you’d be swamped. Of course processes are trying to create connections they’re not allowed to. That’s why we have a permissions system. If you’re running this much software from this many origins then a lot of is has weird assumptions about what it’s allowed to do, or even is actively malicious.

In the end I’d ended up trying to write some additional heuristics for one of the existing zombie hunters. It should have caught this process already but it didn’t because its access to the thermal monitoring hardware meant that it looked useful. So I tried to get it to figure out when some hardware access was read only and if a process only had read-only hardware access it would see if anything useful was escaping it and, if not, flag it for zombie review with a helpful explanation.

I wasn’t very convinced it was going to work, but that was a problem for next time. I shut down my workspace.

Too early to sleep, so I queried the ship to ask it to recommend something for me. I was sure it was going to suggest some socialisation. Instead, to my delight, it reminded me that as well as being overworked I was also behind on my exercise. Flywheel 3 was currently configured for high gravity exercise, which was recommended under my current regime, so it suggested making use of it while the opportunity was available.

I was all too happy to comply.

I exited the pod and made my way to the gym.

The halls were quiet, which I always like. Not for social reasons for once, but because it meant I could go fast. There’s something really satisfying about kicking off the wall and shooting down a couple hundred meters of corridor. I rarely get the aim exactly right, but you can correct by pushing off the sides or grabbing onto one of the various handholds as you pass.

It’s childish, but fun, and the ship will tell you if anyone is nearby so there’s no real danger.

The gym is near the base of the ship with all the other heavy equipment, so it took me about a kilosecond to make my way there.

The entrance area is pretty wide, so as to give you space for multiple people to change. It was completely empty when I arrived – not surprising given we were on mid-voyage levels of crew – but there are hooks around the walls for nearly 20 people to attach while they change, and you could fit another 20 waiting hanging off the central shaft if they cuddled up.

But for now, it was just for me.

I grabbed onto one of the wall hooks, stripped down, and took some shorts and a sports bra out of the locker to change into. Normal clothing went into the refresher, kit went on, and it was time to hit the gym.


Next chapter: How do you do?

If you liked this and want to read more like it, support my writing on Patreon! Patreon supporters get access to early drafts of upcoming chapters. This chapter is also mirrored at archive of our own.

This entry was posted in Fiction, Programmer at Large on by .

Determinism is topologically impossible

I’ve been doing some work on topological models of decision making recently (I do weird things for fun) and a result popped out of it that I was very surprised by, despite it being essentially just a restatement of some elementary definitions in topology.

The result is this: Under many common models of reality, there are no non-trivial deterministic experiments we can perform even if the underlying reality is deterministic.

The conclusion follows from two very simple assumptions (either of which may be wrong but both of which are very physically plausible).

  1. We are interested in some model of reality as a connected topological space \(X\) (e.g. \(\mathbb{R}^n\), some Hilbert space of operators, whatever).
  2. No experimental outcome can give us infinite precision about that model. i.e. any experimental outcome only tells us where we are up to membership of some open subset of \(X\).

Under this model, regardless of the underlying physical laws, any fully deterministic experiment tells us nothing about the underlying reality.

What does this mean?

Let \(X\) be our model of reality and let \(\mathcal{O}\) be some set of experimental outcomes. A deterministic experiment is some function \(f: X \to \mathcal{O}\).

By our finite precision assumption each of the sets \(U_o = \{x \in X: f(x) = o\}\) are open. But if \(f(x) = o\) and \(o \neq o’\) then \(f(x) \neq o’\) so \(x \not\in U_{o’}\). Therefore they’re disjoint.

But certainly \(x \in U_{f(x)}\), so they also cover \(X\).

But we assumed that \(X\) is connected. So we can’t cover it by disjoint non-empty open sets. Therefore at most one of these sets is non-empty, and thus \(X = U_o\) for some \(o\). i.e. \(f\) constantly takes the value \(o\) and as a result tells us nothing about where we are in \(X\).

Obviously this is a slightly toy model, and the conclusion is practically baked into the premise, so it might not map to reality that closely.

But how could it fail to do so?

One way it can’t fail to do so is that the underlying reality might “really” be disconnected. That doesn’t matter, because it’s not a result about the underlying reality, it’s a result about models of reality, and most of our models of reality are connected regardless of whether the underlying reality is. But certainly if our model is somehow disconnected (e.g. we live in some simulation by a cellular automaton) then this result doesn’t apply.

It could also fail because we have access to experiments that grant us infinite precision. That would be weird, and certainly doesn’t correspond to any sort of experiment I know about – mostly the thing we measure reality with is other reality, which tends to put a bound on how precise we can be.

It could also fail to be interesting in some cases. For example if our purpose is to measure a mathematical constant that we’re not sure how to calculate then we want the result of our experiment to be a constant function (but note that this is only for mathematical constants. Physical constants that vary depending on where in the space of our model we are don’t get this get out clause).

There are also classes of experiments that don’t fall into this construction: For example, it might be that \(O\) itself has some topology on it, our experiments are actually continuous functions into O, and that we can’t actually observe which point we get in \(O\), only its value up to some open set. Indeed, the experiments we’ve already considered are the special case where \(O\) is discrete. The problem with this is that then \(f(X)\) is a connected subset of \(O\), so we’ve just recursed to the problem of determining where we are in \(O\)!

You can also have experiments that are deterministic whenever they work but tell you nothing when they fail. So for example you could have an experiment that returns \(1\) or \(0\), and whenever it returns \(1\) you know you’re in some open set \(U\), but when it returns \(0\) you might or might not be in \(U\), you have no idea. This corresponds to the above case of \(O\) having a topology, where we let \(O\) be the Sierpinski space. This works by giving up on the idea that \(0\) and \(1\) are “distinguishable” elements of the output space – under this topology, the set \(\{0\}\) is not open, and so the set \(U_0\) need not be, and the connectivity argument falls apart.

And finally, and most interestingly, our experiment might just not be defined everywhere.

Consider a two parameter model of reality. e.g. our parameters are the mass of a neutron and the mass of a proton (I know these vary because binding energy or something, but lets pretend they don’t for simplicity of example). So our model space is \((0, \infty)^2\) – a model which is certainly connected, and it’s extremely plausible that we cannot determine each value to more than finite precision. Call these parameters \(u\) and \(v\).

We want an experiment to determine whether protons are more massive than neutrons.

This is “easy”. We perform the following sequence of experiments: We measure each of \(u\) and \(v\) to within a value of \(\frac{1}{n}\). If \(|u – v| > \frac{2}{n}\) then we know their masses precisely enough to answer the question and can stop and return the answer. If not, we increase \(n\) and try again.

Or, more abstractly, we know that the sets \(u > v\) and \(v < u\) are open subsets of our model, so we just return whichever one we’re in.

These work fine, except for the pesky case where \(u = v\) – protons and neutrons are equally massive. In that case our first series of experiments never terminates and our second one has no answer to return.

So we have deterministic experiments (assuming we can actually deterministically measure things to that precision, which is probably false but I’m prepared to pretend we can for the sake of the example) that give us the answer we want, but it only works in a subset of our model: The quarter plane with the diagonal removed, which is no longer a connected set!

Fundamentally, this is a result about boundaries in our models of reality – any attempt to create a deterministic experiment will run into a set like the above plane: Suppose we had a deterministic experiment which was defined only on some subset of \(X\). Then we could find some \(o\) with \(U_o\) a non-empty proper subset of \(X\). Then the set \(\overline{U} \cap U^c\) where the closure of \(U_o\) meets its complement (which is non-empty because \(X\) is connected) is a boundary like the diagonal above – on one side of it we know that \(f\) returns \(o\). On the other side we know that it doesn’t return \(o\), but in the middle at the boundary it is impossible for us to tell.

What are the implications?

Well, practically, not much. Nobody believed that any of the experiments we’re currently performing are fully deterministic anyway.

But philosophically this is interesting to me for a couple of reasons:

  1. I for one was very surprised that such a trivial topological result had such a non-trivial physical interpretation.
  2. The idea that non-determinism was some intrinsic property of measurement and not a consequence of underlying physical non-determinism is not one that had ever previously occurred to me.
  3. We need to be very careful about boundaries in our models of reality, because we often can’t really tell if we’re on them or not.
  4. It may in fact be desirable to assume that all interesting quantities are never equal unless we have a deep theoretical reason to believe them to be equal, which largely lets us avoid this problem except when our theory is wrong.

(As per usual, if you like this sort of thing, vote with your wallet and support my writing on Patreon! I mean, you’ll get weird maths posts either way, but you’ll get more weird maths posts, and access to upcoming drafts, if you do).

Programmer at Large: What’s that noise?

After Sam and I had chatted for a while I returned to a pod to resume work. I settled in and brought up my work space and began to review where I was.

My particular troubles of the moment had all started with a bug report:

Reported-By: jad-nic [上子/Kamiko]
Title: What's that noise??
Bounty: 400 millivote.
Body: Every now and then there's a weird noise coming from behind the interior wall
in Pod 11. It's a sort of WHOOSH followed by a flushing noise and a gurgle. I've heard
it three times now, about a megasecond apart each time [timestamps attached].

It's not a big deal but I keep worrying about it. Could someone check it out and
figure out what it is? Fix it if it's easy or important, but I really just want to
know what's going on.

The bounty wasn’t huge, but it was a pretty decent amount. It was nice to encounter people who actually cared about plumbing.

While reviewing I made a note that I should say hi when we were both awake at the same time. It would get ship off my back a bit, and they worked in hydroponics so we’d have plenty of things I was actually good at to talk about.

Anyway, nobody from the official plumbing team was ever going to look at this – the ship is full of strange noises, and they’ve got much higher priority things to worry about. I don’t know offhand what but it’s basically guaranteed that if you work in plumbing you have high priority things to worry about.

But it sounded interesting (to me) and weird, which makes it exactly the sort of problem I get to work on. I love being a programmer at large, and not just because I have to talk to fewer people this way.

So before I last went to sleep I’d set up some monitoring on the microphones in the wall near the pod to listen for the noise then sample and bucket all the semi-relevant data before and after it. After a fifty megasecond nap I woke up to sift through what it had gathered.

During this time about 70 gigaprocesses in the plumbing system had crashed. A bit on the high side, but well within normal variation.

I’d picked the most plausible candidate – a process category with about ten thousand members, all of which crashed shortly before the noise and which normally didn’t crash in quite such a correlated way – and was now digging in to why it was failing.

Which was easy enough: It was appending data to some buffer on its local disk. The buffer was capped at quite a reasonable size – 512MiB – but the process just tried to grow the buffer past that and crashed when it couldn’t rather than doing anything sensible. Nothing very surprising so far, and the system handled it automatically by restarting the process from a fresh state with an empty buffer, at which point the whole cycle began again.

Unfortunately that left me none the wiser about what this process did, which is why I was now having to learn enough C++ to figure that out.

Subject: C++
Category: Programming language, text based.
Lineage: Pre-diaspora, began as a dialect of C in 1983.
Common Tags: Archaic, Esoteric, Low Complexity, Annoying.
Normalised Rating: Best not if you can avoid it.

The wiki entry on it was less than encouraging. Hopefully I wasn’t going to have to learn very much of it.

The relevant line where the process crashed was the following:

client->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(-1 == client->sock) {
    LOG_ERROR << "failed to connect to StatsD";
}

“Wiki, what’s statsd?”

“Historical records suggest that it was a centralised service for metrics aggregation popular in pre-diaspora software. The term subsequently became generic and many cultures use it or a derived word for the general concept.”

OK. So we have two questions now:

Firstly, why can’t it connect to statsd?

Secondly, what does logging an error have to do with appending to a buffer on disk?

Let’s focus on the proximate cause for now and start with the second.

“Ide, show me what this line with LOG_ERROR on it does.”

It expanded the results of the call. Ah. It wasn’t really a log at all.

“Ide, translation note: LOG_ERROR in this context may actually mean that it appends error data to a disk buffer and may not result in any logging occurring.”

“Noted”

“Wiki, what’s a file?”

“In the traditional software practices of pre-diaspora cultures, it was common to arrange a system’s data in a single named hierarchy of disk buffers. The term ‘file’ was used interchangeably for names in this hierarchy and the buffers themselves.”

“What? Why did they organise data that way? Didn’t it get confusing?”

“Historical consensus is that it probably seemed like a good idea at the time and that yes it did.”

“OK. So why is this logging call adding data to a file?”

“Many traditional software practices consider this to be how logging is performed. When problems occurred a human would inspect the contents manually to determine what had happened.”

“Did that work?”

“No.”

“Ugh. Is there a policy on what we do about this sort of archaic logging?”

“Either a separate process converts the buffer into log events periodically or we intercept the calls to write to the buffer and log them directly instead of writing them. Recent consensus is that the latter is preferable.”

The buffer was getting written to, so if we were doing anything about it at all then it had to be the first one.

“OK. Ide, do we have any other processes inspecting this buffer?”

“No, the buffer only grants access rights to the current process.”

I was starting to suspect I was fighting a zombie – a process that had no useful purpose any more but was still shambling around getting in people’s way and occasionally eating their brains.

“Ide, when was the last time someone looked at this process?”

“About 9.7 gigaseconds ago”

9.7 gigaseconds ago… oh no.

“You mean ship launch?

“No, about 5 megaseconds before ship launch.”

“Show me any annotation they left.”

From: nod-sid 1 [Tulela]
Subject: What is this?
Body: I don't know what this is doing. It looks like a zombie? Whatever,
the relevant systems all seem to be working fine and there's like a billion
things still to do for launch. Add figuring this out to the backlog.

Did you just tell me to go waste myself, Tulela? I believe I did, Arthur.

“OK, give me a snapshot of the buffer contents at point of crash.”

As I’d been starting to suspect, the contents looked like the following:

failed to connect to StatsD
failed to connect to StatsD
...
fail

fail indeed.

“Ide, can you automatically convert this code to do actual logging?”

“Yes.”

“OK, do so.”

“Done.”

I sighed. OK, back to the first question. Why can’t it connect to statsd?”

A socket was apparently another word for a network connection. So it was trying to create an outgoing network connection. The most likely explanation was obvious.

“Ide, does this process have rights to create network connections?”

“No.”

Right.

“Ide, show me what’s left if you remove all code that has no effect other than writing to a private disk buffer or can’t run without the process creating a network connection.”

#include <iostream>

int main(){
    std::cout << "Starting up event monitoring system!" << std::endl;
    return 0;
}

Right. Good. It was definitely a zombie and I was going to get to shoot it in the head. That was always satisfying.

So that left just one question: Why was this zombie self-destructing right before the actual event I was interested in?

“Ide, show me the most unusual function on the call stack at point of crash.”

void logAnomalousTemperatureEvent(double t_delta, double time_delta){
    ...
}

So the process crashing was never a cause of the problem at all. It was a symptom.

“Is there a corresponding set of interesting temperature events in our log roughly at the same time as these calls?”

“Yes”

OK. So, in conclusion I had learned two things:

The first was that this was definitely a zombie and was not giving us a useful signal we didn’t otherwise have here, but at least I could kill it.

The second was that this whole thing was otherwise a complete waste of time.

From: vic-taf [Arthur]
Subject: Zombie monitoring service in the plumbing system
Priority: Low
Proposed action: Staged shutdown of service '077a58e24e34b6543da8100c8541a8dd'
Body: This service doesn't do anything and and as far as I can tell has
never done anything except create noise. Development log attached as evidence.

Next chapter: Are you serious?

This chapter is also mirrored at Archive of Our Own. If you liked this and want to read more like it, support my writing on Patreon! Patreon supporters get access to early drafts of upcoming chapters. Although honesty compels me to admit that right at this minute there are no drafts of upcoming chapters available. I’ll probably write more this weekend)

This entry was posted in Fiction, Programmer at Large on by .

Upcoming reduced publishing rate and Patreon

Historically I’ve had a bit of a problem: Blog posts either get finished immediately or die. My drafts folder is more or less a wasteland of things I’ve never finished and am never going to finish, so almost all of my blog posts get written and published in one sitting.

But the recent experiment with Programmer at Large has made me realise the obvious solution that somehow in more than ten years of blogging it never occurred to me before that I could do.

Which is that I can finish the blog post and then not click publish.

Yes I’m embarrassed that I didn’t think of this before too.

The result is that instead of a wasteland of unfinished posts, my drafts folder becomes that place where I have a buffer of things that are ready to publish at any time but if I want to I could spend some time editing and improve a bit first.

Then, when it’s time to publish a post, I can just find an example from the queue which I like and click publish on it. Done. Yay. I can also shortcut and publish something new immediately if I like, but I don’t have to.

So I’m going to do this. It’s going to be great.

What this means for you, dear reader, is the following:

  1. Expect post quality to go up because more editing will be happening
  2. Expect post rate to go down to more or less precisely track the Beeminder goal rate (currently 1.48 posts per week – it’s derived from the monthly Patreon income).
  3. If you want more than that, donate to the Patreon. As well as increasing the publishing rate, I’ll be sharing drafts on the Patreon feed with anyone donating $2 or up. I’ll share these as soon as I have a first draft I’m more or less happy with, so they’ll go up more or less at the level of finished that blog posts currently go up at.

Despite the link to Patreon, this isn’t just me holding my blogging to ransom for money. One of the things I’ve been meaning to work on for a while is my ability to edit prose – I’m much better at writing the initial draft than I am at editing – and this is a great way to start working on that.

This entry was posted in Admin on by .

Programmer at Large: What’s your name?

(Previously. Also, this chapter is mirrored at AO3)

I kicked off down the corridor, caught myself at the entrance and hooked my way into the common area, pausing briefly on the central cable near the entrance to have a look around.

Near me some programmers at arms were having an animated conversation – something about Nash equilibria – while further down there was a larger group hanging off each other in an amiably silent cluster. On the other side of the shaft from them,  two pairs were deep in conversation. I recognised most of the faces, but nobody I was that close to.

Fortunately, I didn’t have to interact with any of them just yet. I was here for a meal, which gave me a solid excuse: I like to eat alone. It’s a registered eccentricity. Sure, it makes people think I’m weird, but having it registered means they don’t think I’m being anti-social.

I pulled my way along the cable to the end of the room, grabbed a pouch from the dispenser,  and bounced back to hook myself on about halfway down – not far enough from people to seem standoffish, not close enough that I might have had to interact with them.

Yes, I know I have a problem. I’m working on it, OK?

The meal had a bit of an odd flavour. The yeast was… well not exactly bad, but there was a musty flavour to it that definitely wasn’t good. I made a note about it and my HUD informed me there was a vote on the subject.

Apparently there had been a harmless contamination of this batch. The vote was whether to dump it and cycle in a new one, or just eat our way through it until it was finished.

I spent some time looking through the predictive models – it wouldn’t really strain us. The reduced resources would mean we’d probably have a couple people go to sleep until they were back up to standard, but we’ve got about 400 megaseconds to destination so there’s plenty of time to go around.

So, why not? We might as well ditch it. I expressed my intended vote and preference strength, my tactical assistant suggested a figure, and I approved it. Done.

As was my meal. Which, sadly, meant that I was going to have to talk to people. I called up the matchmaker and started to ask for suggestions but, thank the Plan, I was saved from having to deal with it by … ugh, let’s go with “Zod-Bim”, sailing in through the doorway.

I sighed slightly and waved at them anyway.

Their response was more enthusiastic. They grinned broadly and practically launched themselves across the room at me. They arrested their momentum by grabbing onto my shirt, hooked in next to me, and then cuddled up close. We cheek-kissed hello.

My HUD made an approving notification at the social contact.

“Arthur! It’s good to see you! It’s been megaseconds!”

(HUD flashed the correction that it had in fact been four hundred kiloseconds. We both ignored it).

“Good to see you too, Zod-Bim”

“Zod-Bim? I have a registered use-name you know.”

“I am not going to call you Ghost Walker 5000.”

“Oh come on. How would you like it if I called you Vic-Taf? I thought we were friends!”

“Arthur is an entirely respectable use name. Ghost Walker 5000 is a terrible cartoon character from an inappropriately antisocial grounder culture.”

“Ghost Walker 5000 is a timeless classic with a lot to teach us!”

I sighed dramatically and buried my head in their shoulder.

“Ghost Walker 5000 is a shallow drama about a hapless individualist who bounces from problem to problem, flails around for a few kiloseconds and then ultimately solves things with violence.”

I solve things with violence.”

“You solve things with tactics. Ghost Walker 5000 hits people with their fists.”

“I hit people with my fists too!”

“Krav Maga practice isn’t the same!”

Zod-Bim sighed dramatically.

“Fine, be like that. You can have a boring person use name for me. Go ahead, pick one. I don’t care.”

That was not an answer I was expecting. Even with the casual attitude Zod-Bim has on the subject, picking someone else’s use name is a big deal.  I hadn’t thought we were that close friends. I didn’t even know where to start, so I asked the system to suggest a couple names and had a quick look over them to get some ideas.

“I’m waiting…”

“Wait you want it now?

“Well you can’t very well keep calling me Zod-Bim until you’ve picked the perfect name, can you?”

“Ugh. Fine.”

I asked for a couple good suggestions with an affinity to my use name – if I didn’t have time to do it properly I was at least going to make it a bit personal – and picked the third one because I thought it would amuse them.

“How about Sam?”

“Wait, I can be Sam?”

I checked with wiki.

“System thinks so. You couldn’t be sam-sam, but with just one byte there’s no ambiguity.”

“Amazing! I’m Sam now!”

My HUD flashed up a notification that Zod-Bim had added a new use name, along with congratulations on the positive social interaction and a cautionary note about the dangers of pairing. I dismissed it.

“So, Sam, what have you been up to?”

“Oh I have had the worst time of it recently. That lot over there” – they waved to the group near the door – “have been hogging all the war simulator time, so I’m mostly just teaching Krav Maga classes at the moment.”

“Why is that bad? Didn’t you just say you liked hitting people?”

“Yes but these students are terrible. It’s like they learned to fight by watching Lesbian Space Pirates.”

“Didn’t you learn to fight by watching Lesbian Space Pirates?”

“Hey! That’s slander!”

I seized up. They were right, it was totally untrue, and now they were going to hate me and I was going to get voted off the ship at the next destination and-

“You’re right, I’m sorry, I, uh, I’ll go I”

I started to pull away towards the door but Sam grabbed me. At about the same time I finally noticed my HUD was flashing a giant “THAT WAS A JOKE STOP PANICKING THEY AREN’T OFFENDED” symbol in my face.

“Waste it, Arthur, I’m sorry. That was stupid.”

I tried to brush it off, but allowed myself to be pulled back into their embrace.

“No, no, it’s fine. I should have realised that was a joke. I’m the one being stupid.”

I breathed deeply, trying to will my heart rate back down below two beats per second and repeatedly telling myself it was fine, just a false alarm, and trying to relax.

“You’re right. You are being stupid.”

I froze again.

“What?”

“I didn’t learn to fight from watching Lesbian Space Pirates. I learned from bod-qof 11, one of the greatest Krav Maga experts in the crew’s history!”

And relaxed again. I could tell I was being deliberately distracted of course, but I went along with it. They meant well, and if they were trying to help me I probably really hadn’t bothered them and they weren’t going to hate me.

“OK, fine. You didn’t learn to fight from a grounder TV show. I was wrong. I get it.”

They learned to fight from watching Lesbian Space Pirates.”

What?”

“Oh, sure, they had a bit of help from the existing self-defence classes and a few millenia worth of VR martial arts training programs… But they started with Lesbian Space Pirates.”

Voice stress analysis on HUD didn’t give any indicators that they were joking.

“You are joking, right?”

“No! You mean you don’t know about the grand martial history of the Eschaton Arbitrage and how it was all started by the Lesbian Space Pirates?”

“I, uh. Let’s assume that I don’t.”

“Right, that’s it. You’re coming to the next movie night, and we’re showing you the documentary.”

I tensed a bit and they backpedalled slightly.

“Uh, if that’s OK of course.”

“No, no, it’s fine. I’d like that.”

Movie nights aren’t too bad. They count as a group social activity but I mostly don’t have to talk to anyone. The system knows about the loophole of course but as long as I don’t use it too often it’s fine with it.

“Right, good. It’s decided.”

A calendar invite flashed up and I accepted it.

“Anyway, let me tell you about what these useless trainees did…”

Next chapter, “What’s that noise?”

(Like this sort of thing? Why not support my writing on Patreon! As well as a warm glow from supporting something they enjoy, backers get access to early drafts of upcoming chapters.)

This entry was posted in Fiction, Programmer at Large on by .