| 445 | } |
| 446 | |
| 447 | void |
| 448 | teleds(coordxy nux, coordxy nuy, int teleds_flags) |
| 449 | { |
| 450 | unsigned was_swallowed; |
| 451 | boolean ball_active, ball_still_in_range = FALSE, |
| 452 | allow_drag = (teleds_flags & TELEDS_ALLOW_DRAG) != 0, |
| 453 | is_teleport = (teleds_flags & TELEDS_TELEPORT) != 0; |
| 454 | struct monst *vault_guard = vault_occupied(u.urooms) ? findgd() : 0; |
| 455 | |
| 456 | if (u.utraptype == TT_BURIEDBALL) { |
| 457 | /* unearth it */ |
| 458 | buried_ball_to_punishment(); |
| 459 | } |
| 460 | ball_active = (Punished && uball->where != OBJ_FREE); |
| 461 | if (!ball_active |
| 462 | || near_capacity() > SLT_ENCUMBER |
| 463 | || distmin(u.ux, u.uy, nux, nuy) > 1) |
| 464 | allow_drag = FALSE; |
| 465 | |
| 466 | /* If they have to move the ball, then drag if allow_drag is true; |
| 467 | * otherwise they are teleporting, so unplacebc(). |
| 468 | * If they don't have to move the ball, then always "drag" whether or |
| 469 | * not allow_drag is true, because we are calling that function, not |
| 470 | * to drag, but to move the chain. *However*, there are some dumb |
| 471 | * special cases: |
| 472 | * 0 0 |
| 473 | * _X move east -----> X_ |
| 474 | * @ @ |
| 475 | * These are permissible if teleporting, but not if dragging. As a |
| 476 | * result, drag_ball() needs to know about allow_drag and might end |
| 477 | * up dragging the ball anyway. Also, drag_ball() might find that |
| 478 | * dragging the ball is completely impossible (ball in range but there's |
| 479 | * rock in the way), in which case it teleports the ball on its own. |
| 480 | */ |
| 481 | if (ball_active) { |
| 482 | if (!carried(uball) && distmin(nux, nuy, uball->ox, uball->oy) <= 2) |
| 483 | ball_still_in_range = TRUE; /* don't have to move the ball */ |
| 484 | else if (!allow_drag) |
| 485 | unplacebc(); /* have to move the ball */ |
| 486 | } |
| 487 | reset_utrap(FALSE); |
| 488 | was_swallowed = u.uswallow; /* set_ustuck(Null) clears uswallow */ |
| 489 | set_ustuck((struct monst *) 0); |
| 490 | u.ux0 = u.ux; |
| 491 | u.uy0 = u.uy; |
| 492 | |
| 493 | if (!hideunder(&gy.youmonst) && gy.youmonst.data->mlet == S_MIMIC) { |
| 494 | /* mimics stop being unnoticed */ |
| 495 | gy.youmonst.m_ap_type = M_AP_NOTHING; |
| 496 | } |
| 497 | |
| 498 | if (was_swallowed) { |
| 499 | if (Punished) { /* ball&chain are off map while swallowed */ |
| 500 | ball_active = TRUE; /* to put chain and non-carried ball on map */ |
| 501 | ball_still_in_range = allow_drag = FALSE; /* (redundant) */ |
| 502 | } |
| 503 | docrt(); |
| 504 | } |
no test coverage detected