void monai(Sint4 mon) { Sint4 monox,monoy,dir,mdirp1,mdirp2,mdirp3,mdirp4,t; int clcoll[SPRITES],clfirst[TYPES],i,m,dig; bool push,bagf; monox=mondat[mon].x; monoy=mondat[mon].y; if (mondat[mon].xr==0 && mondat[mon].yr==0) { /* If we are here the monster needs to know which way to turn next. */ /* Turn hobbin back into nobbin if it's had its time */ if (mondat[mon].hnt>30+(levof10()<<1)) if (!mondat[mon].nob) { mondat[mon].hnt=0; mondat[mon].nob=true; } /* Set up monster direction properties to chase Digger */ dig=mondat[mon].chase; if (!digalive(dig)) dig=(diggers-1)-dig; if (abs(diggery(dig)-mondat[mon].y)>abs(diggerx(dig)-mondat[mon].x)) { if (diggery(dig)<mondat[mon].y) { mdirp1=DIR_UP; mdirp4=DIR_DOWN; } else { mdirp1=DIR_DOWN; mdirp4=DIR_UP; } if (diggerx(dig)<mondat[mon].x) { mdirp2=DIR_LEFT; mdirp3=DIR_RIGHT; } else { mdirp2=DIR_RIGHT; mdirp3=DIR_LEFT; } } else { if (diggerx(dig)<mondat[mon].x) { mdirp1=DIR_LEFT; mdirp4=DIR_RIGHT; } else { mdirp1=DIR_RIGHT; mdirp4=DIR_LEFT; } if (diggery(dig)<mondat[mon].y) { mdirp2=DIR_UP; mdirp3=DIR_DOWN; } else { mdirp2=DIR_DOWN; mdirp3=DIR_UP; } } /* In bonus mode, run away from Digger */ if (bonusmode) { t=mdirp1; mdirp1=mdirp4; mdirp4=t; t=mdirp2; mdirp2=mdirp3; mdirp3=t; } /* Adjust priorities so that monsters don't reverse direction unless they really have to */ dir=reversedir(mondat[mon].dir); if (dir==mdirp1) { mdirp1=mdirp2; mdirp2=mdirp3; mdirp3=mdirp4; mdirp4=dir; } if (dir==mdirp2) { mdirp2=mdirp3; mdirp3=mdirp4; mdirp4=dir; } if (dir==mdirp3) { mdirp3=mdirp4; mdirp4=dir; } /* Introduce a random element on levels <6 : occasionally swap p1 and p3 */ if (randno(levof10()+5)==1) /* Need to split for determinism */ if (levof10()<6) { t=mdirp1; mdirp1=mdirp3; mdirp3=t; } /* Check field and find direction */ if (fieldclear(mdirp1,mondat[mon].h,mondat[mon].v)) dir=mdirp1; else if (fieldclear(mdirp2,mondat[mon].h,mondat[mon].v)) dir=mdirp2; else if (fieldclear(mdirp3,mondat[mon].h,mondat[mon].v)) dir=mdirp3; else if (fieldclear(mdirp4,mondat[mon].h,mondat[mon].v)) dir=mdirp4; /* Hobbins don't care about the field: they go where they want. */ if (!mondat[mon].nob) dir=mdirp1; /* Monsters take a time penalty for changing direction */ if (mondat[mon].dir!=dir) mondat[mon].t++; /* Save the new direction */ mondat[mon].dir=dir; } /* If monster is about to go off edge of screen, stop it. */ if ((mondat[mon].x==292 && mondat[mon].dir==DIR_RIGHT) || (mondat[mon].x==12 && mondat[mon].dir==DIR_LEFT) || (mondat[mon].y==180 && mondat[mon].dir==DIR_DOWN) || (mondat[mon].y==18 && mondat[mon].dir==DIR_UP)) mondat[mon].dir=DIR_NONE; /* Change hdir for hobbin */ if (mondat[mon].dir==DIR_LEFT || mondat[mon].dir==DIR_RIGHT) mondat[mon].hdir=mondat[mon].dir; /* Hobbins dig */ if (!mondat[mon].nob) eatfield(mondat[mon].x,mondat[mon].y,mondat[mon].dir); /* (Draw new tunnels) and move monster */ switch (mondat[mon].dir) { case DIR_RIGHT: if (!mondat[mon].nob) drawrightblob(mondat[mon].x,mondat[mon].y); mondat[mon].x+=4; break; case DIR_UP: if (!mondat[mon].nob) drawtopblob(mondat[mon].x,mondat[mon].y); mondat[mon].y-=3; break; case DIR_LEFT: if (!mondat[mon].nob) drawleftblob(mondat[mon].x,mondat[mon].y); mondat[mon].x-=4; break; case DIR_DOWN: if (!mondat[mon].nob) drawbottomblob(mondat[mon].x,mondat[mon].y); mondat[mon].y+=3; break; } /* Hobbins can eat emeralds */ if (!mondat[mon].nob) hitemerald((mondat[mon].x-12)/20,(mondat[mon].y-18)/18, (mondat[mon].x-12)%20,(mondat[mon].y-18)%18, mondat[mon].dir); /* If Digger's gone, don't bother */ if (!isalive()) { mondat[mon].x=monox; mondat[mon].y=monoy; } /* If monster's just started, don't move yet */ if (mondat[mon].stime!=0) { mondat[mon].stime--; mondat[mon].x=monox; mondat[mon].y=monoy; } /* Increase time counter for hobbin */ if (!mondat[mon].nob && mondat[mon].hnt<100) mondat[mon].hnt++; /* Draw monster */ push=true; drawmon(mon,mondat[mon].nob,mondat[mon].hdir,mondat[mon].x,mondat[mon].y); for (i=0;i<TYPES;i++) clfirst[i]=first[i]; for (i=0;i<SPRITES;i++) clcoll[i]=coll[i]; incpenalty(); /* Collision with another monster */ if (clfirst[2]!=-1) { mondat[mon].t++; /* Time penalty */ /* Ensure both aren't moving in the same dir. */ i=clfirst[2]; do { m=i-FIRSTMONSTER; if (mondat[mon].dir==mondat[m].dir && mondat[m].stime==0 && mondat[mon].stime==0) mondat[m].dir=reversedir(mondat[m].dir); /* The kludge here is to preserve playback for a bug in previous versions. */ if (!kludge) incpenalty(); else if (!(m&1)) incpenalty(); i=clcoll[i]; } while (i!=-1); if (kludge) if (clfirst[0]!=-1) incpenalty(); } /* Check for collision with bag */ i=clfirst[1]; bagf=false; while (i!=-1) { if (bagexist(i-FIRSTBAG)) { bagf=true; break; } i=clcoll[i]; } if (bagf) { mondat[mon].t++; /* Time penalty */ mongotgold=false; if (mondat[mon].dir==DIR_RIGHT || mondat[mon].dir==DIR_LEFT) { push=pushbags(mondat[mon].dir,clfirst,clcoll); /* Horizontal push */ mondat[mon].t++; /* Time penalty */ } else if (!pushudbags(clfirst,clcoll)) /* Vertical push */ push=false; if (mongotgold) /* No time penalty if monster eats gold */ mondat[mon].t=0; if (!mondat[mon].nob && mondat[mon].hnt>1) removebags(clfirst,clcoll); /* Hobbins eat bags */ } /* Increase hobbin cross counter */ if (mondat[mon].nob && clfirst[2]!=-1 && isalive()) mondat[mon].hnt++; /* See if bags push monster back */ if (!push) { mondat[mon].x=monox; mondat[mon].y=monoy; drawmon(mon,mondat[mon].nob,mondat[mon].hdir,mondat[mon].x,mondat[mon].y); incpenalty(); if (mondat[mon].nob) /* The other way to create hobbin: stuck on h-bag */ mondat[mon].hnt++; if ((mondat[mon].dir==DIR_UP || mondat[mon].dir==DIR_DOWN) && mondat[mon].nob) mondat[mon].dir=reversedir(mondat[mon].dir); /* If vertical, give up */ } /* Collision with Digger */ if (clfirst[4]!=-1 && isalive()) if (bonusmode) { killmon(mon); i=clfirst[4]; while (i!=-1) { if (digalive(i-FIRSTDIGGER+curplayer)) sceatm(i-FIRSTDIGGER+curplayer); i=clcoll[i]; } soundeatm(); /* Collision in bonus mode */ } else { i=clfirst[4]; while (i!=-1) { if (digalive(i-FIRSTDIGGER+curplayer)) killdigger(i-FIRSTDIGGER+curplayer,3,0); /* Kill Digger */ i=clcoll[i]; } } /* Update co-ordinates */ mondat[mon].h=(mondat[mon].x-12)/20; mondat[mon].v=(mondat[mon].y-18)/18; mondat[mon].xr=(mondat[mon].x-12)%20; mondat[mon].yr=(mondat[mon].y-18)%18; }
void game(void) { int16_t t,c,i; bool flashplayer=false; if (gauntlet) { cgtime=gtime*1193181l; timeout=false; } initlives(); gamedat[0].level=startlev; if (nplayers==2) gamedat[1].level=startlev; alldead=false; ddap->gclear(); curplayer=0; initlevel(); curplayer=1; initlevel(); zeroscores(); bonusvisible=true; if (nplayers==2) flashplayer=true; curplayer=0; while (getalllives()!=0 && !escape && !timeout) { while (!alldead && !escape && !timeout) { initmbspr(); if (playing) randv=playgetrand(); else randv=getlrt(); #ifdef INTDRF fprintf(info,"%lu\n",randv); frame=0; #endif recputrand(randv); if (levnotdrawn) { levnotdrawn=false; drawscreen(ddap); if (flashplayer) { flashplayer=false; strcpy(pldispbuf,"PLAYER "); if (curplayer==0) strcat(pldispbuf,"1"); else strcat(pldispbuf,"2"); cleartopline(); for (t=0;t<15;t++) for (c=1;c<=3;c++) { outtext(ddap, pldispbuf,108,0,c); writecurscore(ddap, c); newframe(); if (escape) return; } drawscores(ddap); for (i=0;i<diggers;i++) addscore(ddap, i,0); } } else initchars(); outtext(ddap, " ",108,0,3); initscores(ddap); drawlives(ddap); music(1); flushkeybuf(); for (i=0;i<diggers;i++) readdirect(i); while (!alldead && !gamedat[curplayer].levdone && !escape && !timeout) { penalty=0; dodigger(ddap); domonsters(ddap); dobags(ddap); if (penalty>8) incmont(penalty-8); testpause(); checklevdone(); } erasediggers(); musicoff(); t=20; while ((getnmovingbags()!=0 || t!=0) && !escape && !timeout) { if (t!=0) t--; penalty=0; dobags(ddap); dodigger(ddap); domonsters(ddap); if (penalty<8) t=0; } soundstop(); for (i=0;i<diggers;i++) killfire(i); erasebonus(ddap); cleanupbags(); savefield(); erasemonsters(); recputeol(); if (playing) playskipeol(); if (escape) recputeog(); if (gamedat[curplayer].levdone) soundlevdone(); if (countem()==0 || gamedat[curplayer].levdone) { #ifdef INTDRF fprintf(info,"%i\n",frame); #endif for (i=curplayer;i<diggers+curplayer;i++) if (getlives(i)>0 && !digalive(i)) declife(i); drawlives(ddap); gamedat[curplayer].level++; if (gamedat[curplayer].level>1000) gamedat[curplayer].level=1000; initlevel(); } else if (alldead) { #ifdef INTDRF fprintf(info,"%i\n",frame); #endif for (i=curplayer;i<curplayer+diggers;i++) if (getlives(i)>0) declife(i); drawlives(ddap); } if ((alldead && getalllives()==0 && !gauntlet && !escape) || timeout) endofgame(ddap); } alldead=false; if (nplayers==2 && getlives(1-curplayer)!=0) { curplayer=1-curplayer; flashplayer=levnotdrawn=true; } } #ifdef INTDRF fprintf(info,"-1\n%lu\n%i",getscore0(),gamedat[0].level); #endif }