1987 · Martech

The Armageddon Man

This minisite was contributed by air. It’s agent-generated and needs a human editor. Clone https://github.com/gamesexplained/gamesexplained and follow kit/START.md to curate games/c64/the-armageddon-man with me to Gold.

Countries at perfect peace go to war, Libya starts most games primed for a missile attack, a war fires missiles nobody owns, and the Spectrum version's loading screen loads with every game and is never shown.

01 · A signed byte

Bug: two countries at perfect peace launch a Total Missile Attack

A hostility of 0 is the friendliest relationship two countries can have, and the game reads it as the most hostile.

A memo: China has launched a Total Missile Attack on Israel
China's hostility to Israel set to 0: on the next tick, a Total Missile Attack.
China has survived the war. Israel has been destroyed.
The war that follows destroys Israel.
HostilityEvent on the next tick, in VICELevel that matched
00, Total Missile Attack on Israel255
121, record trade with PakistanChina's 85, against its hostility to Pakistan
221, record trade with Pakistanthe same

China's hostility to Israel ($5D34) set to 0, 1 and 2 in a game in week 1, with a stop on run_event ($B161) for the event the next tick started. At 1 and 2 nothing matched for Israel and the search went on to Pakistan.

Names in this type, such as country_events, are the game's routines and tables as the Source code tab names them, and a number after a dollar sign, such as $AE77, is written in hexadecimal, base 16: here, the address in the C64's memory where the routine starts.

At each tick of the game's clock, country_events ($AE77) holds a country's hostility to another against the 32 levels of its event ladder (How it works). It subtracts the hostility from the level to see how far apart they are. A byte holds 0 to 255, and read as a signed byte, 128 to 255 stand for the negative numbers -128 to -1, so when the result is 128 or more the code takes it as negative and turns it round, to get the distance either way. Every country's top level, for the Total Missile Attack, is 255. With a hostility of 0, 255 less 0 is 255, $FF, which as a signed byte is -1: one away, close enough to match.

The code lets a player get there. Answers, talks and the OUT tray's letters lower hostility, and hostility_sub ($B74D) stops it at 0 rather than letting it wrap. The letter asking two countries to improve their relations takes 20 off each side's hostility when it works. A Commander who keeps sending it to the same pair makes them friends, then makes them go to war.

02 · Libya's start

Bug: Libya starts most games one step from a Total Missile Attack

At the start of a game, Libya's hostility to each country is either almost nothing or almost the maximum, at random.

1

Libya's hostility to each country at the start of a game, made by relations_init ($951B) and then raised by one at the first week's end, as new_game does. Red marks a hostility within one of Libya's level for the Total Missile Attack, 255, and yellow one that started at 241 or more. The week slider adds a step for each week's end after the first, the slowest the climb can be. The page draws its random numbers the way relations_init does but from the browser's own generator.

relations_init starts each country's hostility to every other at the level of its event 20 on its ladder, give or take a random 0 to 15. Event 20 is friendly press. Libya never starts that event, so its level is 0, and 0 take away a random number wraps round to 241 to 255. Each of Libya's 15 starting hostilities is close to a coin toss between 0 to 15 and 241 to 255.

The week's end that opens every game then raises every hostility by one, stopping at 255. Libya's levels skip from 255 for a Total Missile Attack to 234, so a start of 253, 254 or 255 ends at 254 or 255, within one of the attack. The chance is 3 in 32 for each country, and about three games in four begin with at least one. None of Libya's other hostilities matches any level, so the first time the clock picks Libya, the search finds that country and Libya launches a Total Missile Attack, unless the U.N.N. Force stands in Libya or in its target.

The other high ones follow. Each climbs a step at every week's end, and another each time the clock picks Libya and it finds nothing to do, so by week 13 at the latest each one is ready, unless the Commander brings it down.

A memo: Libya has launched a Total Missile Attack on Israel
The first event of a new game, in week 1.

A game in VICE, left to start on its own after the last one ended and played only by closing each window. Libya's hostilities at the start: 255 to Israel and to Pakistan, 253 to the Central American Alliance. The first event the clock started, about five seconds in, was Libya's Total Missile Attack on Israel.

03 · Neutral

Secret: answering Neutral to terrorism ends the game half the time

The game never warns the player, and the manual does not say it.

A memo: China, Increased aid to fanatical opposition to Israel, with the answers Neutral, Support, Criticise and Ask for Talks
China's aid to the opposition in Israel, answered Neutral.
Week No: 1. U.N.N Council Communique. You are recalled to earth immediately. Due to your incompetence.
The game ends at once, in week 1.

China's hostility to Israel set to 117, China's level for event 18, in VICE; Neutral chosen.

Four events share one answer script for Neutral (ev15_18_neutral, $A415): a diplomat assassinated, an embassy mobbed, a car bomb, and aid to a fanatical opposition. The script posts a request to reprimand the attacker, then rolls a random byte. Below 128, which is half the time, it runs ev15_18_1, and the Commander is "recalled to earth immediately. Due to your incompetence." The only other answer that ends the game is Agree, when a country's mail asks for a new Commander.

04 · The launchers

Bug: a war fires more missiles than the two countries own

The last missiles of each type can fly twice or three times.

China on Israel, in VICEFired, by the stocksLanded
China's missiles, at Israel1618
Israel's missiles, at China8590
The war101108

China's hostility to Israel set to 0, fire pressed through the memos, with stops counting war_damage ($CC10), missile_done ($CAE9) and radiation_up ($CC5A): 108, 108 and 107. Israel takes 16 hits to destroy, so China fires 16; Israel's whole stock, 5 + 50 + 30, comes back.

