/* Callisto written for the Amiga by Russell Wallace 1987. Please distribute * this source code along with executable program. Compile with long integer * compile option and link with files printlong_unsigned.o scanlong_unsigned.o * input.o console.o. This code may be freely used as a source of example * routines. Requires instructions text file in same directory. */ /* Version 1.01 recompiled with Aztec C 9 July 1988 */ #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b)) #define MINUS(a,b) ((a)>(b)?((a)-(b)):(0)) /* Avoid negative result */ #define NOTENOUGHCASH "Sorry, but you only have enough money for " #define NOTENOUGHWORKERS "Sorry, but there are only enough workers for " #define PLAYERS 6 #define MAXLONG 4000000000 /* To avoid overflow risk, won't allow anything */ /* to exceed this quantity */ /* Costs of various items */ #define SHIP 350 #define ARM 240 #define MINE 170 #define DOME 400 #define RECYCLER 550 #define LASER 730 #define BOMB 4 #define FUEL 2 #define PILOT 6 /* Labour requirements for various items */ #define LARM 8 #define LMINE 10 #define LDOME 30 #define LRECYCLER 22 #define LLASER 12 /* Payment for various things */ #define ORE 2 #define DSHIP 70 #define DLASER 60 #define DRECYCLER 62 #define DDOME 70 #define INLEN 12 long rnd (); struct variables { unsigned long domes,recyclers,fuel,ships,armed,lasers,mines,bombs; unsigned long ore,money,pilots,pop; } player[PLAYERS]; /* Set up variables for each player */ unsigned long innum; /* Number input by player */ char string[INLEN]; /* Raw form of input number */ unsigned long shipd,laserd,recyclerd,domed; /* Numbers of targets destroyed */ unsigned long popk; /* Number of people killed */ unsigned long shipl; /* Number of attackers shot down */ unsigned long bombu; /* Number of bombs expended */ unsigned long payment; /* Payment for attack */ unsigned long year; char *enemyname[]= { "Consolidated Minerals", "Global Resources Inc.", "Eastern Mining Co-operative", "European Petroleum & Minerals", "General Metals" }; main () { register int i,target; short readfile (); if (!(start ())) exit (5); /* Try to set up window */ NEWGAME: print ("\fWelcome to Callisto by Russell Wallace. Do you want instructions? (Type Y or N):"); if (yesno ()) { readfile ("Callisto.instructions.doc"); print ("\nThis version 1.01 has been recompiled with Aztec C on July 9th 1988 and will automatically open a window the size of the "); print ("Workbench screen on a PAL or NTSC Amiga.\n"); anykey (); } year=0; for (i=0;ii) { player[0].money+=((innum-i)*MINE); innum=i; print ("You can't send that many spaceships - only "); printlong (innum); print (" mines can be set up.\n"); } player[0].mines+=innum; player[0].fuel=MINUS (player[0].fuel,innum*8); print ("Do you want to send ships to recover the accumulated ore and sell it to Earth? "); if (yesno ()) { innum=player[0].ore/20; innum=MIN (innum,player[0].ships); innum=MIN (innum,player[0].pilots); innum=MIN (innum,player[0].fuel/8); if (innum) { printnoun (innum,"ship"); print ("sent to recover ore. This was sold for "); player[0].fuel-=innum*8; innum*=20; player[0].ore-=innum; player[0].money+=innum*ORE; printlong (innum*ORE); print (" credits.\n"); } else print ("No ore recovered yet.\n"); } target=0; for (i=1;iPLAYERS-1); if (player[innum].pop==0) { print ("That base has already been wiped out.\n"); goto NOBODYTHERE; } target=innum; print ("How many ships to send? "); getnum (); i=MIN (player[0].armed,player[0].pilots); i=MIN (i,player[0].bombs/2); i=MIN (i,player[0].fuel/8); if (innumi) { innum=i; if (i==0) { print ("Sorry, but you can't send any right now."); goto NOATTACK; } print ("Sorry, but you can only send "); printlong (i); print (".\n"); anykey (); } attack (0,target,i); print ("\fThese are the results of the attack: "); attackreport (i,target); print ("Total payment for damage done is "); printlong (payment); player[0].money+=payment; print (" credits.\nTotal cost of attack was "); printlong (shipl*(SHIP+ARM+PILOT)+bombu*BOMB); print (" credits.\n"); } } NOATTACK: anykey (); if (otherplayers ()) /* Do computer-controlled player moves */ goto END; anykey (); if (events ()) /* Do events e.g. mining, pop. increase etc. */ goto END; /* if returns 1, game over */ anykey (); goto LOOP; END: print ("\n\nDo you want to play again? "); if (yesno ()) goto NEWGAME; else finish (); } attack (attacker,defender,force) /* Do attack */ int attacker,defender; unsigned long force; /* Number of ships involved */ { register unsigned long rembombs; bombu=force*2; player[attacker].fuel-=force*8; shipl=MIN (rnd (player[defender].lasers/8),force); force-=shipl; /* some ships shot down on approach */ rembombs=MINUS (force*2,rnd (player[defender].lasers)); /* some bombs intercepted by lasers */ rembombs=rembombs*4/5; /* some bombs miss targets */ domed=MIN (rnd (rembombs/2),player[defender].domes); rembombs-=domed; player[defender].domes-=domed; laserd=MIN (rnd (rembombs/3),player[defender].lasers); rembombs-=laserd; player[defender].lasers-=laserd; shipd=MIN (rnd (rembombs),player[defender].ships); rembombs-=shipd; player[defender].ships-=shipd; player[defender].armed=MINUS (player[defender].armed,rnd (shipd/2)); recyclerd=MIN (rembombs,player[defender].recyclers); player[defender].recyclers-=recyclerd; shipl+=MIN (rnd (player[defender].lasers/8),force); player[attacker].ships-=shipl; player[attacker].pilots-=shipl; player[attacker].armed-=shipl; player[attacker].bombs-=bombu; popk=MIN (domed*(70+rnd(110))+rnd ((force+3)*3),player[defender].pop); player[defender].pop-=popk; payment=shipd*DSHIP+laserd*DLASER+recyclerd*DRECYCLER+domed*DDOME+popk/10; if (player[defender].domes&player[defender].recyclers==0) player[defender].pop=0; } attackreport (n,defender) /* Report attack by n ships */ unsigned long n; int defender; { if (shipl) { printnoun (shipl,"attacking ship"); print ("shot down from a total of "); printlong (n); print (". "); } if (shipd) { printnoun (shipd,"ship"); print ("bombed on the ground. "); } if (domed) { printnoun (domed,"dome"); print ("destroyed. "); } if (recyclerd) { printnoun (recyclerd,"recycler"); print ("blown up. "); } if (laserd) { printnoun (laserd,"laser"); print ("taken out. "); } if (popk) { print ("Number of people killed = "); printlong (popk); writechar ((long)'.'); } writechar ((long)'\n'); if (player[defender].pop==0) print ("All life on base extinguished.\n"); if (!(shipd|domed|recyclerd|laserd|popk)) print ("The attack did no damage.\n"); } printnoun (number,string) /* Print noun with plural or singular ending */ long number; char *string; { printlong (number); writechar ((long)' '); print (string); if (number!=1) print ("s were "); else print (" was "); } int yesno () /* Get yes or no answer from keyboard */ { register int i; resetscroll (); REPEATYN: do i=checkinput (); while (i==0); if (i==1000) { finish (); exit (0); } if (i=='y' || i=='Y') { print ("YES\n"); return (1); } if (i=='n' || i=='N') { print ("NO\n"); return (0); } else goto REPEATYN; } getnum () /* Get typed-in number from user, put in innum global variable */ { AGAIN: string[0]='\0'; if (input (string,INLEN)==-1000) { finish (); /* If close window, terminate program */ exit (0); } if (string[0]=='\0') { innum=0; return (); } innum=scanlong (string); if (innum==32767 && (string[0]<'0' || string[0]>'9')) { print ("Invalid input-please try again: "); goto AGAIN; } } howmany (cost,lab,error) /* Ask how many items at given cost */ int cost,lab; /* and labour requirements */ char *error; /* Error message for not enough of something */ { getnum (); if (innum*cost>player[0].money) { innum=player[0].money/cost; if (innum*lab>player[0].pop/2) { innum=player[0].pop/(lab+lab); print (error); printlong (innum); print (".\n"); } else { print (NOTENOUGHCASH); printlong (innum); print (".\n"); } } else if (innum*lab>player[0].pop/2) { innum=player[0].pop/(lab+lab); print (error); printlong (innum); print (".\n"); } player[0].money-=innum*cost; } int otherplayers () { register short i; register int x,target; for (i=1;iMAXLONG||player[0].money>MAXLONG) { print ("Congratulations! The base has done incredibly well under your management! You can now retire a millionaire. Well done.\n"); return (1); } popinc=player[0].pop*(5+RangeRand (5))/100; player[0].pop+=popinc; oreinc=player[0].mines*(10+RangeRand (10)); mineslost=0; mineslost=rnd (player[0].mines/47); starved=MINUS (player[0].pop,player[0].recyclers*80); crowded=0; if (popinc) { print ("Population increased by: "); printlong (popinc); writechar ((long)'\n'); } if (oreinc) { print ("Quantity of ore accumulated: "); printlong (oreinc); writechar ((long)'\n'); player[0].ore+=oreinc; } if (mineslost) { printnoun (mineslost,"mine"); print ("destroyed by storms in Jovian atmosphere.\n"); player[0].mines-=mineslost; } if (starved) { player[0].pop-=starved; crowded=MINUS (player[0].pop,player[0].domes*180); printnoun (starved,"death"); print ("caused by lack of food and oxygen due to overload on the recycling systems.\n"); } if (crowded) { player[0].pop-=crowded; printnoun (crowded,"death"); print ("caused by stress and outbreaks of violence due to overcrowding.\n"); } player[0].fuel=MINUS (player[0].fuel,player[0].domes+player[0].recyclers); if (player[0].fuel==0) { print ("\nFuel stocks exhausted. Life-support systems failure. Human life on base extinguished.\n"); return (1); /* Tell main program to terminate game */ } if (player[0].pop==0) { print ("\nAll life on the base has come to an end.\n"); return (1); } for (i=1;iplayer[i].domes*180) player[i].pop=player[i].domes*180; /* If too many people, */ if (player[i].pop>player[i].recyclers*80) /* reduce population */ player[i].pop=player[i].recyclers*80; player[i].fuel=MINUS (player[i].fuel,player[i].domes+player[i].recyclers); if (player[i].fuel==0) player[i].pop=0; /* If fuel stocks exhausted, all die */ if (player[i].pop==0) { print ("Radio and infra-red transmissions from the base of "); print (enemyname[i-1]); print (" have ceased.\n"); } } return (0); } anykey () { register int i; print ("\nPress any key to continue.\n"); do i=checkinput (); while (i==0); if (i==1000) { finish (); exit (0); } } long rnd (x) /* Return random number from 0 to x-1 */ unsigned long x; /* necessary because RangeRand doesn't work for 0 */ { if (x) return (RangeRand (x)); else return (0); }