Annotation of 43BSDReno/games/hunt/NEW/otto.c, revision 1.1.1.1

1.1       root        1: # ifdef OTTO
                      2: /*
                      3:  *     otto    - a hunt otto-matic player
                      4:  *
                      5:  *             This guy is buggy, unfair, stupid, and not extensible.
                      6:  *     Future versions of hunt will have a subroutine library for
                      7:  *     automatic players to link to.  If you write your own "otto"
                      8:  *     please let us know what subroutines you would expect in the
                      9:  *     subroutine library.
                     10:  *
                     11:  *     $Header: otto.c,v 1.8 89/04/19 19:52:39 gregc Exp $
                     12:  */
                     13: 
                     14: # include      <curses.h>
                     15: # include      <ctype.h>
                     16: # include      "hunt.h"
                     17: # include      <sys/time.h>
                     18: # include      <signal.h>
                     19: # undef                WALL
                     20: # undef                NORTH
                     21: # undef                SOUTH
                     22: # undef                WEST
                     23: # undef                EAST
                     24: # undef                FRONT
                     25: # undef                LEFT
                     26: # undef                BACK
                     27: # undef                RIGHT
                     28: 
                     29: extern char    *index();
                     30: 
                     31: extern char    screen[SCREEN_HEIGHT][SCREEN_WIDTH2];
                     32: 
                     33: # ifndef DEBUG
                     34: # define       STATIC          static
                     35: # else
                     36: # define       STATIC
                     37: # endif DEBUG
                     38: 
                     39: # define       OPPONENT        "{}i!"
                     40: # define       PROPONENT       "^v<>"
                     41: # define       WALL            "+\\/#*-|"
                     42: # define       PUSHOVER        " bg;*#&"
                     43: # define       SHOTS           "$@Oo:"
                     44: 
                     45: /* number of "directions" */
                     46: # define       NUMDIRECTIONS   4
                     47: 
                     48: /* absolute directions (facings) - counterclockwise */
                     49: # define       NORTH           0
                     50: # define       WEST            1
                     51: # define       SOUTH           2
                     52: # define       EAST            3
                     53: # define       ALLDIRS         0xf
                     54: 
                     55: /* relative directions - counterclockwise */
                     56: # define       FRONT           0
                     57: # define       LEFT            1
                     58: # define       BACK            2
                     59: # define       RIGHT           3
                     60: 
                     61: # define       ABSCHARS        "NWSE"
                     62: # define       RELCHARS        "FLBR"
                     63: # define       DIRKEYS         "khjl"
                     64: 
                     65: STATIC char    command[BUFSIZ];
                     66: STATIC int     comlen;
                     67: 
                     68: # ifdef        DEBUG
                     69: STATIC FILE    *debug = NULL;
                     70: # endif        DEBUG
                     71: 
                     72: # define       DEADEND         0x1
                     73: # define       ON_LEFT         0x2
                     74: # define       ON_RIGHT        0x4
                     75: # define       ON_SIDE         (ON_LEFT|ON_RIGHT)
                     76: # define       BEEN            0x8
                     77: # define       BEEN_SAME       0x10
                     78: 
                     79: struct item    {
                     80:        char    what;
                     81:        int     distance;
                     82:        int     flags;
                     83: };
                     84: 
                     85: STATIC struct  item    flbr[NUMDIRECTIONS];
                     86: 
                     87: # define       fitem   flbr[FRONT]
                     88: # define       litem   flbr[LEFT]
                     89: # define       bitem   flbr[BACK]
                     90: # define       ritem   flbr[RIGHT]
                     91: 
                     92: STATIC int             facing;
                     93: STATIC int             row, col;
                     94: STATIC int             num_turns;              /* for wandering */
                     95: STATIC char            been_there[HEIGHT][WIDTH2];
                     96: STATIC struct itimerval        pause_time      = { { 0, 0 }, { 0, 55000 }};
                     97: 
                     98: STATIC
                     99: nothing()
                    100: {
                    101: }
                    102: 
                    103: otto(y, x, face)
                    104:        int     y, x;
                    105:        char    face;
                    106: {
                    107:        register int    i;
                    108:        extern  int     Otto_count;
                    109:        int             old_mask;
                    110: 
                    111: # ifdef        DEBUG
                    112:        if (debug == NULL) {
                    113:                debug = fopen("bug", "w");
                    114:                setbuf(debug, NULL);
                    115:        }
                    116:        fprintf(debug, "\n%c(%d,%d)", face, y, x);
                    117: # endif        DEBUG
                    118:        (void) signal(SIGALRM, nothing);
                    119:        old_mask = sigblock(sigmask(SIGALRM));
                    120:        setitimer(ITIMER_REAL, &pause_time, NULL);
                    121:        sigpause(old_mask);
                    122:        sigsetmask(old_mask);
                    123: 
                    124:        /* save away parameters so other functions may use/update info */
                    125:        switch (face) {
                    126:        case '^':       facing = NORTH; break;
                    127:        case '<':       facing = WEST; break;
                    128:        case 'v':       facing = SOUTH; break;
                    129:        case '>':       facing = EAST; break;
                    130:        default:        abort();
                    131:        }
                    132:        row = y; col = x;
                    133:        been_there[row][col] |= 1 << facing;
                    134: 
                    135:        /* initially no commands to be sent */
                    136:        comlen = 0;
                    137: 
                    138:        /* find something to do */
                    139:        look_around();
                    140:        for (i = 0; i < NUMDIRECTIONS; i++) {
                    141:                if (index(OPPONENT, flbr[i].what) != NULL) {
                    142:                        attack(i, &flbr[i]);
                    143:                        bzero(been_there, sizeof been_there);
                    144:                        goto done;
                    145:                }
                    146:        }
                    147: 
                    148:        if (index(SHOTS, bitem.what) != NULL && !(bitem.what & ON_SIDE)) {
                    149:                duck(BACK);
                    150:                bzero(been_there, sizeof been_there);
                    151: # ifdef BOOTS
                    152:        } else if (go_for_ammo(BOOT_PAIR)) {
                    153:                bzero(been_there, sizeof been_there);
                    154:        } else if (go_for_ammo(BOOT)) {
                    155:                bzero(been_there, sizeof been_there);
                    156: # endif
                    157:        } else if (go_for_ammo(GMINE))
                    158:                bzero(been_there, sizeof been_there);
                    159:        else if (go_for_ammo(MINE))
                    160:                bzero(been_there, sizeof been_there);
                    161:        else
                    162:                wander();
                    163: 
                    164: done:
                    165:        (void) write(Socket, command, comlen);
                    166:        Otto_count += comlen;
                    167: # ifdef        DEBUG
                    168:        (void) fwrite(command, 1, comlen, debug);
                    169: # endif        DEBUG
                    170: }
                    171: 
                    172: # define       direction(abs,rel)      (((abs) + (rel)) % NUMDIRECTIONS)
                    173: 
                    174: STATIC
                    175: stop_look(itemp, c, dist, side)
                    176:        struct  item    *itemp;
                    177:        char    c;
                    178:        int     dist;
                    179:        int     side;
                    180: {
                    181:        switch (c) {
                    182: 
                    183:        case SPACE:
                    184:                if (side)
                    185:                        itemp->flags &= ~DEADEND;
                    186:                return 0;
                    187: 
                    188:        case MINE:
                    189:        case GMINE:
                    190: # ifdef BOOTS
                    191:        case BOOT:
                    192:        case BOOT_PAIR:
                    193: # endif
                    194:                if (itemp->distance == -1) {
                    195:                        itemp->distance = dist;
                    196:                        itemp->what = c;
                    197:                        if (side < 0)
                    198:                                itemp->flags |= ON_LEFT;
                    199:                        else if (side > 0)
                    200:                                itemp->flags |= ON_RIGHT;
                    201:                }
                    202:                return 0;
                    203: 
                    204:        case SHOT:
                    205:        case GRENADE:
                    206:        case SATCHEL:
                    207:        case BOMB:
                    208: # ifdef OOZE
                    209:        case SLIME:
                    210: # endif OOZE
                    211:                if (itemp->distance == -1 || (!side
                    212:                    && (itemp->flags & ON_SIDE
                    213:                    || itemp->what == GMINE || itemp->what == MINE))) {
                    214:                        itemp->distance = dist;
                    215:                        itemp->what = c;
                    216:                        itemp->flags &= ~ON_SIDE;
                    217:                        if (side < 0)
                    218:                                itemp->flags |= ON_LEFT;
                    219:                        else if (side > 0)
                    220:                                itemp->flags |= ON_RIGHT;
                    221:                }
                    222:                return 0;
                    223: 
                    224:        case '{':
                    225:        case '}':
                    226:        case 'i':
                    227:        case '!':
                    228:                itemp->distance = dist;
                    229:                itemp->what = c;
                    230:                itemp->flags &= ~(ON_SIDE|DEADEND);
                    231:                if (side < 0)
                    232:                        itemp->flags |= ON_LEFT;
                    233:                else if (side > 0)
                    234:                        itemp->flags |= ON_RIGHT;
                    235:                return 1;
                    236: 
                    237:        default:
                    238:                /* a wall or unknown object */
                    239:                if (side)
                    240:                        return 0;
                    241:                if (itemp->distance == -1) {
                    242:                        itemp->distance = dist;
                    243:                        itemp->what = c;
                    244:                }
                    245:                return 1;
                    246:        }
                    247: }
                    248: 
                    249: look(rel_dir, itemp)
                    250:        int             rel_dir;
                    251:        struct  item    *itemp;
                    252: {
                    253:        register int            r, c;
                    254:        register char           ch;
                    255: 
                    256:        itemp->what = 0;
                    257:        itemp->distance = -1;
                    258:        itemp->flags = DEADEND|BEEN;            /* true until proven false */
                    259: 
                    260:        switch (direction(facing, rel_dir)) {
                    261: 
                    262:        case NORTH:
                    263:                if (been_there[row - 1][col] & NORTH)
                    264:                        itemp->flags |= BEEN_SAME;
                    265:                for (r = row - 1; r >= 0; r--)
                    266:                        for (c = col - 1; c < col + 2; c++) {
                    267:                                ch = screen[r][c];
                    268:                                if (stop_look(itemp, ch, row - r, c - col))
                    269:                                        goto cont_north;
                    270:                                if (c == col && !been_there[r][c])
                    271:                                        itemp->flags &= ~BEEN;
                    272:                        }
                    273:        cont_north:
                    274:                if (itemp->flags & DEADEND) {
                    275:                        itemp->flags |= BEEN;
                    276:                        been_there[r][col] |= NORTH;
                    277:                        for (r = row - 1; r > row - itemp->distance; r--)
                    278:                                been_there[r][col] = ALLDIRS;
                    279:                }
                    280:                break;
                    281: 
                    282:        case SOUTH:
                    283:                if (been_there[row + 1][col] & SOUTH)
                    284:                        itemp->flags |= BEEN_SAME;
                    285:                for (r = row + 1; r < HEIGHT; r++)
                    286:                        for (c = col - 1; c < col + 2; c++) {
                    287:                                ch = screen[r][c];
                    288:                                if (stop_look(itemp, ch, r - row, col - c))
                    289:                                        goto cont_south;
                    290:                                if (c == col && !been_there[r][c])
                    291:                                        itemp->flags &= ~BEEN;
                    292:                        }
                    293:        cont_south:
                    294:                if (itemp->flags & DEADEND) {
                    295:                        itemp->flags |= BEEN;
                    296:                        been_there[r][col] |= SOUTH;
                    297:                        for (r = row + 1; r < row + itemp->distance; r++)
                    298:                                been_there[r][col] = ALLDIRS;
                    299:                }
                    300:                break;
                    301: 
                    302:        case WEST:
                    303:                if (been_there[row][col - 1] & WEST)
                    304:                        itemp->flags |= BEEN_SAME;
                    305:                for (c = col - 1; c >= 0; c--)
                    306:                        for (r = row - 1; r < row + 2; r++) {
                    307:                                ch = screen[r][c];
                    308:                                if (stop_look(itemp, ch, col - c, row - r))
                    309:                                        goto cont_east;
                    310:                                if (r == row && !been_there[r][c])
                    311:                                        itemp->flags &= ~BEEN;
                    312:                        }
                    313:        cont_west:
                    314:                if (itemp->flags & DEADEND) {
                    315:                        itemp->flags |= BEEN;
                    316:                        been_there[r][col] |= WEST;
                    317:                        for (c = col - 1; c > col - itemp->distance; c--)
                    318:                                been_there[row][c] = ALLDIRS;
                    319:                }
                    320:                break;
                    321: 
                    322:        case EAST:
                    323:                if (been_there[row][col + 1] & EAST)
                    324:                        itemp->flags |= BEEN_SAME;
                    325:                for (c = col + 1; c < WIDTH; c++)
                    326:                        for (r = row - 1; r < row + 2; r++) {
                    327:                                ch = screen[r][c];
                    328:                                if (stop_look(itemp, ch, c - col, r - row))
                    329:                                        goto cont_east;
                    330:                                if (r == row && !been_there[r][c])
                    331:                                        itemp->flags &= ~BEEN;
                    332:                        }
                    333:        cont_east:
                    334:                if (itemp->flags & DEADEND) {
                    335:                        itemp->flags |= BEEN;
                    336:                        been_there[r][col] |= EAST;
                    337:                        for (c = col + 1; c < col + itemp->distance; c++)
                    338:                                been_there[row][c] = ALLDIRS;
                    339:                }
                    340:                break;
                    341: 
                    342:        default:
                    343:                abort();
                    344:        }
                    345: }
                    346: 
                    347: STATIC
                    348: look_around()
                    349: {
                    350:        register int    i;
                    351: 
                    352:        for (i = 0; i < NUMDIRECTIONS; i++) {
                    353:                look(i, &flbr[i]);
                    354: # ifdef        DEBUG
                    355:                fprintf(debug, " look(%c)=%c(%d)(0x%x)",
                    356:                        RELCHARS[i], flbr[i].what, flbr[i].distance, flbr[i].flags);
                    357: # endif        DEBUG
                    358:        }
                    359: }
                    360: 
                    361: /*
                    362:  *     as a side effect modifies facing and location (row, col)
                    363:  */
                    364: 
                    365: STATIC
                    366: face_and_move_direction(rel_dir, distance)
                    367:        int     rel_dir, distance;
                    368: {
                    369:        register int    old_facing;
                    370:        register char   cmd;
                    371: 
                    372:        old_facing = facing;
                    373:        cmd = DIRKEYS[facing = direction(facing, rel_dir)];
                    374: 
                    375:        if (rel_dir != FRONT) {
                    376:                register int    i;
                    377:                struct  item    items[NUMDIRECTIONS];
                    378: 
                    379:                command[comlen++] = toupper(cmd);
                    380:                if (distance == 0) {
                    381:                        /* rotate look's to be in right position */
                    382:                        for (i = 0; i < NUMDIRECTIONS; i++)
                    383:                                items[i] =
                    384:                                        flbr[(i + old_facing) % NUMDIRECTIONS];
                    385:                        bcopy(items, flbr, sizeof flbr);
                    386:                }
                    387:        }
                    388:        while (distance--) {
                    389:                command[comlen++] = cmd;
                    390:                switch (facing) {
                    391: 
                    392:                case NORTH:     row--; break;
                    393:                case WEST:      col--; break;
                    394:                case SOUTH:     row++; break;
                    395:                case EAST:      col++; break;
                    396:                }
                    397:                if (distance == 0)
                    398:                        look_around();
                    399:        }
                    400: }
                    401: 
                    402: STATIC
                    403: attack(rel_dir, itemp)
                    404:        int             rel_dir;
                    405:        struct  item    *itemp;
                    406: {
                    407:        if (!(itemp->flags & ON_SIDE)) {
                    408:                face_and_move_direction(rel_dir, 0);
                    409:                command[comlen++] = 'o';
                    410:                command[comlen++] = 'o';
                    411:                duck(FRONT);
                    412:                command[comlen++] = ' ';
                    413:        } else if (itemp->distance > 1) {
                    414:                face_and_move_direction(rel_dir, 2);
                    415:                duck(FRONT);
                    416:        } else {
                    417:                face_and_move_direction(rel_dir, 1);
                    418:                if (itemp->flags & ON_LEFT)
                    419:                        rel_dir = LEFT;
                    420:                else
                    421:                        rel_dir = RIGHT;
                    422:                (void) face_and_move_direction(rel_dir, 0);
                    423:                command[comlen++] = 'f';
                    424:                command[comlen++] = 'f';
                    425:                duck(FRONT);
                    426:                command[comlen++] = ' ';
                    427:        }
                    428: }
                    429: 
                    430: STATIC
                    431: duck(rel_dir)
                    432:        int     rel_dir;
                    433: {
                    434:        int     dir;
                    435: 
                    436:        switch (dir = direction(facing, rel_dir)) {
                    437: 
                    438:        case NORTH:
                    439:        case SOUTH:
                    440:                if (index(PUSHOVER, screen[row][col - 1]) != NULL)
                    441:                        command[comlen++] = 'h';
                    442:                else if (index(PUSHOVER, screen[row][col + 1]) != NULL)
                    443:                        command[comlen++] = 'l';
                    444:                else if (dir == NORTH
                    445:                        && index(PUSHOVER, screen[row + 1][col]) != NULL)
                    446:                                command[comlen++] = 'j';
                    447:                else if (dir == SOUTH
                    448:                        && index(PUSHOVER, screen[row - 1][col]) != NULL)
                    449:                                command[comlen++] = 'k';
                    450:                else if (dir == NORTH)
                    451:                        command[comlen++] = 'k';
                    452:                else
                    453:                        command[comlen++] = 'j';
                    454:                break;
                    455: 
                    456:        case WEST:
                    457:        case EAST:
                    458:                if (index(PUSHOVER, screen[row - 1][col]) != NULL)
                    459:                        command[comlen++] = 'k';
                    460:                else if (index(PUSHOVER, screen[row + 1][col]) != NULL)
                    461:                        command[comlen++] = 'j';
                    462:                else if (dir == WEST
                    463:                        && index(PUSHOVER, screen[row][col + 1]) != NULL)
                    464:                                command[comlen++] = 'l';
                    465:                else if (dir == EAST
                    466:                        && index(PUSHOVER, screen[row][col - 1]) != NULL)
                    467:                                command[comlen++] = 'h';
                    468:                else if (dir == WEST)
                    469:                        command[comlen++] = 'h';
                    470:                else
                    471:                        command[comlen++] = 'l';
                    472:                break;
                    473:        }
                    474: }
                    475: 
                    476: /*
                    477:  *     go for the closest mine if possible
                    478:  */
                    479: 
                    480: STATIC
                    481: go_for_ammo(mine)
                    482:        char    mine;
                    483: {
                    484:        register int    i, rel_dir, dist;
                    485: 
                    486:        rel_dir = -1;
                    487:        dist = WIDTH;
                    488:        for (i = 0; i < NUMDIRECTIONS; i++) {
                    489:                if (flbr[i].what == mine && flbr[i].distance < dist) {
                    490:                        rel_dir = i;
                    491:                        dist = flbr[i].distance;
                    492:                }
                    493:        }
                    494:        if (rel_dir == -1)
                    495:                return FALSE;
                    496: 
                    497:        if (!(flbr[rel_dir].flags & ON_SIDE)
                    498:        || flbr[rel_dir].distance > 1) {
                    499:                if (dist > 4)
                    500:                        dist = 4;
                    501:                face_and_move_direction(rel_dir, dist);
                    502:        } else
                    503:                return FALSE;           /* until it's done right */
                    504:        return TRUE;
                    505: }
                    506: 
                    507: STATIC
                    508: wander()
                    509: {
                    510:        register int    i, j, rel_dir, dir_mask, dir_count;
                    511: 
                    512:        for (i = 0; i < NUMDIRECTIONS; i++)
                    513:                if (!(flbr[i].flags & BEEN) || flbr[i].distance <= 1)
                    514:                        break;
                    515:        if (i == NUMDIRECTIONS)
                    516:                bzero(been_there, sizeof been_there);
                    517:        dir_mask = dir_count = 0;
                    518:        for (i = 0; i < NUMDIRECTIONS; i++) {
                    519:                j = (RIGHT + i) % NUMDIRECTIONS;
                    520:                if (flbr[j].distance <= 1 || flbr[j].flags & DEADEND)
                    521:                        continue;
                    522:                if (!(flbr[j].flags & BEEN_SAME)) {
                    523:                        dir_mask = 1 << j;
                    524:                        dir_count = 1;
                    525:                        break;
                    526:                }
                    527:                if (j == FRONT
                    528:                && num_turns > 4 + (random() %
                    529:                                ((flbr[FRONT].flags & BEEN) ? 7 : HEIGHT)))
                    530:                        continue;
                    531:                dir_mask |= 1 << j;
                    532: # ifdef notdef
                    533:                dir_count++;
                    534: # else
                    535:                dir_count = 1;
                    536:                break;
                    537: # endif
                    538:        }
                    539:        if (dir_count == 0) {
                    540:                duck(random() % NUMDIRECTIONS);
                    541:                num_turns = 0;
                    542:                return;
                    543:        } else if (dir_count == 1)
                    544:                rel_dir = ffs(dir_mask) - 1;
                    545:        else {
                    546:                rel_dir = ffs(dir_mask) - 1;
                    547:                dir_mask &= ~(1 << rel_dir);
                    548:                while (dir_mask != 0) {
                    549:                        i = ffs(dir_mask) - 1;
                    550:                        if (random() % 5 == 0)
                    551:                                rel_dir = i;
                    552:                        dir_mask &= ~(1 << i);
                    553:                }
                    554:        }
                    555:        if (rel_dir == FRONT)
                    556:                num_turns++;
                    557:        else
                    558:                num_turns = 0;
                    559: 
                    560: # ifdef DEBUG
                    561:        fprintf(debug, " w(%c)", RELCHARS[rel_dir]);
                    562: # endif DEBUG
                    563:        face_and_move_direction(rel_dir, 1);
                    564: }
                    565: 
                    566: # endif OTTO

unix.superglobalmegacorp.com

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