Pico-8

The Pico-8 fantasy console.

Parent tag: games

Child tags:

Caoimhe

What I’m reading vol. ⅩⅢ

Vols.: Ⅰ, Ⅱ, Ⅲ, Ⅳ, Ⅴ, Ⅵ, Ⅶ, Ⅷ, Ⅸ, Ⅹ, Ⅺ, Ⅻ, ⅩⅢ, ⅩⅣ, ⅩⅤ, ⅩⅤⅠ

Hello! I am having a lazy Sunday to kick off the start of March and it seemed like a good time to post some more links.

Musical accompaniment is the Celeste soundtrack, inspired by me having just watched Bizmuth’s video on the world record speedrun and getting emotional watching someone playing the summit again. I think Maddy Thorson might be good at making games.

Apologies for the amount of these that are more bitching about “AI” I will keep that section for the end so you can ignore it if you are sick of reading about that.


Warfare in Dune, Part I: Fighting Faufreluches — Bret C. Devereaux

Starting with something fun: I always enjoy Devereaux analysing fiction from the perspective of historical systems and technologies with a particular eye for the reasons why things were done or made in a particular way in a given time and place.

So we might first ask if this fighting system, at the individual level, makes sense given the fantastical constraints Herbert’s shields impose. And I guess my answer is…sort of? I think the idea of a return to contact weaponry in this context works in the main, but with two main exceptions, which is that the style of contact weapon fighting that dominates is not what I would anticipate and second that the way Herbert also excludes laser weaponry strikes me as perhaps not fully thought out.


Games

Finally, a car mechanic sim where your mates do all the work — Brendan Caldwell

First off I am giving Jank another plug. Go read Jank! Support non-ad ridden publications! They got Alice Bell and Sin Vega (as freelancers)! What more do you dogs want?

I sell the wheels, both tires and rims. This is when I notice a small, uh, discrepancy between the listed "sell price" and what we actually receive into our bank account. Jonty expresses some worry, and tells me to check the computer in the corner of the garage to see how much it's going to cost to buy the new wheels, you know, "down the road" as it were. I look at the prices. I walk away from the computer.

"Let's worry about that later," I say, quietly.


I recreated every katsu curry recipe in Romeo is a Dead Man and almost none of them made me better with swords — James Archer

Despite a decent bit of Rock, Paper, Shotgun’s best being distinctly janky these days (read Jank!) there are still some gems coming out of the old site.

Tasting notes: Also delicious, even if – in spite of the in-game description – it’s about as Indian as sumo wrestling. The butter does make the sauce beautifully smooth, though, and the stacking of the breaded chicken creates a pleasant optical illusion of having more breaded chicken. Just don’t expect, if you make this yourself, to achieve the same yellowish colour as in Grasshopper Manufacture’s artwork. On the basis of this experiment, that would require so much butter that your curry would legally become a croissant.

Effects: Increases defence. I caught my finger while loading the dishwasher with curry-smeared plates and it still bloody hurt. Failure.


Technology and Design

A Look At Some Interesting Linux Terminal Text Editors — Pom

I confess that I work on this blog in Visual Studio Code. For general text editing I usually use Sublime text but since installing Bazzite on my desktop I have been using Kate, but I think I am going to swap back to Manjaro (or maybe try Cachy) soon and back to Sublime with it. In the terminal I have stuck to Vim with some plugins to style it for a while but this is making me think of checking out Fresh.

Another thing I've always been very fascinated by, is terminal writing programs; I think that might come from how often you hear people in videos about Linux talk about how much they use terminal text editors, particularly things like Vim and Emacs get commonly mentioned, and how much more efficient they are compared to their GUI counterparts. I personally also have almost exclusively used plain text editors for basically all writing I was doing on a PC; at school I did use Word, but none of my personal computers ever had MS Office installed; as such, I was already used to writing in programs with very minimal interfaces.


The Slow Death of the Power User — Fireborn

I think there is a bit of a degree of rose-tinted glasses in the reminiscing here. The idea that the culture around technology did not use wield levels of technical competency as gatekeeping or elitism does not ring true to my experience at all. Personally I think that a lot of technically minded communities are a lot better about that now than they used to be, or perhaps it just took me a while to find them. Maybe the eighties BBS scene that Fireborn is hearkening back to was better for this than it would be a few decades later when I was dipping my toes online (was it if you were openly a woman? or gay?).

