mnearto() * Put monster near (or at) location if possible. * Returns: * 2 if another monster was moved out of this one's way; * 1 if relocation was successful (without moving another one); * 0 otherwise. * Note: if already at the target spot, result is 1 rather than 0. * * Might be called recursively if 'move_other' is True; if so, that argument * will be False on the nested call so th
| 4028 | * will be False on the nested call so there won't be any further recursion. |
| 4029 | */ |
| 4030 | int |
| 4031 | mnearto( |
| 4032 | struct monst *mtmp, |
| 4033 | coordxy x, |
| 4034 | coordxy y, |
| 4035 | boolean move_other, /* make sure mtmp gets to x, y! so move m_at(x, y) */ |
| 4036 | unsigned int rlocflags) |
| 4037 | { |
| 4038 | struct monst *othermon = (struct monst *) 0; |
| 4039 | coordxy newx, newy; |
| 4040 | coord mm; |
| 4041 | int res = 1; |
| 4042 | |
| 4043 | if (mtmp->mx == x && mtmp->my == y && m_at(x, y) == mtmp) |
| 4044 | return res; |
| 4045 | |
| 4046 | if (move_other && (othermon = m_at(x, y)) != 0) { |
| 4047 | /* take othermon off the map; it might end up immediately returning |
| 4048 | but for the moment it is leaving */ |
| 4049 | mon_leaving_level(othermon); |
| 4050 | othermon->mx = othermon->my = 0; /* 'othermon' is not on the map */ |
| 4051 | othermon->mstate |= MON_OFFMAP; |
| 4052 | } |
| 4053 | |
| 4054 | newx = x; |
| 4055 | newy = y; |
| 4056 | if (!goodpos(newx, newy, mtmp, 0)) { |
| 4057 | /* Actually we have real problems if enexto ever fails. |
| 4058 | * Migrating_mons that need to be placed will cause |
| 4059 | * no end of trouble. |
| 4060 | */ |
| 4061 | if (!enexto(&mm, newx, newy, mtmp->data) || !isok(mm.x, mm.y)) { |
| 4062 | if (othermon) { |
| 4063 | /* othermon already had its mx, my set to 0 above |
| 4064 | * and this would shortly cause a sanity check to fail |
| 4065 | * if we just return 0 here. The caller only possesses |
| 4066 | * awareness of mtmp, not othermon. */ |
| 4067 | deal_with_overcrowding(othermon); |
| 4068 | } |
| 4069 | return 0; |
| 4070 | } |
| 4071 | newx = mm.x; |
| 4072 | newy = mm.y; |
| 4073 | } |
| 4074 | /* [this doesn't honor the 'montelecontrol' option] */ |
| 4075 | rloc_to_flag(mtmp, newx, newy, rlocflags); |
| 4076 | |
| 4077 | if (move_other && othermon) { |
| 4078 | res = 2; /* moving another monster out of the way */ |
| 4079 | /* 'move_other'==FALSE this time; fail rather than recurse */ |
| 4080 | if (!mnearto(othermon, x, y, FALSE, rlocflags)) |
| 4081 | deal_with_overcrowding(othermon); |
| 4082 | } |
| 4083 | |
| 4084 | return res; |
| 4085 | } |
| 4086 | |
| 4087 | /* shrieker special action: shriek, maybe summon monster, aggravate */ |
no test coverage detected