aboutsummaryrefslogtreecommitdiff
path: root/README.txt
blob: 90fd0f898c60a8e241f0f5b6d39af6f530fe4dd1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
Taipan for Atari 800

This is a work in progress. It's a port of the C version for Linux and
curses, modified to look and play more like the original Apple II version.

Currently the game is playable and complete, but has a few known bugs
(see "Bugs" section below) and probably a few unknown ones too.

The latest version of the source can be found here:
http://urchlay.naptime.net/repos/taipan/

A binary of the game can be found here:

http://urchlay.naptime.net/~urchlay/src/taipan.xex

...though it might be outdated.

Linux/curses port can be found here:
http://www.ibiblio.org/pub/linux/games/textrpg/

Original Apple II BASIC source, plus a browser version of the game,
can be found here: http://www.taipangame.com/

What's missing:

- Large integer (or floating point) support for Debt and Cash (the
  Bank is floating point though). As a side effect of this, the "negative
  interest" bug/feature is missing.

Build Requirements:

- make. I use GNU make 3.82, and occasionally test with an old
  version of BSD make (which works).

- cc65. Originally I used version 2.13.3, and part way through I
  upgraded to a git snapshot dated December 29, 2015. Building with
  cc65-2.3.13 is probably broken right now, but it will be supported
  again.

- gcc. I use version 4.8.2. Probably any version will do. It's only
  needed for convfont.c (and there's nothing gcc-specific about it,
  so really you just need any C compiler, see HOSTCC in the Makefile).

- perl. I use version 5.18.1, probably any 5.x version will work.

- git. You don't exactly *need* this to build the code, but if you
  have it, the git hash will be built into the binary and appear on
  the title screen.

- A UNIX/POSIX environment. At least, you need a 'cat' command and
  a shell that does I/O redirection. Linux, BSD, and Mac OS X should
  be fine. If you're on Windows, try Cygwin.

If you plan to edit the port status scrren, you'll need the Atari800
emulator. It's also handy for actually playing the game, whether you
build it or use the provided binary.

If you plan to edit the title screen, you'll need the ImageMagick library
and its perl module (Image::Magick). Also you'll need something that
can edit PNG images (I use the gimp, anything will do).

Building:

Hopefully you can just type "make" to create the binary. If it doesn't
work, you're likely missing one or more of the requirements listed above.

Running:

The game binary is called "taipan.xex". It's a standard Atari DOS
'binary load' file, which expects to be run with BASIC disabled and no
cartridges inserted.

You can run it on a real Atari computer: any 400/800/XL/XE model should
be fine, so long as it has at least 48K of RAM. Use a SIO2PC cable and
software like Atariserver (Linux) or APE (Windows) to serve the game to
the Atari. If you can come up with a way to actually copy it to a real
floppy disk, you probably want a bootable DOS disk with Taipan renamed
to AUTORUN.SYS.

It's also possible to run Taipan in an emulator, such as Atari800,
Atari++, or Altirra. For Atari800, you should be able to do this:

atari800 -nobasic taipan.xex

License:

The legal status of this is quite murky. The original game is still
copyrighted, though quite a few clones of it have been made for various
platforms over the years with no complaints from the copyright holder.

This Atari port includes font and graphics data ripped straight from
the original Apple game, plus more font data ripped from the Atari 800's
OS ROM.

The Linux port of taipan, according to its .lsm file, is GPL (version
uspecified). My C code is definitely a derivative work, so it's GPL
also. The assembly code and ship graphics are my own work, and I release
them under the GPL (version 2).

Notes:

The Atari executable file format allows for concatenating executables.
The result is still a valid executable. I use this to load the splash
screen and custom font directly into memory before the main program loads.
The Makefile documents how all this works, but it might seem pretty
hairy if you're new to the Atari, Makefiles, and/or Perl.

The Apple version of the game was expected to be run on a monochrome
monitor. Like many other ports from the Apple to the Atari, there will
be color artifacts when using a composite monitor. For best results,
use a monochrome monitor. If you can't, at least try using a color
monitor with S-Video (separate chroma/luma) inputs. If all else fails,
try turning the color knob all the way down (and the contrast as high
as you can stand it). In emulators, you can just disable artifacting.

