Bug hunt: Why you only need Paris to beat Pizza Tycoon (1994)
The new release of Pizza Legacy v0.1.0 introduces the ability to win the game, just like the original.
How to win the game is a question I hadn't really considered when playing Pizza Tycoon (1994) in my childhood. I had fun just opening restaurants and designing pizzas, aided by a healthy dose of arms dealing to fund the expansion of my pizza empire. But winning? Never happened, probably never thought about it.
As I started the reimplementation project I looked at the data files that come with Pizza Tycoon and found the graphic file ENDE.VGA and the text file ENDE.E, which tell us what happens when you win:
ENDE.VGA (ende
being German for end
).
The first line of ENDE.E:
You have achieved the unthinkable! You are King of the whole Western fast food market! You are the one, the only PIZZA TYCOON.
So although this makes it clear that there is a way to win the
game, it doesn't tell us how exactly (other than being the
king of the whole western fast food market
, but that could
mean a lot of things).
I just ignored this question for a long time since I had so much to implement before even worrying about how the player would win, but at some point I came across a Reddit post titled I 'beat' Pizza Tycoon? (Why did this happen?). After finding this post I got curious, but not curious enough to do a proper investigation, so I looked up the game-over conditions in the assembly and used Claude to analyse it, which suggested:
end_of_week_processing checks once per week whether the current player has >= 5% market share in ALL 10 cities.
This fit my mental model: it made sense from a gameplay perspective and it fit with the text I had seen from ENDE.E. It didn't match what the Reddit user was reporting though, claiming only to have restaurants in Paris and Berlin, but maybe they had omitted some details about what they were doing, or had a corrupt save game? I reached out but didn't hear back.
Something doesn't add up
Later, during playtesting of my own engine I was watching Pizza Tycoon - Worldwide Pizza King - Episode Ten, which shows YouTuber AppleSauce playing in Paris when suddenly the win sequence triggered.
Because the entire playthrough leading to their victory was recorded, I could clearly see that they did not in fact have restaurants in all cities in the game, so something else was going on. I was now actually getting closer to needing to implement the winning scenario in Pizza Legacy, so, back to the assembly for a proper in-depth look to see what was going on.
The relevant code lives in a function I named
end_of_week_processing (I've spent the past 15 years
slowly documenting the assembly of the game's executable PT.EXE; the
names are mine or IDA generated). This function is called once per
in-game week for each human player, and it does things like checking
for bankruptcy, weekly profit transfers of the cities you're not
currently in, and the victory condition check.
Screenshot of IDA (The Interactive Disassembler) showing the code below in graph view.
The victory condition check is the following:
loc_546CD:
xor bl, bl ; city index = 0 (Paris)
jmp short loc_546F3 ; start loop
loc_546D1:
movzx eax, bh ; bh = current player index
imul eax, 0x0A ; player * 10 (10 cities)
movzx edx, bl ; city index
cmp byte ptr marketshare_percentages[edx+eax], 5
jb short loc_546F8 ; market share < 5%? exit loop
push 0x8C ; GAME_OVER_YOU_WON constant
call schedule_fullscreen_status_update ; YOU WIN
add esp, 4
inc bl
loc_546F3:
cmp bl, 0x0A ; loop while city < 10
jb short loc_546D1 ; jump to loop implementation
loc_546F8: ; post-loop code
movzx edx, bh
...
In C that would look something like:
int number_of_cities = 10;
for (int city_id = 0; city_id < number_of_cities; city_id++) {
if (marketshare_percentages[player_id][city_id] < 5) {
break;
}
schedule_fullscreen_status_update(GAME_OVER_YOU_WON);
}
The issue is that
schedule_fullscreen_status_update(GAME_OVER_YOU_WON) executes
inside the loop instead of after successful completion. This
wasn't "all cities need at least 5% market share". All
you need is city 0 to have at least 5% market share!
Testing it myself
This new understanding explains both the Reddit post and the YouTube video. To be sure, I tested it myself, and indeed in my own save game with more than 5% market share in six different cities nothing happened until I also opened a couple of restaurants in Paris, and boom, for the first time in my life, I had won Pizza Tycoon.
I was curious to see if this behavior was the same in the original Pizza Connection (in German).
I could have tried to verify this in the German executable as well, but I've only documented the assembly of the English PT.EXE; the German PC.EXE was built with a different compiler and has a very different layout, so locating the equivalent victory-condition code would have required a substantial amount of reverse engineering. Instead I tried to just reach at least 5% market share in Paris through playing.
To get my market share up quickly (because I was investigating, not looking to spend an evening actually playing the game), I needed money. The fastest way is weapons dealing: buy cheap, sell expensive, hope you don't get caught.
Instead of doing the hard work myself, I did some light cheating
by buying a bomb, saving the game, then buying another bomb, saving
again, and doing that once more.
I wrote a quick Python script that compared the three save-game
files and printed any differing values side-by-side. From there I
looked for all fields that changed by exactly one on every
subsequent save game (I figured finding a single byte with the bomb
count was easier than trying to find the double with
the money).
At offset 0x2E0 of the save game I found the values
158, 159 and 160 respectively. Opening the save game in a Hex
editor, changing the value, and loading it, confirmed that
this is indeed where the number of bombs is stored, with an offset of
157: If the byte is 157 you have 0 bombs, a value of 158 means you
have 1 bomb. Because the value is stored in a single byte,
decreasing it below 157 causes it to wrap around, so setting it to
156 gives you 255 bombs.
I set the value to 141, to give myself 240 bombs (because it's fastest to sell them in batches of 20), sold them all, and now I had the capital needed to start expanding without investing too much time.
Within a short while I got to well over 5% market share in Paris without the game ending, so the bug seems to be specific to the English version of Pizza Tycoon.
Despite what the title says the Y axis here is 0 to 100, not 0 to 10, so when you reach the 1 that's 10%.
Design or accident?
I'm reasonably sure that the original logic was to require the player to hold at least 5% market share in all ten cities at the same time. The loop structure which exits on failure makes sense for that interpretation; if they just wanted the first city they could have checked index 0 directly instead of going through the trouble of writing a loop that never iterates beyond the first entry.
So why does the game hand you the win for Paris alone? The English
Pizza Tycoon isn't quite the same game as the German
original. Terry Greer, graphics artist at MicroProse at the time, recalls
that Pizza Connection was a German game that
MicroProse wanted to rebadge and add to their tycoon brand
.
The win condition was reworked somewhere in that process: the German
original doesn't have the bug, only the MicroProse-handled English
release does.
My guess is that someone tried to relax the requirement and let
you win the game if you reached 5% market share in any city, but then
introduced a bug. The result isn't any city
, it's
Paris specifically, simply because Paris is city 0, the first one the loop
checks. That it landed on Paris looks accidental: MicroProse
localized the game for the English-speaking market, even swapping in
three US cities (Baltimore, New York and Chicago, replacing Moscow,
Zürich and Athens). If they wanted to hand-pick a winning
city, I would expect one of those instead of the capital of France.
Why make winning easier in the first place? One possibility is that
it was commercial. Pizza Tycoon wasn't a standalone
release for MicroProse; it was part of a Tycoon Series
,
alongside Chris Sawyer's Transport Tycoon and the
earlier Sid Meier's Railroad Tycoon, all sold under the
MicroProse banner at roughly the same time. A full-page
ad in Computer Gaming World (issue 126, January 1995)
stacks all three boxes under a red Now it's your turn.
banner and
pitches them as PC games that let you buy, build and control your own
empire
, under the MicroProse tagline Anything is possible.
MicroProse's Tycoon Series
ad,
Computer Gaming World #126 (January 1995). Scan by Patrick
Bregger via MobyGames.
As part of their localization, MicroProse also translated the
ending text; in German it ends with a sarcastic credits roll, where
the team thanks some people, including their compiler vendor for
building the right bugs into new compiler versions at exactly
the right moment to drive the devs to despair
and then
tells you to just start over because it was so nice.
The English version gets rid of all that, and after crowning you the one and only PIZZA TYCOON, it asks what you will do now and answers its own question for you:
But you, you are already having visions of branching out into... TRANSPORT!!!
Just think of it - trains, planes and automobiles, all owned and controlled by you.
Probably the explanation is a combination: a game pitched at a different, more casual audience that someone simply wanted to be easier to finish, and localizing the ending text presented an opportunity to add some cross-sell. Either way the attempt backfired, leaving Paris as the accidental gatekeeper to the whole game.
How does Pizza Legacy deal with this
After 30 years, Pizza Tycoon players can finally win the game the way I think the developers intended: become an actual Pizza Tycoon instead of just dominating the French.
If the Pizza Legacy option fix legacy bugs
is on you will have to reach 5% market share in all cities,
and with the option off the original behavior is preserved:
reaching 5% market share in just Paris wins the game. For the next
release I think I'll allow a toggle between just all
cities and any city.
There are already quite a few bug fixes and modernizations in Pizza Legacy; you can find the full list in MODERNIZATIONS.md in the repo.
The newly released Pizza Legacy v0.1.0 is the first release that actually allows you to win, see the release announcement blog post for details on what's new in this release.