X-Git-Url: https://jxself.org/git/?p=open-adventure.git;a=blobdiff_plain;f=main.c;h=5a3f2002683de89e3c78aad525adb756b0a447a0;hp=5288e43b24f2aab08821096da64baff39afe2ff8;hb=c5d2d9ddb54647bdb3ca03a0163a5da103dc8946;hpb=c366ddb7334cf85dba1f0dc75a68a8a094960aa3 diff --git a/main.c b/main.c index 5288e43..5a3f200 100644 --- a/main.c +++ b/main.c @@ -3,15 +3,15 @@ * * The author - Don Woods - apologises for the style of the code; it * is a result of running the original Fortran IV source through a - * home-brew Fortran-to-C converter.) + * home-brew Fortran-to-C converter. * * Now that the code has been restructured into something much closer * to idiomatic C, the following is more appropriate: * - * ESR apologizes for the remaing gotos (now confined to two functions - * in this file - there used to be hundreds of them, *everywhere*), - * and the offensive globals. Applying the Structured Program Theorem - * can be hard. + * ESR apologizes for the remaing gotos (now confined to one function + * in this file - there used to be over 350 of them, *everywhere*), + * and for the offensive globals. Applying the Structured Program + * Theorem can be hard. */ #include #include @@ -122,20 +122,9 @@ int main(int argc, char *argv[]) set_seed(seedval); /* Initialize game variables */ - if (!game.setup) - initialise(); - - /* Unlike earlier versions, adventure is no longer restartable. (This - * lets us get away with modifying things such as OBJSND(BIRD) without - * having to be able to undo the changes later.) If a "used" copy is - * rerun, we come here and tell the player to run a fresh copy. */ - if (game.setup <= 0) { - RSPEAK(201); - exit(0); - } + initialise(); /* Start-up, dwarf stuff */ - game.setup= -1; game.zzword=RNDVOC(3,0); game.novice=YES(stdin, 65,1,0); game.newloc=1; @@ -146,7 +135,7 @@ int main(int argc, char *argv[]) if (logfp) fprintf(logfp, "seed %ld\n", seedval); - /* interpret commands ubtil EOF or interrupt */ + /* interpret commands until EOF or interrupt */ for (;;) { if (!do_command(stdin)) break; @@ -267,6 +256,65 @@ static void checkhints(FILE *cmdin) } } +bool spotted_by_pirate(int i) +{ + if (i != PIRATE) + return false; + + /* The pirate's spotted him. He leaves him alone once we've + * found chest. K counts if a treasure is here. If not, and + * tally=1 for an unseen chest, let the pirate be spotted. + * Note that game.place[CHEST]=0 might mean that he's thrown + * it to the troll, but in that case he's seen the chest + * (game.prop=0). */ + if (game.loc == game.chloc || game.prop[CHEST] >= 0) + return true; + int k=0; + for (int j=MINTRS; j<=MAXTRS; j++) { + /* Pirate won't take pyramid from plover room or dark + * room (too easy!). */ + if (j==PYRAM && (game.loc==PLAC[PYRAM] || game.loc==PLAC[EMRALD])) { + return true; + } + if (TOTING(j)) { + if (game.place[CHEST] == 0) { + /* Install chest only once, to insure it is + * the last treasure in the list. */ + MOVE(CHEST,game.chloc); + MOVE(MESSAG,game.chloc2); + } + RSPEAK(128); + for (int j=MINTRS; j<=MAXTRS; j++) { + if (!(j == PYRAM && (game.loc == PLAC[PYRAM] || game.loc == PLAC[EMRALD]))) { + if (AT(j) && game.fixed[j] == 0) + CARRY(j,game.loc); + if (TOTING(j)) + DROP(j,game.chloc); + } + } + game.dloc[PIRATE]=game.chloc; + game.odloc[PIRATE]=game.chloc; + game.dseen[PIRATE]=false; + return true; + } + if (HERE(j)) + k=1; + } + /* Force chest placement before player finds last treasure */ + if (game.tally == 1 && k == 0 && game.place[CHEST] == 0 && HERE(LAMP) && game.prop[LAMP] == 1) { + RSPEAK(186); + MOVE(CHEST,game.chloc); + MOVE(MESSAG,game.chloc2); + game.dloc[PIRATE]=game.chloc; + game.odloc[PIRATE]=game.chloc; + game.dseen[PIRATE]=false; + return true; + } + if (game.odloc[PIRATE] != game.dloc[PIRATE] && PCT(20)) + RSPEAK(127); + return true; +} + static bool dwarfmove(void) /* Dwarves move. Return true if player survives, false if he dies. */ { @@ -328,7 +376,6 @@ static bool dwarfmove(void) attack=0; stick=0; for (int i=1; i<=NDWARVES; i++) { - int k; if (game.dloc[i] == 0) continue; /* Fill TK array with all the places this dwarf might go. */ @@ -362,63 +409,8 @@ static bool dwarfmove(void) game.dseen[i]=(game.dseen[i] && INDEEP(game.loc)) || (game.dloc[i] == game.loc || game.odloc[i] == game.loc); if (!game.dseen[i]) continue; game.dloc[i]=game.loc; - if (i == PIRATE) { - /* The pirate's spotted him. He leaves him alone once we've - * found chest. K counts if a treasure is here. If not, and - * tally=1 for an unseen chest, let the pirate be spotted. - * Note that game.place(CHEST)=0 might mean that he's thrown - * it to the troll, but in that case he's seen the chest - * (game.prop=0). */ - if (game.loc == game.chloc || game.prop[CHEST] >= 0) - continue; - k=0; - for (int j=MINTRS; j<=MAXTRS; j++) { - /* Pirate won't take pyramid from plover room or dark - * room (too easy!). */ - if (j == PYRAM && (game.loc == PLAC[PYRAM] || game.loc == PLAC[EMRALD])) { - if (HERE(j)) - k=1; - continue; - } - if (TOTING(j)) { - if (game.place[CHEST] == 0) { - /* Install chest only once, to insure it is - * the last treasure in the list. */ - MOVE(CHEST,game.chloc); - MOVE(MESSAG,game.chloc2); - } - RSPEAK(128); - for (int j=MINTRS; j<=MAXTRS; j++) { - if (!(j == PYRAM && (game.loc == PLAC[PYRAM] || game.loc == PLAC[EMRALD]))) { - if (AT(j) && game.fixed[j] == 0) - CARRY(j,game.loc); - if (TOTING(j)) - DROP(j,game.chloc); - } - } - game.dloc[PIRATE]=game.chloc; - game.odloc[PIRATE]=game.chloc; - game.dseen[PIRATE]=false; - goto jumpout; - } - if (HERE(j)) - k=1; - } - /* Force chest placement before player finds last treasure */ - if (game.tally == 1 && k == 0 && game.place[CHEST] == 0 && HERE(LAMP) && game.prop[LAMP] == 1) { - RSPEAK(186); - MOVE(CHEST,game.chloc); - MOVE(MESSAG,game.chloc2); - game.dloc[PIRATE]=game.chloc; - game.odloc[PIRATE]=game.chloc; - game.dseen[PIRATE]=false; - continue; - } - if (game.odloc[PIRATE] != game.dloc[PIRATE] && PCT(20)) - RSPEAK(127); + if (spotted_by_pirate(i)) continue; - } - /* This threatening little dwarf is in the room with him! */ ++game.dtotal; if (game.odloc[i] == game.dloc[i]) { @@ -428,7 +420,6 @@ static bool dwarfmove(void) if (randrange(1000) < 95*(game.dflag-2)) ++stick; } - jumpout:; } /* Now we know what's happening. Let's tell the poor sucker about it. @@ -606,96 +597,104 @@ static bool playermove(FILE *cmdin, token_t verb, int motion) } LL=LL/1000; - L12: - for (;;) { - game.newloc=LL/1000; - motion=MOD(game.newloc,100); - if (game.newloc <= 300) { - if (game.newloc <= 100) { - if (game.newloc == 0 || PCT(game.newloc)) - break; + do { + /* + * (ESR) This special-travel loop may have to be repeated if it includes + * the plover passage. Same deal for any future cases wgerw we beed to + * block travel and then redo it once the blocking condition has been + * removed. + */ + for (;;) { + game.newloc=LL/1000; + motion=MOD(game.newloc,100); + if (game.newloc <= 300) { + if (game.newloc <= 100) { + if (game.newloc == 0 || PCT(game.newloc)) + break; + /* else fall through */ + } if (TOTING(motion) || (game.newloc > 200 && AT(motion))) + break; /* else fall through */ - } if (TOTING(motion) || (game.newloc > 200 && AT(motion))) - break; - /* else fall through */ - } - else if (game.prop[motion] != game.newloc/100-3) - break; - do { - if (TRAVEL[KK] < 0)BUG(25); - ++KK; - game.newloc=labs(TRAVEL[KK])/1000; - } while - (game.newloc == LL); - LL=game.newloc; - } - - game.newloc=MOD(LL,1000); - if (game.newloc <= 300) - return true; - if (game.newloc <= 500) { - game.newloc=game.newloc-300; - switch (game.newloc) - { - case 1: - /* Travel 301. Plover-alcove passage. Can carry only - * emerald. Note: travel table must include "useless" - * entries going through passage, which can never be used for - * actual motion, but can be spotted by "go back". */ - game.newloc=99+100-game.loc; - if (game.holdng == 0 || (game.holdng == 1 && TOTING(EMRALD))) - return true; - game.newloc=game.loc; - RSPEAK(117); - return true; - case 2: - /* Travel 302. Plover transport. Drop the emerald (only use - * special travel if toting it), so he's forced to use the - * plover-passage to get it out. Having dropped it, go back and - * pretend he wasn't carrying it after all. */ - DROP(EMRALD,game.loc); + } + else if (game.prop[motion] != game.newloc/100-3) + break; do { if (TRAVEL[KK] < 0)BUG(25); ++KK; game.newloc=labs(TRAVEL[KK])/1000; } while (game.newloc == LL); - goto L12; - case 3: - /* Travel 303. Troll bridge. Must be done only as special - * motion so that dwarves won't wander across and encounter - * the bear. (They won't follow the player there because - * that region is forbidden to the pirate.) If - * game.prop(TROLL)=1, he's crossed since paying, so step out - * and block him. (standard travel entries check for - * game.prop(TROLL)=0.) Special stuff for bear. */ - if (game.prop[TROLL] == 1) { - PSPEAK(TROLL,1); - game.prop[TROLL]=0; - MOVE(TROLL2,0); - MOVE(TROLL2+NOBJECTS,0); - MOVE(TROLL,PLAC[TROLL]); - MOVE(TROLL+NOBJECTS,FIXD[TROLL]); - JUGGLE(CHASM); + LL=game.newloc; + } + + game.newloc=MOD(LL,1000); + if (game.newloc <= 300) + return true; + if (game.newloc <= 500) { + game.newloc=game.newloc-300; + switch (game.newloc) + { + case 1: + /* Travel 301. Plover-alcove passage. Can carry only + * emerald. Note: travel table must include "useless" + * entries going through passage, which can never be used for + * actual motion, but can be spotted by "go back". */ + game.newloc=99+100-game.loc; + if (game.holdng == 0 || (game.holdng == 1 && TOTING(EMRALD))) + return true; game.newloc=game.loc; + RSPEAK(117); return true; - } else { - game.newloc=PLAC[TROLL]+FIXD[TROLL]-game.loc; - if (game.prop[TROLL] == 0)game.prop[TROLL]=1; - if (!TOTING(BEAR)) return true; - RSPEAK(162); - game.prop[CHASM]=1; - game.prop[TROLL]=2; - DROP(BEAR,game.newloc); - game.fixed[BEAR]= -1; - game.prop[BEAR]=3; - game.oldlc2=game.newloc; - croak(cmdin); - return false; + case 2: + /* Travel 302. Plover transport. Drop the emerald (only use + * special travel if toting it), so he's forced to use the + * plover-passage to get it out. Having dropped it, go back and + * pretend he wasn't carrying it after all. */ + DROP(EMRALD,game.loc); + do { + if (TRAVEL[KK] < 0)BUG(25); + ++KK; + game.newloc=labs(TRAVEL[KK])/1000; + } while + (game.newloc == LL); + continue; /* back to top of do/while loop */ + case 3: + /* Travel 303. Troll bridge. Must be done only as special + * motion so that dwarves won't wander across and encounter + * the bear. (They won't follow the player there because + * that region is forbidden to the pirate.) If + * game.prop(TROLL)=1, he's crossed since paying, so step out + * and block him. (standard travel entries check for + * game.prop(TROLL)=0.) Special stuff for bear. */ + if (game.prop[TROLL] == 1) { + PSPEAK(TROLL,1); + game.prop[TROLL]=0; + MOVE(TROLL2,0); + MOVE(TROLL2+NOBJECTS,0); + MOVE(TROLL,PLAC[TROLL]); + MOVE(TROLL+NOBJECTS,FIXD[TROLL]); + JUGGLE(CHASM); + game.newloc=game.loc; + return true; + } else { + game.newloc=PLAC[TROLL]+FIXD[TROLL]-game.loc; + if (game.prop[TROLL] == 0)game.prop[TROLL]=1; + if (!TOTING(BEAR)) return true; + RSPEAK(162); + game.prop[CHASM]=1; + game.prop[TROLL]=2; + DROP(BEAR,game.newloc); + game.fixed[BEAR]= -1; + game.prop[BEAR]=3; + game.oldlc2=game.newloc; + croak(cmdin); + return false; + } } + BUG(20); } - BUG(20); - } + } while + (false); RSPEAK(game.newloc-500); game.newloc=game.loc; return true; @@ -902,7 +901,7 @@ static void listobjects(void) static bool do_command(FILE *cmdin) /* Get and execute a command */ { - long KQ, VERB, KK, V1, V2; + long KQ, VERB, V1, V2; long i, k, KMOD; static long igo = 0; static long obj = 0; @@ -1014,15 +1013,12 @@ static bool do_command(FILE *cmdin) part=transitive; goto Laction; } - if (closecheck()) + if (closecheck()) { if (game.closed) return true; - else - goto L19999; - - lampcheck(); + } else + lampcheck(); - L19999: k=43; if (LIQLOC(game.loc) == WATER)k=70; V1=VOCAB(WD1,-1);