But I do agree with the central point. The ideal form that technology has centred on in a black box. Something that the owner is not meant to understand or be capable of understanding. Something that cannot be repaired, altered, or used to do anything that is not approved of by its real owners.

That culture didn’t die because the knowledge became irrelevant. It died because it became economically inconvenient. The platforms that replaced the open internet — YouTube, Reddit, Discord, eventually TikTok — are consumption platforms. Their business model requires passive engagement. A user who spends three hours going down a documentation rabbit hole, breaking things in a terminal, and actually understanding something is worth less to them than a user who watches three hours of content. They don’t ban technical material. They algorithmically deprioritize anything that demands active engagement, they reward passive consumption, and they shape the culture of their platform accordingly over years and years until the culture that emerges is one that treats passive consumption as the default relationship with technology.


Have We Forgotten How to Design? — Louie Mantia

And adding to the above, it’s also all, of course, shitty and badly designed.

How has Waymo the technical ability to self-drive a motor vehicle around a city carrying human passengers, but they do not possess the skill to automate closing a door? Did they overlook every method that might encourage the passenger to close it themselves? Was there no other possible method to get the door in a closed state without resorting to a third party that commissions human drivers to drive over to the automated car and do it manually?


“AI”

15+ years later, Microsoft morged my diagram — Vincent Driessen

Everyone running every major company really does not give a single shit about anything any more other than shareprice. It’s good for the economy when the entire thing is hollowed out in the name of gambling, right?

The AI rip-off was not just ugly. It was careless, blatantly amateuristic, and lacking any ambition, to put it gently. Microsoft unworthy. The carefully crafted visual language and layout of the original, the branch colors, the lane design, the dot and bubble alignment that made the original so readable—all of it had been muddled into a laughable form. Proper AI slop.


Toolmen — Mandy Brown

Sorry, I meant in the name of gambling and eugenics.

This has always been the intention of AI, and where its connection to the intelligence-rankers of years past is cruelly apparent: if those in power cannot prove that a great many people are already inferior then they will bring that inferiority about by forcing them to use a tool that diminishes their intellectual and creative capacity. I think of the engineers and designers who have spent decades honing their skills, deepening personal and public creative practices in service both to the users of the systems they built and to their own brilliant spirits, now being told to park themselves in front of a sycophantic oracle that can be appeased only through rote dictates, and which never tires of lying even as their own minds and muscles atrophy from disuse. What is being automated here: the work or the people?


Tunic, Night in the Woods Publisher Says TikTok Is Creating and Running Racist GenAI Ads for Its Games Without Permission — Rebekah Valentine

And of course these systems themselves are also opaque, horrendously designed, and shitty.

What really is utterly baffling is what appears to be a profound void where common sense and business sense usually reside. Does TikTok want me to be grateful for the mistreatment of my company and our game? Based on the wild response through the weeks of customer service correspondence we have received, I think this is their stance and take on their obvious offensive and racist technology and process and how they secretly use it on the assets of their paying clients without consent or knowledge.


Caoimhe

Celeste race 2026

Update: Caoimhe³ has also written a post about the race with a bit more narrative detail than my terse summary and statistics below.

The New Year’s Celeste race I do with friends happened today. When I sat down to practise this year I decided to just replay the game from the start, redoing all the main levels, getting all the strawberries and crystal hearts again, etc. I fully cleared1 the A and B sides of chapters one through six and fully cleared the A side of chapter seven and then failed to find the time to do an actual practise runs for the race. Whoops. But I still managed to set a personal best for the race, which surprised me because I felt quite fatigued today during the race and didn’t feel that I was doing my best.

Even so, it was Ruby who came out on top again—managing to come in under the hour mark!—with Caoimhe³, joining for the first time, in second.

🏃 ⏱️ 💀 🍓
🥇Ruby 0°59′30.986″ 69 1
🥈Caoimhe³ 1°02′14.985″ 123 1
🥉Caoimhe′ 1°07′39.175″ 143 0

And of course we also did a pre-run warmup race of Pico-8 Celeste.

🏃 ⏱️ 💀 🍓
🥇Ruby 4′50″ 26 1
🥈Caoimhe′ 5′28″ 26 0
🥉Caoimhe³ 7′42″ 57 1
  1. I got all normal strawberries as well as the crystal hearts and tapes. I have never gotten golden strawberries or winged golden strawberry. ↩


Caoimhe

My first expo

