| 1327 | } |
| 1328 | |
| 1329 | boolean |
| 1330 | linedup( |
| 1331 | coordxy ax, |
| 1332 | coordxy ay, |
| 1333 | coordxy bx, |
| 1334 | coordxy by, |
| 1335 | int boulderhandling) /* 0=block, 1=ignore, 2=conditionally block */ |
| 1336 | { |
| 1337 | int dx, dy, boulderspots; |
| 1338 | |
| 1339 | /* These two values are set for use after successful return. */ |
| 1340 | gt.tbx = ax - bx; |
| 1341 | gt.tby = ay - by; |
| 1342 | |
| 1343 | /* sometimes displacement makes a monster think that you're at its |
| 1344 | own location; prevent it from throwing and zapping in that case */ |
| 1345 | if (!gt.tbx && !gt.tby) |
| 1346 | return FALSE; |
| 1347 | |
| 1348 | /* straight line, orthogonal to the map or diagonal */ |
| 1349 | if ((!gt.tbx || !gt.tby || abs(gt.tbx) == abs(gt.tby)) |
| 1350 | && distmin(gt.tbx, gt.tby, 0, 0) < BOLT_LIM) { |
| 1351 | if (u_at(ax, ay) ? (boolean) couldsee(bx, by) |
| 1352 | : clear_path(ax, ay, bx, by)) |
| 1353 | return TRUE; |
| 1354 | /* don't have line of sight, but might still be lined up |
| 1355 | if that lack of sight is due solely to boulders */ |
| 1356 | if (boulderhandling == 0) |
| 1357 | return FALSE; |
| 1358 | dx = sgn(ax - bx), dy = sgn(ay - by); |
| 1359 | boulderspots = 0; |
| 1360 | do { |
| 1361 | /* <bx,by> is guaranteed to eventually converge with <ax,ay> */ |
| 1362 | bx += dx, by += dy; |
| 1363 | if (blocking_terrain(bx, by)) |
| 1364 | return FALSE; |
| 1365 | if (sobj_at(BOULDER, bx, by)) |
| 1366 | ++boulderspots; |
| 1367 | } while (bx != ax || by != ay); |
| 1368 | /* reached target position without encountering obstacle */ |
| 1369 | if (boulderhandling == 1 || rn2(2 + boulderspots) < 2) |
| 1370 | return TRUE; |
| 1371 | } |
| 1372 | return FALSE; |
| 1373 | } |
| 1374 | |
| 1375 | staticfn int |
| 1376 | m_lined_up(struct monst *mtarg, struct monst *mtmp) |
no test coverage detected