|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T c
Length: 23773 (0x5cdd)
Types: TextFile
Names: »cvmain.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/General/Crystal/cvmain.c«
/* cvmain.c
************************************************************************/
#define SHORT 50
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include "cvobj.h"
#include "cvlocs.h"
#include "cvocab.h"
#include "cvmsg.h"
#include "random.h"
#include "cvorcs.h"
#include "cvmisc.h"
#include "cvcode.h"
extern char etext;
extern char edata;
extern char end;
extern char _etext;
extern char _edata;
extern char _end;
extern char *rmsg[] ;
extern int actspk[] ;
extern struct cmsg ctext[] ;
extern struct cvocab vtab [] ;
extern int maxloc ;
extern void exit();
extern void carry();
extern void move();
extern void move2();
extern void destry();
extern void getin();
extern void juggle();
extern void juggl2();
extern void checkobj();
extern void checkloc();
extern void fixrmsg();
extern void motd();
extern void rspeak();
extern void pspeak();
extern void mspeak();
extern void putcode();
extern int yes();
extern struct cvloc *moveme();
int saved = 0; /* this defines the un-initialized state */
char *word1, *word2;
char *vword, *oword;
struct cvobj *lastobj ;
struct cvloc *loc = NULL;
struct cvloc *newloc, *oldloc, *knfloc, *oldlc2;
int dflag = 0,
demo = 0,
score = 0,
mxscore = 0,
limit = 0, /* how long his lamp will last on current power */
setup = 0, /* state of setup */
tally = 0, /* count of treasures yet to see */
tally2 = 0, /* count of treasures you'll never see */
inorth = 0, /* # of times he said NORTH instead of N */
detail = 0, /* # of times we said "not allowed . . */
numdie = 0, /* # of times he died so far */
maxdie = 0, /* # of ways to resurrect him */
holding = 0, /* # objects he's carrying */
dkill = 0, /* # of dwarves killed */
turns = 0,
nxtchr = 0,
abbnum = 0, /* how often he gets long description */
clock1 = 0, /* time from last treasure to closing */
clock2 = 0, /* time from closing to closed */
/* LOGICALS FOLLOW */
bonus = FALSE, /* gets bonus for correct finish */
closing = FALSE, /* are we closing? */
panic = FALSE, /* has he panicked */
wzdark = FALSE,
closed = FALSE,
gaveup = FALSE,
scoring = FALSE,
mltcmd = FALSE,
blklin = FALSE,
samvrb = FALSE,
finish = FALSE,
lmwarn = FALSE;
\f
struct monster orcs[] = {
{0}, /* spider */ /* monsters first */
{0}, /* dragon */
{0}, /* king */
{0}, /* djinni */
{0}, /* kobold */
{0}, /* bugbear */
{0}, /* unicorn */
{0}, /* giant orc */
{0}, /* balrog */
{62,1}, /* dwarf in pool hall */ /* dwarves next */
{78,1}, /* dwarf in privy chamber */
{85,1}, /* dwarf at window in secret passage */
{100,1}, /* dwarf in the time maze */
{126,1}, /* dwarf in the harem */
{130,1}, /* dwarf at the shelf */
{87}, /* pirate at where he hides his chest */ /* then these */
{0}, /* *YOU* */
{-1}};
\f
void
locchg()
{
if (dodwarf()) die();
}
static void
dohint(hint) register struct hint *hint;
{
switch (hint-hints) {
case 4: if (O_GATE->prop != 0 || HERE(WALLET)) hint->lc = 0;
break;
case 5: if (DAM->prop != 0) hint->lc = 0;
break;
case 6: if (holding <= 1 || loc->atloc.link != NULL ||
oldlc2->atloc.link != NULL || oldloc->atloc.link != NULL)
hint->lc = 0;
break;
} /* end of switch for special tests */
if (hint->lc == 0) return;
hint->lc = 0;
if (!yes(hint->quest,0,54)) return;
printf("I am prepared to give you a hint, but it will cost you %d \
points.",hint->points);
hint->hinted = yes(175,hint->hmsg,54);
if (hint->hinted && limit>30) limit += 30*hint->points;
return;
}
void
bug(num) int num;
{ register long a;
(void) printf("\nFatal error number %d, see source code for\n\
interpretation.\n",num);
a = *((long *) 1);
exit(1);
}
void
mkill(monster,object) register struct monster *monster;
register struct cvobj *object;
{
object->prop = 0;
move(object,loc);
object->conn2.where = FIXED ;
monster->dseen = FALSE ;
monster->dloc = DEAD ;
}
void
showroom() {
putcode(( !(loc->abb++ % abbnum) || (loc->sdesc == NULL))
? loc->ldesc : loc->sdesc);
}
void
what(word) register int word;
{ if (word && PCT(60)) {rspeak(60); return;}
if (PCT(20)) {rspeak(61); return;}
rspeak(13); return;
}
static void
capchk(word) register char *word;
{
if (!strcmp(word,"indian")
|| !strcmp(word,"persian")
|| !strcmp(word,"coke")
|| !strcmp(word,"kobold")
|| !strcmp(word,"balrog")
|| !strcmp(word,"sears")
|| !strcmp(word,"rick") )
{ *word = toupper(*word);
}
}
\f
main(argc, argv)
int argc;
char * argv[];
{
{ register int r;
if (!saved && argc == 2) {
cvinit(argc,argv);
exit(0);
} else if (argc != 1 || saved != 1) {
exit(1);
}
}
/**********
* do initialization (some of it just in case):
* set all objects
* nowhere (both ways)
* to their initial properties
* not linked to any location
* set all locations
* to get long message next
* to have flags = C_FORCED if there's a forced motion
***********/
{ register struct cvobj *object;
for (object = &(cvobj[1]); object->desc != NULL ; object++ )
{ object->conn1.where = object->conn2.where = LOST ;
object->prop = object->iprop ;
object->conn1.link = object->conn2.link = NULL ;
object->conn1.who = object->conn2.who = object ;
object->conn1.where = object->conn2.where = LOST ;
}
lastobj = object - 1 ;
}
{ register struct cvloc *curloc;
for (curloc = &cvloc[1]; curloc->travel != NULL; curloc++ )
{ register struct cvtrav *curtrv;
curloc->abb = 0;
curloc->atloc.link = NULL ;
curtrv = curloc->travel ;
if (curtrv->word == 1)
curloc->flags = C_FORCED ;
}
}
/************
* set up the location arrays to that objects are at their indicated
* places. We use drop, which puts things on the head of the list, so
* we run this backwards. Things with two locations are dropped twice,
* and since these are normally best described last, we do them first.
************/
{ register struct cvobj *object;
#define ILOC(obj) (((obj)->iloc) ? (&(cvloc[(obj)->iloc])) : LOST )
for (object = lastobj; ONUM(object); object--)
{ if (object->iloc2 > 0 )
{ move2(object,&(cvloc[object->iloc2]));
move(object, ILOC(object) );
}
}
for (object = lastobj; ONUM(object); object-- )
{ if (object->iloc2 <= 0 )
{ move(object, ILOC(object) );
object->conn2.where = object->iloc2 ? FIXED : LOST;
}
}
}
/*************************************************************************
* clear the hint stuff. loc is how long he's been at a loc with the
* cond bit set. hinted is true if the hint has already been given.
*************************************************************************/
{ register struct hint *hint;
for (hint = hints; hint->turns >= 0; ++hint)
{ hint->lc = 0;
hint->hinted = FALSE ;
}
}
/*************************************************************************
* initialize the monsters.
* they are all known generically as dwarves because they all move like
* dwarves, though the adventurer never really knows this.
*
* dloc is current location
* oloc is old location
* dseen is a flag. If on, this dwarf has the adventurer in sight and
* is in hot pursuit.
* dflag indicates the level of activity:
* 0 no monster stuff yet (wait until pool hall is reached)
* 1 no monsters met yet (thus, no axe)
* 2 have axe, but no knives yet. most dwarves moving.
* 3 first knives thrown (first set always miss)
* 3+ dwarves are mad (and thus more accurate)
* some dwarves don't look much like dwarves
* 1 is grendl the spider
* 2 is the dragon
* 3 is the king
* 4 is the djinni
* 5 is the kobold
* 6 is the bugbear
* 7 is the unicorn
* 8 is the giant orc
* 9 is the balrog
* 10-15 are just dwarves
* 16 is the pirate.
* 17 is *you*
* no two of the initial locations for 10-16 are adjacent. The others
* only start as part of a pre-set encounter.
*************************************************************************/
dflag = 0;
{ register struct monster *cre;
for (cre = orcs ; (cre->iloc) != -1; cre++) {
cre->dloc = &cvloc[cre->iloc] ;
cre->dseen = FALSE ;
}
}
/*************************************************************************
* 'tally' keeps track of how many treasures are yet to be found so we
* know when to close the cave. 'tally2' keeps track of how many can
* never be found because the adventurer klutzed out (e.g. lost the
* scroll in the maze).
* ***** tally2 is not yet implemented *****
* the objects must be assigned numbers in the following order
* treasures
* end-game weapons
* artifacts in outer cave
* other objects
*************************************************************************/
tally = tally2 = 0 ;
{ register struct cvobj *object;
for (object = MINTRS ; object != ENDTRS ; ++object ) {
object->prop = -1 ;
++tally ;
}
}
BATTER->prop = -1 ;
oldlc2 =
knfloc = LOST ;
inorth = /* # of times he said NORTH instead of N */
detail = /* # of times we said "not allowed . . */
numdie = /* # of times he died so far */
holding = /* # objects he's carrying */
dkill = /* # of dwarves killed */
turns =
nxtchr = 0;
abbnum = 5 ; /* how often he gets long description */
clock1 = 30 ; /* time from last treasure to closing */
clock2 = 50 ; /* time from closing to closed */
bonus = /* gets bonus for correct finish */
closing = /* are we closing? */
panic = /* has he panicked */
closed =
gaveup =
scoring =
mltcmd =
samvrb =
finish =
lmwarn = FALSE ;
{ register int i;
for (i=0 ; i<=4; ++i)
if ( rmsg[2*i+81] != NULL ) maxdie = i+1 ;
}
saved = saved == 1 ? -1 : 2 ;
/*************************************************************************
* OK, we're close now. Get a couple more things set.
*************************************************************************/
demo = FALSE; /* everyone's a class 1 user here */
motd(FALSE); /* message of the day? */
hints[3].hinted = yes(65,1,0); /* instructions? */
newloc = &(cvloc[1]) ; /* start here */
oldloc = DEAD ; /* make lint happy */
wzdark = FALSE ;
setup = 3 ; /* in full swing */
limit = hints[3].hinted ? 1000 : 330 ;
juggl2(O_GATE);
juggle(BEAR);
juggle(HANG);
/*************************************************************************
* begin the real stuff
*************************************************************************/
dodwarf();
while (!finish) /* motion loop */
{ register struct cvobj *object;
int verb, oldvrb, obj ;
blklin = TRUE ;
if (loc == DEAD) {die(); continue; } ;
if (FORCED(loc)) {
showroom();
verb = 1; /* for the benefit of a later switch */
} else { /* motion not forced */
if (DARK) {
if (wzdark && PCT(35)) {
rspeak(23);
oldlc2 = loc;
{die(); continue; };
} else rspeak(16);
} else { /* not dark: describe objects found here */
register struct conn *curcon, *lastcon;
if (DARKRM)
pspeak(UNICRN,6); /* that must be the light */
showroom();
if (TOTING(BOAT)) pspeak(BOAT,BOAT->prop);
if (TOTING(RUG) && (RUG->prop == 1)) pspeak(RUG,1);
curcon = &(loc->atloc);
while (curcon->link != NULL) {
register struct cvobj *adobj;
register int i;
lastcon = curcon;
curcon = curcon->link ;
adobj = curcon->who ;
if (curcon->where != loc) bug(32);
if (adobj->prop < 0) {
adobj->prop = adobj->iprop;
if (IFTREAS(adobj)) --tally;
if ((tally == tally2) && tally)
limit = MIN(limit,35);
}
i = adobj->prop ;
/* handle special cases */
/* tell about the inside of the gate, if the dummy's there */
if ((adobj == O_GATE)
&& (O_GATE->conn2.where == loc))
i = 1;
/* funny way to tell what happened to the container */
if (((adobj == CUP) || (adobj == BOTTLE))
&& (adobj->conn2.where == FIXED)
&& (BEAR->prop == 0)
&& (HERE(BEAR)) ) i = 13 ;
pspeak(adobj,i) ;
blklin = FALSE ;
/* seeing the poo close up means there are footprints in it */
if (adobj == CRAP) adobj->prop = 1 ;
/* remove ranger from gate after the first time he's seen */
if (adobj == RICK) {
RICK->prop++ ;
destry(RICK);
curcon = lastcon;
}
} /* end showing adobjs */
} /* end describing objects here */
goto okay;
/* stuff for when you can't find the indicated object (it may be too dark)
*/
dark: ;
capchk(word1); /* capitalize some proper nouns */
(void) printf("I see no %s here.\n",word1);
mltcmd = FALSE ;
/* loop here when you say "okay" and such -- less dangerous place than
* most, but still must watch the skeleton, the lamp, etc.
*/
okay: ;
blklin = TRUE ;
/* if the skeleton's active, it can kill you */
if (SKELTN->prop == 1) {
if (PCT(25)) {
rspeak(102);
oldlc2 = loc ;
{die(); continue; };
}
rspeak(101);
}
miss: if (TOTING(MEDAL) && (loc->flags & SECRET)) rspeak(112);
if ((loc->flags & RANGER)
&& (RICK->prop == 0)
&& (DAM->prop == 0)
&& (PCT(25) || (loc->atloc.link != NULL))
) {
pspeak(RICK,6);
RICK->prop = 3;
destry(RICK);
loc = &(cvloc[O_GATE->iloc]);
break;
}
/* finds you hanging in there? */
if ((LNUM(loc) == 144) && PCT(25)) {
rspeak(217) ;
if (PCT(50)) rspeak(218);
}
/* when we don't understand, we come back here for a relatively safe retry.
*/
huh: oldvrb = verb ;
verb = 0;
newobj: obj = 0;
object = NULL ;
/* if he left off the verb, we let him come back here to say it.
*/
getvrb: ;
/* check if this place is eligible for any hints. If the sucker has been
* here long enough, perform the help section.
*/
{ register struct hint *hint;
for (hint = hints+4; hint->turns != -1; ++hint) {
if (!(hint->hinted)) {
if (!(loc->flags & hint->bit)) hint->lc = -1 ;
++(hint->lc);
if (hint->lc >= hint->turns) dohint(hint);
}
}
} /* end of hint block */
/* if closing this turn, check for any objects being toted with prop<0.
* set the prop to -1-prop. This way objects won't be described until
* they've been picked up and put down separate from their respective
* piles. Don't let any of this happen unless well into the cave.
*/
if (closed) {
register struct cvobj *adobj;
for (adobj=cvobj;adobj->desc != NULL; ++adobj)
if (TOTING(adobj) && (adobj->prop < 0))
adobj->prop = -adobj->prop - 1;
}
wzdark = DARK ;
if ((knfloc != LOST) & (knfloc != loc)) knfloc = FIXED;
/* get input */
getin() ; /* set word1, word2 */
if (!(turns++)
&& !strcmp("magic",word1)
&& !strcmp("mode",word2) )
{ maint(argv[0]); }
/* demo games are ended by the wizard */
if (demo && (turns >= SHORT))
{ mspeak(1);
{finish = TRUE; continue; };
}
if (samvrb) verb = oldvrb ;
if ((verb == SAY) && (word2 != NULL)) verb = 0 ;
if (verb == SAY) goto process ;
/* detect closing, closed, etc */
if ((LNUM(loc) >= 31) && !tally && !(--clock1))
{ register struct monster *cre;
DOOR->prop = 0;
if (O_GATE->prop != 2) O_GATE->prop = 3;
for (cre = orcs; cre->iloc != -1; ++cre)
{ cre->dloc = DEAD ;
cre->dseen = FALSE ;
}
if (BEAR->prop) destry(BEAR);
if (CHAIN->prop == 2) CHAIN->prop = 1;
AXE->prop = 0 ;
AXE->conn2.where = DEAD;
rspeak(129);
clock1 = -1;
closing = TRUE ;
}
if (clock1 < 0 && !(--clock2))
{ register struct cvobj *curobj;
loc = oldloc = newloc = OFFICE ;
/* Put him there "naked" except for compass */
for (curobj=cvobj; curobj->desc != NULL; ++curobj) {
if (TOTING(curobj) && curobj != COMPASS)
destry(curobj);
}
move(AXE,REPOS);
rspeak(132);
closed = TRUE;
{locchg(); continue; };
}
/* one way to get to the end of the game is for the lamp to give out.
* When it gets close, we warn him. If the lamp and fresh batteries are
* handy, we replace the batteries for him. Otherwise, he may be in
* trouble, depending on where he is.
*/
if ((LAMP->prop == 1)
&& (--limit <= 30)
&& HERE(BATTER)
&& !(BATTER->prop)
&& HERE(LAMP) )
{ rspeak(188);
BATTER->prop = 1 ;
if (TOTING(BATTER)) move(BATTER,loc) ;
limit += 500 ;
lmwarn = FALSE ;
}
/* if lamp runs out */
if (!limit)
{ limit = -1;
LAMP->prop = 0 ;
if (HERE(LAMP)) rspeak(184) ;
}
/* if it's dark and he's outside the cave proper, he just gives up */
if ((limit < 0) && (LNUM(loc) <= 30))
{ rspeak(185) ;
gaveup = TRUE;
{finish = TRUE; continue; } ;
}
/* give warning about dim lamp */
if ((limit <= 30) && HERE(LAMP) && !lmwarn)
{ lmwarn = TRUE ;
if ((BATTER->prop == 1) || (BATTER->conn1.where == LOST))
rspeak(189);
else if (BATTER->prop == 0)
rspeak(183);
else
rspeak(187);
}
/* now for the real work: we have to figure out what he means by what
* he just said.
*/
for ( ; word1 != NULL; word1=word2, word2=NULL)
{ register int i;
if (!strcmp(word1,"north"))
if (++inorth == 10) rspeak(17);
i = vocab(word1,-1);
if (i == -1)
{ what(TRUE); /* some form of not understanding */
goto huh;
}
/* if he says ENTER, he may not really go anywhere because of some special
* cases. Going into the water just gets him wet. Going into the boat
* is treated as "take boat", so we change his verb.
*/
if ((i == ENTER)
&& (word2 != NULL))
{ if (!strcmp(word2,"stream")
|| !strcmp(word2,"water")
|| !strcmp(word2,"river") )
{ if (LIQLOC(loc) == _WATER)
rspeak(70); /* wet feet! */
else
rspeak(43); /* Where? */
goto okay ; /* maybe this should just be moved */
}
else if (!strcmp(word2,"boat"))
{ obj = _BOAT;
object = OBJ(obj) ;
i = TAKE;
}
}
switch(i/1000)
{
/* this is one of the big holes in the parser here. Motion words are
* hardly checked for syntax at all. The object is usually not even
* looked at, if given. There are just a few special cases, and they
* do not go through the normal vocabulary stuff.
*/
case 0: /* motion word */
if (obj || (verb && (verb != WALK)))
{what(FALSE); goto huh; }
if ((i == OUT) && (!strcmp(word2,"boat")))
{ i = DROP ; } /* deal with word ambiguity here */
if (i == OUT
&& TOTING(BOAT)
&& (word2 == NULL || !strcmp(word2,""))
&& obj == 0) {
i = DROP ;
object = OBJ(obj = _BOAT);
}
verb = i ; /* this sets dispatch switch */
break;
/* for objects, we make sure that there are not two objects being named,
* and that the object is here. Also, if there's another word, we clear
* 'verb' which may have been set by the operation of 'samvrb'.
*/
case 1: /* object */
oword = word1;
if (obj != i)
{ if (obj
|| (verb && (word2 != NULL)))
{ what(FALSE); /* don't understand */
goto huh;
}
}
object = OBJ(obj = i) ;
if (word2 != NULL) verb = 0; /* defeat samvrb */
if ((object->conn2.where != loc)
&& !HERE(object)) /* object maybe not here */
{ register int flag;
flag = FALSE ;
if ((obj == _DWARF) && (dflag > 1))
{ register struct monster *cre;
for (cre = orcs; cre->iloc >= 0; ++cre)
{ if (cre->dloc == loc)
{ flag = TRUE ;
break;
}
}
}
if (flag
|| (obj == LIQLOC(loc))
|| ((obj == LIQ(BOTTLE)) && HERE(BOTTLE))
|| ((obj == LIQ(CUP)) && HERE(CUP) )
|| ((object == SPIDER)
&& (GRENDL->dloc == loc))
|| ((object == DRAGON)
&& (PUFF->dloc == loc))
|| ((object == DJINN)
&& (JEANNIE->dloc == loc))
|| ((object == KOBOLD)
&& (SLASHER->dloc == loc))
|| ((object == BALROG)
&& (BALLY->dloc == loc))
|| ((object == SELF)
&& (ME->dloc == loc))
)
; /* okay to keep going */
else if ((object == KNIFE)
&& (knfloc == loc))
{ knfloc = LOST;
rspeak(116); /* sorry about them knives */
goto okay ;
} else if ((object == ROPE)
&& (HERE(ROPE2)))
{ object = ROPE2 ;
; /* substitute the "other" rope */
} else if ((object == ROPE)
&& (HERE(EROPE)))
{ object = EROPE ;
} else if ((object == ROPE)
&& (HERE(EROPE2)))
{ object = EROPE2;
} else if ( (word2 == NULL)
&& ((verb == FIND)
|| (verb == INVENT)
|| (verb == DESCRB)
|| (verb == TOUCH) ) )
{ ; /* allow questions about things not here */
} else {
if (!verb && (word2 == NULL))
/* this test is sensitive to verb funnies */
{ register int k;
if ((k=vocab(word1,3)) > 0)
{ rspeak(k%1000); /* word has msg num */
goto okay ;
}
}
goto dark;
}
} /* end of the case the object is not here */
if ((object == TOMB) && (HELM->prop))
object = HELM ; /* actually a synonym */
if (word2 != NULL) break;
if (verb) break ;
{ register int k;
if ((k=vocab(word1,3)) >0)
{ rspeak(k%1000); /* word has msg num in it */
goto okay;
}
}
capchk(word1); /* capitialize some proper nouns */
(void) printf(
"What do you want to do with the %s?",word1);
mltcmd = FALSE ;
goto getvrb ;
case 2: /* action (verb) */
vword = word1;
if ((verb == TAKE)
&& ((i == INVENT)
|| (i == verb)))
{ verb = 0; /* destroy old verb */
}
if (verb && !obj && (word2 == NULL))
{ what(FALSE); /* two verbs */
goto huh;
}
if (word2 != NULL) {obj = 0 ; object = NULL ; }
verb = i;
if (word2 != NULL)
if (verb == SAY)
{ obj = 1;
goto process;
}
break;
case 3: /* special (just gets message) */
verb = i ; /* this sets dispatch switch */
break;
} /* end of word-type switch */
} /* end of word analysis */
} /* end of getting new instructions (motion not forced) */
process:
switch (verb/1000)
{
case 0: /* motion verb */
newloc = moveme(loc,verb) ;
locchg();
continue ;
case 2: /* true verb */
if (verb == SAY) {
if (word2 != NULL) word1 = word2;
obj = vocab(word1,-1); /* what would happen? */
if (obj == HOPE || obj == BANIS || obj == MISFO) {
verb = obj; obj = 0; object = NULL;
} else {
printf("Okay, \"%s\".\n",word1);
goto okay;
}
}
switch (cvact(verb,obj,object))
{
case S_okay: goto okay;
case S_miss: goto miss;
case S_move: break;
case S_obj: goto newobj;
case S_what: *vword = toupper(*vword);
printf("%s what?\n",vword);
mltcmd = FALSE;
goto newobj;
case S_light: if (!DARK && wzdark) continue;
goto okay;
case S_show: continue;
case S_dark: goto dark;
default: bug(40);
}
locchg();
continue;
case 3: /* magic word */
rspeak(verb%1000);
goto okay;
default: /* how could this be? */
bug(1);
}
} /* end of motion loop */
getscore();
(void) printf("\nYou scored %d out of a possible %d, using %d turns.\n",
score,mxscore,turns);
{ register struct cmsg *cmsg;
for (cmsg = ctext;cmsg->score != -1; ++cmsg) ;
for (--cmsg; cmsg - ctext; --cmsg) {
if (cmsg->score <= 0) cmsg->score += mxscore ;
if (cmsg->score <= score) break;
}
(void) fputs(cmsg->msg,stdout);
if ((cmsg+1)->score == -1) {
(void) fputs("To achieve the next higher rating would be a\
neat trick!\n\n Congratulations!\n",stdout);
}else{
(void) printf("To achieve the next higher rating, you need %d \
more point%s.\n",(cmsg+1)->score - score, ((cmsg+1)->score - score > 1) ?
"s" : "");
}
} /* end of figuring the appropriate message */
puts("\nTouch ENTER to continue.\n");
{ auto char answer[5];
fgets(answer,4,stdin);
}
}