I exhibited at a showcase for local game makers yesterday. It was the first time I had done something like that and it was extremely fun and utterly exhausting. Working on games is an occasionally hobby; I don’t intend to make it my job and I haven’t worked on any game projects since the game jam last year, but I dusted off Snolf Robo Blast 2 and Conway’s Garden and set them up with some controllers for people to try out.

Someone “enjoying” Snolf.

I had not thought about how exhibiting these would work before the event but I quickly realised that I was going to have to give a lot of context to people as to what they were playing. The vast majority of people attending never heard of Sonic Robo Blast 2 before so I had to give a quick rundown to everyone on what it was and sometimes the concept of fangames and mods.

Even with that explained, though, it became apparent how awkward it was to try to convey what the mod is doing when people seeing it do not have a context of the base game and how the mod is creating an experience on top of that. They are coming in and seeing and playing this game for the first time and expecting it to be a coherent whole, not this deliberate awkward layer on top of a base game. You don’t have the context that the joy in it is that you are playing the game “wrong”, layering a control scheme and method of play that the world was not intended for. Many people when seeing it as a golf-type thing started looking for a hole or guidance on where they are shooting for. The levels have a fairly legible linear structure when played normally, but when you have never seen them before and can freely shoot yourself much farther and higher than the levels for designed for, bouncing every which way, it is become very difficult to parse the structure of the space. More than one person suggested there should be guiding arrows of some sort to help.

Some people, though, did gel with it straight away and were delighted by blasting Snolf around, which was really nice to see. I was quick to give credit to the SRB2 team for the game itself and Dr. Melon for the concept. A line I fell into saying that got a laugh from a lot of people is that “all I did was make the controls worse.” A lot of people also got a kick out of it when I pointed out that the game was technically an extremely heavily modified version of Doom. Some people did have more of a concept of an antigame and compared it to QWOP and Getting Over It when I tried to explain the awkwardness of it not being entirely unintentional and the other game makers there generally got it and found it interesting. There were a few parents who brought children, including a Sonic fan or two, and they gravitated over to it being one of the more brightly coloured, exciting looking things on display, only to get pretty frustrated with it. For the kids at least I did quickly quit back to the main menu and restart the game with normal Sonic so that they could have a bit of fun trying it out and gave on the details of SRB2 to their parents if they were interested in it, pointing out that it was free. I think if exhibiting it again it would be useful to have a second computer set up with the unmodified version of the game, both to give context and to allow any child who sees Sonic and gets excited to play something that would actually be fun for them.

Similarly for Conway’s Garden I had to let people know that there wasn’t really any goal or point to it and it was more of a piece of art and a challenge to make something in a tiny amount of code. I had the code open in a second in a second window to the side so people could see how small it was for themselves. A lot of people, quite fairly, lost interest in it quickly, but some people were fascinated by the highly condensed code and the idea of tweetcarts and Pico-8 itself and a surprising number of people were already familiar with and recognised Conway’s Game of Life.

There was one man in particular I had a lovely chat with who was unfamiliar with games generally (he had to ask to clarify if “mods” was short for “modifications”) but enthusiastic about discussing the things on display as art. He said the mix of chaotic generation with the player’s simple, deliberate movements in Conway’s Garden reminded him of Joseph Beuys’s I Like America and America Likes Me and immediately recognised the Sisyphean nature of Snolf.

I don’t know if I will do anything like this again any time soon (and I won’t be working on anything new to show for the moment) but I had a great time and met some very cool people.


Caoimhe

The annual Celeste race

Since New Year’s Eve 2021 some some friends and I have done an annual race of the game Celeste. We all start at the same time and then the first person to get to the summit wins. We track it using the in-game speedrun timer.

2021

I was very into Celeste at the time and won by a pretty wide margin. I don’t have a record of how everyone else did, but I completed the game in just under two hours, with three hundred and six deaths and six strawberries1.

🏃 ⏱️ 💀 🍓
🥇Caoimhe 1°54′55.047″ 306 6

2022

After this two of my friends got into the game very hard. My friend Ruby ended up getting most of the golden berries2, something I haven’t even attempted and another friend, who wished to be called The Shadowblade in this post, started getting into Celeste mods. So when the next race happpened on the 8th of January 2022 Ruby took the gold medal from me, beating my time by half an hour while I barely improved. The Shadowblade sadly did not finish and gave up four flags from the summit due to hand pain.

🏃 ⏱️
🥇Ruby 1°22′10.918″
🥈Caoimhe 1°51′25.318″
🥉The Shadowblade DNF

2023:

