diff options
Diffstat (limited to 'taipan.c_before_timed_getch')
| -rw-r--r-- | taipan.c_before_timed_getch | 2877 | 
1 files changed, 2877 insertions, 0 deletions
diff --git a/taipan.c_before_timed_getch b/taipan.c_before_timed_getch new file mode 100644 index 0000000..7b399eb --- /dev/null +++ b/taipan.c_before_timed_getch @@ -0,0 +1,2877 @@ +#include <conio.h> +#include <time.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <peekpoke.h> + +/* define this for testing sea_battle(). it causes a pirate +	attack every time you leave port. Don't leave defined for +	a relese!! */ +// #define COMBAT_TEST + +/**** atari-specific stuff */ + +/* values returned by cgetc() for backspace & enter keys */ +#define BKSP 0x7e +#define ENTER 0x9b + +/* timed_getch() args for seconds, based on jiffy clock of +	target system. No adjustment made for PAL, sorry. */ +#define TMOUT_1S 60 +#define TMOUT_3S 180 +#define TMOUT_5S 300 + +/* original plan was to use time() or _systime(). It turns out that +	these are not implemented on the Atari, and always return -1. +	So, use the OS's countdown timer instead. +	Anyone porting to another cc65 platform needs to rewrite this. + +	TODO: rewrite in terms of clock() and CLOCKS_PER_SEC. Will make it +	less atari-specific, plus auto-adjust for pal/ntsc. + +	TODO: there is atari-specific stuff elsewhere in the code :( + */ + +static unsigned int tmout_jiffies = 0; + +void timeout(unsigned int msec) { +	if(msec > 0) +		tmout_jiffies = (msec / 100) * 6; // TODO: should be 5 for PAL +	else +		tmout_jiffies = 0; +} + +/* set timer with interrupts disabled, to avoid race condition +   where an interrupt happens between setting the high & low bytes. */ +void start_timer() { +	__asm__("SEI"); +	POKE(541, tmout_jiffies / 256); +	POKE(540, tmout_jiffies % 256); +	__asm__("CLI"); +} + +#define timer_running() (PEEK(541) || PEEK(540)) +#define timer_expired() (!timer_running()) + +int flushinp() { +	POKE(764, 255); +	return 0; +} + +void atari_text_setup() { +	POKE(710, 0xc0); // green background +	POKE(709, 0x0c); // bright text +	POKE(756, 0xb8); // use our custom font +} + +void jsleep(unsigned int jiffies) { +	tmout_jiffies = jiffies; +	start_timer(); +	while(timer_running()) +		; +	timeout(-1); +} + + +/* Atari-specific random number functions from rand.s. +	Non-Atari platforms can probably just: +#define initrand() _randomize(); +#define randi() rand(); +#define randl() (unsigned long)((randi() << 16) | randi()) +*/ + +#define initrand() /* no-op on Atari */ +extern unsigned int __fastcall__ randi(void); +extern unsigned long __fastcall__ randl(void); + +/* used to use this: +unsigned long randl() { +	unsigned long r = rand(); +	char *buf = (char *)r; +	buf[2] = PEEK(53770); +	buf[3] = PEEK(53770); +	return r; +} +*/ + + +/**** End of atari-specific stuff */ + +unsigned long randclamp(unsigned long clamp) { +	return randl() % clamp; +} + +/* TODO: rewrite in asm */ +void clrtobot() { +	unsigned char rows, cols, y, oldx, oldy; +	oldx = wherex(); +	oldy = wherey(); +	screensize(&cols, &rows); +	cclear(cols - wherex()); /* leaves cursor at start of next line */ +	for(y = wherey(); y < rows; y++) +		cclearxy(0, y, cols); +	gotoxy(oldx, oldy); +} + +/* TODO: rewrite in asm */ +void clrtoeol() { +	unsigned char cols, rows, oldx, oldy; +	oldx = wherex(); +	oldy = wherey(); +	screensize(&cols, &rows); +	cclear(cols - wherex()); +	gotoxy(oldx, oldy); +} + +/* TODO: rewrite in asm */ +/* this getch() works like curses, except it always acts +	like it's in cbreak mode. */ +int getch() { +	int ret = -1; + +	if(tmout_jiffies == 0) return cgetc(); + +	start_timer(); + +	do { +		if(kbhit()) { +			ret = cgetc(); +			break; +		} +	} while (timer_running()); + +	return ret; +} + +/* TODO: rewrite in asm */ +int lc(int a) { +	if(a >= 'A' && a <= 'Z') a ^= 0x20; +	return a; +} + +/* TODO: rewrite in asm */ +/* wrapper for getch() that returns letters as lowercase only +	(and everything else normally). Avoids a bunch of reduntant +	if(foo == 'A' || foo == 'a') tests. */ +int lcgetch() { +	return lc(getch()); +} + +/* taipan functions (modified as little as possible) */ +#define GENERIC 1 +#define LI_YUEN 2 + +void splash_intro(void); +int get_one(void); +unsigned long get_num(int maxlen); +void name_firm(void); +void cash_or_guns(void); +void set_prices(void); +void port_stats(void); +int port_choices(void); +void new_ship(void); +void new_gun(void); +void li_yuen_extortion(void); +void elder_brother_wu(void); +void good_prices(void); +void buy(void); +void sell(void); +void visit_bank(void); +void transfer(void); +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, int displacement, int mask); +void clear_lorcha(int x, int y); +void draw_blast(int x, int y); +void sink_lorcha(int which); +void fight_stats(int ships, int orders); +void mchenry(void); +void retire(void); +void final_stats(void); + +char    firm[23], +        fancy_num[24]; + +char    *item[] = { "Opium", "Silk", "Arms", "General Cargo" }; + +char    *location[] = { "At sea", "Hong Kong", "Shanghai", "Nagasaki", +                        "Saigon", "Manila", "Singapore", "Batavia" }; + +char    *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", +                      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +char    *st[] = { "Critical", "  Poor", "  Fair", +                  "  Good", " Prime", "Perfect" }; + +unsigned long   cash         = 0, +        bank         = 0, +        debt         = 0, +        booty        = 0, +        ec           = 20, +        ed           = 1; // used to be a float, 0.5 + +unsigned long    price[4]; + +int     base_price[4][8] = { {1000, 11, 16, 15, 14, 12, 10, 13}, +                             {100,  11, 14, 15, 16, 10, 13, 12}, +                             {10,   12, 16, 10, 11, 13, 14, 15}, +                             {1,    10, 11, 12, 13, 14, 15, 16} }; + +int     hkw_[4], +        hold_[4]; + +int     hold         = 0, +        capacity     = 60, +        guns         = 0, +        bp           = 0, +        damage       = 0, +        month        = 1, +        year         = 1860, +        li           = 0, +        port         = 1, +        wu_warn      = 0, +        wu_bailout   = 0; + +/* print an int or long as a string, conio-style */ +void cprintulong(unsigned long ul) { +	cputs(ultoa(ul, fancy_num, 10)); +} + +#ifdef COMBAT_TEST +void show_damage(void) { +	cputc(' '); +	cprintulong(damage); +	cputc('/'); +	cprintulong(capacity); +} +#else +#define show_damage() +#endif + +// fancy_numbers() will get replaced sooner or later. +// void cprintfancy(unsigned long ul) { +// } + +void at_sea() { +	gotoxy(30, 6); +	cputc(' '); +	revers(1); +	cputs(location[0]); +	revers(0); +	cputc(' '); +	cputc(' '); +} + +/* this bit of code was duplicated a *bunch* of times, +	making it a function makes the binary 2K smaller. */ + +void prepare_report() { +   gotoxy(0, 16); +   clrtobot(); +} + +void compradores_report() { +	prepare_report(); +   cputs("Comprador's Report\r\n\n"); +} + +void captains_report() { +	prepare_report(); +   cputs("  Captain's Report\r\n\n"); +} + + +void overload(void) +{ +	compradores_report(); +   cputs("Your ship is overloaded, Taipan!!"); +   timeout(5000); +   getch(); +   timeout(-1); +   return; +} + +void new_ship(void) +{ +   int  choice = 0, +        time; + +   // float amount; +   unsigned long amount; + +   time = ((year - 1860) * 12) + month; +   amount = randi()%(1000 * (time + 5) / 6) * (capacity / 50) + 1000; + +   if (cash < amount) +   { +      return; +   } + +   fancy_numbers(amount, fancy_num); + +	compradores_report(); +   cputs("Do you wish to trade in your "); +   if (damage > 0) +   { +		revers(1); +      cputs("damaged"); +		revers(0); +   } else { +      cputs("fine"); +   } +   cputs("\r\nship for one with 50 more capacity by\r\n"); +   cputs("paying an additional "); +   cputs(fancy_num); +   cputs(", Taipan? "); + +   while ((choice != 'Y') && (choice != 'y') && +          (choice != 'N') && (choice != 'n')) +   { +      choice = get_one(); +   } + +   if ((choice == 'Y') || (choice == 'y')) +   { +      cash -= amount; +      hold += 50; +      capacity += 50; +      damage = 0; +   } + +   if ((randi()%2 == 0) && (guns < 1000)) +   { +      port_stats(); +      new_gun(); +   } + +   port_stats(); + +   return; +} + +void new_gun(void) +{ +   int choice = 0, +       time; + +   unsigned long amount; + +   time = ((year - 1860) * 12) + month; +   amount = randi()%(1000 * (time + 5) / 6) + 500; + +   if ((cash < amount) || (hold < 10)) +   { +      return; +   } + +   fancy_numbers(amount, fancy_num); + +	compradores_report(); +   cputs("Do you wish to buy a ship's gun\r\n for "); +	cputs(fancy_num); +   cputs(", Taipan? "); + +   while ((choice != 'Y') && (choice != 'y') && +          (choice != 'N') && (choice != 'n')) +   { +      choice = get_one(); +   } + +   if ((choice == 'Y') || (choice == 'y')) +   { +      cash -= amount; +      hold -= 10; +      guns += 1; +   } + +   port_stats(); + +   return; +} + +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; + +   if (num >= 100000000L) +   { +      num1 = (num / 1000000L); +		ultoa(num1, fancy, 10); +		mil = 1; +   } else if (num >= 10000000L) { +      num1 = (num / 1000000L); +      num2 = ((num % 1000000L) / 100000L); +		ultoa(num1, fancy, 10); +      if (num2 > 0) +      { +         strcat(fancy, "."); +			ultoa(num2, number, 10); +         strcat(fancy, number); +      } +		mil = 1; +   } else if (num >= 1000000L) { +      num1 = (num / 1000000L); +      num2 = ((num % 1000000L) / 10000L); +		ultoa(num1, fancy, 10); +      if (num2 > 0) +      { +         strcat(fancy, "."); +			ultoa(num2, number, 10); +         strcat(fancy, number); +      } +		mil = 1; +   } else { +		ultoa(num, fancy, 10); +   } + +	if(mil) strcat(fancy, " Million"); +} + +/* +void fancytest(void) { +	fancy_numbers(1000, fancy_num); +	cputs(fancy_num); +	cputs("\r\n"); +	fancy_numbers(10000, fancy_num); +	cputs(fancy_num); +	cputs("\r\n"); +	fancy_numbers(100000, fancy_num); +	cputs(fancy_num); +	cputs("\r\n"); +	fancy_numbers(1000000, fancy_num); +	cputs(fancy_num); +	cputs("\r\n"); +	fancy_numbers(4294967295, fancy_num); // LONG_MAX +	cputs(fancy_num); +	cputs("\r\n"); +	cgetc(); +} +*/ + +void fight_stats(int ships, int orders) +{ +   // char ch_orders[12]; + +	/* +   if (orders == 0) +   { +      strcpy(ch_orders, "\0"); +   } else if (orders == 1) { +      strcpy(ch_orders, "Fight      "); +   } else if (orders == 2) { +      strcpy(ch_orders, "Run        "); +   } else { +      strcpy(ch_orders, "Throw Cargo"); +   } +	*/ + +   gotoxy(0, 0); + +	/* +   if (ships >= 1000) +   { +      printw("%d", ships); +   } else if (ships >= 100) { +      printw(" %d", ships); +   } else if (ships >= 10) { +      printw("  %d", ships); +   } else { +      printw("   %d", ships); +   } +	*/ + +	if(ships < 1000) cputc(' '); +	if(ships <  100) cputc(' '); +	if(ships <   10) cputc(' '); +	cprintulong(ships); + +   // gotoxy(0, 5); +	cputs(" ship"); +	if(ships != 1) cputc('s'); +	cputs(" attacking, Taipan! \r\n"); + +	/* +   if (ships == 1) +   { +      printw("ship attacking, Taipan! \n"); +   } else { +      printw("ships attacking, Taipan!\n"); +   } +	*/ + +   // printw("Your orders are to: %s", ch_orders); +	cputs("Your orders are to: "); +	if(orders == 1) +		cputs("Fight      "); +	else if(orders == 2) +		cputs("Run        "); +	else if(orders == 3) +		cputs("Throw Cargo"); + +	/* +   move(0, 50); +   printw("|  We have"); +   move(1, 50); +   printw("|  %d guns", guns); +   move(2, 50); +   printw("----------"); +   move(16, 0); +	*/ + +	revers(1); +	gotoxy(30, 0); +	cputs("   We have"); +	gotoxy(30, 1); +	cputc(' '); +	if(guns < 1000) cputc(' '); +	if(guns <  100) cputc(' '); +	if(guns <   10) cputc(' '); +	cprintulong(guns); +	cputs(" guns"); +	revers(0); +   return; +} + +void sink_lorcha(int which) { +	int i; +	for(i = 1; i < 8; i++) { +		draw_lorcha(which, i, 0); +		jsleep(5); +	} +} + +/* print an inverse video plus if there are offscreen ships, +	or clear it to a space if not. */ +void plus_or_space(unsigned char b) { +	gotoxy(39, 15); +	cputc(b ? 0xab : ' '); +} + +int sea_battle(int id, int num_ships) { +	/* These locals seem to eat too much stack and +		cause weird behaviour, so they're static now. */ + 	static int ships_on_screen[10]; +   static int orders, +       num_on_screen, +       time, +       s0, +       ok, +       ik, +       i, +       input, +       status; + +	orders = 0; +	num_on_screen = 0; +	time = ((year - 1860) * 12) + month; +	s0 = num_ships; +	ok = 0; +	ik = 1; + +   booty = (time / 4 * 1000 * num_ships) + randi()%1000 + 250; + +   for(i = 0; i <= 9; i++) { +      ships_on_screen[i] = 0; +   } + +   clrscr(); +   flushinp(); +   fight_stats(num_ships, orders); + +   while(num_ships > 0) { +		status = 100 - ((damage * 100 / capacity)); +      if(status <= 0) { +         return 4; +      } +      flushinp(); +      gotoxy(0, 3); +      clrtoeol(); + +      cputs("Current seaworthiness: "); +		cputs(st[status / 20]); +		cputs(" ("); +		cprintulong(status); +		cputs("%)"); +		gotoxy(0, 4); +		show_damage(); + +      for(i = 0; i <= 9; i++) { +         if (num_ships > num_on_screen) { +            if (ships_on_screen[i] == 0) { +					jsleep(5); +               ships_on_screen[i] = (randi() % ec) + 20; +               draw_lorcha(i, 0, 0); +               num_on_screen++; +            } +         } +      } + +      plus_or_space(num_ships > num_on_screen); + +      gotoxy(0, 16); +		cputs("\r\n"); +      timeout(3000); +      input = lcgetch(); +      timeout(-1); + +      if(input == 'f') { +         orders = 1; +      } else if(input == 'r') { +         orders = 2; +      } else if (input == 't') { +         orders = 3; +      } + +      if(orders == 0) { +         timeout(3000); +         input = lcgetch(); +         timeout(-1); + +         if (input == 'f') +         { +            orders = 1; +         } else if ((input == 'R') || (input == 'r')) { +            orders = 2; +         } else if ((input == 'T') || (input == 't')) { +            orders = 3; +         } else { +            gotoxy(0, 3); +            clrtoeol(); +            cputs("Taipan, what shall we do??\r\n(f=fight, r=run, t=throw cargo)"); +            timeout(-1); +            while ((input != 'f') && +                   (input != 'r') && +                   (input != 't')) +            { +               input = lcgetch(); +            } +            gotoxy(0, 3); +				clrtoeol(); +            gotoxy(0, 4); +				clrtoeol(); +            if (input == 'f') { +               orders = 1; +            } else if (input == 'r') { +               orders = 2; +            } else { +               orders = 3; +            } +         } +      } + +      fight_stats(num_ships, orders); +      if((orders == 1) && (guns > 0)) { +         static int targeted, sk; +			sk = 0; + +         ok = 3; +         ik = 1; +         gotoxy(0, 3); +         clrtoeol(); +         cputs("Aye, we'll fight 'em, Taipan."); +         timeout(3000); +         input = getch(); +         timeout(-1); + +         gotoxy(0, 3); +         clrtoeol(); +         cputs("We're firing on 'em, Taipan!"); +         timeout(1000); +         input = getch(); +         timeout(-1); + +         for(i = 1; i <= guns; i++) { +            if ((ships_on_screen[0] == 0) && (ships_on_screen[1] == 0) && +                (ships_on_screen[2] == 0) && (ships_on_screen[3] == 0) && +                (ships_on_screen[4] == 0) && (ships_on_screen[5] == 0) && +                (ships_on_screen[6] == 0) && (ships_on_screen[7] == 0) && +                (ships_on_screen[8] == 0) && (ships_on_screen[9] == 0)) +            { +               static int j; + +               for (j = 0; j <= 9; j++) { +                  if (num_ships > num_on_screen) { +                     if(ships_on_screen[j] == 0) { +								ships_on_screen[j] = randclamp(ec) + 20; +                        draw_lorcha(j, 0, 0); +                        num_on_screen++; +                     } +                  } +               } +            } + +				plus_or_space(num_ships > num_on_screen); + +            gotoxy(0, 16); +				cputc('\r'); +				cputc('\n'); + +            targeted = randi()%10; +            while(ships_on_screen[targeted] == 0) { +               targeted = randi()%10; +            } + +            draw_lorcha(targeted, 0, 0x80); +				jsleep(5); + +            draw_lorcha(targeted, 0, 0); +				jsleep(5); + +            draw_lorcha(targeted, 0, 0x80); +				jsleep(5); + +            draw_lorcha(targeted, 0, 0); +				jsleep(5); + +            ships_on_screen[targeted] -= randi()%30 + 10; + +            if(ships_on_screen[targeted] <= 0) { +               num_on_screen--; +               num_ships--; +               sk++; +               ships_on_screen[targeted] = 0; + +               sink_lorcha(targeted); + +					plus_or_space(num_ships > num_on_screen); +					/* +               if(num_ships == num_on_screen) { +						gotoxy(39, 7); +						cputc(' '); +               } +					*/ + +               fight_stats(num_ships, orders); +            } + +            if(num_ships == 0) { +               i += guns; +            } else { +					jsleep(10); +            } +         } +         gotoxy(0, 3); +         clrtoeol(); +         if(sk > 0) { +				cputs("Sunk "); +				cprintulong(sk); +				cputs(" of the buggers, Taipan!"); +         } else { +            cputs("Hit 'em, but didn't sink 'em, Taipan!"); +         } +         timeout(3000); +         input = getch(); +         timeout(-1); + +         // if ((randi()%s0 > (num_ships * .6 / id)) && (num_ships > 2)) +         if((randi()%s0 > ((num_ships / 2) / id)) && (num_ships > 2)) { +            static int ran; +            ran = randi()%(num_ships / 3 / id) + 1; + +            num_ships -= ran; +            fight_stats(num_ships, orders); +            gotoxy(0, 3); +            clrtoeol(); +				cprintulong(ran); +            cputs(" ran away, Taipan!"); + +            if(num_ships <= 10) { +               for(i = 9; i >= 0; i--) { +                  if ((num_on_screen > num_ships) && (ships_on_screen[i] > 0)) { +                     ships_on_screen[i] = 0; +                     num_on_screen--; + +							draw_lorcha(i, 7, 0); +							jsleep(5); +                  } +               } +               if(num_ships == num_on_screen) { +						plus_or_space(0); +               } +            } + +            gotoxy(0, 16); + +            timeout(3000); +            input = lcgetch(); +            timeout(-1); + +            if(input == 'f') { +               orders = 1; +            } else if(input == 'r') { +               orders = 2; +            } else if(input == 't') { +               orders = 3; +            } +         } +      } else if ((orders == 1) && (guns == 0)) { +         gotoxy(0, 3); +         clrtoeol(); +         cputs("We have no guns, Taipan!!"); +         timeout(3000); +         input = getch(); +         timeout(-1); +      } else if (orders == 3) { +         static int  choice; +			static long amount, total; +         choice = 0; +         amount = 0; +			total = 0; + +         gotoxy(0, 18); +         cputs("You have the following on board, Taipan:"); +         gotoxy(4, 19); +			cputs(item[0]); +			cputs(": "); +			cprintulong(hold_[0]); +         gotoxy(24, 19); +			cputs(item[1]); +			cputs(": "); +			cprintulong(hold_[1]); +         gotoxy(5, 20); +			cputs(item[2]); +			cputs(": "); +			cprintulong(hold_[2]); +         gotoxy(21, 20); +			cputs(item[3]); +			cputs(": "); +			cprintulong(hold_[3]); + +         gotoxy(0, 3); +         clrtoeol(); +         cputs("What shall I throw overboard, Taipan? "); + +			/* TODO: this, buy(), sell() have common code */ +         while ((choice != 'o') && +                (choice != 's') && +                (choice != 'a') && +                (choice != 'g') && +                (choice != '*')) +         { +            choice = lc(get_one()); +         } + +         if(choice == 'o') { +            choice = 0; +         } else if(choice == 's') { +            choice = 1; +         } else if(choice == 'a') { +            choice = 2; +         } else if(choice == 'g') { +            choice = 3; +         } else { +            choice = 4; +         } + +         if(choice < 4) { +            gotoxy(0, 3); +            clrtoeol(); +            cputs("How much, Taipan? "); + +            amount = get_num(9); +            if((hold_[choice] > 0) && ((amount == -1) || (amount > hold_[choice]))) +            { +               amount = hold_[choice]; +            } +            total = hold_[choice]; +         } else { +            total = hold_[0] + hold_[1] + hold_[2] + hold_[3]; +         } + +         if(total > 0) { +            gotoxy(0, 3); +            clrtoeol(); +            cputs("Let's hope we lose 'em, Taipan!"); +            if (choice < 4) { +               hold_[choice] -= amount; +               hold += amount; +               ok += (amount / 10); +            } else { +               hold_[0] = 0; +               hold_[1] = 0; +               hold_[2] = 0; +               hold_[3] = 0; +               hold += total; +               ok += (total / 10); +            } +            gotoxy(0, 18); +            clrtobot(); + +            timeout(3000); +            input = getch(); +            timeout(-1); +         } else { +            gotoxy(0, 3); +            clrtoeol(); +            cputs("There's nothing there, Taipan!"); +            gotoxy(0, 18); +            clrtobot(); + +            timeout(3000); +            input = getch(); +            timeout(-1); +         } +      } + +      if((orders == 2) || (orders == 3)) { +         if(orders == 2) { +            gotoxy(0, 3); +            clrtoeol(); +            cputs("Aye, we'll run, Taipan."); +            timeout(3000); +            input = getch(); +            timeout(-1); +         } + +         ok += ik++; +         if(randi()%ok > randi()%num_ships) { +            flushinp(); +            gotoxy(0, 3); +            clrtoeol(); +            cputs("We got away from 'em, Taipan!"); +            timeout(3000); +            input = getch(); +            timeout(-1); +            num_ships = 0; +         } else { +            gotoxy(0, 3); +            clrtoeol(); +            cputs("Couldn't lose 'em."); +            timeout(3000); +            input = getch(); +            timeout(-1); + +            if((num_ships > 2) && (randi()%5 == 0)) { +               static int lost; +               lost = (randi()%num_ships / 2) + 1; + +               num_ships -= lost; +               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!"); + +               if(num_ships <= 10) { +                  for(i = 9; i >= 0; i--) { +                     if((num_on_screen > num_ships) && (ships_on_screen[i] > 0)) { +                        ships_on_screen[i] = 0; +                        num_on_screen--; + +								draw_lorcha(i, 7, 0); +								jsleep(5); +                     } +                  } +						plus_or_space(num_ships > num_on_screen); +						/* +                  if(num_ships == num_on_screen) { +							gotoxy(39, 7); +							cputc(' '); +                  } +						*/ +               } + +               gotoxy(0, 16); + +               timeout(3000); +               input = lcgetch(); +               timeout(-1); + +               if(input == 'f') { +                  orders = 1; +               } else if(input == 'r') { +                  orders = 2; +               } else if(input == 't') { +                  orders = 3; +               } +            } +         } +      } + +      if(num_ships > 0) { +         gotoxy(0, 3); +         clrtoeol(); +         cputs("They're firing on us, Taipan!"); + +         timeout(3000); +         input = getch(); +         timeout(-1); +         flushinp(); + +			for(i = 0; i < 3; i++) { +				POKE(710, 0xcc); +				jsleep(10); +				POKE(710, 0xc0); +				jsleep(10); +			} + +         fight_stats(num_ships, orders); +         for(i = 0; i <= 9; i++) { +            if(ships_on_screen[i] > 0) { +					draw_lorcha(i, 0, 0); +            } +         } + +			plus_or_space(num_ships > num_on_screen); + +         gotoxy(0, 3); +         clrtoeol(); +         cputs("We've been hit, Taipan!!"); + +         timeout(3000); +         input = getch(); +         timeout(-1); + +         i = (num_ships > 15) ? 15 : num_ships; + +			// is this really correct? +         // if ((guns > 0) && ((randi()%100 < (((float) damage / capacity) * 100)) || +             // ((((float) damage / capacity) * 100) > 80))) + +         if((guns > 0) && ((randi()%100 < ((damage * 100) / capacity)) || +             (((damage * 100) / capacity)) > 80)) +         { +            i = 1; +            guns--; +            hold += 10; +            fight_stats(num_ships, orders); +            gotoxy(0, 3); +            clrtoeol(); +            cputs("The buggers hit a gun, Taipan!!"); +            fight_stats(num_ships, orders); + +            timeout(3000); +            input = getch(); +            timeout(-1); +         } + +         // damage = damage + ((ed * i * id) * ((float) randi() / RAND_MAX)) + (i / 2); +			// remember, ed is now scaled by 2 (used to be 0.5, now 1) +			// damage = damage + randclamp((ed * i * id)/2) + (i / 2); +			// damage = damage + randclamp((ed * i * id)/2) + (i / 2); // b0rked + +			damage = damage + (randi() % ((ed * i * id)/2)) + (i / 2); +			if(damage > capacity) damage = capacity; /* just in case */ +         if((id == GENERIC) && (randi()%20 == 0)) { +            return 2; +         } +      } +   } + +   if(orders == 1) { +      clrscr(); +      fight_stats(num_ships, orders); +      gotoxy(0, 3); +      clrtoeol(); +      cputs("We got 'em all, Taipan!"); +      timeout(3000); +      getch(); +      timeout(-1); + +      return 1; +   } else { +      return 3; +   } +} + +/* TODO: rewrite in asm */ +int get_one(void) +{ +   int input, +       choice = 0, +       character = 0; + +	// Atari cursor doesn't change visibility until a character +	// is printed... can't use cputc() here as it escapes the +	// character (prints graphics char instead of actually backspacing) +	putchar(' '); +	cursor(1); +	putchar(BKSP); + +   while ((input = getch()) != '\n') +   { +      if (((input == BKSP) || (input == 127)) && (character == 0)) +      { +      } else if ((input == BKSP) || (input == 127)) { +			putchar(BKSP); +         character--; +      } else if (character >= 1) { +      } else if (input == '\33') { +         flushinp(); +      } else { +			putchar(input); +         choice = input; +         character++; +      } +   } +	cursor(0); + +   return choice; +} + +/* TODO: rewrite in asm. Maybe. */ +unsigned long get_num(int maxlen) +{ +	/* see comment in fancy_numbers for why this is static */ +   static char number[20]; + +   int  input, +        character = 0; + +   long amount; + +	putchar(' '); +	cursor(1); +	putchar(BKSP); +   while ((input = getch()) != '\n') +   { +      if (((input == BKSP) || (input == 127)) && (character == 0)) +      { +      } else if ((input == BKSP) || (input == 127)) { +			putchar(BKSP); +         number[character] = '\0'; +         character--; +      } else if (character >= maxlen) { +      } else if (input == '\33') { +         flushinp(); +      } else if (((input == 'A') || (input == 'a')) && +                 (character == 0) && (maxlen > 1)) { +         putchar(input); +         number[character] = input; +         character++; +      } else if ((input < 48) || (input > 57)) { +      } else { +         putchar(input); +         number[character] = input; +         character++; +      } +   } + +   number[character] = '\0'; +   if ((strcmp(number, "A") == 0) || (strcmp(number, "a") == 0)) +   { +      amount = -1; +   } else { +      amount = strtol(number, (char **)NULL, 10); +   } + +	cursor(0); +   return amount; +} + +/* TODO: rewrite in asm */ +void cash_or_guns(void) +{ +   int choice = 0; + +   clrscr(); +   cputs("Do you want to start . . .\r\n\r\n"); +   cputs("  1) With cash (and a debt)\r\n\r\n"); +   cputs("                >> or <<\r\n\r\n"); +   cputs("  2) With five guns and no cash\r\n"); +   cputs("                (But no debt!)\r\n"); + +   while ((choice != '1') && (choice != '2')) +   { +      gotoxy(10, 10); +		cursor(1); +		cputc('?'); +      choice = get_one(); +		cursor(0); +   } + +	cputc(choice); +   if (choice == '1') +   { +      cash = 400; +      debt = 5000; +      hold = 60; +      guns = 0; +      li = 0; +      bp = 10; +   } else { +      cash = 0; +      debt = 0; +      hold = 10; +      guns = 5; +      li = 1; +      bp = 7; +   } + +   return; +} + +void set_prices(void) +{ +   price[0] = base_price[0][port] / 2 * (randi()%3 + 1) * base_price[0][0]; +   price[1] = base_price[1][port] / 2 * (randi()%3 + 1) * base_price[1][0]; +   price[2] = base_price[2][port] / 2 * (randi()%3 + 1) * base_price[2][0]; +   price[3] = base_price[3][port] / 2 * (randi()%3 + 1) * base_price[3][0]; +   return; +} + + +void port_stats(void) +{ +   int  i, in_use, +		  status = 100 - ((damage * 100) / capacity); + +	clrscr(); +	gotox(12 - strlen(firm) / 2); /* TODO: store in global */ +	cputs("Firm: "); +	cputs(firm); +	cputs(", Hong Kong"); + +	show_damage(); +	chlinexy(1, 1, 26); +	chlinexy(1, 7, 26); +	chlinexy(1, 13, 26); +	cvlinexy(0, 2, 5); +	cvlinexy(27, 2, 5); +	cvlinexy(0, 8, 5); +	cvlinexy(27, 8, 5); +	chlinexy(0, 15, 40); + +	cputcxy(0, 1, 17); // upper left corner +	cputcxy(0, 7, 1); // |- +	cputcxy(0, 13, 26); // lower left corner + +	cputcxy(27, 1, 5); // upper right corner +	cputcxy(27, 7, 4); // -| +	cputcxy(27, 13, 3); // lower right corner + +	cputsxy(1, 2, "Hong Kong Warehouse"); +	cputsxy(4, 3, "Opium           In use"); +	cputsxy(4, 4, "Silk            "); +   in_use = hkw_[0] + hkw_[1] + hkw_[2] + hkw_[3]; +	// printw("%d", in_use); +	cprintulong(in_use); +	cputsxy(4, 5, "Arms            Vacant"); +	cputsxy(4, 6, "General         "); +   // printw("%d", (10000 - in_use)); +	cprintulong(10000 - in_use); + +	gotoxy(12, 3); +   // printw("%d", hkw_[0]); +	cprintulong(hkw_[0]); + +	gotoxy(12, 4); +   // printw("%d", hkw_[1]); +	cprintulong(hkw_[1]); + +	gotoxy(12, 5); +   // printw("%d", hkw_[2]); +	cprintulong(hkw_[2]); + +	gotoxy(12, 6); +   // printw("%d", hkw_[3]); +	cprintulong(hkw_[3]); + +	cputsxy(1, 8, "Hold "); +   if (hold >= 0) +   { +      // printw("%d", hold); +		cprintulong(hold); +   } else { +		revers(1); +      cputs("Overload"); +		revers(0); +   } + +	cputsxy(16, 8, "Guns "); +	// printw("%d", guns); +	cprintulong(guns); + +	cputsxy(4, 9,  "Opium   "); +   // printw("%d", hold_[0]); +   cprintulong(hold_[0]); + +	cputsxy(4, 10, "Silk    "); +   // printw("%d", hold_[1]); +   cprintulong(hold_[1]); + +	cputsxy(4, 11, "Arms    "); +   // printw("%d", hold_[2]); +   cprintulong(hold_[2]); + +	cputsxy(4, 12, "General "); +   // printw("%d", hold_[3]); +   cprintulong(hold_[3]); + +	cputsxy(32, 2, "Date"); +	cputsxy(29, 3, "15 ");  +	revers(1);  +   cputs(months[month - 1]); +	revers(0);  +	cputc(' '); +   // printw(" %d", year); +	cprintulong(year); + +	cputsxy(30, 5, "Location"); +	revers(1);  +	cputsxy(30, 6, location[port]);  +	revers(0);  + +	cputsxy(32, 8, "Debt"); +	revers(1);  +	gotoxy(33, 9); +	fancy_numbers(debt, fancy_num); +	cputs(fancy_num); +	revers(0);  + +	cputsxy(29, 11, "Ship Status"); +	gotoxy(29, 12); +   i = status / 20; +   if (i < 2) { +		revers(1); +   } +	cputs(st[i]); +	cputc(':'); +	cprintulong(status); +	revers(0);  + +	cputsxy(0, 14, "Cash: "); +	fancy_numbers(cash, fancy_num); +	cputs(fancy_num); +	cputsxy(20, 14, "Bank: "); +	fancy_numbers(bank, fancy_num); +	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. + */ +void splash_intro(void) +{ +	int i; + +	for(i=0; i<3; i++) draw_lorcha(i, 0, 0); +	for(i=5; i<8; i++) draw_lorcha(i, 0, 0); + +	while(!kbhit()) +		; + +	// for(i=0; i<3; i++) sink_lorcha(i); +	// for(i=5; i<8; i++) sink_lorcha(i); + +	flushinp(); +	return; +} + +void mchenry(void) +{ +   int choice = 0; + +	compradores_report(); +   cputs("Taipan, Mc Henry from the Hong Kong\r\n"); +   cputs("Shipyards has arrived!!  He says, \"I see\r\n"); +   cputs("ye've a wee bit of damage to yer ship.\r\n"); +   cputs("Will ye be wanting repairs? "); + +   while ((choice != 'Y') && (choice != 'y') && +          (choice != 'N') && (choice != 'n')) +   { +      choice = get_one(); +   } + +   if ((choice == 'Y') || (choice == 'y')) +   { +      // int  percent = ((float) damage / capacity) * 100, +		// this is likely wrong: +      int  percent = ((damage * 100) / (capacity * 100)) * 100, +           time = ((year - 1860) * 12) + month; + +		/* +      long br = ((((60 * (time + 3) / 4) * (float) randi() / RAND_MAX) + +                25 * (time + 3) / 4) * capacity / 50), +           repair_price = (br * damage) + 1, +           amount; +			  */ + +		long br, repair_price, amount; +		br = ((randclamp(60 * (time + 3) / 4) + 25 * (time + 3) / 4) * capacity / 50); +		repair_price = (br * damage) + 1; + +      gotoxy(0, 18); +      clrtobot(); +      cputs("Och, 'tis a pity to be "); +		cprintulong(percent); +      cputs("% damaged.\r\nWe can fix yer whole ship for "); +		cprintulong(repair_price); +      cputs(",\r\nor make partial repairs if you wish.\r\n"); +      cputs("How much will ye spend? "); + +      for (;;) { +         gotoxy(24, 21); +         amount = get_num(9); +         if(amount == -1) { +				if(repair_price > cash) +					amount = repair_price; +				else +					amount = cash; +         } +         if(amount <= cash) { +            cash -= amount; +            // damage -= (int)((amount / br) + .5); +            damage -= (int)(amount / br); +            damage = (damage < 0) ? 0 : damage; +            port_stats(); +            break; +         } +      } +   } + +   return; +} + +void retire(void) +{ +	compradores_report(); +	revers(1); +   cputs("                         \r\n"); +   cputs(" Y o u ' r e    a        \r\n"); +   cputs("                         \r\n"); +   cputs(" M I L L I O N A I R E ! \r\n"); +   cputs("                         \r\n"); +	revers(1); +   timeout(5000); +   getch(); +   timeout(-1); + +   final_stats(); +} + +void final_stats(void) +{ +   int years = year - 1860, +       time = ((year - 1860) * 12) + month, +       choice = 0; + +   clrscr(); +   cputs("Your final status:\r\n\r\n"); +   cash = cash + bank - debt; +   fancy_numbers(cash, fancy_num); +	cputs("Net cash:  "); +	cputs(fancy_num); +	cputs("\r\nShip size: "); +	cprintulong(capacity); +	cputs(" units with "); +	cprintulong(guns); +	cputs(" guns\r\n\r\n"); +	cputs("You traded for "); +	cprintulong(years); +	cputs(" year"); +   if (years != 1) +   { +      cputc('s'); +   } +   cputs(" and "); +	cprintulong(month); +	cputs(" month"); +   if (month > 1) +   { +      cputc('s'); +   } +   cputs("\r\n\r\n"); +   cash = cash / 100 / time; +	revers(1); +	cputs("Your score is "); +	cprintulong(cash); +	cputs(".\r\n"); +	revers(0); +   if ((cash < 100) && (cash >= 0)) +   { +      cputs("Have you considered a land based job?\r\n\r\n\r\n"); +   } else if (cash < 0) { +      cputs("The crew has requested that you stay on\r\n"); +      cputs("shore for their safety!!\r\n\r\n"); +   } else { +      cputs("\r\n\r\n\r\n"); +   } +   cputs("Your Rating:\r\n"); +   cputs(" _______________________________\r\n"); +   cputs("|"); +   if (cash > 49999) +   { +		revers(1); +   } +   cputs("Ma Tsu"); +	revers(0); +   cputs("         50,000 and over |\r\n"); +   cputs("|"); +   if ((cash < 50000) && (cash > 7999)) +   { +		revers(1); +   } +   cputs("Master Taipan"); +	revers(0); +   cputs("   8,000 to 49,999|\r\n"); +   cputs("|"); +   if ((cash < 8000) && (cash > 999)) +   { +		revers(1); +   } +   cputs("Taipan"); +	revers(0); +   cputs("          1,000 to  7,999|\r\n"); +   cputs("|"); +   if ((cash < 1000) && (cash > 499)) +   { +		revers(1); +   } +   cputs("Compradore"); +	revers(0); +   cputs("        500 to    999|\r\n"); +   cputs("|"); +   if (cash < 500) +   { +		revers(1); +   } +   cputs("Galley Hand"); +	revers(0); +   cputs("       less than 500|\r\n"); +   cputs("|_______________________________|\r\n\r\n"); + +   while ((choice != 'Y') && (choice != 'y') && +          (choice != 'N') && (choice != 'n')) +   { +      gotoxy(0, 22); +      cputs("Play again? "); +      choice = get_one(); +   } + +   if ((choice == 'Y') || (choice == 'y')) +   { +      bank         = 0; +      hkw_[0]      = 0; +      hkw_[1]      = 0; +      hkw_[3]      = 0; +      hkw_[4]      = 0; +      hold_[0]     = 0; +      hold_[1]     = 0; +      hold_[2]     = 0; +      hold_[3]     = 0; +      hold         = 0; +      capacity     = 60; +      damage       = 0; +      month        = 1; +      year         = 1860; +      port         = 1; + +      // splash_intro(); +      name_firm(); +      cash_or_guns(); +      set_prices(); + +      return; +   } + +   clrscr(); + +   exit(0); +} + +void transfer(void) +{ +   int i, in_use; + +   long amount = 0; + +   if ((hkw_[0] == 0) && (hold_[0] == 0) && +       (hkw_[1] == 0) && (hold_[1] == 0) && +       (hkw_[2] == 0) && (hold_[2] == 0) && +       (hkw_[3] == 0) && (hold_[3] == 0)) +   { +      gotoxy(0, 22); +      clrtobot(); +      cputs("You have no cargo, Taipan.\r\n"); + +      timeout(5000); +      getch(); +      timeout(-1); +      return; +   } + +   for (i = 0; i < 4; i++) +   { +      if (hold_[i] > 0) +      { +         for (;;) +         { +				compradores_report(); +				cputs("How much "); +				cputs(item[i]); +				cputs(" shall I move\r\nto the warehouse, Taipan? "); + +            amount = get_num(9); +            if (amount == -1) +            { +               amount = hold_[i]; +            } +            if (amount <= hold_[i]) +            { +               in_use = hkw_[0] + hkw_[1] + hkw_[2] + hkw_[3]; +               if ((in_use + amount) <= 10000) +               { +                  hold_[i] -= amount; +                  hkw_[i] += amount; +                  hold += amount; +                  break; +               } else if (in_use == 10000) { +                  gotoxy(0, 21); +                  cputs("Your warehouse is full, Taipan!"); +               } else { +                  gotoxy(0, 21); +                  cputs("Your warehouse will only hold an\r\nadditional "); +						cprintulong(10000 - in_use); +                  cputs("%d, Taipan!"); + +                  timeout(5000); +                  getch(); +                  timeout(-1); +               } +            } else { +               gotoxy(0, 18); +               clrtobot(); +               cputs("You have only "); +					cprintulong(hold_[i]); +               cputs(", Taipan.\r\n"); + +               timeout(5000); +               getch(); +               timeout(-1); +            } +         } +         port_stats(); +      } + +      if (hkw_[i] > 0) +      { +         for (;;) +         { +				compradores_report(); +				cputs("How much "); +				cputs(item[i]); +				cputs("shall I move\r\naboard ship, Taipan? "); + +            amount = get_num(9); +            if (amount == -1) +            { +               amount = hkw_[i]; +            } +            if (amount <= hkw_[i]) +            { +               hold_[i] += amount; +               hkw_[i] -= amount; +               hold -= amount; +               break; +            } else { +               gotoxy(0, 18); +               clrtobot(); +					cputs("You have only "); +					cprintulong(hkw_[i]); +					cputs(", Taipan.\r\n"); + +               timeout(5000); +               getch(); +               timeout(-1); +            } +         } +         port_stats(); +      } +   } + +   return; +} + +void quit(void) +{ +   int choice = 0, +       result = 0; + +	compradores_report(); +   cputs("Taipan, do you wish me to go to:\r\n"); +   cputs("1) Hong Kong, 2) Shanghai, 3) Nagasaki,\r\n"); +   cputs("4) Saigon, 5) Manila, 6) Singapore, or\r\n"); +   cputs("7) Batavia ? "); + +   for (;;) +   { +      gotoxy(13, 21); +      clrtobot(); + +      choice = get_num(1); + +      if (choice == port) +      { +         cputs("\r\n\nYou're already here, Taipan."); +         timeout(5000); +         getch(); +         timeout(-1); +      } else if ((choice >= 1) && (choice <= 7)) { +         port = choice; +         break; +      } +   } + +	at_sea(); +	captains_report(); + +#ifdef COMBAT_TEST +   if(1) +#else +   if (randi()%bp == 0) +#endif +   { +      int num_ships = randi()%((capacity / 10) + guns) + 1; + +      if (num_ships > 9999) +      { +         num_ships = 9999; +      } +		cprintulong(num_ships); +      cputs(" hostile ships approaching, Taipan!\r\n"); + +      timeout(3000); +      getch(); +      timeout(-1); + +      result = sea_battle(GENERIC, num_ships); +   } + +   if (result == 2) +   { +      port_stats(); +		at_sea(); + +		captains_report(); +      cputs("Li Yuen's fleet drove them off!"); + +      timeout(3000); +      getch(); +      timeout(-1); +   } + +   if (((result == 0) && (randi()%(4 + (8 * li))) == 0) || (result == 2)) +   { +      gotoxy(0, 18); +      clrtobot(); +      cputs("Li Yuen's pirates, Taipan!!\r\n\n"); + +      timeout(3000); +      getch(); +      timeout(-1); + +      if (li > 0) +      { +         cputs("Good joss!! They let us be!!\r\n"); + +         timeout(3000); +         getch(); +         timeout(-1); + +         return; +      } else { +         int num_ships = randi()%((capacity / 5) + guns) + 5; + +			cprintulong(num_ships); +         cputs("ships of Li Yuen's pirate\r\n"); +         cputs("fleet, Taipan!!\r\n"); + +         timeout(3000); +         getch(); +         timeout(-1); + +         sea_battle(LI_YUEN, num_ships); +      } +   } + +   if (result > 0) +   { +      port_stats(); +		at_sea(); + +		captains_report(); +      if (result == 1) +      { +         fancy_numbers(booty, fancy_num); +         cputs("We captured some booty.\r\n"); +         cputs("It's worth "); +         cputs(fancy_num); +			cputc('!'); +         cash += booty; +      } else if (result == 3) { +         cputs("We made it!"); +      } else { +         cputs("The buggers got us, Taipan!!!\r\n"); +         cputs("It's all over, now!!!"); + +         timeout(5000); +         getch(); +         timeout(-1); + +         final_stats(); +         return; +      } + +      timeout(3000); +      getch(); +      timeout(-1); +   } + +   if (randi()%10 == 0) +   { +      gotoxy(0, 18); +      clrtobot(); +      cputs("Storm, Taipan!!\r\n\n"); +      timeout(3000); +      getch(); +      timeout(-1); + +      if (randi()%30 == 0) +      { +         cputs("   I think we're going down!!\r\n\n"); +         timeout(3000); +         getch(); +         timeout(-1); + +         // if (((damage / capacity * 3) * ((float) randi() / RAND_MAX)) >= 1) +			if(randclamp(damage / capacity * 3) >= 1) +         { +            cputs("We're going down, Taipan!!\r\n"); +            timeout(5000); +            getch(); +            timeout(-1); + +            final_stats(); +         } +      } + +      cputs("    We made it!!\r\n\n"); +      timeout(3000); +      getch(); +      timeout(-1); + +      if (randi()%3 == 0) +      { +         int orig = port; + +         while (port == orig) +         { +            port = randi()%7 + 1; +         } + +         gotoxy(0, 18); +         clrtobot(); +         cputs("We've been blown off course\r\nto "); +         cputs(location[port]); +         timeout(3000); +         getch(); +         timeout(-1); +      } +   } + +   month++; +   if (month == 13) +   { +      month = 1; +      year++; +      ec += 10; +      ed += 1; +   } + +	/* debt calculation original formula was: + +			debt = debt + (debt * .1); + +		int-based formula is the same, except it would never +		increase if debt is <= 10, so we fudge it with debt++ +		in that case. Which means small debts accrue interest +		*much* faster, but that shouldn't affect gameplay much. +		There needs to be some overflow detection though... or +		maybe we let the overflow through, and the player can +		think of it as Wu forgiving the debt after enough years +		go by (or, he lost the paperwork?). Most likely though, +		the player gets his throat cut long before the amount +		overflows. + +	*/ + +	if(debt) { +		if(debt > 10) +			debt += (debt / 10); +		else +			debt++; +	} + +	/* bank calculation original formula was: +			bank = bank + (bank * .005); +		int-based formula is the same, except when bank <= 200, +		it's linear. +	*/ +	if(bank) { +		if(bank > 200) +			bank += (bank / 200); +		else +			bank++; +	} + +   set_prices(); + +   gotoxy(0, 18); +   clrtobot(); +   cputs("Arriving at "); +   cputs(location[port]); +   cputs("..."); +   timeout(3000); +   getch(); +   timeout(-1); + +   return; +} + +void li_yuen_extortion(void) +{ +   int time = ((year - 1860) * 12) + month, +       choice = 0; + +	/* +   float i = 1.8, +         j = 0, +         amount = 0; +			*/ +	unsigned long amount = 0; +	unsigned int i = 2, j = 0; + +   if (time > 12) +   { +      j = randi()%(1000 * time) + (1000 * time); +      i = 1; +   } + +   // amount = ((cash / i) * ((float) randi() / RAND_MAX)) + j; +	amount = randclamp((cash >> (i - 1))) + j; + +   fancy_numbers(amount, fancy_num); + +	compradores_report(); +	cputs("Li Yuen asks "); +	cputs(fancy_num); +	cputs(" in donation\r\nto the temple of Tin Hau, the Sea\r\n"); + +   while ((choice != 'Y') && (choice != 'y') && +          (choice != 'N') && (choice != 'n')) +   { +      gotoxy(0, 20); +      cputs("Goddess.  Will you pay? "); +      choice = get_one(); +   } + +   if ((choice == 'Y') || (choice == 'y')) +   { +      if (amount <= cash) +      { +         cash -= amount; +         li = 1; +      } else { +         gotoxy(0, 18); +         clrtobot(); +         cputs("Taipan, you do not have enough cash!!\r\n\r\n"); + +         timeout(3000); +         getch(); +         timeout(-1); + +         cputs("Do you want Elder Brother Wu to make up\r\n"); +         cputs("the difference for you? "); +         choice = 0; +         while ((choice != 'Y') && (choice != 'y') && +                (choice != 'N') && (choice != 'n')) +         { +            choice = get_one(); +         } + +         if ((choice == 'Y') || (choice == 'y')) +         { +            amount -= cash; +            debt += amount; +            cash = 0; +            li = 1; + +            gotoxy(0, 18); +            clrtobot(); +            cputs("Elder Brother has given Li Yuen the\r\n"); +            cputs("difference between what he wanted and\r\n"); +            cputs("your cash on hand and added the same\r\n"); +            cputs("amount to your debt.\r\n"); + +            timeout(5000); +            getch(); +            timeout(-1); +         } else { +            cash = 0; + +            cputs("Very well. Elder Brother Wu will not pay\r\n"); +            cputs("Li Yuen the difference.  I would be very\r\n"); +            cputs("wary of pirates if I were you, Taipan.\r\n"); + +            timeout(5000); +            getch(); +            timeout(-1); +         } +      } +   } + +   port_stats(); + +   return; +} + +void elder_brother_wu(void) +{ +   int  choice = 0; + +   long wu = 0; + +	compradores_report(); +   cputs("Do you have business with Elder Brother\r\n"); +   cputs("Wu, the moneylender? "); + +   for (;;) +   { +      gotoxy(21, 19); + +      choice = get_one(); +      if ((choice == 'N') || (choice == 'n') || choice == 0) +      { +         break; +      } else if ((choice == 'Y') || (choice == 'y')) { +         if (((int)cash == 0) && ((int)bank == 0) && (guns == 0) && +             (hold_[0] == 0) && (hkw_[0] == 0) && +             (hold_[1] == 0) && (hkw_[1] == 0) && +             (hold_[2] == 0) && (hkw_[2] == 0) && +             (hold_[3] == 0) && (hkw_[3] == 0)) +         { +            int i = randi()%1500 + 500, +                j; + +            wu_bailout++; +            j = randi()%2000 * wu_bailout + 1500; + +            for (;;) +            { +					compradores_report(); +               cputs("Elder Brother is aware of your plight,\r\n"); +               cputs("Taipan.  He is willing to loan you an\r\n"); +               cputs("additional "); +					cprintulong(i); +					cputs(" if you will pay back\r\n"); +					cprintulong(j); +					cputs(". Are you willing, Taipan? "); + +               choice = get_one(); +               if ((choice == 'N') || (choice == 'n')) +               { +						compradores_report(); +                  cputs("Very well, Taipan, the game is over!\r\n"); + +                  timeout(5000); +                  getch(); +                  timeout(-1); + +                  final_stats(); +               } else if ((choice == 'Y') || (choice == 'y')) { +                  cash += i; +                  debt += j; +                  port_stats(); + +						compradores_report(); +                  cputs("Very well, Taipan.  Good joss!!\r\n"); + +                  timeout(5000); +                  getch(); +                  timeout(-1); + +                  return; +               } +            } +         } else if ((cash > 0) && (debt != 0)) { +            for (;;) +            { +					compradores_report(); +               cputs("How much do you wish to repay\r\n"); +               cputs("him? "); + +               wu = get_num(9); +               if (wu == -1) +               { +                  wu = cash; +               } +               if (wu <= cash) +               { +						if(wu > debt) wu = debt; +                  cash -= wu; +						debt -= wu; +						/* // currently debt is unsigned so the negative debt +							// bug (or feature) is unimplemented. +                  if ((wu > debt) && (debt > 0)) +                  { +                     debt -= (wu + 1); +                  } else { +                     debt -= wu; +                  } +						*/ +                  break; +               } else { +                  gotoxy(0, 18); +                  clrtobot(); +                  fancy_numbers(cash, fancy_num); +                  cputs("Taipan, you only have "); +						cputs(fancy_num); +                  cputs("\r\nin cash.\r\n"); + +                  timeout(5000); +                  getch(); +                  timeout(-1); +               } +            } +         } +         port_stats(); + +         for (;;) +         { +				compradores_report(); +            cputs("How much do you wish to\r\n"); +            cputs("borrow? "); + +            wu = get_num(9); +            if (wu == -1) +            { +               wu = (cash * 2); +            } +            if (wu <= (cash * 2)) +            { +               cash += wu; +               debt += wu; +               break; +            } else { +               cputs("\r\n\r\nHe won't loan you so much, Taipan!"); + +               timeout(5000); +               getch(); +               timeout(-1); +            } +         } +         port_stats(); + +         break; +      } +   } + +   if ((debt > 20000) && (cash > 0) && (randi()%5 == 0)) +   { +      int num = randi()%3 + 1; + +      cash = 0; +      port_stats(); + +		compradores_report(); +      cputs("Bad joss!!\r\n"); +		cprintulong(num); +      cputs(" of your bodyguards have been killed\r\n"); +      cputs("by cutthroats and you have been robbed\r\n"); +      cputs("of all of your cash, Taipan!!\r\n"); + +      timeout(5000); +      getch(); +      timeout(-1); +   } + +   return; +} + +void good_prices(void) +{ +	/* see comment in fancy_numbers for why this is static */ +   static char item[14]; + +   int i = randi()%4, +       j = randi()%2; + +   if (i == 0) +   { +      strcpy(item, "Opium"); +   } else if (i == 1) { +      strcpy(item, "Silk"); +   } else if (i == 2) { +      strcpy(item, "Arms"); +   } else { +      strcpy(item, "General Cargo"); +   } + +	compradores_report(); +   cputs("Taipan!!  The price of "); +	cputs(item); +	cputs("\r\n has "); +   if (j == 0) +   { +      price[i] = price[i] / 5; +      cputs("dropped"); +   } else { +      price[i] = price[i] * (randi()%5 + 5); +      cputs("risen"); +   } +	cputs(" to "); +	cprintulong(price[i]); +	cputs("!!\r\n"); + +   timeout(3000); +   getch(); +   timeout(-1); +} + +int port_choices(void) +{ +   int choice = 0; + +	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]); + +   for (;;) +   { +      gotoxy(0, 22); +      clrtobot(); + +		cursor(1); +      if (port == 1) +      { +         if ((cash + bank) >= 1000000) +         { +            cputs("Shall I Buy, Sell, Visit bank, Transfer\r\n"); +            cputs("cargo, Quit trading, or Retire? "); + +            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')) +            { +               break; +            } +         } else { +            cputs("Shall I Buy, Sell, Visit bank, Transfer\r\n"); +            cputs("cargo, or Quit trading? "); + +            choice = cgetc(); +            if ((choice == 'B') || (choice == 'b') || +                (choice == 'S') || (choice == 's') || +                (choice == 'V') || (choice == 'v') || +                (choice == 'T') || (choice == 't') || +                (choice == 'Q') || (choice == 'q')) +            { +               break; +            } +         } +      } else { +         cputs("Shall I Buy, Sell, or Quit trading? "); + +         choice = cgetc(); +         if ((choice == 'B') || (choice == 'b') || +             (choice == 'S') || (choice == 's') || +             (choice == 'Q') || (choice == 'q')) +         { +            break; +         } +      } +		cursor(1); +   } + +   return choice; +} + + +/* TODO: rewrite in asm, or at least better C */ +void name_firm(void) +{ +   int  input, +        character = 0; + +   clrscr(); + +	chlinexy(1, 7, 38); +	chlinexy(1, 16, 38); +	cvlinexy(0, 8, 8); +	cvlinexy(39, 8, 8); +	cputcxy(0, 7, 17); // upper left corner +	cputcxy(0, 16, 26); // lower left corner +	cputcxy(39, 7, 5); // upper right corner +	cputcxy(39, 16, 3); // lower right corner + +	gotoxy(6, 9); +	cputs("Taipan,"); +	gotoxy(2, 11); +	cputs("What will you name your"); +	gotoxy(6, 13); +	cursor(1); +	cputs("Firm:"); +	chlinexy(12, 14, 22); + +	gotoxy(12, 13); + +   while (((input = getch()) != ENTER) && (character < 22)) +   { +      if (((input == BKSP) || (input == 127)) && (character == 0)) +      { +			// nop +      } else if ((input == BKSP) || (input == 127)) { +			gotox(12 + character - 1); +			cputc(' '); +			gotox(12 + character - 1); +         firm[character] = '\0'; +         character--; +      } else if (input == '\33') { +         flushinp(); +      } else { +			cputc(input); +         firm[character] = input; +         character++; +      } +   } + +	cursor(0); +   firm[character] = '\0'; + +   return; +} + +void buy(void) +{ +	/* see comment in fancy_numbers for why this is static */ +   // static char space[5]; + +   int  choice = 0; + +   long afford, +        amount; + +   for (;;) +   { +      gotoxy(0, 22); +      clrtobot(); + +      cputs("What do you wish me to buy, Taipan? "); + +		/* TODO: buy() sell() and throwing cargo, common code in get_item() */ +      choice = lc(get_one()); +      if(choice == 'o') { +         choice = 0; +         break; +      } else if (choice == 's') { +         choice = 1; +         break; +      } else if (choice == 'a') { +         choice = 2; +         break; +      } else if (choice == 'g') { +         choice = 3; +         break; +      } +   } + +   for (;;) +   { +      gotoxy(31, 21); +      clrtobot(); + +      afford = cash / price[choice]; +		revers(1); +      cputs(" You can "); +		revers(0); +      gotoxy(0, 22); +      cputs("How much "); +      cputs(item[choice]); +      cputs(" shall"); +      gotoxy(31, 22); +		revers(1); +      cputs("  afford "); +      gotoxy(31, 23); +      cputs("         "); +      gotoxy(31, 23); + +		/* TODO: is this really right? */ +		if(afford <       100) cputc(' '); +		if(afford <     10000) cputc(' '); +		if(afford <   1000000) cputc(' '); +		if(afford < 100000000) cputc(' '); + +		/* +      if (afford < 100) +      { +         strcpy(space, "    "); +      } else if (afford < 10000) { +         strcpy(space, "   "); +      } else if (afford < 1000000) { +         strcpy(space, "  "); +      } else if (afford < 100000000) { +         strcpy(space, " "); +      } else { +         strcpy(space, ""); +      } +		cputs(space); +		*/ + +		cprintulong(afford); +		revers(0); + +      gotoxy(0, 23); +      cputs("I buy, Taipan: "); + +      amount = get_num(9); +      if(amount == -1) { +         amount = afford; +      } +      if(amount <= afford) { +         break; +      } +   } + +   cash -= (amount * price[choice]); +   hold_[choice] += amount; +   hold -= amount; + +   return; +} + +void sell(void) { +   int  choice = 0; + +   long amount; + +   for (;;) +   { +      gotoxy(0, 22); +      clrtobot(); + +      cputs("What do you wish me to sell, Taipan? "); + +		/* TODO: buy() sell() and throwing cargo, common code in get_item() */ +      choice = lc(get_one()); +      if(choice == 'o') { +         choice = 0; +         break; +      } else if(choice == 's') { +         choice = 1; +         break; +      } else if(choice == 'a') { +         choice = 2; +         break; +      } else if(choice == 'g') { +         choice = 3; +         break; +      } +   } + +   for (;;) +   { +      gotoxy(0, 22); +      clrtobot(); + +      cputs("How much "); +      cputs(item[choice]); +      cputs(" shall\r\n"); +      cputs("I sell, Taipan: "); + +      amount = get_num(9); + +      if (amount == -1) +      { +         amount = hold_[choice]; +      } +      if (hold_[choice] >= amount) +      { +         hold_[choice] -= amount; +         break; +      } +   } + +   cash += (amount * price[choice]); +   hold += amount; + +   return; +} + +void visit_bank(void) +{ +   long amount = 0; + +   for (;;) +   { +		compradores_report(); +      cputs("How much will you deposit? "); + +      amount = get_num(9); +      if (amount == -1) +      { +         amount = cash; +      } +      if (amount <= cash) +      { +         cash -= amount; +         bank += amount; +         break; +      } else { +         gotoxy(0, 18); +         clrtobot(); +         fancy_numbers(cash, fancy_num); +         cputs("Taipan, you only have "); +			cputs(fancy_num); +         cputs("\r\nin cash.\r\n"); + +         timeout(5000); +         getch(); +         timeout(-1); +      } +   } +   port_stats(); + +   for (;;) +   { +		compradores_report(); +      cputs("How much will you withdraw? "); + +      amount = get_num(9); +      if (amount == -1) +      { +         amount = bank; +      } +      if (amount <= bank) +      { +         cash += amount; +         bank -= amount; +         break; +      } else { +         fancy_numbers(cash, fancy_num); +         cputs("Taipan, you only have "); +			cputs(fancy_num); +         cputs("\r\nin the bank."); + +         timeout(5000); +         getch(); +         timeout(-1); +      } +   } +   port_stats(); + +   return; +} + +/* +void debttest() { +	int i; + +	debt = 1; + +	for(i=0; i<20; i++) { +		debt = debt + (debt >> 8) + (debt >> 10); +		// debt = debt + (debt >> 4) + (debt >> 5) + (debt >> 7) - (debt >> 9); // debt *= 0.09961 +		printf("%lu\n", debt); +	} + +	cgetc(); +	clrscr(); +	debt = 1; + +	for(i=0; i<20; i++) { +		if(debt > 200) +			debt += (debt / 200); +		else +			debt++; + +		printf("%lu\n", debt); +	} +	cgetc(); + +} +*/ + +/* N.B. cc65 is perfectly OK with main(void), and it avoids +   warnings about argv/argc unused. */ +int main(void) { +   int choice; + +	/* +	{ +		int status; +		capacity = 60; +		damage = 47; +		status = 100 - ((damage * 100) / capacity); +		cprintulong(status); +hang: goto hang; +	} +	*/ + +	/* +	_randomize(); +	while(1) { +		clrscr(); +		cprintulong(randi()); +		cputs("\r\n"); +		cprintulong(rand()); +		cgetc(); +	} +	*/ + +	// fancytest(); +	// debttest(); +	atari_text_setup(); +	initrand(); +	splash_intro(); +	name_firm(); +	cash_or_guns(); +	set_prices(); + +   for (;;) +   { +      choice = 0; + +      port_stats(); + +      if ((port == 1) && (li == 0) && (cash > 0)) +      { +         li_yuen_extortion(); +      } + +      if ((port == 1) && (damage > 0)) +      { +         mchenry(); +      } + +      if ((port == 1) && (debt >= 10000) && (wu_warn == 0)) +      { +         int braves = randi()%100 + 50; + +			compradores_report(); +         cputs("Elder Brother Wu has sent "); +			cprintulong(braves); +			cputs(" braves\r\n"); +         cputs("to escort you to the Wu mansion, Taipan.\r\n"); + +         timeout(3000); +         getch(); +         timeout(-1); + +         gotoxy(0, 18); +         clrtobot(); +         cputs("Elder Brother Wu reminds you of the\r\n"); +         cputs("Confucian ideal of personal worthiness,\r\n"); +         cputs("and how this applies to paying one's\r\n"); +         cputs("debts.\r\n"); + +         timeout(3000); +         getch(); +         timeout(-1); + +         gotoxy(0, 18); +         clrtobot(); +         cputs("He is reminded of a fabled barbarian\r\n"); +         cputs("who came to a bad end, after not caring\r\n"); +         cputs("for his obligations.\r\n\r\n"); +         cputs("He hopes no such fate awaits you, his\r\n"); +         cputs("friend, Taipan.\r\n"); + +         timeout(5000); +         getch(); +         timeout(-1); + +         wu_warn = 1; +      } + +      if (port == 1) +      { +         elder_brother_wu(); +      } + +      if (randi()%4 == 0) +      { +         if (randi()%2 == 0) +         { +            new_ship(); +         } else if (guns < 1000) { +            new_gun(); +         } +      } + +      if ((port != 1) && (randi()%18 == 0) && (hold_[0] > 0)) +      { +         // float fine = ((cash / 1.8) * ((float) randi() / RAND_MAX)) + 1; +			// the 1.8 is now a 2 +			unsigned long fine = randclamp(cash >> 1) + 1; + +         hold += hold_[0]; +         hold_[0] = 0; +         cash -= fine; + +         port_stats(); + +         fancy_numbers(fine, fancy_num); +			compradores_report(); +         cputs("Bad Joss!!\r\n"); +         cputs("The local authorities have seized your\r\n"); +         cputs("Opium cargo and have also fined you\r\n"); +			cputs(fancy_num); +			cputs(", Taipan!\r\n"); + +         timeout(5000); +         getch(); +         timeout(-1); +      } + +      if ((randi()%50 == 0) && +          ((hkw_[0] + hkw_[1] + hkw_[2] + hkw_[3]) > 0)) +      { +         int i; + +         for (i = 0; i < 4; i++) +         { +            // hkw_[i] = ((hkw_[i] / 1.8) * ((float) randi() / RAND_MAX)); +				// the 1.8 is now a 2 +            hkw_[i] = randclamp(hkw_[i] >> 1); +         } + +         port_stats(); + +			compradores_report(); +         cputs("Messenger reports large theft\r\n"); +         cputs("from warehouse, Taipan.\r\n"); + +         timeout(5000); +         getch(); +         timeout(-1); +      } + +      if (randi()%20 == 0) +      { +         if (li > 0) { li++; } +         if (li == 4) { li = 0; } +      } + +      if ((port != 1) && (li == 0) && (randi()%4 != 0)) +      { +			compradores_report(); +         cputs("Li Yuen has sent a Lieutenant,\r\n"); +         cputs("Taipan.  He says his admiral wishes\r\n"); +         cputs("to see you in Hong Kong, posthaste!\r\n"); + +         timeout(3000); +         getch(); +         timeout(-1); +      } + +      if (randi()%9 == 0) +      { +         good_prices(); +      } + +      if ((cash > 25000) && (randi()%20 == 0)) +      { +         // float robbed = ((cash / 1.4) * ((float) randi() / RAND_MAX)); +			// line below changes the 1.4 to 1.5 +			unsigned long robbed = randclamp((cash >> 2) + (cash >> 1)); + +         cash -= robbed; +         port_stats(); + +         fancy_numbers(robbed, fancy_num); +			compradores_report(); +         cputs("Bad Joss!!\r\n"); +         cputs("You've been beaten up and\r\n"); +         cputs("robbed of "); +			cputs(fancy_num); +         cputs(" in cash, Taipan!!\r\n"); + +         timeout(5000); +         getch(); +         timeout(-1); +      } + +      for (;;) +      { +         while ((choice != 'Q') && (choice != 'q')) +         { +            switch (choice = port_choices()) +            { +               case 'B': +               case 'b': +                  buy(); +                  break; + +               case 'S': +               case 's': +                  sell(); +                  break; + +               case 'V': +               case 'v': +                  visit_bank(); +                  break; + +               case 'T': +               case 't': +                  transfer(); +                  break; + +               case 'R': +               case 'r': +                  retire(); +            } + +            port_stats(); +         } + +         choice = 0; +         if (hold >= 0) +         { +            quit(); +            break; +         } else { +            overload(); +         } +      } +   } + +	cgetc(); +	POKE(709, 0); +hangmain: +	goto hangmain; +	return 0; +}  | 
