billr@saab.CNA.TEK.COM (Bill Randle) (06/24/89)
Submitted-by: adb@bu-it.bu.edu (Adam Bryant) Posting-number: Volume 6, Issue 86 Archive-name: conquer4/Part04 Superseeds: conquer3; Volume 4, Issue 42-49 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 4 (of 14)." # Contents: combat.c io.c run # Wrapped by billr@saab on Thu Jun 15 15:20:12 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'combat.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'combat.c'\" else echo shar: Extracting \"'combat.c'\" \(39440 characters\) sed "s/^X//" >'combat.c' <<'END_OF_FILE' X/*conquer : Copyright (c) 1988 by Ed Barlow. X * I spent a long time writing this code & I hope that you respect this. X * I give permission to alter the code, but not to copy or redistribute X * it without my explicit permission. If you alter the code, X * please document changes and send me a copy, so all can have it. X * This code, to the best of my knowledge works well, but it is my first X * 'C' program and should be treated as such. I disclaim any X * responsibility for the codes actions (use at your own risk). I guess X * I am saying "Happy gaming", and am trying not to get sued in the process. X * Ed X */ X X#include <math.h> X#include "header.h" X#include "data.h" X X#define MGKNUM 32 /* number of units possible in battle */ X#define ATKR 2 X#define DFND 1 X#define NTRL 0 X#define WIMP 3 X Xextern FILE *fpmsg; Xextern FILE *fnews; Xextern short country; X Xshort retreatside; /* ATKR, DFND, or none (0) */ Xshort retreatx; /* retreat x square */ Xshort retreaty; /* retreat y square */ X Xint unit[MGKNUM]; /*armynum*/ Xint owner[MGKNUM]; /*owner*/ Xint side[MGKNUM]; /*see definitions->1=units 2=unit*/ Xlong troops[MGKNUM]; /*starting troops in army */ Xint xspot,yspot; /*location of battles*/ Xint anation; /*nation attacking in this fight*/ Xint dnation; /*one nation defending in this fight*/ X X/************************************************************************/ X/* COMBAT() run all combat on the map */ X/* for each sector, determine if armies in with attack mode */ X/************************************************************************/ Xvoid Xcombat() X{ X register int i,j; X char **fought; /* TRUE if already fought in sctr */ X int temp,ctry; X short armynum,nvynum; X int valid; X int count=0; X X fought = (char **) m2alloc(MAPX,MAPY,sizeof(char)); X X printf("Run Combat Routines\n"); X fprintf(fnews,"4\tBATTLE SUMMARY STATISTICS\n"); X /*for each nation, if in attack mode run a check*/ X X /* no sectors have been fought in yet */ X for(i=0;i<MAPX;i++) for(j=0;j<MAPY;j++) fought[i][j]=FALSE; X X for(ctry=NTOTAL-1;ctry>0;ctry--) if(isactive(ntn[ctry].active)) { X X /*army combat*/ X for(j=0;j<MAXARM;j++) X if((ntn[ctry].arm[j].sold>0) X &&(ntn[ctry].arm[j].stat>=ATTACK) X &&(ntn[ctry].arm[j].stat<=SORTIE X ||ntn[ctry].arm[j].stat>=NUMSTATUS) X &&(fought[ntn[ctry].arm[j].xloc][ntn[ctry].arm[j].yloc]==0)){ X X /* someone can initiate combat in xspot,yspot */ X xspot=ntn[ctry].arm[j].xloc; X yspot=ntn[ctry].arm[j].yloc; X fought[xspot][yspot]=TRUE; X X /*initialize matrix*/ X for(temp=0;temp<MGKNUM;temp++){ X unit[temp]=(-1); X owner[temp]=(-1); X side[temp]=NTRL; X troops[temp]=0; X } X X /*check all armies in sector and add to matrix*/ X count=0; X valid=FALSE; X /*is valid,set matrix*/ X for(country=0;country<NTOTAL;country++) X if(isactive(ntn[country].active)) X for(armynum=0;armynum<MAXARM;armynum++) X if((ASOLD>0) X &&(ASTAT!=SCOUT) X &&(AXLOC==xspot) X &&(AYLOC==yspot) X &&(count<MGKNUM)) { X if((country!=ctry) X &&(ntn[ctry].dstatus[country]>HOSTILE)) { X valid=TRUE; X if( sct[xspot][yspot].owner==ctry ) { X dnation=ctry; X anation=country; X } else if(( rand()%2==0 ) X ||( sct[xspot][yspot].owner==country )){ X anation=ctry; X dnation=country; X } else { X dnation=ctry; X anation=country; X } X } X unit[count]=armynum; X owner[count]=country; X count++; X } X X if(valid==TRUE) fight(); X } X X /*navy combat*/ X for(j=0;j<MAXNAVY;j++) X if((ntn[ctry].nvy[j].warships!=0) X&&(fought[ntn[ctry].nvy[j].xloc][ntn[ctry].nvy[j].yloc]==0) X&&(sct[ntn[ctry].nvy[j].xloc][ntn[ctry].nvy[j].yloc].altitude==WATER)){ X X xspot=ntn[ctry].nvy[j].xloc; X yspot=ntn[ctry].nvy[j].yloc; X fought[xspot][yspot]=1; X X /*initialize matrix*/ X for(temp=0;temp<MGKNUM;temp++){ X unit[temp]=(-1); X owner[temp]=(-1); X side[temp]=NTRL; X troops[temp]=0; X } X X /*check all fleets in 2 sector range and add to matrix*/ X count=0; X valid=FALSE; X /*is valid,set matrix*/ X for(country=0;country<NTOTAL;country++) X if(isactive(ntn[country].active)) X for(nvynum=0;nvynum<MAXNAVY;nvynum++) X if((NWSHP+NMSHP+NGSHP!=0) X &&(abs(NXLOC-xspot)<=2) X &&(abs(NYLOC-yspot)<=2) X &&(sct[NXLOC][NYLOC].altitude==WATER) X &&(count<MGKNUM)) { X fought[NXLOC][NYLOC]=1; X if((country!=ctry) X &&(ntn[ctry].dstatus[country]>HOSTILE)){ X valid=TRUE; X anation=ctry; X dnation=country; X } X unit[count]=nvynum; X owner[count]=country; X count++; X } X if(valid==TRUE) navalcbt(); X } X } X free(fought); X printf("\nall army and navy attacks completed\n"); X} X X/* macro for owner, accounts for runaway indicator */ X#define UOWNER(x) ((owner[(x)]<(-1))?(-owner[(x)]-1):(owner[(x)])) X/************************************************************************/ X/* FIGHT() - fight an individual battle given the three */ X/* matricies global to this module */ X/************************************************************************/ Xvoid Xfight() X{ X int roll,strength,fortdam=FALSE; X int odds; /* odds (asold/dsold) times 100 */ X int done; X int i,j,k; X long asold=0,dsold=0; /*a's and d's total soldiers*/ X long astr=0,dstr=0; /*a's and d's relative strength*/ X long Aloss,Dloss; /*a's and d's total losses*/ X int PAloss,PDloss; /*percent a and d loss*/ X long loss; X int abonus=0,dbonus=0; /* bonus aggregate */ X long vampire=0; /* # non vamps deaded */ X short nvamps=0; /* number of vampire armies */ X X /* determine who is attacker & who is on defenders side?*/ X for(j=0;j<MGKNUM;j++) if(owner[j]!=(-1)){ X if(owner[j]==anation) side[j]=ATKR; X else if(owner[j]==dnation) side[j]=DFND; X else if(ntn[anation].dstatus[owner[j]]==JIHAD) side[j]=DFND; X else if(ntn[owner[j]].dstatus[anation]==JIHAD) side[j]=DFND; X else if(ntn[anation].dstatus[owner[j]]==WAR) side[j]=DFND; X else if(ntn[owner[j]].dstatus[anation]==WAR) side[j]=DFND; X else if((ntn[owner[j]].dstatus[anation]==TREATY)&&(ntn[owner[j]].dstatus[dnation]>HOSTILE)) side[j]=ATKR; X else if((ntn[owner[j]].dstatus[anation]==ALLIED)&&(ntn[owner[j]].dstatus[dnation]>HOSTILE)) side[j]=ATKR; X } X X /*calculate number of troops and assign statuses */ X asold=0; X dsold=0; X for(i=0;i<MGKNUM;i++) if(owner[i]>(-1)) { X /* record troops for all units in sector */ X troops[i]=ntn[owner[i]].arm[unit[i]].sold; X X if(((ntn[owner[i]].arm[unit[i]].unittyp == A_MERCENARY) X ||(ntn[owner[i]].arm[unit[i]].unittyp == A_ORC) X ||(ntn[owner[i]].arm[unit[i]].unittyp == A_GOBLIN)) X &&( ntn[owner[i]].arm[unit[i]].stat < NUMSTATUS ) X &&( rand()%100<15 )) { X if( ispc(ntn[owner[i]].active)) { X mailopen( owner[i] ); X fprintf(fm,"Message to %s from Conquer\n",ntn[owner[i]].name); X fprintf(fm,"\n Your %s Army %d Refuses to Fight\n", X unittype[ntn[owner[i]].arm[unit[i]].unittyp], X unit[i]); X mailclose(); X } X retreatside = side[i]; X fdxyretreat(); X if((retreatx==xspot)&&(retreaty==yspot)){ X /* move to capitol & kill 30% */ X ntn[owner[i]].arm[unit[i]].xloc=ntn[owner[i]].capx; X ntn[owner[i]].arm[unit[i]].yloc=ntn[owner[i]].capy; X ntn[owner[i]].arm[unit[i]].sold*=7; X ntn[owner[i]].arm[unit[i]].sold/=10; X } else { X /* retreat normally and kill 20% */ X ntn[owner[i]].arm[unit[i]].sold*=8; X ntn[owner[i]].arm[unit[i]].sold/=10; X retreat( i ); X } X owner[i]=(-1-owner[i]); X continue; X } X else if(side[i]==ATKR){ X if((ntn[owner[i]].arm[unit[i]].stat!=RULE) X &&( ntn[owner[i]].arm[unit[i]].stat!=TRADED) X &&( ntn[owner[i]].arm[unit[i]].stat!=SCOUT)) { X asold += ntn[owner[i]].arm[unit[i]].sold; X } else { X side[i]=NTRL; X } X /* sortie 20% bonus in odds */ X if(ntn[owner[i]].arm[unit[i]].stat==SORTIE) X asold += ntn[owner[i]].arm[unit[i]].sold/5; X } else if(side[i]==DFND){ X if(ntn[owner[i]].arm[unit[i]].stat!=RULE) { X dsold += ntn[owner[i]].arm[unit[i]].sold; X } X } X if((magic(owner[i],VAMPIRE)==TRUE) && X (ntn[owner[i]].arm[unit[i]].unittyp==A_ZOMBIE)) nvamps++; X } X X if(asold<=0) { X printf("\nCombat aborted due to lack of attackers.\n"); X return; X } X if( asold > dsold*100) odds=10000; X else if( dsold > asold*100 ) odds=1; X else odds = (asold*100)/dsold; X X /* mercenaries/orcs/goblins might run away */ X for(i=0;i<MGKNUM;i++) if(owner[i]>(-1)) { X if(((( odds > 200 )&&(side[i]==DFND)) X ||(( odds < 100 )&&(side[i]==ATKR))) X &&((ntn[owner[i]].arm[unit[i]].unittyp == A_MERCENARY) X ||(ntn[owner[i]].arm[unit[i]].unittyp == A_ORC) X ||(ntn[owner[i]].arm[unit[i]].unittyp == A_GOBLIN)) X &&(ntn[owner[i]].arm[unit[i]].stat < NUMSTATUS) X &&( rand()%100<30 )) { X if( ispc(ntn[owner[i]].active)) { X mailopen( owner[i] ); X fprintf(fm,"Message to %s from Conquer\n",ntn[owner[i]].name); X fprintf(fm," Your %s Army %d Runs Away\n", X unittype[ntn[owner[i]].arm[unit[i]].unittyp], X unit[i]); X mailclose(); X } X retreatside = side[i]; X if( side[i] == ATKR ) asold-= troops[i]; X if( side[i] == DFND ) dsold-= troops[i]; X fdxyretreat(); X if((retreatx==xspot)&&(retreaty==yspot)){ X /* move to capitol & kill 75% */ X ntn[owner[i]].arm[unit[i]].xloc=ntn[owner[i]].capx; X ntn[owner[i]].arm[unit[i]].yloc=ntn[owner[i]].capy; X ntn[owner[i]].arm[unit[i]].sold/=4; X } else { X /* retreat normally and kill 50% */ X ntn[owner[i]].arm[unit[i]].sold/=2; X retreat( i ); X } X owner[i]=(-1-owner[i]); X continue; X } X } X retreatside=0; X if( asold<=0 ) { X printf("Exit from battle due to lack of attackers\n"); X return; X } X X /* CALCULATE AVERAGE COMBAT BONUS */ X abonus=0; X dbonus=0; X for(i=0;i<MGKNUM;i++) if(owner[i]>(-1)) { X if(side[i]==ATKR) X abonus += cbonus(i)*troops[i]; X else if(side[i]==DFND && ntn[owner[i]].arm[unit[i]].stat!=RULE) X dbonus += cbonus(i)*troops[i]; X } X X /*archer bonus if not in fort vs knights/cavalry*/ X j=0; X k=0; X for(i=0;i<MGKNUM;i++) if(owner[i]>(-1)) X if(ISCITY(sct[xspot][yspot].designation)){ X if((ntn[owner[i]].arm[unit[i]].unittyp == A_CAVALRY) X ||(ntn[owner[i]].arm[unit[i]].unittyp == A_KNIGHT)) X if(side[i]==ATKR) j+=troops[i]; X else if(side[i]==DFND) k+=troops[i]; X } X X for(i=0;i<MGKNUM;i++) if(owner[i]>(-1)) { X if(j>0) abonus += (15 * j * troops[i]) / asold; X if(k>0 && dsold>0) dbonus += (15 * k * troops[i]) / dsold; X } X X abonus/=asold; X if (dsold>0) dbonus/=dsold; X X /*CALCULATED BONUSES TO WHOLE COMBAT*/ X for(i=0;i<MGKNUM;i++) if(owner[i]>(-1)) { X if(fort_val(&sct[xspot][yspot]) != 0){ X /*Catapults add +1%/20 men defending castle (max +10%)*/ X if((ntn[owner[i]].arm[unit[i]].unittyp == A_CATAPULT) X &&(side[i]==DFND)) X dbonus += max((troops[i]/20),10); X /*Catapults add +1%/40 men attacking castle (max +10%)*/ X else if((ntn[owner[i]].arm[unit[i]].unittyp == A_CATAPULT) X &&(side[i]==ATKR)) { X strength = max((troops[i]/40),10); X abonus += strength; X /* possible damage 20% chance */ X if(rand()%100<2*strength) { X fortdam=TRUE; X sct[xspot][yspot].fortress--; X if(sct[xspot][yspot].fortress == 0) X sct[xspot][yspot].designation = DRUIN; X } X } X /*Siege_engines add +1%/20 men when attacking fortress*/ X else if((ntn[owner[i]].arm[unit[i]].unittyp == A_SIEGE) X &&(side[i]==ATKR)) { X strength = max((troops[i]/20),30); X abonus += strength; X /* possible damage 15% chance */ X if(rand()%100<strength/2) { X fortdam=TRUE; X sct[xspot][yspot].fortress--; X if(sct[xspot][yspot].fortress == 0) X sct[xspot][yspot].designation = DRUIN; X } X } X } else { X /*Catapults add +1%/40 men normal combat (max +10%)*/ X if(ntn[owner[i]].arm[unit[i]].unittyp == A_CATAPULT) X abonus+=max((troops[i]/40),10); X } X } X X /*RUN COMBAT */ X /*FIRST GIVE RANDOM ROLL FROM 0 to 100 */ X /*WITH A PROBABILITY BELL CURVE */ X /* high roll favors attacker [ 5 d21 - 5 ] */ X roll = 0; X for(i=0;i<5;i++) { X roll += rand()%21+1; X } X roll -= 5; X X /*find relative strength of troops*/ X astr = asold * (100 + abonus); X dstr = dsold * (100 + dbonus); X X /*Recalculate odds based on quality of troops*/ X if( astr > dstr*100) odds=10000; X else if( dstr > astr*100 ) odds=1; X else odds = (astr*100)/dstr; X X /* calculate loss for an even battle */ X PDloss = MAXLOSS * roll / 100; X PAloss = MAXLOSS * (100 - roll) / 100; X X /* adjust for odds */ X if( odds == 1 ) { X PDloss=0; X PAloss=200; X } else if( odds == 10000 ) { X PAloss=0; X PDloss=200; X } else if(odds > 100) { X PDloss += (odds / 12 - 8); /* 8.33% for higher odds */ X PAloss -= (odds / 16 - 6); /* 6.25% for lower odds */ X if(PAloss<(100-roll)/20) X PAloss=(100-roll)/20; /* can't get too small */ X } else { X PAloss += ( 800 / odds - 8); /* 8% for higher odds */ X PDloss -= ( 600 / odds - 6); /* 6% for lower odds */ X if(PDloss<roll/20) X PDloss = roll/20; /* can't get too small */ X } X X if( fort_val(&sct[xspot][yspot]) > 0 ){ X PDloss *= 120; X PAloss *= 120; X PDloss /= 100; X PAloss /= 100; X } X X retreatside = 0; X X if((PDloss > 2* PAloss) X &&(odds>150) X &&(((PDloss>=50)&&(rand()%4==0)) X ||(rand()%8))) retreatside=DFND; X X if((PAloss > 2* PDloss) X &&(odds<150) X &&(((PAloss>=50)&&(rand()%2==0)) X ||(rand()%6))) retreatside=ATKR; X X if(retreatside!=0) { X fdxyretreat(); X /* no legal retreat route */ X if((retreatside!=0) && (retreatx== xspot) X && (retreaty== yspot)){ X if(retreatside==ATKR) PAloss+=15; X else if(retreatside==DFND) PDloss+=15; X#ifdef DEBUG X printf("side %d (%d %d) can't retreat...+15%% loss\n",retreatside,retreatx,retreaty); X#endif DEBUG X retreatside = 0; X } X#ifdef DEBUG X else printf("retreat side %d to %d %d\n",retreatside,retreatx,retreaty); X#endif DEBUG X } X X if(PAloss>100) PAloss = 100; X if(PDloss>100) PDloss = 100; X X Aloss = Dloss = 0; X for(i=0;i<MGKNUM;i++) if(owner[i]>(-1)){ X if(side[i]==ATKR){ X if( ntn[owner[i]].arm[unit[i]].unittyp >= MINLEADER) { X if((rand()%100) < PAloss){ /* kill it */ X for(j=0;j<MAXARM;j++) X if(ntn[owner[i]].arm[j].stat==unit[i]+NUMSTATUS) X ntn[owner[i]].arm[j].stat=ATTACK; X Aloss += troops[i]; X ntn[owner[i]].arm[unit[i]].sold=0; X } X } else { X loss=(troops[i]*PAloss)/100; X /*archers/catapults on sortie take 1/4 damage*/ X if((ntn[owner[i]].arm[unit[i]].stat==SORTIE) X &&(fort_val(&sct[xspot][yspot]) > 0) X &&(sct[xspot][yspot].owner==country) X &&((ntn[owner[i]].arm[unit[i]].unittyp==A_ARCHER) X ||(ntn[owner[i]].arm[unit[i]].unittyp==A_CATAPULT))) X loss /= 4; X /*army can't have less than 25 men in it*/ X if(troops[i]-loss<25) X loss=troops[i]; Xif( loss>troops[i] ) { Xprintf("I AM VERY CONFUSED - PLEASE HELP... combat.c\n"); X} X Aloss+=loss; X ntn[owner[i]].arm[unit[i]].sold-=loss; X if((ntn[owner[i]].arm[unit[i]].unittyp==A_MILITIA)&&(retreatside==ATKR)) { X sct[ntn[owner[i]].arm[unit[i]].xloc][ntn[owner[i]].arm[unit[i]].yloc].people += ntn[owner[i]].arm[unit[i]].sold; X ntn[owner[i]].arm[unit[i]].sold-=0; X } X } X } else if(side[i]==DFND){ X if( ntn[owner[i]].arm[unit[i]].unittyp >= MINLEADER) { X if((ntn[owner[i]].arm[unit[i]].stat!=RULE X ||PDloss>=80)&&((rand()%100) < PDloss)){ /* kill it */ X for(j=0;j<MAXARM;j++) X if(ntn[owner[i]].arm[j].stat==unit[i]+NUMSTATUS) X ntn[owner[i]].arm[j].stat=ATTACK; X Dloss +=troops[i]; X ntn[owner[i]].arm[unit[i]].sold=0; X } X } else { X loss=(troops[i]*PDloss)/100; X /*destroy army if < 25 men*/ X if(troops[i]-loss<25) X loss=troops[i]; X Dloss+=loss; X ntn[owner[i]].arm[unit[i]].sold-=loss; X if((ntn[owner[i]].arm[unit[i]].unittyp==A_MILITIA)&&(retreatside==DFND)) { X sct[ntn[owner[i]].arm[unit[i]].xloc][ntn[owner[i]].arm[unit[i]].yloc].people += ntn[owner[i]].arm[unit[i]].sold; X ntn[owner[i]].arm[unit[i]].sold-=0; X } X } X } X /* non-vampire troops are sucked in by vampires */ X if((nvamps>0)&&(magic(owner[i],VAMPIRE)==FALSE) X &&(ntn[owner[i]].arm[unit[i]].unittyp!=A_ZOMBIE) X &&(ntn[owner[i]].arm[unit[i]].unittyp<MINLEADER)) X vampire+= loss / 3; X } X /* use k variable to hold length */ X#ifdef HIDELOC X if( isntn( ntn[sct[xspot][yspot].owner].active )) { X fprintf(fnews,"4.\tBattle occurs in %s", ntn[sct[xspot][yspot].owner].name); X k = 27+strlen(ntn[sct[xspot][yspot].owner].name); X } else { X fprintf(fnews,"4.\tBattle on unowned land"); X k = 30; X } X#else X fprintf(fnews,"4.\tBattle in %d,%d",xspot,yspot); X k = 25; X#endif X for(j=0;j<MGKNUM;j++) if(UOWNER(j)>(-1)){ X done=FALSE; X for(i=0;i<j;i++) if(UOWNER(j)==UOWNER(i)) done=TRUE; X if(done==FALSE) { X loss=NTRL; X for(i=j;(loss==NTRL||loss==WIMP) && i<MGKNUM;i++) X if(UOWNER(i)==UOWNER(j)) { X if(owner[i]<(-1)) loss=WIMP; X else loss=side[i]; X } X if(loss!=NTRL) { X k += 11 + strlen(ntn[UOWNER(j)].name); X if(loss==WIMP) k++; X if(k>79) { X k = 30; X fprintf(fnews,",\n4.\t "); X } else fprintf(fnews,", "); X if(loss==ATKR) X fprintf(fnews,"attacker %s",ntn[UOWNER(j)].name); X else if(loss==DFND) X fprintf(fnews,"defender %s",ntn[UOWNER(j)].name); X else if(loss==WIMP) X fprintf(fnews,"retreater %s",ntn[UOWNER(j)].name); X } X } X } X fprintf(fnews,"\n"); X if(nvamps>0){ X for(i=0;i<MGKNUM;i++) if(owner[i]>(-1)){ X if((magic(owner[i],VAMPIRE)==TRUE) X &&(ntn[owner[i]].arm[unit[i]].unittyp==A_ZOMBIE) X &&(ntn[owner[i]].arm[unit[i]].sold > 0)) X ntn[owner[i]].arm[unit[i]].sold+=vampire/nvamps; X } X } X X /*who is in the battle; but don't send to scared armies */ X for(j=0;j<MGKNUM;j++) if(owner[j]>(-1)){ X done=FALSE; X X /*first time your nation appears done=FALSE*/ X for(i=0;i<j;i++) if(owner[j]==owner[i]) done=TRUE; X X if((done==FALSE)&&(ispc(ntn[owner[j]].active))) { X X loss=NTRL; X for(i=j;loss==NTRL && i<MGKNUM;i++) X loss=side[i]; X mailopen( owner[j] ); X X fprintf(fm,"BATTLE SUMMARY for sector %d, %d\n",xspot,yspot); X fprintf(fm,"Battle occured during %s of Year %d\n",PSEASON(TURN),YEAR(TURN)); X X if(loss==ATKR) X fprintf(fm,"You are on the Attacking Side\n"); X else if(loss==DFND) X fprintf(fm,"You are on the Defending Side\n"); X else fprintf(fm,"You are Neutral\n"); X X /*detail all participants in battle*/ X for(k=0;k<MGKNUM;k++) if(owner[k]!=(-1)){ X fprintf(fm," %s ",ntn[UOWNER(k)].name); X if(owner[k]<(-1)) X fprintf(fm,"chickens out: "); X else if(side[k]==DFND X && ntn[UOWNER(k)].arm[unit[k]].stat!=RULE) X fprintf(fm,"defending: "); X else if(side[k]==ATKR) X fprintf(fm,"attacking: "); X else fprintf(fm,"neutral: "); X fprintf(fm,"army %d (%s, men %d, bonus=%d, loss=%d)", X unit[k], X unittype[ntn[UOWNER(k)].arm[unit[k]].unittyp%UTYPE], X troops[k], X cbonus(k), X troops[k]-ntn[UOWNER(k)].arm[unit[k]].sold); X if((ntn[UOWNER(k)].arm[unit[k]].unittyp >= MINLEADER) X &&( ntn[UOWNER(k)].arm[unit[k]].sold == 0)) X fprintf(fm," (killed)\n"); X else if((ntn[owner[k]].arm[unit[k]].unittyp == A_MILITIA) X &&( ntn[owner[k]].arm[unit[k]].sold == 0)) X fprintf(fm," (disbanded)\n"); X else fputc('\n',fm); X } X X fprintf(fm,"attacking soldiers=%ld -> percent loss %d%%\n",asold,PAloss); X fprintf(fm,"defending soldiers=%ld -> percent loss %d%%\n",dsold,PDloss); X fprintf(fm,"ODDS=%d => adjusted to %d to 100; Die Roll is %d\n",odds*(100+dbonus)/(100+abonus),odds,roll); X fprintf(fm,"RESULT: Attackers lose %ld men, Defenders lose %ld men\n",Aloss, Dloss); X if(fortdam==TRUE) fprintf(fm,"Fortifications damaged during the attack\n"); X if(retreatside==ATKR){ X if(Aloss<asold) X fprintf(fm,"Additionally, All attackers retreat to %d %d\n",retreatx,retreaty); X } else if(retreatside==DFND){ X if(Dloss<dsold) X fprintf(fm,"Additionally, All defenders retreat to %d %d\n",retreatx,retreaty); X } X mailclose(); X } X } X retreat( -1 ); X} X X/************************************************************************/ X/* CBONUS() - return combat bonuses for unit i */ X/************************************************************************/ Xint Xcbonus(num) X{ X short armynum; X int armbonus; X X armbonus=0; X armynum=unit[num]; X country=UOWNER(num); X X /*Racial combat bonus due to terrain (the faster you move the better)*/ X armbonus+=5*(9-movecost[xspot][yspot]); /* this line always has */ X /* the same result... must fix -- ADB */ X X if(((magic(country,DESTROYER)==1) X ||(magic(country,DERVISH)==1)) X &&((sct[xspot][yspot].vegetation==ICE) X ||(sct[xspot][yspot].vegetation==DESERT))) X armbonus+=30; X X if(ASTAT>=NUMSTATUS) armbonus+=20; /* army group */ X if(side[num]==DFND){ X X if(sct[xspot][yspot].altitude==MOUNTAIN) armbonus+=20; X else if(sct[xspot][yspot].altitude==HILL) armbonus+=10; X X if(sct[xspot][yspot].vegetation==JUNGLE) armbonus+=20; X else if(sct[xspot][yspot].vegetation==FOREST) armbonus+=15; X else if(sct[xspot][yspot].vegetation==WOOD) armbonus+=10; X X if(ATYPE==A_MERCENARY) armbonus += MERCDEF; X else armbonus += ntn[UOWNER(num)].dplus; X X if(ASTAT==MAGDEF) armbonus+=30; X else if(ASTAT==SORTIE) armbonus-=30; X else if(ASTAT==SIEGED) armbonus-=20; X X if((sct[xspot][yspot].owner==country) X &&(ASTAT==GARRISON||ASTAT==MILITIA||ASTAT==SIEGED)){ X if(ATYPE == A_ZOMBIE) /* don't utilize walls well */ X armbonus += fort_val(&sct[xspot][yspot])/2; X else armbonus += fort_val(&sct[xspot][yspot]); X } X } X else if(side[num]==ATKR) { X if( (fort_val(&sct[xspot][yspot]) > 0) X &&( magic(country,SAPPER)==TRUE)) armbonus += 10; X X if(ATYPE == A_MERCENARY) armbonus += MERCATT; X else armbonus += ntn[UOWNER(num)].aplus; X if(ASTAT==MAGATT) armbonus += 30; X if(ASTAT==SORTIE && (fort_val(&sct[xspot][yspot]) > 0) X && sct[xspot][yspot].owner==country) { X armbonus += 10; X if((ATYPE==A_DRAGOON)||(ATYPE==A_LEGION) X ||(ATYPE==A_PHALANX)) { X /* bonus for organization or riding cavalry */ X armbonus += 5; X } else if ((ATYPE==A_LT_CAV)||(ATYPE==A_CAVALRY)) { X /* bonus for mounted sortie */ X armbonus += 10; X } else if (avian(ATYPE)||ATYPE==A_ELEPHANT||ATYPE==A_KNIGHT) { X /* bonus for mounted or flying sortie */ X armbonus += 15; X } X if ((ATYPE>=MINMONSTER)||(ATYPE<=MAXMONSTER)) { X /* bonus for monsters (scare factor) */ X armbonus += 5; X } X } X } X X /*army status is important*/ X if(ASTAT==MARCH) armbonus-=40; X X /*if a fortress*/ X if(fort_val(&sct[xspot][yspot]) > 0){ X /*Cavalry and Knights get -20%*/ X if((ATYPE == A_CAVALRY) ||(ATYPE == A_KNIGHT)) armbonus -= 20; X /*Archers gain pluses*/ X else if((ATYPE == A_ARCHER)&&(sct[xspot][yspot].owner==country)) X armbonus += 15; X else if(ATYPE == A_ARCHER) armbonus += 5; X } X X if(side[num]==ATKR) armbonus+= *(unitattack+(ATYPE%UTYPE)); X else armbonus+= *(unitdefend+(ATYPE%UTYPE)); X X /*Phalanx and Legionaires need certain numbers of troops*/ X if((ATYPE==A_PHALANX)||(ATYPE==A_LEGION)) { X if(ASOLD>1000){ armbonus+=20; X } else if(ASOLD>500) armbonus+=10; X } X X return(armbonus); X} X Xvoid Xfdxyretreat() /* finds retreat location */ X{ X int x,y,nation=(-1); X int xsctr= xspot; X int ysctr= yspot; X X retreatx=xsctr; X retreaty=ysctr; X X if((sct[xsctr][ysctr].designation==DTOWN) X ||(sct[xsctr][ysctr].designation==DCAPITOL) X ||(sct[xsctr][ysctr].designation==DCITY)){ X retreatside=0; X return; X } X X if(retreatside == ATKR) nation=anation; X else nation=dnation; X X for(x= xsctr-1; x<=xsctr+1; x++) X for(y= ysctr-1; y<=ysctr+1; y++) if(ONMAP(x,y)){ X if(tofood( &sct[x][y], X sct[x][y].owner == country ? country : 0)==0) continue; X if(((sct[x][y].owner == nation) X ||(ntn[sct[x][y].owner].dstatus[nation] < NEUTRAL)) X ||(solds_in_sector( x, y, sct[x][y].owner) == 0)){ X retreatx=x; X retreaty=y; X#ifdef DEBUG X printf("armies in %d %d retreat to %d %d\n",xsctr,ysctr,x,y); X#endif DEBUG X return; X } X } X} X Xvoid Xretreat(unitnum) Xint unitnum; /* if -1 then normal, else retreat only unit ismerc */ X{ X int cnum; X X if(retreatside == 0) return; X X for(cnum=0;cnum<MGKNUM;cnum++) if(owner[cnum]>(-1)){ X if( unitnum != (-1) ) cnum=unitnum; X if((side[cnum]==ATKR)&&(retreatside==ATKR)){ X ntn[owner[cnum]].arm[unit[cnum]].xloc = retreatx; X ntn[owner[cnum]].arm[unit[cnum]].yloc = retreaty; X } X else if((side[cnum]==DFND)&&(retreatside==DFND)){ X ntn[owner[cnum]].arm[unit[cnum]].xloc = retreatx; X ntn[owner[cnum]].arm[unit[cnum]].yloc = retreaty; X } X if( unitnum != (-1) ) return; X } X} X X X/*SUBROUTINE TO RUN NAVAL COMBAT ON ALL SHIPS */ X/* quick define for easier reading */ X#define QWAR 1 X#define QGAL 2 X#define QMER 3 X/* just like fight, this takes array of owner,side,unit and calculates */ X/* a random battle based on the strengths of the combatants. */ Xvoid Xnavalcbt() X{ X int acrew=0,dcrew=0; /*a's and d's crew and soldier strength*/ X int ahold=0,dhold=0; /*a's and d's warship strength*/ X int awsunk=0,dwsunk=0; /*a's and d's warship losses for the round*/ X int agsunk=0,dgsunk=0; /*a's and d's galley losses for the round*/ X int amsunk=0,dmsunk=0; /*a's and d's merchent losses for the round*/ X int awcapt=0,dwcapt=0; /*a's and d's warship captures for the round*/ X int agcapt=0,dgcapt=0; /*a's and d's galley captures for the round*/ X int amcapt=0,dmcapt=0; /*a's and d's merchant captures for the round*/ X int akcrew=0,dkcrew=0; /*a's and d's crew losses for the round*/ X char wnum[MGKNUM],gnum[MGKNUM],mnum[MGKNUM]; X register int done,i,j,k; X int roll,odds,savecntry=country; X int PAloss, PDloss, Ploss, which, shipsize; X int thold, ghold, nvynum, armynum; X int dcptpct, acptpct, cptpct; X struct s_nation *saventn=curntn; X void show_ships(),capture(); X X printf("In Naval Combat....\n"); X X /* determine who is attacker & who is on defenders side?*/ X for(j=0;j<MGKNUM;j++) if(owner[j]!=(-1)){ X if(owner[j]==anation) side[j]=ATKR; X else if(ntn[anation].dstatus[owner[j]]==JIHAD) side[j]=DFND; X else if(ntn[owner[j]].dstatus[anation]==JIHAD) side[j]=DFND; X else if(ntn[anation].dstatus[owner[j]]==WAR) side[j]=DFND; X else if(ntn[owner[j]].dstatus[anation]==WAR) side[j]=DFND; X else if((ntn[owner[j]].dstatus[anation]==TREATY) X &&(ntn[owner[j]].dstatus[dnation]>HOSTILE)) side[j]=ATKR; X else if((ntn[owner[j]].dstatus[anation]==ALLIED) X &&(ntn[owner[j]].dstatus[dnation]>HOSTILE)) side[j]=ATKR; X } X X /* Loop through all competitors to determine X * relative combat strengths: X * men/unit strength X * crew on ship: X * warship crew 1 X * galley crew 2 X * merchant crew 4 X * soldiers onboard: X * SAILOR/ARCHER 3/4 X * MARINE 1/3 X * others 4/3 X */ X for(j=0;j<MGKNUM;j++) if(owner[j]!=(-1)){ X curntn= &ntn[owner[j]]; X country= owner[j]; X wnum[j]=SHIPS(ntn[country].nvy[unit[j]].warships,N_LIGHT)+ X SHIPS(ntn[country].nvy[unit[j]].warships,N_MEDIUM)+ X SHIPS(ntn[country].nvy[unit[j]].warships,N_HEAVY); X mnum[j]=SHIPS(ntn[country].nvy[unit[j]].merchant,N_LIGHT)+ X SHIPS(ntn[country].nvy[unit[j]].merchant,N_MEDIUM)+ X SHIPS(ntn[country].nvy[unit[j]].merchant,N_HEAVY); X gnum[j]=SHIPS(ntn[country].nvy[unit[j]].galleys,N_LIGHT)+ X SHIPS(ntn[country].nvy[unit[j]].galleys,N_MEDIUM)+ X SHIPS(ntn[country].nvy[unit[j]].galleys,N_HEAVY); X if(side[j]==DFND) { X if((k=fltwhold(unit[j]))>0) { X dhold += k; X if (magic(country,SAILOR)==TRUE) { X dcrew += 5*k*curntn->nvy[unit[j]].crew/4; X } else dcrew += k*curntn->nvy[unit[j]].crew; X } X if((k=fltmhold(unit[j]))>0) { X if (magic(country,SAILOR)==TRUE) { X dcrew += 5*k*curntn->nvy[unit[j]].crew/16; X } else dcrew += k*curntn->nvy[unit[j]].crew/4; X } X if((k=fltghold(unit[j]))>0) { X if (magic(country,SAILOR)==TRUE) { X dcrew += 5*k*curntn->nvy[unit[j]].crew/8; X } else dcrew += k*curntn->nvy[unit[j]].crew/2; X if(curntn->nvy[unit[j]].armynum!=MAXARM) { X k = curntn->nvy[unit[j]].armynum; X switch (curntn->arm[k].unittyp) { X case A_ARCHER: X case A_SAILOR: X dcrew += 3*curntn->arm[k].sold/2; X break; X case A_MARINES: X dcrew += 3*curntn->arm[k].sold; X break; X default: X dcrew += 3*curntn->arm[k].sold/4; X break; X } X } X } X } else if(side[j]==ATKR) { X if((k=fltwhold(unit[j]))>0) { X ahold += k; X if (magic(country,SAILOR)==TRUE) { X acrew += 5*k*curntn->nvy[unit[j]].crew/4; X } else acrew += k*curntn->nvy[unit[j]].crew; X } X if((k=fltmhold(unit[j]))>0) { X if (magic(country,SAILOR)==TRUE) { X acrew += 5*k*curntn->nvy[unit[j]].crew/16; X } else acrew += k*curntn->nvy[unit[j]].crew/4; X } X if((k=fltghold(unit[j]))>0) { X if (magic(country,SAILOR)==TRUE) { X acrew += 5*k*curntn->nvy[unit[j]].crew/8; X } else acrew += k*curntn->nvy[unit[j]].crew/2; X if(curntn->nvy[unit[j]].armynum!=MAXARM) { X k = curntn->nvy[unit[j]].armynum; X switch (curntn->arm[k].unittyp) { X case A_ARCHER: X case A_SAILOR: X acrew += 3*curntn->arm[k].sold/2; X break; X case A_MARINES: X acrew += 3*curntn->arm[k].sold; X break; X default: X acrew += 3*curntn->arm[k].sold/4; X break; X } X } X } X } X } X X /*find battle odds*/ X if( acrew > dcrew*100 ) odds=10000; X else if ( dcrew > acrew*100 ) odds=1; X else odds = (acrew*100)/dcrew; X X /* calculate capture percentages */ X /* X * This formula produces: X * 0% capture for 1:100 odds X * 2% capture for 1:10 odds X * 15% capture for 1:1 odds X * 60% capture for 10:1 odds X * 100% capture for >60:1 odds X * with linear progression between each. X */ X if (odds>6000) { X dcptpct=0; X acptpct=100; X } else if (odds>1000) { X dcptpct= (6000-odds)/2500; X acptpct= (odds-1000)/125+60; X } else if (odds>100) { X dcptpct= (1000-odds)/69+2; X acptpct= (odds-100)/20+15; X } else if (odds>10) { X dcptpct= (100-odds)/2+15; X acptpct= (odds-10)/6.9+2; X } else if (odds>6) { X dcptpct= (10-odds)*14+60; X acptpct= (odds-6)/2; X } else { X dcptpct= 100; X acptpct= 0; X } X#ifdef DEBUG X printf("capture percentage: attack = %d defend = %d\n",acptpct,dcptpct); X#endif DEBUG X X /*figure combat on a one-to-one basis */ X /* use a bell curve roll */ X roll = 0; X for(i=0;i<5;i++) { X roll += rand()%21+1; X } X roll -= 5; X PDloss = MAXLOSS * roll / 100; X PAloss = MAXLOSS * (100 - roll) / 100; X#ifdef DEBUG X printf("Pdloss = %d PAloss = %d\n",PDloss,PAloss); X#endif DEBUG X X /* adjust based on the odds */ X if( odds == 1 ) { X PDloss = 0; X PAloss = 100; X } else if ( odds == 10000 ) { X PAloss = 0; X PDloss = 100; X } else if ( odds > 100 ) { X PDloss += (odds / 10 - 10); /* 10% increase */ X PAloss -= (odds / 25 - 4); /* 4% decrease */ X if(PAloss<(100-roll)/5) X PAloss=(100-roll)/5; X } else { X PAloss += ( 1000 / odds - 10); /* 10% increase */ X PDloss -= ( 400 / odds - 4); /* 4% decrease */ X if(PDloss<roll/5) X PDloss = roll/5; X } X if (PAloss>100) PAloss=100; X if (PDloss>100) PDloss=100; X X /* calculate actual losses */ X for(j=0;j<MGKNUM;j++) if(owner[j]!=(-1)){ X curntn= &ntn[owner[j]]; X country= owner[j]; X X /* determine side */ X which=side[j]; X /* capturing is by foe so use other percent */ X if(which==ATKR) { X cptpct=dcptpct; X Ploss= PAloss; X } else if(which==DFND) { X cptpct=acptpct; X Ploss= PDloss; X } else continue; X X /* find all weighting info */ X nvynum = unit[j]; X thold = flthold(nvynum); X ghold = fltghold(nvynum); X X /* go through all ships in the navy */ X for(shipsize=N_LIGHT;shipsize<=N_HEAVY;shipsize++) { X /* check warships */ X for(i=0;i<P_NWAR(shipsize);i++) X if (rand()%100<Ploss) { X if(rand()%100<cptpct/2) { X /* capture a ship */ X if(which==ATKR){ X if (dhold) { X awcapt++; X ahold-=(shipsize+1); X capture(QWAR,DFND,shipsize,rand()%dhold+1); X NSUB_WAR(1); X } X } else { X if (ahold) { X dwcapt++; X dhold-=(shipsize+1); X capture(QWAR,ATKR,shipsize,rand()%ahold+1); X NSUB_WAR(1); X } X } X if(which==ATKR) akcrew += P_NCREW; X else dkcrew += P_NCREW; X } else if (rand()%2==0 || Ploss>90) { X /* destroy a ship */ X NSUB_WAR(1); X k = P_NCREW*(shipsize+1); X thold -= (shipsize+1); X if(which==ATKR) { X awsunk++; X ahold-=(shipsize+1); X akcrew+=k; X } else { X dwsunk++; X dhold-=(shipsize+1); X dkcrew+=k; X } X } else { X /* damage a ship */ X k = (shipsize+1)*Ploss*P_NCREW/100; X if(which==ATKR) akcrew += k; X else dkcrew += k; X P_NCREW -= k/thold; X } X } X /* check galleys */ X for(i=0;i<P_NGAL(shipsize);i++) X if (rand()%100<Ploss) { X if(rand()%100<cptpct) { X /* capture a ship */ X if(which==ATKR){ X if (dhold) { X agcapt++; X ghold-=(shipsize+1); X thold-=(shipsize+1); X capture(QGAL,DFND,shipsize,rand()%dhold+1); X NSUB_GAL(1); X } X } else if(which==DFND) { X if (ahold) { X dgcapt++; X ghold-=(shipsize+1); X thold-=(shipsize+1); X capture(QGAL,ATKR,shipsize,rand()%ahold+1); X NSUB_GAL(1); X } X } X if(which==ATKR) akcrew += P_NCREW; X else dkcrew += P_NCREW; X if (P_NARMY!=MAXARM) { X armynum = P_NARMY; X k = P_ASOLD*(shipsize+1)/(ghold+shipsize+1); X if(P_ATYPE<MINLEADER) { X if(which==ATKR) akcrew += k; X else dkcrew += k; X P_ASOLD -= k; X } else if(rand()%100<k*100/P_ASOLD){ X if(which==ATKR) akcrew += P_ASOLD; X else dkcrew += P_ASOLD; X P_ASOLD = 0; X P_NARMY = MAXARM; X } X } X } else if (rand()%3==0||Ploss>90) { X /* ship destroyed */ X k = (shipsize+1)*SHIPCREW; X if(which==ATKR) akcrew += k; X else dkcrew += k; X NSUB_GAL(1); X ghold-=(shipsize+1); X thold-=(shipsize+1); X /* kill all soldiers onboard */ X if (P_NARMY!=MAXARM) { X armynum = P_NARMY; X k = P_ASOLD*(shipsize+1)/(ghold+shipsize+1); X if(P_ATYPE<MINLEADER) { X if(which==ATKR) akcrew += k; X else dkcrew += k; X P_ASOLD -= k; X } else if(rand()%100<k*100/P_ASOLD){ X if(which==ATKR) akcrew += P_ASOLD; X else dkcrew += P_ASOLD; X P_ASOLD = 0; X P_NARMY = MAXARM; X } X } X if(which==ATKR) agsunk++; X else dgsunk++; X } else { X /* damage a ship */ X k = (shipsize+1)*Ploss*P_NCREW/100; X if(which==ATKR) akcrew += k; X else dkcrew += k; X P_NCREW -= k/thold; X /* damage any soldiers onboard */ X if (P_NARMY!=MAXARM) { X armynum = P_NARMY; X k = P_ASOLD*(shipsize+1)*Ploss/(ghold*100); X if(P_ATYPE<MINLEADER) { X P_ASOLD -= k; X if(which==ATKR) akcrew += k; X else dkcrew += k; X } else if(rand()%100<k*100/P_ASOLD){ X if(which==ATKR) akcrew += P_ASOLD; X else dkcrew += P_ASOLD; X P_ASOLD = 0; X P_NARMY = MAXARM; X } X } X } X } X /* check merchants */ X for(i=0;i<P_NMER(shipsize);i++) X if (rand()%100<Ploss) { X if(rand()%100<cptpct) { X /* capture a ship */ X if(which==ATKR){ X if (dhold) { X amcapt++; X capture(QMER,DFND,shipsize,rand()%dhold+1); X NSUB_MER(1); X } X } else if(which==DFND) { X if (ahold) { X dmcapt++; X capture(QMER,ATKR,shipsize,rand()%ahold+1); X NSUB_MER(1); X } X } X if(which==ATKR) akcrew += P_NCREW; X else dkcrew += P_NCREW; X } else if (rand()%3==0 || Ploss>90) { X /* ship destroyed */ X k = (shipsize+1)*P_NCREW; X if(which==ATKR) akcrew += k; X else dkcrew += k; X P_NCREW -= k/thold; X k = P_NCREW*thold; X NSUB_MER(1); X if((thold-=(shipsize+1))!=0) P_NCREW = k / thold; X else P_NCREW = 0; X /* kill all people onboard */ X k = (shipsize+1)*P_NPEOP; X if(which==ATKR) akcrew += k; X else dkcrew += k; X P_NPEOP -= k/(thold+shipsize+1); X k = P_NPEOP*(thold+shipsize+1); X if (thold>0) P_NPEOP = k / thold; X else P_NPEOP=0; X if(which==ATKR) amsunk++; X else dmsunk++; X } else { X /* damage a ship */ X k = (shipsize+1)*Ploss*P_NCREW/100; X if(which==ATKR) akcrew += k; X else dkcrew += k; X P_NCREW -= k/thold; X /* damage any people onboard */ X k = (shipsize+1)*Ploss*P_NPEOP/100; X if(which==ATKR) akcrew += k; X else dkcrew += k; X P_NPEOP -= k/thold; X } X } X } X } X#ifdef HIDELOC X fprintf(fnews,"4.\tNaval Battle occurs"); X#else X fprintf(fnews,"4.\t%d,%d: Naval Battle",xspot,yspot); X#endif X for(j=0;j<MGKNUM;j++) if(owner[j]!=(-1)){ X k=0; X for(i=0;i<j;i++) if(owner[j]==owner[i]) k=1; X if(k==0) { X if(side[i]==DFND) X fprintf(fnews,", attacker %s",ntn[owner[j]].name); X else if(side[i]==ATKR) X fprintf(fnews,", defender %s",ntn[owner[j]].name); X } X } X fprintf(fnews,"\n"); X X /*mail results; who is in the battle*/ X for(j=0;j<MGKNUM;j++) if(owner[j]!=(-1)){ X done=FALSE; X X /*first time your nation appears done=FALSE*/ X for(i=0;i<j;i++) if(owner[j]==owner[i]) done=TRUE; X X if((done==FALSE)&&(ispc(ntn[owner[j]].active))) { X mailopen( owner[j] ); X X fprintf(fm,"NAVAL BATTLE in sector %d %d\n",xspot,yspot); X fprintf(fm,"Battle occured during %s of Year %d\n", X PSEASON(TURN),YEAR(TURN)); X X if(side[j]==ATKR) X fprintf(fm,"You are on the Attacking Side\n"); X else if(side[j]==DFND) X fprintf(fm,"You are on the Defending Side\n"); X else fprintf(fm,"You are on the Neutral Side\n"); X X /*detail all participants in battle*/ X for(k=0;k<MGKNUM;k++) if(owner[k]!=(-1)){ X if(side[k]==DFND) X fprintf(fm," %s is defender with navy ",ntn[owner[k]].name); X else if(side[k]==ATKR) X fprintf(fm," %s is attacker with navy ",ntn[owner[k]].name); X else X fprintf(fm," %s is neutral with navy ",ntn[owner[k]].name); X fprintf(fm,"%d (%d warships %d galleys %d merchants)", X unit[k],wnum[k],gnum[k],mnum[k]); X putc('\n',fm); X X } X X fprintf(fm,"attacker strength (%d men) -> percent loss %d%%\n",acrew,PAloss); X fprintf(fm,"defender strength (%d men) -> percent loss %d%%\n",dcrew,PDloss); X fprintf(fm,"Odds are %d to 100; RANDOM ROLL is %d\n",odds,roll); X fprintf(fm,"RESULT: Attackers lose %d men Defenders lose %d men\n",akcrew,dkcrew); X /* display any other results */ X show_ships("Attacking","sunk",awsunk,agsunk,amsunk); X show_ships("Defending","sunk",dwsunk,dgsunk,dmsunk); X show_ships("Attacking","captured",awcapt,agcapt,amcapt); X show_ships("Defending","captured",dwcapt,dgcapt,dmcapt); X mailclose(); X } X } X curntn= saventn; X country= savecntry; X printf("Out Naval Combat....\n"); X} X X/* routine to distribute a captured ship */ Xvoid Xcapture(type,to,shipsize,holdcount) X int type,to,shipsize,holdcount; X{ X int i,nvynum; X struct s_nation *saventn=curntn; X#ifdef DEBUG X printf("capture: hdcnt==%d typ==%d spsz==%d to==%d\n",holdcount, X type,shipsize,to); X#endif DEBUG X for (i=0;holdcount && i<MGKNUM;i++) { X if (owner[i]!=(-1) && side[i]==to) { X curntn= &ntn[owner[i]]; X holdcount -= fltwhold(unit[i]); X } X if(holdcount<=0) { X holdcount=0; X i--; X } X } X#ifdef DEBUG X printf("capture 2: holdcount==%d i==%d\n",holdcount,i); X#endif DEBUG X if (i==MGKNUM) { X curntn = saventn; X return; X } X nvynum = unit[i]; X#ifdef DEBUG X printf("Should have succesful capture of %d\n",type); X#endif DEBUG X switch(type) { X case QWAR: X (void) NADD_WAR(1); X break; X case QGAL: X (void) NADD_GAL(1); X break; X case QMER: X (void) NADD_MER(1); X break; X default: X fprintf(stderr,"unknown type in function capture"); X break; X } X curntn = saventn; X} X X/* routine to display combat results */ Xvoid Xshow_ships(who,what,war,gal,mer) X char *who,*what; X int war, gal, mer; X{ X if (war+gal+mer>0) { X fprintf(fm,"%s ships %s: ",who,what); X if (war) fprintf(fm,"%d Warships ",war); X if (gal) fprintf(fm,"%d Galleys ",gal); X if (mer) fprintf(fm,"%d Merchants",mer); X putc('\n',fm); X } X} END_OF_FILE if test 39440 -ne `wc -c <'combat.c'`; then echo shar: \"'combat.c'\" unpacked with wrong size! fi # end of 'combat.c' fi if test -f 'io.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'io.c'\" else echo shar: Extracting \"'io.c'\" \(12125 characters\) sed "s/^X//" >'io.c' <<'END_OF_FILE' X/*io.c*/ X/*Print and io subroutines for game*/ X X/*conquer : Copyright (c) 1988 by Ed Barlow. X * I spent a long time writing this code & I hope that you respect this. X * I give permission to alter the code, but not to copy or redistribute X * it without my explicit permission. If you alter the code, X * please document changes and send me a copy, so all can have it. X * This code, to the best of my knowledge works well, but it is my first X * 'C' program and should be treated as such. I disclaim any X * responsibility for the codes actions (use at your own risk). I guess X * I am saying "Happy gaming", and am trying not to get sued in the process. X * Ed X */ X X#include "header.h" X#include "data.h" X#include "patchlevel.h" X#include <ctype.h> X Xextern FILE *fexe; X/*offset of upper left hand corner*/ Xextern short xoffset, yoffset; X/*current cursor postion (relative to 00 in upper corner)*/ X/* position is 2*x,y*/ Xextern short xcurs,ycurs; Xextern short redraw; /*redraw map in this turn if redraw is a 1*/ Xextern short hilmode,dismode; /*display state*/ Xextern short country; /* nation id of owner*/ X X/************************************************************************/ X/* GETSPACE() - malloc all space needed */ X/************************************************************************/ Xvoid Xgetspace() X{ X sct = (struct s_sector **) m2alloc(MAPX,MAPY,sizeof(struct s_sector)); X occ = (char **) m2alloc(MAPX,MAPY,sizeof(char)); X movecost = (short **) m2alloc(MAPX,MAPY,sizeof(short)); X} X X#ifdef ADMIN X/************************************************************************/ X/* PRINTELE() - print a sector.altitude map */ X/************************************************************************/ Xvoid Xprintele() X{ X register int X, Y; X printf("doing print of altitude\n"); X for(Y=0;Y<MAPY;Y++) { X for(X=0;X<MAPX;X++) putc(sct[X][Y].altitude,stdout); X putc('\n',stdout); X } X} X#endif ADMIN X#ifdef ADMIN X/************************************************************************/ X/* PR_NTNS() - print nation marks */ X/************************************************************************/ Xvoid Xpr_ntns() X{ X register int X, Y; X printf("doing print of nations\n"); X for(Y=0;Y<MAPY;Y++) { X for(X=0;X<MAPX;X++) { X if(sct[X][Y].owner==0) X putc(sct[X][Y].altitude,stderr); X else putc(ntn[sct[X][Y].owner].mark,stderr); X } X putc('\n',stderr); X } X} X#endif ADMIN X X/************************************************************************/ X/* WRITEDATA() - write data to datafile */ X/* trashes/creates datafile in the process */ X/************************************************************************/ Xvoid Xwritedata() X{ X long bytes; X int fd; X X printf("\ndoing write of data\n"); X if((fd = creat(datafile,0666))==-1) { X printf("cant open data. check permissions\n"); X abrt(); X } X X/* write world structure */ X if((bytes=write(fd,&world,sizeof(struct s_world)))!=sizeof(struct s_world)) X { X printf("error writing world data\n"); X printf("wrong data format (%ld vs. %d)\n",bytes,sizeof(struct s_world) ); X abrt(); X } X X if((bytes=write(fd,*sct,MAPX*MAPY*sizeof(struct s_sector))) == -1) X { X printf("Wrong number of bytes (%ld) written for sct (should be %d)\n",bytes,MAPX*MAPY*sizeof(struct s_sector)); X abrt(); X }; X printf("writing %ld bytes of sector data\n",bytes); X if((bytes=write(fd,ntn,NTOTAL*sizeof(struct s_nation))) == -1) X { X printf("Wrong number of bytes (%ld) written for ntn (should be %d)\n",bytes,NTOTAL*sizeof(struct s_nation)); X abrt(); X } X printf("writing %ld bytes of nation data\n",bytes); X close(fd); X} X X/************************************************************************/ X/* READDATA() - read data & malloc space */ X/************************************************************************/ Xvoid Xreaddata() X{ X int fd; X int n_read; X X /*read in existing nation army and navy data*/ X /*check if file openable*/ X printf("reading data file\n"); X if( (fd = open(datafile,0)) < 0 ) { X fprintf( stderr, "can not open %s \n", datafile ); X fprintf( stderr, "for help with conquer, type conquer -h\n"); X exit(FAIL); X } X X/* read world structure */ X if((n_read=read(fd,&world,sizeof(struct s_world)))!=sizeof(struct s_world)) X { X printf("error reading world data\n"); X printf("wrong data format (%d vs. %d)\n",n_read, sizeof(struct s_world) ); X abrt(); X } X#ifdef DEBUG X printf("reading %d bytes of world data\n",sizeof(struct s_world)); X#endif DEBUG X X getspace(); X X if((n_read=read(fd,*sct,MAPX*MAPY*sizeof(struct s_sector)))==0) X printf("EOF\n"); X else if(n_read==-1) printf("error reading sector data (sct)\n"); X if(n_read != (MAPX*MAPY*sizeof(struct s_sector))) { X printf("error reading sector data (sct)\n"); X printf( "wrong data format (%d vs. %d)\n",n_read, MAPX*MAPY*sizeof(struct s_sector) ); X abrt(); X } X#ifdef DEBUG X printf("reading %d bytes of sector data\n",n_read); X#endif DEBUG X if((n_read=read(fd,ntn,NTOTAL*sizeof(struct s_nation))) == -1) X printf("error reading s_nation data (ntn)\n"); X else if(n_read!= NTOTAL*sizeof(struct s_nation)) { X printf("error reading s_nation data (ntn)\n"); X printf( "wrong data format (%d vs. %d)\n",n_read, NTOTAL*sizeof(struct s_nation) ); X abrt(); X } X#ifdef DEBUG X printf("reading %d bytes of nation data\n",n_read); X#endif DEBUG X close(fd); X} /* readdata() */ X X#ifdef ADMIN X/************************************************************************/ X/* PRINTVEG() - print a vegetation map subroutine */ X/************************************************************************/ Xvoid Xprintveg() X{ X register int X, Y; X printf("doing print of vegetation\n"); X for(Y=0;Y<MAPY;Y++) { X for(X=0;X<MAPX;X++) putc(sct[X][Y].vegetation,stderr); X putc('\n',stderr); X } X} X#endif ADMIN X#ifdef CONQUER X/************************************************************************/ X/* OFFMAP() deal if cursor is off the map */ X/************************************************************************/ Xvoid Xoffmap() X{ X /*set offset offsets can not be < 0*/ X if(xcurs<1){ X if(XREAL<=0) { X xoffset=0; X xcurs=0; X } X else { X redraw=TRUE; X xoffset-=15; X xcurs+=15; X } X } X else if(xcurs >= (COLS-23)/2){ X if(XREAL<MAPX) { X redraw=TRUE; X xoffset+=15; X xcurs-=15; X } X } X if(XREAL>=MAPX) xcurs=MAPX-1-xoffset; X if(xoffset<0) { X xcurs += xoffset; X xoffset=0; X } X if(xcurs<0) { X xoffset += xcurs; X xcurs=0; X } X else if(xcurs >= (COLS-23)/2) { X redraw=TRUE; X xoffset+=15; X xcurs-=15; X } X X if(ycurs<1){ X if(YREAL<=0) { X yoffset=0; X ycurs=0; X } X else { X redraw=TRUE; X ycurs+=15; X yoffset-=15; X } X } X else if(ycurs >= SCREEN_Y_SIZE-1){ X if(YREAL<MAPY) { X redraw=TRUE; X yoffset+=15; X ycurs-=15; X } X } X if(YREAL>=MAPY) ycurs=MAPY-1-yoffset; X if(yoffset<0) { X ycurs += yoffset; X yoffset=0; X } X if(ycurs<0) { X yoffset += ycurs; X ycurs=0; X } X else if(ycurs >= SCREEN_Y_SIZE-1) { X redraw=TRUE; X yoffset+=15; X ycurs-=15; X } X whatcansee(); X} X#endif CONQUER X#ifdef CONQUER X/************************************************************************/ X/* PRINTSCORE() - like it says */ X/************************************************************************/ Xvoid Xprintscore() X{ X int i; X int nationid; /*current nation id */ X X printf("Conquer %s.%d: %s of Year %d, Turn %d\n",VERSION,PATCHLEVEL, X PSEASON(TURN),YEAR(TURN), TURN); X printf("id name race class align score talons military civilians sect\n"); X for (nationid=1; nationid<NTOTAL; nationid++) { X if(!isntn(ntn[nationid].active)) continue; X printf("%2d ",nationid); X printf("%9s ",ntn[nationid].name); X for(i=1;i<8;i++) X if(ntn[nationid].race==*(races+i)[0]) X printf("%6s ",*(races+i)); X printf("%8s ",*(Class+ntn[nationid].class)); X printf(" %7s ",allignment[npctype(ntn[nationid].active)]); X printf("%6ld %8ld %8ld %8ld %4d\n", X ntn[nationid].score ,ntn[nationid].tgold X ,ntn[nationid].tmil ,ntn[nationid].tciv X ,ntn[nationid].tsctrs ); X } X} X#endif CONQUER X X/************************************************************************/ X/* FLEE() - civilains in x,y flee from somebody */ X/* slaver means 25% of populace stays */ X/* isupd is TRUE if it is update */ X/************************************************************************/ Xvoid Xflee(x,y,isupd,slaver) Xint x,y,isupd,slaver; X{ X int count=0; /*count is number of acceptable sectors to go to */ X int svcountry=country; X int slaves=0; X int i,j; X country=sct[x][y].owner; X X if(slaver==TRUE){ X slaves= sct[x][y].people/4; X sct[x][y].people-=slaves; X } X X /*flee*/ X sct[x][y].people*=6; X sct[x][y].people/=10; X /*check if next to anybody of the sectors owners race*/ X for(i=x-2;i<=x+2;i++) for(j=y-2;j<=y+2;j++) X if(ONMAP(i,j) X &&(ntn[sct[i][j].owner].race==ntn[sct[x][y].owner].race)) X count++; X X if(count>0) { X#ifdef CONQUER X if(isupd==0) { X if(slaver==TRUE){ X mvprintw(LINES-2,20,"CIVILIANS ABANDON SECTOR (%d slaves)",slaves); X }else{ X mvaddstr(LINES-2,20,"CIVILIANS ABANDON SECTOR"); X } X } X#endif CONQUER X for(i=x-2;i<=x+2;i++) for(j=y-2;j<=y+2;j++) X if(ONMAP(i,j) X &&(ntn[sct[i][j].owner].race==ntn[sct[x][y].owner].race)) { X sct[i][j].people += sct[x][y].people / count; X if(isupd==0) SADJCIV2; X } X } else { X sct[x][y].people /= 2; X for(i=x-4;i<=x+4;i++) for(j=y-4;j<=y+4;j++) X if(ONMAP(i,j) X &&(ntn[sct[i][j].owner].race==ntn[sct[x][y].owner].race)) X count++; X if(count>0) { X#ifdef CONQUER X if(isupd==0) mvaddstr(LINES-2,20,"PEOPLE FLEE SECTOR AND HALF DIE"); X#endif CONQUER X for(i=x-4;i<=x+4;i++) for(j=y-4;j<=y+4;j++) X if(ONMAP(i,j) X &&(ntn[sct[i][j].owner].race==ntn[sct[x][y].owner].race)) { X sct[i][j].people += sct[x][y].people / count; X if(isupd==0) SADJCIV2; X } X } X#ifdef CONQUER X else if(isupd==0) mvaddstr(LINES-2,20,"PEOPLE IN SECTOR DIE"); X#endif CONQUER X } X X sct[x][y].people = slaves; X if(isupd==0) SADJCIV; X sct[x][y].fortress=0; X /*SINFORT;*/ X if(tofood( &sct[XREAL][YREAL],sct[XREAL][YREAL].owner)!=0) { X DEVASTATE(x,y); X if(isupd==0) SADJDES2; X } X country=svcountry; X} X#ifdef ADMIN X/************************************************************************/ X/* READMAP() - read a map in from map files */ X/* returns TRUE for success, FALSE for fail */ X/************************************************************************/ Xint Xreadmap() X{ X FILE *mapfile; X char line[128]; X register int x,y; X X /* read in ele.map */ X strcpy(line,scenario); X strcat(line,".ele"); X if ((mapfile=fopen(line,"r"))==NULL) { X fprintf(stderr,"error on read of %s file\n",line); X return(TRUE); X } else fprintf(stderr,"reading elevation map file from %s\n",line ); X X y=0; X while( TRUE ) { X if(fgets( line, 128, mapfile )==NULL) break; X for(x=0;x<MAPX;x++) sct[x][y].altitude = line[x]; X y++; X if(y>=MAPY) break; X } X fprintf(stderr,"done reading %d lines of %d characters\n",y,strlen(line)); X X /* read in veg.map */ X strcpy(line,scenario); X strcat(line,".veg"); X if ((mapfile=fopen(line,"r"))==NULL) { X fprintf(stderr,"error on read of %s file\n",line); X return(TRUE); X } else fprintf(stderr,"reading vegetation map file from %s\n",line ); X y=0; X while( TRUE ) { X if(fgets( line, 128, mapfile )==NULL) break; X for(x=0;x<MAPX;x++) sct[x][y].vegetation = line[x]; X y++; X if(y>=MAPY) break; X } X fprintf(stderr,"done reading %d lines of %d characters\n",y,strlen(line)); X X return(TRUE); X} X#endif ADMIN X X/*********************************************************************/ X/* M2ALLOC() - two dimensional array allocator (because C is stupid) */ X/*********************************************************************/ Xchar **m2alloc(nrows, ncols, entrysize) Xint nrows; /* row dimension */ Xint ncols; /* column dimension */ Xint entrysize; /* # bytes in items to be stored */ X{ X char **baseaddr; X int j; X entrysize *= ncols; X baseaddr = (char **) X malloc( (unsigned) (nrows*(sizeof(char *)+entrysize))); X X if( baseaddr == (char **) NULL ) { X printf("OOPS - cant allocate %d by %d blocks of %d bytes\n",nrows,ncols,entrysize); X abrt(); X } X if(nrows>0){ X *baseaddr = (char *) (baseaddr + nrows); X for(j=1; j<nrows; j++) X baseaddr[j] = baseaddr[j-1] + entrysize; X } X return(baseaddr); X} END_OF_FILE if test 12125 -ne `wc -c <'io.c'`; then echo shar: \"'io.c'\" unpacked with wrong size! fi # end of 'io.c' fi if test -f 'run' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'run'\" else echo shar: Extracting \"'run'\" \(1789 characters\) sed "s/^X//" >'run' <<'END_OF_FILE' X#below is a shell script that runs updates 3 times a day every day but sunday X# X#PLEASE CHANGE TIME* VARIABLES TO APPROPRIATE TIMES, and CHANGE PATH VARIABLES X# X#KEEP THE TIMES IN CHRONOLOGICAL ORDER AND THE TIME1H and TIME2H values X#represent the hours of TIME1 and TIME2 X######################################################### X# use the command "at -l" to get a list of existing at jobs X# use the command "at -r <jobname>" to remove existing at jobs X######################################################### XTIME1=1000 XTIME1H=10 XTIME2=1700 XTIME2H=17 XTIME3=2300 X#Below is the full command to update a game of conquer XPATHTOCONQ="/d7/c7913/smile/oldgame/conquer -x -d/d7/c7913/smile/oldgame/temp" X#Path to this file XPATHTORUN=/d7/c7913/smile/oldgame/run X#LOG is full path name of log file XLOG=/d7/c7913/smile/oldgame/runlog X X/bin/date >> $LOG X$PATHTOCONQ >> $LOG X XDAY=`/bin/date | /usr/bin/awk '{ print $1 }'` Xecho "day is $DAY" >> $LOG XHOUR=`/bin/date|/usr/bin/awk '{ print $4 }'|/usr/bin/awk -F: '{ print $1 }'` Xecho "hour is $HOUR" >> $LOG X#BELOW IS AN EXAMPLE OF A BSD SCRIPT X#switch $DAY X# case Sat: X# set nextday=mon X# breaksw X# default: X# set nextday = X# breaksw X#endsw Xcase $DAY in X Sat) X nextday=mon X ;; X *) X nextday="" X ;; Xesac X#switch $HOUR X# case 00: X# set nexthour=$TIME1 X# breaksw X# default: X# set nexthour=$TIME2 X# breaksw X#endsw Xcase $HOUR in X$TIME1H) X nexthour=$TIME2 X echo "nexthour is $nexthour" >> $LOG X ;; X$TIME2H) X nexthour=$TIME3 X echo "nexthour is $nexthour" >> $LOG X ;; X*) X nexthour=$TIME1 X echo "nexthour is $nexthour" >> $LOG X ;; Xesac X#below for bsd (i think) X#/usr/bin/at $nexthour $nextday $PATHTORUN X#below for SYSV Xecho "/usr/bin/at $nexthour $nextday < $PATHTORUN" >> $LOG Xecho "XXX" >> $LOG X/usr/bin/at $nexthour $nextday < $PATHTORUN END_OF_FILE if test 1789 -ne `wc -c <'run'`; then echo shar: \"'run'\" unpacked with wrong size! fi chmod +x 'run' # end of 'run' fi echo shar: End of archive 4 \(of 14\). cp /dev/null ark4isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 14 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0