On the same day the next year myself and Ruby both improved our times, with Ruby coming in first again, a newcomer who I will call D. in second and myself in third. The Shadowblade did not finish again.

🏃 ⏱️ 💀 🍓
🥇Ruby 1°08′01.275″
🥈D. 1°21′03.071″
🥉Caoimhe 1°34′46.007″ 245 0
🏅The Shadowblade DNF

2024:

The next race was on the 14th of January 2024 and I managed to take more than twenty minutes off of my time, which was not enough to beat Ruby’s best time, but Ruby did a worse race than the previous year and it was enough for me to win for the second time.

🏃 ⏱️ 💀 🍓
🥇Caoimhe 1°12′40.296″ 128 0
🥈Ruby 1°14′53.679″ 144 3
🥉The Shadowblade DNF

We also decided to do a little race of the Pico-8 version of Celeste, which Ruby won.

🏃 ⏱️ 💀 🍓
🥇Ruby 5′11″ 29 4
🥈Caoimhe 7′50″ 57 1

2025

Finally, this year’s one took place on New Year’s Day. Ruby had a clear lead from the start and has gotten very close to the one-hour mark, just three minutes short of it. I came in second, doing a bit worse than last year, which shouldn’t be a surprise considering an hour before the race I posted about how worn down, tired and sore I was. The Shadowblade finished this time, coming in at just over an hour and a half.

We were also joined by our friend Stella who had never played Celeste before but decided to join in on the race. After the rest of us had finished Ruby said if that Stella actually finished she would forfeit her victory to her and shockingly Stella actually did. She finished the game in one sitting in just over ten hours with closing in on four thousand deaths and nine strawberries.

Ruby insists that I should record Stella as the winner, but I am a petty bitch and I never said that I was going to forfeit. If she wants to fine but if I she does I’m saying that makes me the winner.

🏃 ⏱️ 💀 🍓
🥇Ruby 1°03′38.846″ 75 1
🥈Caoimhe 1°22′37.421″ 190 0
🥉The Shadowblade 1°31′51.536″ 275 0
🏅Stella 10°06′38.428″ 3839 9

2026

Maybe next year we will come in under the one-hour mark?

  1. Strawberries are optional collectables throughout the game. They don’t mean anything for the race but the game records how many you collect so I’ve included them for the runs that we recorded that information for. ↩

  2. A challenge for completing chapters in zero deaths for a game where an average number of deaths per playthrough is in the thousands. ↩


Caoimhe

Tablet Ⅴ

Yesterday I took part the Cork Game Jam which was the first in-person game jam I’ve taken part in and my first time diving back into game programming in a few months and Pico-8 programming in a few years.

The theme—“myth”—was announced at ten and the pizza arrived for the after party at around four, which gave me about six hours to derust and bang something out. It was exhausting and stressful but also a lot of fun. Here’s the result:

Control with ⏴⏶⏷⏵, Z and X

The theme being myth immediately reminded me of an idea I had years ago based on the Epic of Gilgamesh, one of the oldest pieces of literature that we have a record of. There exists no complete copy of it. What we have of it is an amalgam of fragments from various damaged cuneiform tablets.

My concept is an adaptation of Gilgamesh, probably a sidescrolling action platformer, that uses the aesthetics of corrupted data to fill in for the missing sections of text. Within the six hour window I managed to get a sample of that core idea implemented, though admittedly little else.

So that I wouldn’t have to do everything from scratch I used Matthew Hughson’s platformer starter kit as a base and started making modifications to the sprites and speed values to get more in line with my concept, using Castlevania sprites as a bit of a reference for the walk cycle initially.

I spent far too long getting an attack animation working before I realised I would probably not have time to implement any sort of combat. But its presence at least speaks to setting up an expectation of what the game might involve before you end up running into the faux-corrupted mess it actually is, or within the metafiction of the premise what the game once was before most of it was damaged and lost.

The other thing I added is, of course, the scrolling text taking up the top part of the screen, consisting of the start of the text of tablet 5 of the epic, taken from Maureen Gallery Kovacs’ translation. It starts out fairly normal and then getting more and more broken as it gets to the parts of the poem that are lost.

Within the code these are represented by lines of hashes. I wrote a text drawing function that, when it encounters a hash, draws random data from the spritesheet (from specifically selected sprites in it, not the entire thing) over it, mimicking the aesthetics of famous bugs such as glitch pokémon.

Ideally the progress of the broken text would correspond to the player discovering the broken nature of the game, but it just scrolls at a constant rate with a lot of normal text up front and there is not that much in the way of level so if a player simply walks to the right they will outpace it.

