Annotation of researchv9/jtools/src/demo/pacman/monsters.c, revision 1.1.1.1

1.1       root        1: /*----------------------------------------------------------------------*/
                      2: /*                                                                     */
                      3: /*     PACMAN for BBN BitGraphs                                        */
                      4: /*                                                                     */
                      5: /*               File: monsters.c68                                    */
                      6: /*           Contents: monster definitions and manipulation routines   */
                      7: /*             Author: Bob Brown (rlb)                                 */
                      8: /*                     Purdue CS                                       */
                      9: /*               Date: May, 1982                                       */
                     10: /*        Description: Initialization, movement, drawing routines.     */
                     11: /*                     Interacts with several pacman routines.         */
                     12: /*                                                                     */
                     13: /*----------------------------------------------------------------------*/
                     14: 
                     15: #include "style.h"
                     16: #include "pacman.h"
                     17: 
                     18: /*
                     19: **  Monster structure initialization
                     20: **
                     21: ** The following lists the static part of the monster structures, in the order
                     22: ** that they leave the stable.
                     23: */
                     24: 
                     25: monster Monster[MAXMONSTER] = {
                     26:        { 45, 36, MOVEUP,     0,    5,   -10 },
                     27:        { 45, 41, MOVEUP,    24,    0,   -20 }, /* fast, but stupid */
                     28:        { 39, 33, MOVEDOWN,  52,    9,     0 },
                     29:        { 39, 48, MOVEDOWN,  80,   13,     5 }, /* slow, but methodical */
                     30: };
                     31: 
                     32: /*
                     33: ** monnew - create a new set of monsters.
                     34: **
                     35: **     Called once at the beginning of a game.
                     36: */
                     37: 
                     38: monnew()
                     39: {
                     40:        register monster *mptr;
                     41:        for ( mptr=Monster ; mptr < &Monster[MAXMONSTER] ; mptr++ )
                     42:                mptr->time = Monbase + mptr->inittime;
                     43: }
                     44: 
                     45: /*
                     46: ** moninit - reinitialize the monsters.
                     47: **
                     48: **     Called at the beginning of each wave or when Pacman dies.
                     49: */
                     50: 
                     51: moninit()
                     52: {
                     53:        register monster *mptr;
                     54:        for ( mptr=Monster ; mptr < &Monster[MAXMONSTER] ; mptr++ ) {
                     55:                if ( mptr == Monster ) {
                     56:                        mptr->row = STARTROW;
                     57:                        mptr->col = STARTCOL;
                     58:                        mptr->dir = MOVERIGHT;
                     59:                        mptr->movestate = ROAMING;
                     60:                } else {
                     61:                        mptr->row = mptr->initrow;
                     62:                        mptr->col = mptr->initcol;
                     63:                        mptr->dir = mptr->initdir;
                     64:                        mptr->movestate = STABLED;
                     65:                }
                     66:                mptr->mrow = SCtoMZ(mptr->row);
                     67:                mptr->mcol = SCtoMZ(mptr->col);
                     68:                mptr->state = DANGEROUS;
                     69:                mptr->delay = mptr->initdelay;
                     70:                mptr->font = MONSTERCHAR[0];
                     71:                Monseeking = FALSE;
                     72:                mondraw(mptr);
                     73:                eladd(mptr->time+STARTDELAY,monmove,(char *)mptr);
                     74:        }
                     75: }
                     76: /*
                     77: ** monfont - change the font of the monsters.
                     78: **
                     79: **     Called when Pacman swallows a pill or starts getting weaker.
                     80: */
                     81: 
                     82: monfont(chr)
                     83: char chr;
                     84: {
                     85:        register monster *mptr;
                     86:        for ( mptr=Monster ; mptr < &Monster[MAXMONSTER] ; mptr++ ) {
                     87:                monfont1(mptr,chr);
                     88:        }
                     89: }
                     90: 
                     91: monfont1(mptr,chr)
                     92: register monster *mptr;
                     93: char chr;
                     94: {
                     95:                mondraw(mptr);
                     96:                mptr->font = chr;
                     97:                mondraw(mptr);
                     98: }
                     99: /*
                    100: ** moncomp - turn on/off (i.e. complement) all the monsters
                    101: */
                    102: 
                    103: moncomp()
                    104: {
                    105:        register monster *mptr;
                    106:        for ( mptr=Monster ; mptr < &Monster[MAXMONSTER] ; mptr++ )
                    107:                mondraw(mptr);
                    108: }
                    109: 
                    110: /*
                    111: ** mondraw - complement a single monster
                    112: */
                    113: 
                    114: mondraw(mptr)
                    115: register monster *mptr;
                    116: {
                    117:        blt40(mptr->font,mptr->row,mptr->col,INVERT);
                    118: }
                    119: 
                    120: /*
                    121: ** Move a particular monster
                    122: **
                    123: ** This routine moves a given monster based its current movestate
                    124: */
                    125: 
                    126: int
                    127: monmove(mptr)
                    128: register monster *mptr;
                    129: {
                    130:        register move *newmove;
                    131:        int newdelay;
                    132:        /*
                    133:        ** Motion depends on the monster movestate
                    134:        */
                    135:        mondraw(mptr);
                    136:        switch ( mptr->movestate ) {
                    137:        /*
                    138:        ** In the center box - won't come out until time delay elapses and
                    139:        ** the pacman isn't dangerous (fixes ambush bug).
                    140:        */
                    141:        case STABLED:
                    142:                newmove = bounce(mptr);
                    143:                if ( mptr->delay > 0 )
                    144:                        mptr->delay = max(mptr->delay-1,0);
                    145:                else
                    146:                        mptr->movestate = LEAVING;
                    147:                break;
                    148:        case LEAVING:
                    149:                newmove = tostart(mptr);
                    150:                if ( newmove->row == STARTROW && newmove->col == STARTCOL )
                    151:                        mptr->movestate = ROAMING;
                    152:                break;
                    153:        /*
                    154:        ** If roaming about, switch to seeking if someone sees him and fall
                    155:        ** into seeking code.
                    156:        */
                    157:        case ROAMING:
                    158:                if ( Monseeking )
                    159:                        mptr->movestate = SEEKING;
                    160:                else if ( seeshim(mptr) ) {
                    161:                        Monseeking = TRUE;
                    162:                        mptr->movestate = SEEKING;
                    163:                } else {
                    164:                        newmove = dumbmove(mptr);
                    165:                        break;
                    166:                }
                    167:        /*
                    168:        **  When seeking the pacman, they may always make a random move.  if the
                    169:        **  Pacman is powerful, then they move away if edible, else random.
                    170:        */
                    171:        case SEEKING:
                    172:                if ( grand(0,100) < Seekprob+mptr->bonus && !Pacman.safe && !(Pacman.power>0 && mptr->state==DANGEROUS))
                    173:                        newmove = seekmove(mptr);
                    174:                else
                    175:                        newmove = dumbmove(mptr);
                    176:                break;
                    177:        case HOMING:
                    178:                newmove = todoor(mptr);
                    179:                if ( newmove->row == STARTROW && newmove->col == STARTCOL )
                    180:                        mptr->movestate = HOMING2;
                    181:                break;
                    182:        case HOMING2:
                    183:                newmove = tostable(mptr);
                    184:                if ( newmove->row==mptr->initrow && newmove->col==mptr->initcol ) {
                    185:                        mptr->movestate = STABLED;
                    186:                        mptr->state = DANGEROUS;
                    187:                        mptr->font = MONSTERCHAR[mptr->initdir];
                    188:                        newmove->dir = mptr->initdir;
                    189:                        mptr->delay = Pacman.power+(mptr-Monster)*24;
                    190:                }
                    191:                break;
                    192:        }
                    193:        /*
                    194:        ** Move the monster on the screen
                    195:        */
                    196:        mptr->row = newmove->row;
                    197:        mptr->col = newmove->col;
                    198:        mptr->dir = newmove->dir;
                    199:        mptr->mrow = SCtoMZ(mptr->row);
                    200:        mptr->mcol = SCtoMZ(mptr->col);
                    201:        if ( mptr->state == DANGEROUS )
                    202:                mptr->font = MONSTERCHAR[mptr->dir];
                    203:        mondraw(mptr);
                    204:        /*
                    205:        ** Check for collision with the pacman
                    206:        */
                    207:        if ( mptr->state == DANGEROUS && collide(mptr) && Pacman.alive ) {
                    208:                pacdie();
                    209:                return;
                    210:        }
                    211:        /*
                    212:        **  The time till next move depends on whether the monster is alive,
                    213:        **  or is in the slow corridor, or is weakened by the pacman's power.
                    214:        */
                    215:        newdelay = mptr->state==DEAD ? EYESDELAY :
                    216:                   inslow(mptr->row,mptr->col) ? Pacman.time+SLOWDELTA :
                    217:                   mptr->time+Pacman.power*POWERDELAY;
                    218: 
                    219:        eladd(newdelay,monmove,mptr);
                    220: }
                    221: /*
                    222: ** Simplest of all possible move commands - chooses random direction
                    223: */
                    224: move *
                    225: dumbmove(mptr)
                    226: register monster *mptr;
                    227: {
                    228:        register int moves;
                    229:        static move movelist[4];
                    230:        if ( !aligns(mptr->row, mptr->col) ) {
                    231:                onestep(mptr->row,mptr->col,mptr->dir,&movelist[0]);
                    232:                return movelist;
                    233:        }
                    234:        moves=compmoves(mptr->row,mptr->col,movelist,mptr->dir,FALSE);
                    235:        if (moves == 1 )
                    236:                return movelist;
                    237:        return &movelist[grand(0,moves-1)];
                    238: }
                    239: /*
                    240: **  Direction seeking Monster move
                    241: */
                    242: move *
                    243: seekmove(mptr)
                    244: register monster *mptr;
                    245: {
                    246:        register int moves;
                    247:        static move movelist[4];
                    248:        if ( !aligns(mptr->row, mptr->col) ) {
                    249:                onestep(mptr->row,mptr->col,mptr->dir,&movelist[0]);
                    250:                return movelist;
                    251:        }
                    252:        /*
                    253:        ** Monsters can reverse once when the pacman swallows a pill -
                    254:        ** Should save it until the pacman is close (unimplemented).
                    255:        */
                    256:        if ( mptr->canreverse ) {
                    257:                moves=compmoves(mptr->row,mptr->col,movelist,0,FALSE);
                    258:                mptr->canreverse = FALSE;
                    259:        } else
                    260:                moves=compmoves(mptr->row,mptr->col,movelist,mptr->dir,FALSE);
                    261:        if (moves == 1 )
                    262:                return movelist;
                    263:        if ( mptr->state == EDIBLE )
                    264:                return furthest(movelist,moves,Pacman.row,Pacman.col);
                    265:        return closest(movelist,moves,Pacman.row,Pacman.col);
                    266: }
                    267: /*
                    268: **  Compute all the possible moves a monster can make.
                    269: **
                    270: */
                    271: 
                    272: compmoves(mrow, mcol, list, curdir, doorok)
                    273: int mrow, mcol, curdir;
                    274: register move *list;
                    275: bool doorok;
                    276: {
                    277:        register int moves, i;
                    278:        /*
                    279:        **  The list of moves will not include the direction opposite
                    280:        **  of curdir, if it is nonzero.  This statement computes the
                    281:        **  opposite direction effeciently.
                    282:        */
                    283:        if ( curdir > 0 )
                    284:                curdir = ((curdir+1)&3)+1;
                    285:        moves = 0;
                    286:        for ( i=1 ; i<=4 ; i++ ) {
                    287:                if ( i == curdir )
                    288:                        continue;
                    289:                onestep(mrow,mcol,i,list);
                    290:                if ( (doorok && hitdoor(list->row,list->col)) ||
                    291:                    !(hitwall(list->row,list->col,i)||(i==MOVEUP&&hitblk(list->row,list->col))) ) {
                    292:                        list++;
                    293:                        moves++;
                    294:                }
                    295:        }
                    296:        return moves;
                    297: }
                    298: onestep(mrow, mcol, dir, list)
                    299: register int mrow, mcol, dir;
                    300: register move *list;
                    301: {
                    302:        list->col = mcol;
                    303:        list->row = mrow;
                    304:        list->dir = dir;
                    305:        switch ( dir ) {
                    306:        case MOVERIGHT:
                    307:                list->col++;
                    308:                break;
                    309:        case MOVEUP:
                    310:                list->row--;
                    311:                break;
                    312:        case MOVELEFT:
                    313:                list->col--;
                    314:                break;
                    315:        case MOVEDOWN:
                    316:                list->row++;
                    317:                break;
                    318:        }
                    319:        if ( list->col < 0 )
                    320:                list->col += MZtoSC(MAZECOLS);
                    321:        if ( list->col >= MZtoSC(MAZECOLS) )
                    322:                list->col = 0;
                    323: }
                    324: /*
                    325: ** Choose the move from a list the goes in the direction closest to a
                    326: ** given point.
                    327: **
                    328: **   SCREEN COORDINATES
                    329: */
                    330: move *
                    331: closest(list,moves,row,col)
                    332: register move *list;
                    333: register int moves;
                    334: register int row, col;
                    335: {
                    336:        register move *lptr;
                    337:        int dist, diff, diffr, diffc;
                    338:        dist = 0x7fff;
                    339:        for ( ; moves>0 ; moves-- ) {
                    340:                diffr = iabs(row-list->row);
                    341:                diffc = iabs(col-list->col);
                    342:                diff = max(diffr,diffc);
                    343:                if ( diff < dist ) {
                    344:                        lptr = list;
                    345:                        dist = diff;
                    346:                }
                    347:                list++;
                    348:        }
                    349:        return lptr;
                    350: }
                    351: move *
                    352: furthest(list,moves,row,col)
                    353: register move *list;
                    354: register int moves;
                    355: register int row, col;
                    356: {
                    357:        register move *lptr;
                    358:        int dist, diff, diffr, diffc;
                    359:        dist = -1;
                    360:        for ( ; moves>0 ; moves-- ) {
                    361:                diffr = iabs(row-list->row);
                    362:                diffc = iabs(col-list->col);
                    363:                diff = min(diffr,diffc);
                    364:                if ( diff > dist ) {
                    365:                        lptr = list;
                    366:                        dist = diff;
                    367:                }
                    368:                list++;
                    369:        }
                    370:        return lptr;
                    371: }
                    372: 
                    373: /*
                    374: ** Check if a monster "sees" the pacman
                    375: */
                    376: seeshim(mptr)
                    377: register monster *mptr;
                    378: {
                    379:        register int rdiff, cdiff;
                    380:        register int i;
                    381:        rdiff = abs(mptr->row - Pacman.row);
                    382:        cdiff = abs(mptr->col - Pacman.col);
                    383:        switch ( mptr->dir ) {
                    384:        case MOVERIGHT:
                    385:                if ( rdiff > 3 || mptr->col > Pacman.col )
                    386:                        return FALSE;
                    387:                for ( i=mptr->mcol ; i<Pacman.mcol ; i++ )
                    388:                        if ( (Board[mptr->mrow][i]&TYPEMASK) <= WALLMAX )
                    389:                                return FALSE;
                    390:                return TRUE;
                    391:        case MOVEUP:
                    392:                if ( cdiff > 3 || mptr->row < Pacman.row )
                    393:                        return FALSE;
                    394:                for ( i=mptr->mrow ; i>Pacman.mrow ; i-- )
                    395:                        if ( (Board[i][mptr->mcol]&TYPEMASK) <= WALLMAX )
                    396:                                return FALSE;
                    397:                return TRUE;
                    398:        case MOVELEFT:
                    399:                if ( rdiff > 3 || mptr->col < Pacman.col )
                    400:                        return FALSE;
                    401:                for ( i=mptr->mcol ; i>Pacman.mcol ; i-- )
                    402:                        if ( (Board[mptr->mrow][i]&TYPEMASK) <= WALLMAX )
                    403:                                return FALSE;
                    404:                return TRUE;
                    405:        case MOVEDOWN:
                    406:                if ( cdiff > 3 || mptr->row > Pacman.row )
                    407:                        return FALSE;
                    408:                for ( i=mptr->mrow ; i<Pacman.mrow ; i++ )
                    409:                        if ( (Board[i][mptr->mcol]&TYPEMASK) <= WALLMAX )
                    410:                                return FALSE;
                    411:                return TRUE;
                    412:        }
                    413: }
                    414: 
                    415: /*
                    416: ** Bounce the monster around in the stable
                    417: */
                    418: move *
                    419: bounce(mptr)
                    420: register monster *mptr;
                    421: {
                    422:        static move newmove;
                    423:        onestep(mptr->row, mptr->col, mptr->dir, &newmove);
                    424:        if ( hitwall(newmove.row, newmove.col,mptr->dir) ) {
                    425:                mptr->dir = ((mptr->dir+1)&3)+1;
                    426:                onestep(mptr->row, mptr->col, mptr->dir, &newmove);
                    427:        }
                    428:        return &newmove;
                    429: }
                    430: /*
                    431: ** move a monster closer to the starting position
                    432: */
                    433: move *
                    434: tostart(mptr)
                    435: register monster *mptr;
                    436: {
                    437:        static move movelist[4];
                    438:        int moves;
                    439:        moves = compmoves(mptr->row, mptr->col, movelist, mptr->dir, TRUE);
                    440:        if ( mptr->col != STARTCOL )
                    441:                return closest(movelist,moves, mptr->row, STARTCOL);
                    442:        return closest(movelist,moves, STARTROW, STARTCOL);
                    443: }
                    444: /*
                    445: ** Move the monster towards the door
                    446: */
                    447: move *
                    448: todoor(mptr)
                    449: register monster *mptr;
                    450: {
                    451:        static move movelist[4];
                    452:        int moves;
                    453:        if ( !aligns(mptr->row, mptr->col) ) {
                    454:                onestep(mptr->row,mptr->col,mptr->dir,&movelist[0]);
                    455:                return movelist;
                    456:        }
                    457:        moves = compmoves(mptr->row, mptr->col, movelist, mptr->dir, FALSE);
                    458:        return closest(movelist,moves, STARTROW, STARTCOL);
                    459: 
                    460: }
                    461: /*
                    462: ** move a monster back to the stable
                    463: */
                    464: move *
                    465: tostable(mptr)
                    466: register monster *mptr;
                    467: {
                    468:        static move movelist[4];
                    469:        int moves;
                    470:        moves = compmoves(mptr->row, mptr->col, movelist, mptr->dir, TRUE);
                    471:        if ( mptr->row!=mptr->initrow )
                    472:                return closest(movelist,moves, mptr->initrow, mptr->col);
                    473:        return closest(movelist,moves, mptr->initrow, mptr->initcol);
                    474: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.