RollerCoaster Tycoon Optimizations are Insane
260 segments
Hey, you see this man right here? Okay,
do you know who it is? Well, guess what,
buddy? If you don't know who it is, you
got to you got to go back to school,
okay? You got to get a little bit of
respect in you, cuz this right here is
Chris Sawyer. Now, you may not recognize
even the name, which hey, I don't blame
you, but you should. He's the man that
can handcraft some assembly better than
pretty much anybody else. In fact, he
handcrafted one of the greatest games
ever, Roller Coaster Tycoon. Yes, we all
know Roller Coaster Tycoon. Okay, that
game has some serious aura as the as the
zoomers say. That game came out in 1999,
6 years after Doom. Doom written in C.
Chris Sawyer wrote his in assembly.
Absolutely diabolical, man. The roller
coaster tycoon optimizations are insane
and we're going to go over three of
them. And the third one, it's kind of
the craziest. It's also just a very,
very good idea. Besides for being
written in assembly, one thing about
Roller Coaster Tycoon is that it has
insane optimizations. If you've ever
played it, it was just creamy smooth on
any system. Now, remember, there's
thousands of individual NPCs, all the
little agents running through your park.
Yes, they were called agents at the
time. And look at this. The system
requirements were nothing. 16 megabytes
of RAM. To put that in perspective, look
at this. This is Node right here. A
little wild true loop. I'm going to do
this. I'm going to hit it with the old
amperand. I'm going to grab that and go
VMRSS and go 2 3 5 6 1 BAM. A while loop
in node
takes 57.3 mgabytes of RAM. Roller
coaster tycoon less than 16. Even the
fabled the bun requires 41.41
megabytes for a while loop.
>> Here at Terminal, we love Planet Scale.
We've been using Planet Scale since day
one of Terminal.shop and had an amazing
experience. So if you want a database
you don't have to worry about, choose
Planet Scale. Now back to the video.
So let's go over this gold standard of
optimization. Now I know a lot of you
have never actually had to concern
yourself with a little thing called
memory. Effectively unlimited and coding
has largely been solved. So you just
don't think about these things. But back
in the day, you had to be a lot more
careful. Now I want you to really think
about something when it comes to Roller
Coaster Tycoon. Every single one of the
park adventurers had some sort of memory
associated with them because each
individual one could become angry, they
could become nauseated, they could
become hungry, or they would just want
to leave the park. So that means every
single person had to have its own
memory. And this is our first type of
optimization. It actually involves the
size of money. Now, individual little
park adventurers, they would have a
little bit less memory associated with
their money. Okay? Hey, you don't got
the memory, you don't got the money. And
that's because the average Park
Adventure, they didn't need a ton of
money. They just needed something, say,
less than 256. So, you could just have
one bite of memory associated with how
much money that Park Adventure had. Or
in this case, it could be two bytes
associated with money. Now, remember,
there could be somewhere between 2 to
4,000 of these little guys walking
around. And so, a singular bite saved is
2 to 4K worth of memory. You can see why
that adds up a lot when you only have 16
megabytes and that is the system
requirement which means you still need
to load up the source code. You still
need to load up all the graphic tiles.
You still need to have the operating
system running somewhere. Therefore,
every single bite actually mattered. So
even the money representation, the
position representation, everything
would be squashed down such that each
character could save the maximal amount
of memory. Now, the next one's a bit
stranger, but it actually makes a ton of
sense. You'll see a bunch of these these
bit shifts of old value, say by two. All
right, so I know not all of you are
going to have some binary knowledge out
there. And let's just face it, teaching
you base 2 might take a bit of a moment,
but you can see this right here. Here is
a value 1 0 1 0 0 0. This value is
actually technically five. That's
because this value is four. This value
is one. You add those two together, bada
bing, bada boom, you got yourself five.
Now, a left shift or a shift that's
represented like this is actually pretty
easy to understand. If I were to shift
this by one, you just actually shift
over all the binary. So, that means the
original value 1 0 1 would actually
become 0 1 0 1 because it's been shifted
over by a singular bit. Now, this value
right here is actually 10. And that's
because a single left shift is the
equivalent of multiplying by two. A
single right shift is the same thing as
dividing by two. Now, you're probably
asking, well, why would you do this? Why
not just multiply by two? It's so much
more clear for everybody. Well, first
off, back then, people knew how to kind
of read a little bit of that binary. But
second off, the reason being is actually
quite simple. A singular multiplication
could end up taking somewhere between 3
to eight cycles is what I've read on the
internet back on those machines. And a
divided by can take tens of cycles to be
able to execute. So, if you can center
your game around these divide by twos
and multiply by twos, you can save many,
many cycles, thus making your game feel
much, much faster. So, in roller coaster
tycoon land, everything's going to be a
left shift, a left shift by two, or the
same thing as multiplying by two,
multiplying by two, or just multiplying
by four. Or you're going to see a lot of
things like right shift three or divided
by 8. I it is a very different world
because everything we kind of live with
today has just almost no bearing on
what's actually happening underneath the
hood or the CPU cycles that are being
taken by individual instructions.
Instead, you just kind of have these
really abstracted concepts and you just
go, okay, hey, I'm going to create a new
object. I'm going to throw some keys and
values in there. One of those values is
going to be a function. I'm going to
execute the function. you don't actually
think about all the individual little
cycles and instructions that are going
through your CPU at any one point, let
alone the memory that you're actually
taking up. Now, the last optimization is
actually the craziest optimization,
which is pathf finding. If you ever
watch one of these little park
adventurers kind of walk through the
park, they just wander aimlessly. They
don't actually attempt to go anywhere.
They actually choose random directions
until they find a ride that they're
interested in. or if they're hungry,
they actually continue to take random
directions until they find food. And the
reason being is that path finding is
actually really expensive. Let's pretend
we have the following graph right here.
And you are right here and you wanted to
leave this park. This is the exit right
here. How would you actually leave it?
For us, it's very easy. We just look
through and be like, "Dog, just goam
bam." Well, unfortunately, computers
can't do that. So instead, you have to
take every single one of these nodes,
node being represented by one of these
little circles, and you have to put it
into a list. And then you're going to
have to resolve slowly how to find the
exit. This is called Dystra's shortest
path. It's a decently complicated
algorithm that involves a minimum heap
and you have to store a bunch of values
and you have to look up stuff. But for
the sake of it, you can obviously see
having to do this for say 2 to 4,000
individual agents every time they want
to go somewhere is clearly going to
cause frame stuttering, especially on a
90 megahertz CPU. So to put that into
perspective, that means without any
instruction optimization. These CPUs
back then were over 30 times slower than
the CPUs you have today. Just pure raw
instruction power. Not to mention
reading from RAM, significantly slower.
So doing this kind of thing over and
over again for every single agent would
just cause massive frame freezing. But
pathf finding did actually happen in the
game. It would happen under two
conditions. One, if there was a
mechanic, the mechanic would come in and
try to find where in the park is a ride
actually broken at. And they would get
up to eight paths they could look into
to go and find. So they'd be able to go
decently far, but sometimes even the
mechanic couldn't find the ride it
needed to go fix. And two, when one of
the little park adventurers needed to
leave the park, they would get up to
five depth to be able to leave the park.
And if they couldn't find that, you
would end up seeing a picture like this.
This very familiar picture. They're
angry. They can't find the park exit.
And did you know that if you sold
individual customers maps, those that
had maps, they'd get up to a depth of
seven to be able to search for an exit.
Meaning you would have happier customers
not to find the rides. No, no, no, no,
no. Which was always a little bit That
is a very surprising fact. They bought
maps not to find rides, but to find
exits. And all of this was done just
simply to be able to make Roller Coaster
Tycoon run. The money size was to help
reduce RAM usage. The multiplication and
division being XNATE in favor of being
able to multiply or divide by two CPU
optimizations. Then Pathfinding, the
ultimate CPU uh optimization was
throughout the entire game to prevent
frame stutter. And all of this was done
not in some highlevel JavaScript
language, but just straight up in the
Lord's language, okay? Assembly. All
right? So, the next time you see this
face, put a little respect on it, okay,
buddy? Because this face right here,
this is the face of a man who made not
just one roller coaster tycoon, but two
roller coaster tycoons in assembly. The
name is the primogen.
Ask follow-up questions or revisit key timestamps.
This video highlights the incredible technical feats of Chris Sawyer, the creator of Roller Coaster Tycoon. It explains how he achieved extraordinary performance and efficiency for the 1999 game by writing it entirely in assembly language, specifically focusing on memory management, bitwise operations for performance, and clever pathfinding limitations to handle thousands of NPCs.
Videos recently processed by our community