In a more full implementation of this idea the game could perhaps corrupt dynamically as parts of the text are reached, simulating live memory corruption. Or perhaps the scrolling text is a bit too much of a blunt instrument and should not be included in a more complete game.

That said, I think there is definitely potential for playing with some of the more evocative parts of the fragmented parts of the text.

The oft-quoted fragment of one of the works Sappho springs to mind:

μνάσεσθαί τινά φαῖμι
καὶ ἕτερον
ἀμμέων.

someone will remember us
I say
even in another time.

Sappho

Within a section of the text that made it into the jam game is the sudden implicit violence of mention of various weapons, axes smeared with what is not said, followed simply by the word alone. I placed a long, blank pause before and after “alone” for effect.

…Suddenly the swords…,
and after the sheaths …,
the axes were smeared…
dagger and sword…
alone …
The Epic of Gilgamesh, tablet 5.

A segment shortly after features has some broken dialogue mentioning something in Humbaba’s belly, a throat and next, and Gilgamesh then saying “Humbaba’s face keeps changing!” which is begging for a scene involving the level’s tileset suddenly being replaced with disjointed meat level sprites as the boss becomes a horrible jumbled mess.

When you were still young I saw you but did not go over to you;
… you,… in my belly.
…,you have brought Gilgamesh into my presence,
… you stand.., an enemy, a stranger.
… Gilgamesh, throat and neck,
I would feed your flesh to the screeching vulture, the eagle, and
the vulture!"
Gilgamesh spoke to Enkidu, saying: "My Friend, Humbaba’s face keeps changing!

The Epic of Gilgamesh, tablet 5.

For what I actually managed to accomplish in the jam the only tricks I managed are the corrupted text and a short corridor level which becomes more visually broken as it goes along, but is completely static.

I made a pretty minimalist tileset for the background of six tiles with only two colours and tried my best to use them to give the impression of a forest, as per the epic narration.

I spent a while drawing these and then getting down trying to draw trees with them, though some of what I mapped out for the background ended up getting hidden by the tablet with the scrolling text, whoops.

As you cross the bridge you encounter a group tile in place of a bridge tile and above it a tree drawn in the same style as the first few background trees, but with the left and right side tiles swapped. Then and broken skull and a serpent implying some sort of non-functional boss mark the boundary for things really going wrong.

I still tried to keep to drawing similar tree shapes but with tiles swapped out to tiles from other parts of the spritesheet, including ones that only appear here, implying that some more game exists beyond what is implemented. Then the bridge itself corrupts and is replaced by corner ground tiles and then invisible but solid tiles as you walk into a screen of just skulls marking a little ending point.

I have expressed here some ideas for a larger game but I do not really have any plans to expand this out. It very much the kind of thing I might do eventually in a world where I had endless free time to work on every project idea I have, which is sadly not the world I live in, and it is far down the list and I only have very vague notions of how to expand this out into something bigger. It would probably not be done in Pico-8 as Pico-8’s size constraints and limited character count, not to mention tiny resolution, don’t make it ideal for games involving lots of text or expansive levels.


Táibléad Ⅴ

Triail Pico-8 a rinne me don Cork Game Jam. Is é “myth” an téama.

Is féidir an leathanach seo a léamh chun tuilleadh a fháil.

Control with ⏴⏶⏷⏵, Z and X

Creidiúintí



Caoimhe

Conway’s Game of Life in 138 characters

k=2^13::s::for a=0,k do
n=0 for x=0,8 do
n+=peek(k*3+a+x/3+x%3*64-65)end
poke(a,n==12 and 4 or n==16 and peek(a))end
memcpy(k*3,0,k)goto s

That is the entire source code for my my Pico-8 implementation of Conway’s Game of Life, which you can run here:

Control with ⏴⏶⏷⏵, Z and X

I made this as a tweetcart back when tweets were still 140 characters and I am still pretty proud of it. Let’s run through how this works!

If you have never heard of it, the Game of Life is a type of cellular automation, a simulation consisting of a grid of cells. Each cell is either alive or dead and with each iteration of the simulation the state of each cell changes based on the following rules, as copied from Wikipedia:

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

It’s pretty hard to see how those rules translate to the above code, so I’ll try to explain it as best I can. It relies on some tricks specific to Pico-8.

The first thing in the code is is setting k=2^13, that is 8,192. This is a magic number that is going to have a few uses.