On PAL systems, the ship explosions and sinking animations will be 20%
slower, and the prompt timeouts will be 20% longer (1 sec => 1.2 sec). I
don't think this is a real issue (it's not like Taipan is a fast-paced
arcade game).

BUGS! At least these:

- After a battle, the prices don't get reset (or, not always?) when
  entering the new port (confirm?).

- The "negative interest" bug is currently missing, due to using
  unsigned values for debt. Plus, it's cheating. It'll get added back when
  I either start using big numbers (floats or 64-bit ints or whatever),
  or just decide to live with the limits of 32-bit ints.

- Not really a bug, but, the interest calculation for debt
  is slightly different, due to using integer math. Very small debt
  amounts will grow much faster than they should, then stabilize and
  converge towards the correct values over time. This only happens when
  you have less than 10 in debt, which (at least for me) is a pretty
  rare situation.

- A few things in the screen layout are slightly off comapred to
  the Apple version. Would really like to get it exact.

- The 'Please limit your firm name to 22 characters' prompt is missing.
  The Apple version actually allows you to type all you want until you
  press Enter. This port works like the Linux version: as soon as you type
  the 22nd character, it acts like you pressed Enter after it.  A good
  compromise might be to allow up to 22 characters, then any keypress
  other than backspace or enter will show the "please limit" prompt.

- Damaged ship graphics need work. I don't have enough unused font
  characters to duplicate the Apple bitmapped graphics exactly, plus
  each damage location must fit entirely within a character cell... but a
  couple of my damaged sections are pretty hokey-looking. Also, now that
  I'm using the graphical title screen, I have a few more characters I
  can redefine as damaged ship sections.

- Fixed, I think: One of my playtesters reported that, when running away
  from combat, it said 4 billion ships were attacking (number of ships
  must have gone negative).

- After a fight, "Arriving at Manila" or such will sometimes appear on the
  fight screen without clearing it first (ships still visible).
  sea_battle() is returning something unexpected, but how?

Deliberate differences between the Apple II and Atari ports:

1. "Press ESC for help" rather than ESC to start.

2. I made it possible to disable the sound, since it's kinda repetitive
   and annoying, plus the game "freezes" while sounds are playing (no
   threading on Atari!) which slows down gameplay.

3. Added a way to change the background color and text brightness. Only
   3 brightness levels available, and only 3 colors: green, amber, and
   black (to mimic the 3 most popular types of monitor used with Apple
   computers back in the day).

4. Prompts that only accept one character no longer require pressing Enter.
   Gameplay is more streamlined this way. Apple and Linux are inconsistent:
   some prompts need Enter, some don't. In the Atari port, the only prompts
   that require Enter are:
   - naming your firm
   - entering a cash amount (but not if you hit a for "all")

5. "We have 5 guns" is in an inverse video box. I think it looks nicer, and
   it matches the "You can afford 5" inverse video box on the trading
   screen.

6. The + that indicates more ships offscreen is inverse video. I find
   that I don't notice it's there, if it's normal video.

7. "You're ship is overloaded" => "Your ship is overloaded". Sorry,
   grammar nazi.

8. Updating the port status screen, and text printing in general, happens
   faster and cleaner-looking, due to using C and asm rather than BASIC,
   and also because the static parts of the screen aren't redrawn unless
   they need to be.

9. The title screen now has a help menu and some key commands to change the
   screen colors and enable/disable sound. The "Press 'ESC' to start"
   has been changed to "Press 'ESC' for help", and any non-command key
   starts the game.

10. Apple uses floating point, no practical limit on cash/bank/debt.
    Atari currently uses 32-bit unsigned longs for cash and debt,
    though the bank is now floating point.

11. On Apple, price of General Cargo isn't always an integer (e.g. 6.5).

12. On Apple, dead enemy ships sink one scanline at a time, and there are
    at least 2 sinking speeds. On Atari, it's one character (8 scanlines)
    at a time, and the speed is always the same.


Differences between the Apple II original and Linux port:

