* Try to find a dismount point adjacent to the steed's location. * If all else fails, try enexto(). Use enexto() as a last resort because * enexto() chooses its point randomly, possibly even outside the * room's walls, which is not what we want. * Adapted from mail daemon code. */
| 457 | * Adapted from mail daemon code. |
| 458 | */ |
| 459 | staticfn boolean |
| 460 | landing_spot( |
| 461 | coord *spot, /* landing position (we fill it in) */ |
| 462 | int reason, |
| 463 | int forceit) |
| 464 | { |
| 465 | coord cc, try[8]; /* 8: the 8 spots adjacent to the hero's spot */ |
| 466 | int i, j, best_j, clockwise_j, counterclk_j, |
| 467 | n, viable, distance, min_distance = -1; |
| 468 | coordxy x, y; |
| 469 | boolean found, impaird, kn_trap, boulder; |
| 470 | struct trap *t; |
| 471 | |
| 472 | (void) memset((genericptr_t) try, 0, sizeof try); |
| 473 | n = 0; |
| 474 | j = xytodir(u.dx, u.dy); |
| 475 | if (reason == DISMOUNT_KNOCKED && j != DIR_ERR) { |
| 476 | /* we'll check preferred location first; if viable it'll be picked */ |
| 477 | best_j = j; |
| 478 | try[0].x = u.dx, try[0].y = u.dy; |
| 479 | /* the two next best locations are checked second and third */ |
| 480 | i = rn2(2); |
| 481 | clockwise_j = DIR_RIGHT(j); /* (j + 1) % 8 */ |
| 482 | dirtocoord(&cc, clockwise_j); |
| 483 | try[1 + i].x = cc.x, try[1 + i].y = cc.y; /* [1] or [2] */ |
| 484 | counterclk_j = DIR_LEFT(j); /* (j + 8 - 1) % 8 */ |
| 485 | dirtocoord(&cc, counterclk_j); |
| 486 | try[2 - i].x = cc.x, try[2 - i].y = cc.y; /* [2] or [1] */ |
| 487 | n = 3; |
| 488 | debugpline3("knock from saddle: best %s, next %s or %s", |
| 489 | directionname(best_j), |
| 490 | directionname(clockwise_j), directionname(counterclk_j)); |
| 491 | } else { |
| 492 | best_j = clockwise_j = counterclk_j = -1; |
| 493 | } |
| 494 | for (j = 0; j < N_DIRS; ++j) { |
| 495 | /* fortunately NODIAG() handling isn't needed for DISMOUNT_KNOCKED |
| 496 | because hero can only ride when humanoid */ |
| 497 | if (j == best_j || j == clockwise_j || j == counterclk_j) |
| 498 | continue; |
| 499 | /* j==0 is W, j==1 NW, j==2 N, j==3 NE, ..., around to j==7 SW; |
| 500 | so odd j values are diagonal directions here */ |
| 501 | if (reason == DISMOUNT_POLY && NODIAG(u.umonnum) && (j % 1) != 0) |
| 502 | continue; |
| 503 | dirtocoord(&cc, j); |
| 504 | try[n++] = cc; |
| 505 | } |
| 506 | |
| 507 | /* |
| 508 | * Up to three passes; |
| 509 | * i==0: voluntary dismount without impairment avoids known traps and |
| 510 | * boulders; |
| 511 | * i==1: voluntary dismount with impairment or knocked out of saddle |
| 512 | * avoids boulders but allows known traps; |
| 513 | * i==2: other, allow traps and boulders. |
| 514 | * |
| 515 | * Fallback to i==1 if nothing appropriate was found for i==0 and |
| 516 | * to i==2 as last resort. |
no test coverage detected