* Is (x,y) a good position of mtmp? If mtmp is NULL, then is (x,y) good * for an object? * * This function will only look at mtmp->mdat, so makemon, mplayer, etc can * call it to generate new monster positions with fake monster structures. */
| 83 | * call it to generate new monster positions with fake monster structures. |
| 84 | */ |
| 85 | boolean |
| 86 | goodpos( |
| 87 | coordxy x, coordxy y, |
| 88 | struct monst *mtmp, |
| 89 | mmflags_nht gpflags) |
| 90 | { |
| 91 | struct permonst *mdat = (struct permonst *) 0; |
| 92 | boolean ignorewater = ((gpflags & MM_IGNOREWATER) != 0), |
| 93 | ignorelava = ((gpflags & MM_IGNORELAVA) != 0), |
| 94 | checkscary = ((gpflags & GP_CHECKSCARY) != 0), |
| 95 | allow_u = ((gpflags & GP_ALLOW_U) != 0), |
| 96 | avoid_monpos = ((gpflags & GP_AVOID_MONPOS) != 0); |
| 97 | |
| 98 | if (!isok(x, y)) |
| 99 | return FALSE; |
| 100 | |
| 101 | /* in many cases, we're trying to create a new monster, which |
| 102 | * can't go on top of the player or any existing monster. |
| 103 | * however, occasionally we are relocating engravings or objects, |
| 104 | * which could be co-located and thus get restricted a bit too much. |
| 105 | * oh well. |
| 106 | */ |
| 107 | if (!allow_u) { |
| 108 | if (u_at(x, y) && mtmp != &gy.youmonst |
| 109 | && (mtmp != u.ustuck || !u.uswallow) |
| 110 | && (!u.usteed || mtmp != u.usteed)) |
| 111 | return FALSE; |
| 112 | } |
| 113 | |
| 114 | if (MON_AT(x, y) && avoid_monpos) |
| 115 | return FALSE; |
| 116 | |
| 117 | if (mtmp) { |
| 118 | struct monst *mtmp2 = m_at(x, y); |
| 119 | |
| 120 | /* Be careful with long worms. A monster may be placed back in |
| 121 | * its own location. Normally, if m_at() returns the same monster |
| 122 | * that we're trying to place, the monster is being placed in its |
| 123 | * own location. However, that is not correct for worm segments, |
| 124 | * because all the segments of the worm return the same m_at(). |
| 125 | * Actually we overdo the check a little bit--a worm can't be placed |
| 126 | * in its own location, period. If we just checked for mtmp->mx |
| 127 | * != x || mtmp->my != y, we'd miss the case where we're called |
| 128 | * to place the worm segment and the worm's head is at x,y. |
| 129 | */ |
| 130 | if (mtmp2 && (mtmp2 != mtmp || mtmp->wormno)) |
| 131 | return FALSE; |
| 132 | |
| 133 | mdat = mtmp->data; |
| 134 | if (is_pool(x, y) && !ignorewater) { |
| 135 | /* [what about Breathless?] */ |
| 136 | if (mtmp == &gy.youmonst) |
| 137 | return (Swimming || Amphibious |
| 138 | || (!Is_waterlevel(&u.uz) |
| 139 | && !is_waterwall(x, y) |
| 140 | /* water on the Plane of Water has no surface |
| 141 | so there's no way to be on or above that */ |
| 142 | && (Levitation || Flying || Wwalking))); |
no test coverage detected