diff options
Diffstat (limited to 'taipan.c')
-rw-r--r-- | taipan.c | 441 |
1 files changed, 296 insertions, 145 deletions
@@ -20,12 +20,6 @@ /**** atari-specific stuff */ -void atari_text_setup() { - POKE(710, 0xc0); // green background - POKE(709, 0x0c); // bright text - POKE(756, 0xb8); // use our custom font -} - /* values returned by cgetc() for backspace & enter keys */ #define BKSP 0x7e #define ENTER 0x9b @@ -40,6 +34,22 @@ void atari_text_setup() { /* wait up to j jiffies for a keypress. returns -1 if no key pressed */ extern int __fastcall__ timed_getch(unsigned int j); +/* custom Atari-aware cgetc() wrapper. returns only non-inverse + plain ASCII characters, except EOL and BS. Unlike the real cgetc(), + it's an unsigned char, and can't return -1 for failure (but, it will never + fail. real cgetc() never fails either, even if user hits Break) */ +extern unsigned char agetc(void); + +/* wrapper for agetc(): lowercases letters */ +extern unsigned char lcgetc(void); + +/* wrapper for agetc(): returns only numbers, enter, backspace */ +extern unsigned char numgetc(void); + +/* wrapper for agetc(): returns only y or n. + dflt is 'y' 'n' to set the default answer, or 0 for no default. */ +extern unsigned char __fastcall__ yngetc(char dflt); + /* sleep for j jiffies (no PAL adjustment at the moment) */ extern void __fastcall__ jsleep(unsigned int j); @@ -53,7 +63,10 @@ extern void __fastcall__ jsleep(unsigned int j); */ #define initrand() /* no-op on Atari */ +/* random positive int, 0 to 32767 */ extern unsigned int __fastcall__ randi(void); + +/* random long, 0 to 2**32-1 */ extern unsigned long __fastcall__ randl(void); /* defined in portstat.s, this is the contents of PORTSTAT.DAT. @@ -68,9 +81,29 @@ char port_stat_dirty = 1; /* asm curses/conio funcs from clrtobot.s. Old C versions moved to oldcurses.c for reference. */ -extern void clrtobot(); -extern void clrtoeol(); +extern void clrtobot(void); +extern void clrtoeol(void); +/* asm funcs from draw_lorcha.s for drawing/animating enemy ships. + used by sea_battle() */ +extern void __fastcall__ draw_lorcha(int which); +extern void __fastcall__ flash_lorcha(int which); +extern void __fastcall__ damage_lorcha(int which); +extern void __fastcall__ sink_lorcha(int which); +extern void __fastcall__ clear_lorcha(int which); + +void atari_text_setup() { + jsleep(1); + POKE(560, PEEK(212)); // restore the + POKE(561, PEEK(213)); // display list + jsleep(1); + POKE(559, 34); // turn on the screen (normal playfield) + jsleep(1); + POKE(710, 0xc0); // green background + POKE(709, 0x0c); // bright text + POKE(756, 0xb8); // use our custom font + POKE(731, 1); // disable keyclick on XL/XE (does nothing on 400/800) +} /**** End of atari-specific stuff */ @@ -85,38 +118,48 @@ unsigned long randclamp(unsigned long clamp) { return r % clamp; } -/* wrapper for cgetc() that returns letters as lowercase only - (and everything else normally). Avoids a bunch of reduntant - if(foo == 'A' || foo == 'a') tests. */ -int lcgetc() { - return tolower(cgetc()); -} - /* print 'count' spaces, but leave the cursor where it was. - doesn't work if the cursor wraps to the next line! - TODO: rewrite in asm. - */ + TODO: rewrite in asm. */ void cblank(unsigned char count) { char oldx = wherex(); + char oldy = wherey(); while(count--) cputc(' '); - gotox(oldx); + gotoxy(oldx, oldy); } /* conio doesn't back up the cursor if you cputc(BS), it - prints the graphics character instead. So: */ + prints the graphics character instead. Could use putchar(), + but using stdio links a bunch of extra support code. So: */ +/* TODO: rewrite in asm */ void backspace() { gotox(wherex()-1); cblank(1); } +unsigned char get_item(unsigned char allow_all) { + unsigned char i; + for(;;) { + i = lcgetc(); + switch(i) { + case 'o': return 0; + case 's': return 1; + case 'a': return 2; + case 'g': return 3; + case '*': if(allow_all) return 4; /* else fall thru */ + default: break; + } + } +} /* taipan functions (modified as little as possible) */ #define GENERIC 1 #define LI_YUEN 2 +/* title screen now a separate xex segment (see Makefile for details) */ // void splash_intro(void); + int get_one(void); -unsigned long get_num(int maxlen); +long get_num(void); void name_firm(void); void cash_or_guns(void); void set_prices(void); @@ -135,11 +178,6 @@ void quit(void); void overload(void); void fancy_numbers(unsigned long num, char *fancy); int sea_battle(int id, int num_ships); -extern void __fastcall__ draw_lorcha(int which); -extern void __fastcall__ flash_lorcha(int which); -extern void __fastcall__ damage_lorcha(int which); -extern void __fastcall__ sink_lorcha(int which); -extern void __fastcall__ clear_lorcha(int which); void fight_stats(int ships, int orders); void mchenry(void); void retire(void); @@ -194,6 +232,7 @@ int newdamage; // void cprintfancy(unsigned long ul) { // } /* print an int or long as a string, conio-style */ + void cprintulong(unsigned long ul) { cputs(ultoa(ul, fancy_num, 10)); } @@ -229,16 +268,14 @@ void captains_report() { } -void overload(void) -{ +void overload(void) { compradores_report(); cputs("Your ship is overloaded, Taipan!!"); timed_getch(TMOUT_5S); return; } -void new_ship(void) -{ +void new_ship(void) { int choice = 0, time; @@ -248,8 +285,7 @@ void new_ship(void) time = ((year - 1860) * 12) + month; amount = randi()%(1000 * (time + 5) / 6) * (capacity / 50) + 1000; - if (cash < amount) - { + if(cash < amount) { return; } @@ -257,8 +293,7 @@ void new_ship(void) compradores_report(); cputs("Do you wish to trade in your "); - if (damage > 0) - { + if(damage > 0) { revers(1); cputs("damaged"); revers(0); @@ -270,6 +305,15 @@ void new_ship(void) cputs(fancy_num); cputs(", Taipan? "); + choice = yngetc(0); + if(choice == 'y') { + cash -= amount; + hold += 50; + capacity += 50; + damage = 0; + } + + /* while ((choice != 'Y') && (choice != 'y') && (choice != 'N') && (choice != 'n')) { @@ -283,6 +327,7 @@ void new_ship(void) capacity += 50; damage = 0; } + */ if ((randi()%2 == 0) && (guns < 1000)) { @@ -316,6 +361,14 @@ void new_gun(void) cputs(fancy_num); cputs(", Taipan? "); + choice = yngetc(0); + if(choice == 'y') { + cash -= amount; + hold -= 10; + guns += 1; + } + + /* while ((choice != 'Y') && (choice != 'y') && (choice != 'N') && (choice != 'n')) { @@ -328,6 +381,7 @@ void new_gun(void) hold -= 10; guns += 1; } + */ port_stats(); @@ -336,10 +390,6 @@ void new_gun(void) void fancy_numbers(unsigned long num, char *fancy) { - /* note to self: find out why there's graphic corruption - if this isn't static. It's caused by sprintf() or strcpy() - writing to the font, which is supposed to be above cc65's max - usable address! */ static char number[18]; char mil = 0; unsigned int num1, num2; @@ -499,12 +549,11 @@ int sea_battle(int id, int num_ships) { if(orders == 0) { input = timed_getch(TMOUT_3S); - if (input == 'f') - { + if (input == 'f') { orders = 1; - } else if ((input == 'R') || (input == 'r')) { + } else if(input == 'r') { orders = 2; - } else if ((input == 'T') || (input == 't')) { + } else if(input == 't') { orders = 3; } else { gotoxy(0, 3); @@ -521,9 +570,9 @@ int sea_battle(int id, int num_ships) { clrtoeol(); gotoxy(0, 4); clrtoeol(); - if (input == 'f') { + if(input == 'f') { orders = 1; - } else if (input == 'r') { + } else if(input == 'r') { orders = 2; } else { orders = 3; @@ -701,14 +750,15 @@ int sea_battle(int id, int num_ships) { clrtoeol(); cputs("What shall I throw overboard, Taipan? "); - /* TODO: this, buy(), sell() have common code */ + choice = get_item(1); + /* while ((choice != 'o') && (choice != 's') && (choice != 'a') && (choice != 'g') && (choice != '*')) { - choice = tolower(get_one()); + choice = lcgetc(); } if(choice == 'o') { @@ -722,13 +772,14 @@ int sea_battle(int id, int num_ships) { } else { choice = 4; } + */ if(choice < 4) { gotoxy(0, 3); clrtoeol(); cputs("How much, Taipan? "); - amount = get_num(9); + amount = get_num(); if((hold_[choice] > 0) && ((amount == -1) || (amount > hold_[choice]))) { amount = hold_[choice]; @@ -799,7 +850,6 @@ int sea_battle(int id, int num_ships) { fight_stats(num_ships, orders); gotoxy(0, 3); clrtoeol(); - // printw("But we escaped from %d of 'em!", lost); cputs("But we escaped from "); cprintulong(lost); cputs(" of 'em!"); @@ -815,12 +865,6 @@ int sea_battle(int id, int num_ships) { } } plus_or_space(num_ships > num_on_screen); - /* - if(num_ships == num_on_screen) { - gotoxy(39, 7); - cputc(' '); - } - */ } gotoxy(0, 16); @@ -943,7 +987,23 @@ int sea_battle(int id, int num_ships) { } } -/* TODO: rewrite in asm */ +#if 0 +/* TODO: rewrite in asm + get_one() gets one character of input, but waits for Enter + to be pressed, and allows backspacing over it. + Honestly I don't see the value in using this instead of + cgetc(). Plenty of prompts in the game (e.g. Buy/Sell/Quit Trading), + and all the stuff in combat, just accept one character without + need to press Enter. + This is called from: + mchenry() (y or n) + cash_or_guns() (1 or 2) + final_stats() (play again, y or n) + li_yuen_extortion() (y or n, twice) + elder_brother_wu() (y or n, twice) + buy() (for picking item) + sell() (idem) + */ int get_one(void) { int input, @@ -978,11 +1038,18 @@ int get_one(void) return choice; } +#else +int get_one(void) { + cursor(1); + cblank(1); + return agetc(); +} +#endif /* TODO: rewrite in asm. Maybe. */ +#if 0 unsigned long get_num(int maxlen) { - /* see comment in fancy_numbers for why this is static */ static char number[20]; int input, @@ -1029,6 +1096,33 @@ unsigned long get_num(int maxlen) cursor(0); return amount; } +#else +long get_num(void) { + static char number[20]; + unsigned char count = 0; + int input; + + cursor(1); + cblank(1); + + while((input = numgetc()) != '\n') { + if(input == BKSP) { + if(!count) continue; + backspace(); + number[count] = '\0'; + count--; + } else if(input == 'a') { + if(!count) return -1; + } else { + cputc(input); + number[count] = input; + count++; + } + } + cursor(0); + return strtol(number, (char **)NULL, 10); +} +#endif /* TODO: rewrite in asm */ void cash_or_guns(void) @@ -1215,7 +1309,6 @@ void port_stats(void) cputsxy(30, 6, location[port]); revers(0); - // gotoxy(33, 9); gotoy(9); fancy_numbers(debt, fancy_num); gotox(33 - strlen(fancy_num) / 2); @@ -1245,48 +1338,9 @@ void port_stats(void) cputs(fancy_num); } -/* Unlike the Linux port, splash_intro() doesn't have to draw - the "programmed by" etc. text in the intro screen, as it's - preloaded into screen memory as a xex segment... but it - means splash_intro() can *only* be called by main(), once, - at program startup. So we don't get a 2nd splash intro - when answering Y to 'Play Again?". - Ideally, I should redefine enough graphics characters - that I can draw a nice ATASCII trading ship. But for - now I'll just draw 6 of the lorchas. - */ -#if 0 -void splash_intro(void) -{ - int i; - - cursor(0); - gotoxy(0,23); -#ifdef VERSION - cputs(VERSION); -#else - cputs("(no version info)"); -#endif - - /* if we print anything in this function, the character at (2,0) - gets inversed because the OS placed a cursor there. Fix it: */ - gotoxy(2,0); - cputc(0xa0); - - for(i=0; i<3; i++) draw_lorcha(i); - for(i=5; i<8; i++) draw_lorcha(i); - - timed_getch(TMOUT_5M); - - flushinp(); - return; -} -#endif - void mchenry(void) { static int choice; - choice = 0; compradores_report(); cputs("Taipan, Mc Henry from the Hong Kong\r\n"); @@ -1294,14 +1348,16 @@ void mchenry(void) cputs("ye've a wee bit of damage to yer ship.'\r\n"); cputs("Will ye be wanting repairs? "); + choice = yngetc('y'); + /* while ((choice != 'Y') && (choice != 'y') && (choice != 'N') && (choice != 'n')) { choice = get_one(); } + */ - if ((choice == 'Y') || (choice == 'y')) - { + if(choice == 'y') { static int percent, time; static long br, repair_price, amount; // int percent = ((float) damage / capacity) * 100, @@ -1329,7 +1385,7 @@ void mchenry(void) for (;;) { gotoxy(24, 21); - amount = get_num(9); + amount = get_num(); if(amount == -1) { if(cash > repair_price) amount = repair_price; @@ -1468,6 +1524,11 @@ void final_stats(void) chline(31); cputc(3); // lower right corner + gotoxy(0, 22); + cputs("Play again? "); + choice = yngetc(0); + + /* while ((choice != 'Y') && (choice != 'y') && (choice != 'N') && (choice != 'n')) { @@ -1475,9 +1536,9 @@ void final_stats(void) cputs("Play again? "); choice = get_one(); } + */ - if ((choice == 'Y') || (choice == 'y')) - { + if(choice == 'y') { bank = 0; hkw_[0] = 0; hkw_[1] = 0; @@ -1494,7 +1555,6 @@ void final_stats(void) year = 1860; port = 1; - // splash_intro(); name_firm(); cash_or_guns(); set_prices(); @@ -1537,7 +1597,7 @@ void transfer(void) cputs(item[i]); cputs(" shall I move\r\nto the warehouse, Taipan? "); - amount = get_num(9); + amount = get_num(); if (amount == -1) { amount = hold_[i]; @@ -1584,7 +1644,7 @@ void transfer(void) cputs(item[i]); cputs(" shall I move\r\naboard ship, Taipan? "); - amount = get_num(9); + amount = get_num(); if (amount == -1) { amount = hkw_[i]; @@ -1629,7 +1689,7 @@ void quit(void) gotoxy(13, 21); clrtobot(); - choice = get_num(1); + choice = numgetc() - '0'; if (choice == port) { @@ -1951,7 +2011,8 @@ void elder_brother_wu(void) { gotoxy(21, 19); - choice = get_one(); + // choice = get_one(); + choice = yngetc('n'); if ((choice == 'N') || (choice == 'n') || choice == 0) { break; @@ -2008,7 +2069,7 @@ void elder_brother_wu(void) cputs("How much do you wish to repay\r\n"); cputs("him? "); - wu = get_num(9); + wu = get_num(); if (wu == -1) { wu = cash; @@ -2048,7 +2109,7 @@ void elder_brother_wu(void) cputs("How much do you wish to\r\n"); cputs("borrow? "); - wu = get_num(9); + wu = get_num(); if (wu == -1) { wu = (cash * 2); @@ -2092,12 +2153,15 @@ void elder_brother_wu(void) void good_prices(void) { - /* see comment in fancy_numbers for why this is static */ - static char item[14]; + // static char item[14]; + unsigned char i = randi()%4; + /* int i = randi()%4, j = randi()%2; + */ + /* if (i == 0) { strcpy(item, "Opium"); @@ -2108,11 +2172,23 @@ void good_prices(void) } else { strcpy(item, "General Cargo"); } + */ compradores_report(); cputs("Taipan!! The price of "); - cputs(item); + // cputs(item); + cputs(item[i]); cputs("\r\n has "); + if(randi()&1) { + price[i] *= (randi()%5 + 5); + cputs("risen"); + } else { + price[i] /= 5; + cputs("dropped"); + } + cputs(" to "); + + /* if (j == 0) { price[i] = price[i] / 5; @@ -2122,12 +2198,15 @@ void good_prices(void) cputs("risen"); } cputs(" to "); + */ + cprintulong(price[i]); cputs("!!\r\n"); timed_getch(TMOUT_3S); } +#if 0 int port_choices(void) { int choice = 0; @@ -2159,13 +2238,13 @@ int port_choices(void) cputs("cargo, Quit trading, or Retire?"); cursor(1); cputc(' '); - choice = cgetc(); - if ((choice == 'B') || (choice == 'b') || - (choice == 'S') || (choice == 's') || - (choice == 'V') || (choice == 'v') || - (choice == 'T') || (choice == 't') || - (choice == 'Q') || (choice == 'q') || - (choice == 'R') || (choice == 'r')) + choice = agetc(); + if ((choice == 'b') || + (choice == 's') || + (choice == 'v') || + (choice == 't') || + (choice == 'q') || + (choice == 'r')) { break; } @@ -2174,12 +2253,12 @@ int port_choices(void) cputs("cargo, or Quit trading?"); cursor(1); cputc(' '); - choice = cgetc(); - if ((choice == 'B') || (choice == 'b') || - (choice == 'S') || (choice == 's') || - (choice == 'V') || (choice == 'v') || - (choice == 'T') || (choice == 't') || - (choice == 'Q') || (choice == 'q')) + choice = agetc(); + if ((choice == 'b') || + (choice == 's') || + (choice == 'v') || + (choice == 't') || + (choice == 'q')) { break; } @@ -2188,10 +2267,10 @@ int port_choices(void) cputs("Shall I Buy, Sell, or Quit trading?"); cursor(1); cputc(' '); - choice = cgetc(); - if ((choice == 'B') || (choice == 'b') || - (choice == 'S') || (choice == 's') || - (choice == 'Q') || (choice == 'q')) + choice = agetc(); + if ((choice == 'b') || + (choice == 's') || + (choice == 'q')) { break; } @@ -2201,22 +2280,67 @@ int port_choices(void) return choice; } +#else +int port_choices(void) { + int choice = 0; + char retire_ok; + + compradores_report(); + cputs("Taipan, present prices per unit here are"); /* NB: exactly 40 cols */ + cputs(" Opium: Silk:\r\n"); + cputs(" Arms: General:\r\n"); + gotoxy(11, 19); + cprintulong(price[0]); + gotoxy(29, 19); + cprintulong(price[1]); + gotoxy(11, 20); + cprintulong(price[2]); + gotoxy(29, 20); + cprintulong(price[3]); + + gotoxy(0, 22); + clrtobot(); + cursor(0); + + retire_ok = (port == 1 && ((cash + bank) >= 1000000)); + cputs("Shall I Buy, Sell, "); + if(port ==1) { + cputs("Visit bank, Transfer\r\ncargo, "); + } + if(!retire_ok) cputs("or "); + cputs("Quit trading"); + if(retire_ok) cputs(", or Retire"); + cursor(1); + cputs("? "); + + for(;;) { + choice = lcgetc(); + if(choice == 'b' || choice == 's' || choice == 'q') + break; + if(port == 1) { + if(retire_ok && choice == 'r') + break; + if(choice == 't' || choice == 'v') + break; + } + } + cursor(0); + return choice; +} +#endif /* TODO: rewrite in asm, or at least better C */ void name_firm(void) { + /* int input, character = 0; + */ + unsigned char input, count = 0; cursor(0); clrscr(); - gotoxy(0,23); -#ifdef VERSION - cputs(VERSION); -#else - cputs("(no version info)"); -#endif chlinexy(1, 7, 38); chlinexy(1, 16, 38); @@ -2238,6 +2362,22 @@ void name_firm(void) gotoxy(12, 13); + while(((input = agetc()) != ENTER) && (count < 22)) { + if(input == BKSP) { + if(count) { + backspace(); + firm[count--] = '\0'; + } + } else { + cputc(input); + firm[count++] = input; + } + } + + cursor(0); + firm[count] = '\0'; + + /* while (((input = cgetc()) != ENTER) && (character < 22)) { if (((input == BKSP) || (input == 127)) && (character == 0)) @@ -2260,12 +2400,12 @@ void name_firm(void) cursor(0); firm[character] = '\0'; + */ return; } -void buy(void) -{ +void buy(void) { /* see comment in fancy_numbers for why this is static */ // static char space[5]; @@ -2274,6 +2414,12 @@ void buy(void) long afford, amount; + gotoxy(0, 22); + clrtobot(); + cputs("What do you wish me to buy, Taipan? "); + choice = get_item(0); + + /* for (;;) { gotoxy(0, 22); @@ -2281,7 +2427,6 @@ void buy(void) cputs("What do you wish me to buy, Taipan? "); - /* TODO: buy() sell() and throwing cargo, common code in get_item() */ choice = tolower(get_one()); if(choice == 'o') { choice = 0; @@ -2297,6 +2442,7 @@ void buy(void) break; } } + */ for (;;) { @@ -2346,7 +2492,7 @@ void buy(void) gotoxy(0, 23); cputs("I buy, Taipan: "); - amount = get_num(9); + amount = get_num(); if(amount == -1) { amount = afford; } @@ -2367,6 +2513,12 @@ void sell(void) { long amount; + gotoxy(0, 22); + clrtobot(); + cputs("What do you wish me to buy, Taipan? "); + choice = get_item(0); + + /* for (;;) { gotoxy(0, 22); @@ -2374,7 +2526,6 @@ void sell(void) { cputs("What do you wish me to sell, Taipan? "); - /* TODO: buy() sell() and throwing cargo, common code in get_item() */ choice = tolower(get_one()); if(choice == 'o') { choice = 0; @@ -2390,6 +2541,7 @@ void sell(void) { break; } } + */ for (;;) { @@ -2401,7 +2553,7 @@ void sell(void) { cputs(" shall\r\n"); cputs("I sell, Taipan: "); - amount = get_num(9); + amount = get_num(); if (amount == -1) { @@ -2429,7 +2581,7 @@ void visit_bank(void) compradores_report(); cputs("How much will you deposit? "); - amount = get_num(9); + amount = get_num(); if (amount == -1) { amount = cash; @@ -2457,7 +2609,7 @@ void visit_bank(void) compradores_report(); cputs("How much will you withdraw? "); - amount = get_num(9); + amount = get_num(); if (amount == -1) { amount = bank; @@ -2491,10 +2643,10 @@ int main(void) { while(1) { clrscr(); cputs("dmg? "); - damage = get_num(9); + damage = get_num(); cputs("\r\n"); cputs("cap? "); - capacity = get_num(9); + capacity = get_num(); mchenry(); } } @@ -2502,7 +2654,6 @@ int main(void) { atari_text_setup(); initrand(); - // splash_intro(); name_firm(); cash_or_guns(); set_prices(); |