Then we set a label ::s::. This is a label we can use goto later on in the code to return to.

Then we start a for loop, for a=0,k do, counting from 0 to 8,192. This is the length, in bytes, of the part of the the Pico-8 virtual machine’s memory that holds the current screen state. Pico-8 has a resolution of 128×128 pixels, for 16,384 pixels total, and each pixel can have one of 16 colours. That means that the colour of each pixel can be stored in 4 bits—half a byte—and therefore the full screen information can be stored in 8,192 bytes. We are going to treat every byte as a single cell, which means every cell is actually made of two pixels. You can see how every cell in the simulation is one brown and one black pixel side-by-side.

The reason we’re doing this is so that we can iterate over the current screen state in order to determine the next iteration and which cells survive or die. By examining the screen memory directly we don’t have to create a different data structure for storing the cell information; it’s just whatever’s currently on screen. This saves an awful lot of characters.

Then, inside the loop, we start by setting n=0, this is going to be used to track the number of neighbours that every cell has.

Then we start up a new loop, for x=0,8 do, to iterate over all the neighbouring cells.

Which brings us to the first complicated expression, n+=peek(k*3+a+x/3+x%3*64-65). This is adding up the values of all the neighbours (for the purposes of this implementation, each cell is considered to be be one of its own neighbours). It peeks at the memory addresses of each of the neighbours, then adds it to the running total, stored in n.

k*3 (24,576 or 0x6000) is the start of the screen memory, the starting point for iterating over the screen data. Adding a to it is iterating over each cell in sequence in the memory.

Every byte (cell) is going to have a value of 0, for dead, or 4, for alive. I’ll explain why I used the value of 4 rather than the more obvious value of 1 later.

The screen memory is arranged in the order you would probably expect, it starts in the top left corner and scans left to right, top to bottom. The first 64 bytes are the first line of the screen, the next 64 bytes are the second line, etc. As such getting the cells to the left and right of the left and right of the current one is just a matter of taking away or adding one to the address we’re querying. Getting the cells above and below means subtracting or adding 64, respectively.

To get all nine neighbours (including the current cell itself) we need to check nine memory addresses: The current address, k*3+a, and offsets of -1, +1, -64, +64, -65, -63, +63, +65. This is accomplished with the +x/3+x%3*64-65 part of the expression as it iterates from 0 to 8. +x/3 will go from +0, +1, +2 over the course of the loop1. +x%3*64 cycles through +0, +64 and +128. Then the -65 corrects these to be centred around 0 (-1 for the horizontal and -64 for the vertical).

You may notice that this is going to behave weirdly at screen edges: For the first and last row it will be checking for “neighbours” in memory before and after the screen data. These are simply going to be blank as they aren’t otherwise being used for this programme. Additionally, due to the layout of the memory the left and right edges will wrap around and be treated as neighbours of each other, with a one pixel vertical offset. This weird behaviour is going to be the price we have to pay for trying to fit a mathematical simulation into a tweet2.

Once we have the total value of n totted up it’s time to write the next iteration of the simulation: poke(a,n==12 and 4 or n==16 and peek(a)).

Poke is the opposite of peak, it lets us write to a value in memory, and we’re going to just starting writing at address 0x0, which in Pico-8 is normally spritesheet data, but we’re not using sprites in this programme so we can treat it as effectively free memory.

The poke expression is a bit weird but effectively we’re either going to poke a value of 4, 0 or the current value of the cell (peek(a)).

Let’s go back to our bullet points from Wikipedia for a second. We need to rewrite them slightly because we’ve changed the way we counted living neighbours to include the cell itself as its own neighbour. Rephrasing it in those terms we have:

  • A live cell with fewer than three live neighbours dies.
  • A live cell with three or four neighbours lives.
  • A live cell with more than four neighbours dies.
  • A dead cell with exactly three live neighbours lives.

Or, simplifying it:

  • Any cell with three live neighbours is alive in the next iteration.
  • Any cell with four live neighbours keeps its current value in the next iteration.
  • Any other cell is dead in the next iteration.

Or, n==12 and 4 or n==16 and peek(a). If n==12 this evaluates as 4, the value we’re using for a living cell. If n==16 this evaluates as peek(a), write whatever the value for the cell is currently. Otherwise this evaluates as nil, and fortunately for us Pico-8 treats poke(a,nil) as being equivalent to poke(a,0), meaning every other case produces a dead cell.