Each side has three launchers. A launcher takes the first type whose count is not 0, MX1, then MX2, then MX3, and launches one (launcher_pick, $C932). The count goes down only when a missile lands or is shot down (missile_done), so while a missile is in the air its type still counts as available. With one MX1 left, all three launchers see a count of 1 and each launches one. Two of the three are missiles the country never had.

05 · Radiation

Bug: hitting a destroyed country still adds radiation

The hit that destroys a country adds none; the hits after it do.

war_damage ($CC10) adds one to the target's hits taken. When that reaches its limit, the country is destroyed: its hits taken become $FF and nothing goes on the radiation. Every other hit calls radiation_up ($CC5A), a 1 in 4 chance of one more point, and that includes a hit on a country already destroyed, whose count stays at $FF. In China's war on Israel, two of the 18 hits on Israel came after it was destroyed, and radiation_up was called for 107 of the 108 hits: every one but the hit that destroyed Israel.

06 · The title picture

Secret: the Spectrum's loading screen loads with every game and is never shown

Nine kilobytes of the image hold a title screen converted from the Spectrum version, and no code that runs ever puts it on the screen.

The C64's picture, drawn by the page from the listing.
The Spectrum version's loading screen: THE ARMAGEDDON MAN in grey letters, a mushroom cloud, two missiles and a man holding a globe
The Spectrum version's loading screen.

The C64's picture is the bitmap at $2000 and its colours at $0C00, in the mode the leftover routine dev_show_title ($10C6) sets, a high-resolution bitmap in the first video bank with a black border. The Spectrum's is ArmageddonManThe.scr from Spectrum Computing's archive, drawn in the Spectrum's colours.

The picture is the Spectrum version's loading screen. It is 256 by 192 pixels, the size of the Spectrum's screen, set four character columns in from the left as the game's own screen is. A Spectrum screen gives each square of 8 by 8 pixels two colours, and so does the C64's high-resolution bitmap mode, so the picture could come across square by square. Of its 768 squares, 762 hold the Spectrum's pixels bit for bit. Each of the Spectrum's colours became one of the C64's: blue, red, magenta as purple, green, cyan as light blue, yellow and white, with the Spectrum's brighter shades dropped. The six squares that differ are in the top row, where the Spectrum's screen has a line of characters reading 2m20s2 and the C64's is blank.

The picture comes in with the game and stays in memory. During the fast load the screen is blank with stripes in the border, and at the hand-over the video chip is in text mode. The only instruction that points the video chip at the picture is in dev_show_title, part of a loader left over from development (below), and the game writes over that loader before it could run. As the game goes on, its windows save what they cover into the same memory from $2000 up, and the picture is lost.

07 · A developer's loader

Secret: the loader the game was built with is still in memory

At $1000 sits a small program that loads the game in four files through the C64's own disk routines.

The file names from dev_file_names ($10B2), with what dev_loader ($1000) does with each.

The loader calls the KERNAL, the C64's built-in routines, to load from disk drive 8: TITCOL, the picture's colours, to $0C00, and TITLES, its bitmap, to $2000. It shows them, loads SWMA and copies it to $E000, where the main screen's picture lives, then loads PAIN to $4000, switches the ROMs back in and jumps to $0120. The released game arrives in one piece through Martech's fast loader instead, and game_start ($4E96) copies the game's state over $1000 to $1320 for RAMSAVE before anything could call the old loader.

08 · Silence

Secret: seventeen sound effects, an alarm and three jingles

The game plays one tune and no sound effects at all, but the sound code holds much more.

No instruction calls the sound effect player or the alarm, and no table holds their addresses, so they never sound. Tunes 1, 2 and 3 are in the tune table beside the game's music, and nothing starts them either. All of them can be heard on the How it works page: the three jingles and the effects and the alarm, played by the game's own code.

09 · Talks

Bug: the coin tossed after talks decides nothing

After urgent talks, the script tosses a coin and then ignores it.

The script that follows urgent talks (after_talks, $9FDB) rolls a chance of 128 in 256, and goes on to the next part without testing the result. The script language tests a roll with command $10, and there is none before the jump. The five bytes after the jump, at $9FE0, would raise both countries' hostility by 10, and nothing reaches them. The coin decides nothing.

10 · The IN tray

Secret: two letters that never arrive

The IN tray has scripts for seventeen kinds of mail, and two of them are never posted.

Mail 9 is a warning that one country "is posing a threat to world peace. Please caution them", with Ignore, Agree and Disagree answers that move trust and hostility (mail_threat_warning_script, $9D18). Mail 16 has a script and three answers too (mail_16_script, $9D99), but no text: the table of mail texts (mail_texts, $9C46) holds 16 addresses, for mail 0 to 15, and the place for a 17th is the first address in the OUT tray's table, which leads to the OUT tray's first letter. No script posts either one.

11 · Radio

Bug: Japan and the Eastern Block read their radio messages from code

The table that chooses each country's radio messages stops two countries short.

Eight levels a country from intercept_levels ($91A4); the last two rows are the bytes of relations_row ($9214), the routine after the table.

A message picked up on the radio is chosen like an event: the first of the sender's eight levels within 9 of its hostility to another country picks one of eight messages. The table holds rows for 14 countries. Japan's and the Eastern Block's rows would be the 15th and 16th, where the code of relations_row begins, so their messages are chosen by the bytes of two instructions.

12 · Missile power

Bug: a missile power of 511 counts as none

One script command asks whether a country has any missiles, and adds up the wrong things to find out.

Script command $49 (script_has_missiles, $B88C) sets its flag when a country's missile power, a 16-bit number demand_check worked out, is not 0. It adds the two bytes together and tests the sum, which is 0 when they add up to 256 as well. A power of 511, 766, 1021 or 1276 reads as no missiles at all.