1. Linux has an 80-column screen layout, Apple is 40.
2. Apple version uses a custom font (actually, two, but I'm ignoring that).
3. Apple has sound, Linux does not.
4. Apple has graphical title screen, Linux has ASCII art.
5. Apple has graphical ships during battles, Linux has ASCII art.
6. On Apple, price of General Cargo isn't always an integer (e.g. 6.5).
   As a consequence, the cash and bank amounts aren't always ints either.
7. On Apple, some Y/N prompts (like 'Do you have business with Elder Brother
   Wu') you can press Enter for No. Linux port waits until you hit Y or N.
8. On Apple, ships show damage (get holes in them) as they get shot up.
9. On Linux, you can overpay McHenry (though you get no benefit from it).
   On Apple, payment amount gets clamped to the repair price, so you can
   e.g. be asked to pay 50,000 when you have 70,000 and safely enter A
   (you'll end up 100% repaired and still have 20,000 cash).
10. On Apple, dead enemy ships sink one scanline at a time, and there are
    at least 2 sinking speeds. On Linux, it's one character at a time.

The plan for the Atari port is to mimic the Apple version as closely as
possible... except #6 above. It doesn't really add anything to the game,
and it complicates the code more than I want to deal with. Also #10
will probably not happen (to me, the slow ship-sinking of the Apple
version is annoying anyway).

Right now, items 1, 2, 3, 4, 5, 7, 8, and 9 are implemented Apple-style;
and 6, 10 are Linux-style.

Added a few features not in the Apple or Linux versions:

Other things that need doing to the code:

- Decide what to do about integer overflow. Possibilities:

  - This one seems like the best solution to me. The rest of the
    stuff listed here is left for reference (for now). Here we go: Keep
    using unsigned long for cash and debt, and use a ROM float for the
    bank only. If you try to make a sale, borrow from wu, or withdraw an
    amount that would overflow 32-bit cash, "Taipan, you cannot carry so
    much cash! Your ship would sink under the weight of your riches!". If
    pirate booty would overflow, don't award it. If debt interest would
    result in overflow, the player gets assassinated instead. Advantages
    of this: less code has to be changed, and the FP stuff is limited
    so we don't need a good API for it, just a few functions that can
    call the ROM directly, as needed: bank_deposit(), bank_withdraw(),
    bank_interest(), bank_compare(). These will need a common ul_to_fp().
    Also need a would_overflow(unsigned long value, unsigned long amount)
    to return true if adding value + amount would overflow... actually it
    can return MAX_LONG - value (still true, but also useful as a value).

  - Use a "bigint" library (e.g. 64-bit ints). Would still be
    possible to overflow, but it would take a really determined
    player. Disadvantage: slow. Maxes out at:
    40-bit:   1,099,511,627,776 (1 trillion)
    48-bit: 281,474,976,710,656 (281 trillion)
    64-bit: 1.84467440737096e+19 (beaucoup!)

  - Use the ROM floating point routines. Nobody's likely to ever
    overflow them. But, would have to write wrapper code to call
    them from C and convert longs to floats and back. And it'll
    be slower than bigints even. Maxes out at 1.0e+97

  - Use packed BCD (base 100) like the FP ROM, but as an integer (no
    magnitude). Maxes out at:
    6 bytes:      1,000,000,000,000 (1 trillion)
    7 bytes:    100,000,000,000,000 (100 trillion)
    8 bytes: 10,000,000,000,000,000 (10 quadrillion)
    Advantage: as above, but more so: "1.2 million" gets even easier
    to calculate. Math would be faster than FP, slower than 64-bit ints,
    but conversion to/from longs would be slower.

  - Use a hybrid data format: one long for the bottom 5 decimal digits,
    range 0 to 99,9999 (value % 100000) and the other for the high part
    (value / 100000). Advantage: the game prints strings like "1.2
    million", this would be faster/easier than a regular bigint.
    Maxes out at 429,496,729,600,000 (429 trillion).

  - Another hybrid idea, might be faster: one long ranging up to
    999,999,999, or 1 billion - 1, and an unsigned int for the top
    bits. Existing cprintfancy() can handle the bottom part, if the
    top is 0. If not, we only ever need the top digit of the bottom
    (e.g. the .2 in "1.2 billion"), and then only if the top int is
    less than 10. Maxes out at 65.535 trillion, meaning we'll need
    to be able to print "Trillion", perhaps with no space. This is
    approximately equivalent to a 46-bit int, but uses 48 bits of
    storage.

  - Leave it as-is. Obviously the easiest option, but not very satisfying.
    Maxes out at a measly 4.2 billion.

  Whatever format we pick, we'll run into limitations. The "Cash" area
  of the display is only so wide, we can only fill it with so many
  characters. At some point, we need artificial limits:

  - If your debt maxes out: "Taipan, you have been assassinated!" and
    the game is over.

  - If the bank maxes out, stop calculating interest. On deposit,
    "Taipan, the bank's coffers are full!"

  - If cash maxes out, forcibly retire the player. "Taipan, you are now
    so rich that you own the entire continent of Asia!" or maybe "Taipan,
    your ship has sunk under the weight of your massive fortune!"

  Tricky part about these limits is checking for overflow without
  actually overflowing. E.g. instead of "cash += amount" we have to
  write "if(cash + amount < cash) overflow(); else cash += amount".
  Also, backing out of the call tree will be a PITA. longjmp() anyone?
  cc65's implementation seems to work OK. If I use ROM floats, I
  won't worry about this at all.

  For display, "million" can become "billion" if needed... then "trillion"
  but without a space in front ("1.2trillion"). We have enough room for
  4 digits there, 9999trillion would be the max. Or, abbreviate "billion"
  as "bil", allowing 4 more digits. "99999999 bil" would be 99 quadrillion.

- Size optimization. Right now, the executable is almost 30K of code. I'd
  like it to at least fit on a 16K cartridge. A lot of the C code is
  redundant, and some things can be rewritten in asm if need be. I've
  already eliminated all uses of printf() and its ilk, which removed 2K
  of library code from the executable. Removing all other stdio.h functions
  saved another 1/2K or so.

- In aid of the above: split splash_intro(), cash_or_guns(), name_firm() into
  separate .xex segments. Have to write a linker script to generate an
  init header rather than a run header (or, write in raw asm and forget
  the linker). Use cassette buffer and/or page 6 to pass variables to the main
  program. name_firm() is 1/2K, cash_or_guns() is 1/4K, rewrite in asm and
  they may both fit in page 6.

- Another memory saver: keep some variables in page 6 and/or the tape
  buffer. Also, find out how much page zero cc65 leaves us to
  work with, maybe enough contiguous bytes for e.g. the fancy_num[]
  buffer. draw_lorcha is using FR0 at $D4, but using it for fancy numbers
  wouldn't conflict...  it looks like cc65 uses 26 bytes of ZP from
  $80-$99, so we have quite a bit free.

- A thought: if memory gets too tight, switch to a boot disk rather than a
  .xex file, and load code from disk at runtime (e.g. sea_battle() could be
  loaded on top of some other routines, then the other routines reloaded
  when the fight is over). That, or use a bankswitched cartridge.

- Temporarily add a "god mode" to allow me to test situations that would take
  a lot of regular gameplay to reach.

Future Ideas:

I may do a "Taipan Plus" at some point. The regular Taipan game will be
faithful to the original, and the Plus version could have some or all of:

- More ports to dock at, some of which might have their own warehouses,
  repair yards, etc.

- More trade goods, not all of which are available at all ports.

- Actual market trends, rather than a base price + random number. There
  might be news events that cause prices to go up/down (e.g. Arms are
  up at Saigon because there's a gang war in progress, Opium is up at
  some port but the chances of getting busted are higher). This feature
  actually exists in Art Canfil's TRS-80 Taipan "version 10".

- Ability to control a fleet of ships. Each one will either be a cargo
  ship or a warship.

- A "Turbo Combat" feature like one of the phone versions I've seen. You
  set your orders and hit Turbo, and it finishes the fight instantly,
  but you can't change your mind about your orders (fight until you win
  or die, or run until you escape or die).

- Special missions. Someone at some port needs you to transport documents
  or whatever, to some other port... you will almost certainly be attacked
  by whoever's trying to get the documents though.

- Rival trading companies. Their activities can influence prices, and
  you can fight them and possibly salvage actual cargo.

- Variable passage of time. Distant ports take longer to get to. Also,
  winds or ship damage can slow you down.

I dunno how many of the above will fit in the Atari's RAM. Probably have
to rewrite the whole game from scratch in assembly before adding features.