Now we’ve iterated across the entire screen and made the next iteration of our simulation, the only thing left to do is copy the new iteration into the screen memory (memcpy(k*3,0,k)) and then start our loop again (goto s).

That’s it! Except, you might wonder, what about our starting state? We didn’t set any initial data, so why is there anything here in the first place when you run it? Well, our initial data is whatever is on screen when we run the code. You can have any starting state you want simply by having something different drawn to the screen when you hit run.

And that’s also why I used 4 for the value of a living cell: it produced interesting results when running directly after Pico-8’s boot screen rather than dying instantly, which happens if you used 13. 4 was chosen by trial and error. It’s also a bit easier to look at than using 1, which uses a dark blue colour rather than brown that’s harder to see against the black.

You can play around with this code yourself using Pico-8 Education Edition4 or check out my other Pico-8 projects

And that’s (actually) it! I hope you found this interesting.

  1. peek thankfully ignores any fractional values, so we can act as if these are being rounded. ↩

  2. At least to fit into what the size a tweet was back in the good old days, when men were men and tweets were tweets. Now I’m a woman and I’ve deleted my Twitter account… Actually, those might have been the bad old days. ↩

  3. Which would have shaved off two two more characters as the poke command would have been changed to n==3 and 1 or n==4 and peek(a). ↩

  4. Click the ⏵ button to start it and then hit Esc twice to open the editor. To run it again hit Esc again to bring up the command line, enter run and hit Enter . ↩


Caoimhe

Insular R

This post uses obscure Unicode codepoints and custom fonts which may not display in RSS readers and some browsers.

A few years ago I made a Gaelic-style monospaced pixel font that I called Cló Piocó-8. This was originally just testing out the custom font mode in Pico-8 for fun. I then ended up making a truetype font using Pixel Forge.

If custom fonts can display it looks like this.

This was mainly for fun and I haven’t used it terribly much.

Around the same time I made it I also made a similar pixel font for Ogham. I think the reason for making these separately was because the main font was monospaced but the Ogham one wasn’t? Or perhaps it just didn’t occur to me to include the Ogham section with the original font at the time. Either way I’ve decided I wasn’t happy with them being two separate fonts so I made a new version of Cló Piocó-8 that includes the Ogham block.

I also changed another character: R.

The original R character in the font was more straightforwardly based on an Insular R and looked like this: R.

You might be wondering what an Insular R is.

Insular? Why is this R so withdrawn?

Because in the middle ages Ireland was a pretty isolated place, and Irish monks were left to their devices, eventually developing a style of writing called Insular script.

A Latin manuscript written in the Insular script.
7th century manuscript featuring Insular script via Wikimedia Commons.

When printing came to Ireland, which took a while, most things were printed in English. Gaeilgeoirí didn’t have much to read (but most of them couldn’t, anyway). The first book printed with an Irish type was Aibidil Gaoidheilge agus Caiticiosma in 1571, using a font which had been commissioned by Elizabeth Tudor, though it was actually a bit of a hodgepodge of Gaelic, Roman and Italic, with the new Gaelic letters resembling the Anglo-Saxon type made by John Day.

Since then Irish has been printed in both Roman and Gaelic type, the former often simply due to practical considerations of the availability or expense of Gaelic fonts or because it was seen as more modern. It is rare to see Gaelic script used now except for in decorative text such as signs and plaques.

«Saoirse don Phalaistín» painted on the side of a small building.
“Freedom for Palestine” painted on a building in Irish Carraroe via Gaelchló.

But I quite like the Gaelic-style scripts and—as evidenced by my homepage—I quite like playing with typefaces. I use Mínchló from Gaelchló for most the Gaelic script on this site.

But I will admit there can be some drawbacks to readability. Particularly with f, s and r, or rather their Insular variants, which Unicode has unique codepoints for: ꝼ ꞅ and ꞃ, respectively.

ꝼ ꞅ ꞃ

Compared to a Roman f, the Insular ꝼ almost appears as if it has been hammered into the ground like a post. The tail of the character dips below the line and the stroke is level with it, the top of the character only reaching to the same height as a small letter like e. But it is still distinct and recognisable as an f.

The problem starts with s. You might be familiar with a long s, which is basically an old-fashioned way of writing an s where it looks like an f without the stroke in the middle. The Insular ꞅ similarly strongly resembles an Insular ꝼ and if one is more familiar with Roman type it is very easy to confuse them at a glance. Many modern Gaelic typefaces simply use a Roman-style s instead for clarity, or offer the use of both using stylistic sets. I opted to use a Roman-style s when making Cló Piocó-8 for clarity. When your characters are only four characters high you need to be careful about legibility and it’s very common to do this anyway with Gaelic typefaces for both s and r.

