|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.