The gold standard of optimization: A look under the hood of RollerCoaster Tycoon

(larstofus.com)

Comments

netcoyote 23 March 2026
Warcraft 1 (1994), Warcraft 2 (1995), and StarCraft (1998) all use power-of-2 aligned map sizes (64 blocks, 128 blocks, and 256 blocks) so the shift-factor could be pre-computed to avoid division/multiplication, which was dang slow on those old 386/486 computers.

Each map block was 2x2 cells, and each cell, 8x8 pixels. Made rendering background cells and fog-of-war overlays very straightforward assembly language.

All of Warcraft/etc. had only a few thousand lines of assembly language to render maps/sprites/fonts/fog-of-war into the offscreen buffer, and to blit from the offscreen buffer to the screen.

The rest of the code didn't need to be in assembly, which is too time-consuming to write for code where the performance doesn't matter. Everything else was written in portable assembler, by which I mean C.

Edit:

By way of comparison, Blackthorne for Super Nintendo was all 85816 assembly. The Genesis version (Motorola 68000) and DOS version (Intel 80386) were manually transcribed into their respective assembly languages.

The PC version of Blackthorne also had a lot of custom assembler macros to generate 100K of rendering code to do pixel-scrollable chunky-planar VGA mode X (written by Bryan Waters - https://www.mobygames.com/person/5641/bryan-waters/).

At Blizzard we learned from working on those console app ports that writing assembly code takes too much programmer time.

Edit 2:

I recall that Comanche: Maximum Overkill (1992, a voxel-based helicopter simulator) was written in all assembly in DOS real mode. A huge technical feat, but so much work to port to protected mode that I think they switched to polygon-rendering for later versions.

applfanboysbgon 22 March 2026
> Imagine a programmer asking a game designer if they could change their formula to use an 8 instead of a 9.5 because it is a number that the CPU prefers to calculate with. There is a very good argument to be made that a game designer should never have to worry about the runtime performance characteristics of binary arithmetic in their life, that’s a fate reserved for programmers

Numeric characteristics are absolutely still a consideration for game designers even in 2026, one that influences what numbers they use in their game designs. The good ones, anyways. There are, of course, also countless bad developers/designers who ignore these things these days, but not because it is free to do so; rather, because they don't know better, and in many cases it is one of many silent contributing factors to a noticeable decrease in the quality of their game.

youarentrightjr 22 March 2026
> The same trick can also be used for the other direction to save a division: NewValue = OldValue >> 3; This is basically the same as NewValue = OldValue / 8; RCT does this trick all the time, and even in its OpenRCT2 version, this syntax hasn’t been changed, since compilers won’t do this optimization for you.

(emphasis mine)

Not at all true. Assuming the types are such that >> is equivalent to /, modern compilers will implement division by a power of two as a shift every single time.

ConceptJunkie 23 March 2026
> The same trick can also be used for the other direction to save a division:

> NewValue = OldValue >> 3; > This is basically the same as

> NewValue = OldValue / 8;

> RCT does this trick all the time, and even in its OpenRCT2 version, this syntax hasn’t been changed, since compilers won’t do this optimization for you.

The author loses a lot of credibility by suggesting the compiler won't replace multiplying or dividing by a factor of 2 with the equivalent bit shift. That's a trivial optimization that's always been done. I'm sure compilers were doing that in the 70s.

HelloUsername 22 March 2026
Fun read, thx! I'd also recommend more about RCT:

"Interview with RollerCoaster Tycoon's Creator, Chris Sawyer (2024)" https://news.ycombinator.com/item?id=46130335

"Rollercoaster Tycoon (Or, MicroProse's Last Hurrah)" https://news.ycombinator.com/item?id=44758842

"RollerCoaster Tycoon at 25: 'It's mind-blowing how it inspired me'" https://news.ycombinator.com/item?id=39792034

"RollerCoaster Tycoon was the last of its kind [video]" https://news.ycombinator.com/item?id=42346463

"The Story of RollerCoaster Tycoon" https://www.youtube.com/watch?v=ts4BD8AqD9g

fweimer 22 March 2026
What language is this article talking where compilers don't optimize multiplication and division by powers of two? Even for division of signed integers, current compilers emit inline code that handles positive and negative values separately, still avoiding the division instruction (unless when optimizing for size, of course).
Validark 23 March 2026
"Since the number is stored in a binary system, every shift to the left means the number is doubled.

At first this sounds like a strange technical obscurity"

Do we not know binary in 2026? Why is this a surprise to the intended audience?

troad 23 March 2026
> When reading through OpenRCT2’s source, there is a common syntax that you rarely see in modern code, lines like this:

> NewValue = OldValue << 2;

I disagree with the framing of this section. Bit shifts are used all the time in low-level code. They're not just some archaic optimisation, they're also a natural way of working with binary data (aka all data on a computer). Modern low-level code continues to use lots of bit shifts, bitwise operators, etc.

Low-level programming is absolutely crucial to performant games. Even if you're not doing low-level programming yourself, you're almost certainly using an engine or library that uses it extensively. I'm surprised an article about optimisation in gaming, of all things, would take the somewhat tired "in ye olde days" angle on low-level code.

bluelightning2k 22 March 2026
Great write up. Thank you. Really great!

I was reminded of the factorio blog. That game's such a huge optimization challenge even by today's standards and I believe works with the design.

One interesting thing I remember is if you have a long conveyor belt of 10,000 copper coils, you can basically simplify it to just be only the entry and exit tile are actually active. All the others don't actually have to move because nothing changes... As long as the belts are fully or uniformly saturated. So you avoid mechanics which would stop that.

WillAdams 7 hours ago
I'm still kind of sad that application development no longer uses much assembly language, WriteNow, which was ~100,000 lines of assembler is still my gold standard for word processor and performance.
evandale 23 March 2026
The pathfinding section reminded me that there's a YouTube steamer, Marcel Vos, who goes into a deep dive of how the pathfinding works.

https://youtu.be/twU1SsFP-bE

He has lots of videos that are deep dives into how RCT works and how things are implemented!

jwilliams 23 March 2026
Definitely made me feel old to see bit-shifting needed an explainer! I must admit as I was reading I was "why is he explaining this? it's obvious!".
sroerick 22 March 2026
I had always heard about how RCT was built in Assembly, and thought it was very impressive.

The more I actually started digging into assembly, the more this task seems monumental and impossible.

I didn't know there was a fork and I'm excited to look into it

ben7799 22 hours ago
I guess I'm showing my age but having read stuff like Michel Abrash's books years ago this article was a bit underwhelming.

Like no one who wrote any code back in the 80s or 90s even for a homebrew game was skipping this stuff, it was in almost every book and tutorial. Stuff like bit shifting was extremely common and a lot of games would have had design choices that were informed by coding challenges. Lots and lots of code had data structures aligned on byte/word boundaries or had data massaged to fit into the limits of hardware in order to make reads happen in a certain # of cycles, etc.. certainly almost all console games had lots and lots of fascinating design choices like this.

This game may have been exceptionally well optimized but it feels like if the original code is not in the public domain these weren't the best examples.

When he started writing about their being a clean sheet re-implementation I thought there was going to be a benchmark comparison of the modern rewrite vs the original on old hardware or something, that would have been interesting.

Thankfully or not I'm just barely young enough that I never had to write anything professional in assembly, though if I had gone into games maybe I would have.

raffraffraff 23 March 2026
On huge games produced by large game studios, I wonder if the idea of using a real world technical challenge as a "feature" within the game is considered genius? Consider a coder and a game designer who are on different teams and don't attend the same meetings.

But if you look at creative writing, story arcs are all about obstacles. A boring story is made interesting by an obstacle. It is what our protagonist needs to overcome. A one-man-band game dev who simultaneously holds the story and the technical challenge their head, might spot the opportunity to use a glitch or limitation as, I dunno, a mini game that riffs on the glitch.

TheGRS 23 March 2026
This is a fun read, its one of my favorite games growing up by far, countless hours sunk into it. I didn't need this write-up to know that Chris Sawyer was god among men and that the open source version is a huge labor of love, but its a good reminder :) I will need to give OpenRCT a try some time, I've tried a little OpenTTD and really enjoy it, but RCT was always my jam.

For the lesson here, I think re-contextualizing the product design in order to ease development should be a core tenant of modern software engineering (or really any form of engineering). This is why we are usually saying that we need to shift left on problems, discussing the constraints up-front lets us inform designers how we might be able to tweak a few designs early in order to save big time on the calendar. All of the projects that I loved being a part of in my career did this well, all of the slogs were ones that employed a leadership-driven approach that amounted to waterfall.

maxglute 23 March 2026
Is there a place to find stories of recent game optimization? What's most ridiculous on like quick inverse square route. As someone who spent way too much time vraying in prior life, I still can't believe we got real time ray tracing.
ionwake 23 March 2026
also I remember the excitement of a new game that looked different to others.

Somehow even as a child I just knew that it would be a whole new emergent game play experience.

Ofcourse I didnt know waht went into making Rolelrcoaster Tycoon but I could just by a couple of screenshots how this was clearly a ground up new game with new mechanics that would be extremely fun to play.

I dont get this feeling anymore, as I just assyne everything is just a clone of another game in the same engine generally.

Unless its been a decade in production like Breath of the Wild of GTA 5 i just dont expect much.

pmg102 23 March 2026
The article refers several times to the benefits of the game designer and the coder being the same person. I've often felt that this is the only way to build anything impressive, and in fact I'm amazed that corporations with their hierarchical organisation model ever get anything built at all but I suppose you can brute force anything with enough employees.

It does make you wonder if the future of AI-assisted development will look more like the early days of coding, where one single mind can build and deliver a whole piece of software from beginning to end.

makapuf 23 March 2026
Compilers won't do multiplication by power of two to bit shift for you ? I remember reading in ~2000: the only thing writing a<<2 instead of a/4 will do is make your compiler yawn
derodero24 23 March 2026
Biggest lesson from string matching work: layout beats instructions every time. Batch your comparisons into a contiguous buffer so the prefetcher can actually help, and you'll outperform hand-rolled SIMD on random-access data. Compilers handle the arithmetic tricks fine now — they can't fix your cache misses though.
bze12 23 March 2026
> This part is especially fascinating to me, since it turns an optimization done out of technical necessity into a gameplay feature.

Reminds me of blood moons in Zelda https://www.polygon.com/legend-zelda-tears-kingdom/23834440/...

egypturnash 23 March 2026
I have to wonder how much of the original assembly source looked a lot more succinct than whatever's in OpenRCT due to the use of macros. Looking up his gameography on Mobygames, Chris had been writing stuff since 1984 when RCT came out in 1999, it's hard to imagine he was still writing every single opcode out by hand given that I had some macros in the assembler I was fooling around with on my c64 back in the eighties.
MisterTea 23 March 2026
While it has been a while since playing RCT, one thing that was really nice about the game is that it runs flawlessly under Wine.

I really wish I could see the source code.

lefty2 22 March 2026
> The same trick can also be used for the other direction to save a division:

> NewValue = OldValue >> 3;

You need to be careful, because this doesn't work if the value is negative. A

hermitcrab 23 March 2026
>the game was written in the low-level language Assembly

Surely it wasn't all assembly. There is little to be gained in performance from writing non-bottleneck parts of the code in assembly.

londons_explore 22 March 2026
> it turns an optimization done out of technical necessity into a gameplay feature

And this folks is why an optimizing compiler can never beat sufficient quantities of human optimization.

The human can decide when the abstraction layers should be deliberately broken for performance reasons. A compiler cannot do that.

random__duck 23 March 2026
So this is what programing on hard mode looks like ?
sghiassy 22 March 2026
Another great optimization is storing the year as two digits, because you only need the back half…

… oh wait, nvm. Don’t preoptimize!

throw_m239339 23 March 2026
Fantastic write-up, that's exactly why I came to HN many years ago, to find such articles about mundane things or products, but the technical aspect is just fascinating.
almostdeadguy 23 March 2026
The pathfinder algorithm is a great example of why constraints are so important for creativity and creative development.

If AI has any benefit to creative endeavors at all it will be because of the challenges of coaxing a machine defined to produce an averaging of a large corpus of work (producing inherently mediocre slop) provides novel limitations, not because it makes art any more "accessible".