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; }
static void updatedigger(struct digger_draw_api *ddap, int n) { int16_t dir,ddir,diggerox,diggeroy,nmon; bool push=true,bagf; int clfirst[TYPES],clcoll[SPRITES],i; readdirect(n-curplayer); dir=getdirect(n-curplayer); if (dir==DIR_RIGHT || dir==DIR_UP || dir==DIR_LEFT || dir==DIR_DOWN) ddir=dir; else ddir=DIR_NONE; if (digdat[n].rx==0 && (ddir==DIR_UP || ddir==DIR_DOWN)) digdat[n].dob.dir=digdat[n].mdir=ddir; if (digdat[n].ry==0 && (ddir==DIR_RIGHT || ddir==DIR_LEFT)) digdat[n].dob.dir=digdat[n].mdir=ddir; if (dir==DIR_NONE) digdat[n].mdir=DIR_NONE; else digdat[n].mdir=digdat[n].dob.dir; if ((digdat[n].dob.x==292 && digdat[n].mdir==DIR_RIGHT) || (digdat[n].dob.x==12 && digdat[n].mdir==DIR_LEFT) || (digdat[n].dob.y==180 && digdat[n].mdir==DIR_DOWN) || (digdat[n].dob.y==18 && digdat[n].mdir==DIR_UP)) digdat[n].mdir=DIR_NONE; diggerox=digdat[n].dob.x; diggeroy=digdat[n].dob.y; if (digdat[n].mdir!=DIR_NONE) eatfield(diggerox,diggeroy,digdat[n].mdir); switch (digdat[n].mdir) { case DIR_RIGHT: drawrightblob(digdat[n].dob.x,digdat[n].dob.y); digdat[n].dob.x+=4; break; case DIR_UP: drawtopblob(digdat[n].dob.x,digdat[n].dob.y); digdat[n].dob.y-=3; break; case DIR_LEFT: drawleftblob(digdat[n].dob.x,digdat[n].dob.y); digdat[n].dob.x-=4; break; case DIR_DOWN: drawbottomblob(digdat[n].dob.x,digdat[n].dob.y); digdat[n].dob.y+=3; break; } if (hitemerald((digdat[n].dob.x-12)/20,(digdat[n].dob.y-18)/18, (digdat[n].dob.x-12)%20,(digdat[n].dob.y-18)%18, digdat[n].mdir)) { if (digdat[n].emocttime==0) digdat[n].emn=0; scoreemerald(ddap, n); soundem(); soundemerald(digdat[n].emn); digdat[n].emn++; if (digdat[n].emn==8) { digdat[n].emn=0; scoreoctave(ddap, n); } digdat[n].emocttime=9; } drawdig(n); for (i=0;i<TYPES;i++) clfirst[i]=first[i]; for (i=0;i<SPRITES;i++) clcoll[i]=coll[i]; incpenalty(); i=clfirst[1]; bagf=false; while (i!=-1) { if (bagexist(i-FIRSTBAG)) { bagf=true; break; } i=clcoll[i]; } if (bagf) { if (digdat[n].mdir==DIR_RIGHT || digdat[n].mdir==DIR_LEFT) { push=pushbags(ddap, digdat[n].mdir,clfirst,clcoll); digdat[n].bagtime++; } else if (!pushudbags(ddap, clfirst,clcoll)) push=false; if (!push) { /* Strange, push not completely defined */ digdat[n].dob.x=diggerox; digdat[n].dob.y=diggeroy; digdat[n].dob.dir = digdat[n].mdir; drawdig(n); incpenalty(); digdat[n].dob.dir=reversedir(digdat[n].mdir); } } if (clfirst[2]!=-1 && bonusmode && digdat[n].dob.alive) for (nmon=killmonsters(clfirst,clcoll);nmon!=0;nmon--) { soundeatm(); sceatm(ddap, n); } if (clfirst[0]!=-1) { scorebonus(ddap, n); initbonusmode(ddap); } digdat[n].h=(digdat[n].dob.x-12)/20; digdat[n].rx=(digdat[n].dob.x-12)%20; digdat[n].v=(digdat[n].dob.y-18)/18; digdat[n].ry=(digdat[n].dob.y-18)%18; }