But I still, in that first version, decided to go with an Insular ꞃ, a character that resembles a cross between the Insular ꞅ and an n, or perhaps a Greek η with the tail on the other side. In an attempt to make it not look too much like an n I cut one pixel off the right-side, to try and maybe make it look a bit more like a Roman r, but really it just makes it look weird. I left it like that for a long time, but I was never fully satisfied with it.

Deciding to change it

When I was making my custom cartridge designs for my Pico-8 projects (something else I could write a bog post on, really) I decided to use Cló Piocó-8 to sign my name and the URL of this site on them. This made me have to face that bloody R again. I was never happy with the compromise I made originally and quite frankly people were not going read it as an r. I don’t want anyone typing “oakneef.ie” into their browsers and finding nothing there.

My custom Pico-8 cartridge containing the Cló Piocó-8 font.
Check out my other Pico-8 stuff.

It was here that I came up with my new compromise: R. It is mostly an upper-case Roman R but with a little bit of a tail sticking down for a bit of Insular influence. I have actually started scribbling my r like this when handwriting in Irish as well.

Handwriting in a notebook of the standard insular f, s and r and my compromise r.

It took me a while to actually bring this change back to the font file itself but when making the 88×31 pixel badge for this site I was reusing elements from my Pico-8 cartridge design and it reminded me to go back and make the change, and I while doing it I also rolled the Ogham font into it as well, which I had also been intending to do for a while.

So check out Cló Piocó-8.

Appendix: Comparison of fonts

Source Serif 4 Mínchló Insular-style Mínchló Roman-style Cló Piocó-8 v1 Cló Piocó-8 v2
fsrn fꞅꞃn fsrn fsrn fsrn

Source for historical claims: The Irish Character in Print: 1571-1923, E.W. Lynam







Pico-8 animation editor

A Pico-8 animator editor I made for a project that never really got off the ground.

In particular it’s designed to help compress animations that have lots of repeated elements. E.g. In the example data in this cart the head layer is used across almost every animation, but only appears once in the exported spritesheet.

To this end it is very much optimised to favour saving space in the sprite sheet, and not optimised for CPU or RAM usage.

The version usable in browser here has some animations pre-loaded and you can play around, but you won’t be able to export any of them from this page. To do that you’ll have to download the cart and run it in your own copy of Pico-8.

Exporting

The editor defines characters, which have a set of animations, which have a number of frames, which each have a duration and ten layers to draw on. General usage is just to create animations, which can be exported via the "export" button. This will create four files:

  • spritesheet.png - the exported sprite sheet to be used in your game
  • metadata.p8l - lua table structure containing all the animation information needed to draw animations from the above spritesheet
  • metasheet.png - the same information, but stored in a different format as image data so that the animation editor is able to re-import it
  • debug.p8l - the exact data as in metasheet.png but in text format, just for debugging purposes

On startup the editor will import any data from metasheet.png and spritesheet.png back in so that you can continue editing where you left off.

Controls

  • The window on the left is for drawing, the ten windows on the right are ten layers each frame can use.
  • You can’t rearrange or add more layers but the C and V keys can be used to copy and paste the selected layer.
  • You need to create at least one character, animation and frame and select a layer before you start editing.
  • When entering names only English alphabet characters are accepted. Use enter to submit and / or \ to cancel. Backspace works as you would expect.
  • Use the arrows keys to move layers around (no wrapping - going off the edge will just erase data).
  • Use the WASD keys to move the origin point.
  • Use - and + to navigate through characters quickly.
  • Use [ and ] to navigate through animations quickly.
  • Use ’ and \ to navigate through frames quickly.
  • P/F toggles the paint or fill tool. Be warned there’s no undo button so be very careful with the fill tool.
  • ‘oni’ toggles onion skinning.
  • The ‘w’ next to it toggles wrapping for the onion skinning. When enabled and viewing the first frame in an animation, the onion skin layer will show the last frame from that animation.
  • ‘orig’ toggles showing the origin point for the current frame.

Importing

When you have your animations finished you should import the spritesheet into your own cart and copy the contents of metadata.p8l into an initialisation function in your game. You will then obviously need some special draw functions to do something with that data. Here is an implementation I have done as an example. You can download the Pico-8 cart for it here.