… | |
… | |
374 | */ |
374 | */ |
375 | int |
375 | int |
376 | path_to_player (object *mon, object *pl, unsigned mindiff) |
376 | path_to_player (object *mon, object *pl, unsigned mindiff) |
377 | { |
377 | { |
378 | rv_vector rv; |
378 | rv_vector rv; |
379 | sint16 x, y; |
|
|
380 | int lastx, lasty, dir, i, diff, firstdir = 0, lastdir, max = MAX_SPACES, mflags, blocked; |
379 | int dir, i, diff, firstdir = 0, lastdir, max = MAX_SPACES, mflags, blocked; |
381 | maptile *m, *lastmap; |
|
|
382 | |
380 | |
383 | get_rangevector (mon, pl, &rv, 0); |
381 | get_rangevector (mon, pl, &rv, 0); |
384 | |
382 | |
385 | if (rv.distance < mindiff) |
383 | if (rv.distance < mindiff) |
386 | return 0; |
384 | return 0; |
387 | |
385 | |
388 | x = mon->x; |
386 | mapxy pos (mon); |
389 | y = mon->y; |
|
|
390 | m = mon->map; |
|
|
391 | dir = rv.direction; |
387 | dir = rv.direction; |
392 | lastdir = firstdir = rv.direction; /* perhaps we stand next to pl, init firstdir too */ |
388 | lastdir = firstdir = rv.direction; /* perhaps we stand next to pl, init firstdir too */ |
393 | diff = ::max (abs (rv.distance_x), abs (rv.distance_y)); |
389 | diff = ::max (abs (rv.distance_x), abs (rv.distance_y)); |
394 | |
390 | |
395 | /* If we can't solve it within the search distance, return now. */ |
391 | /* If we can't solve it within the search distance, return now. */ |
396 | if (diff > max) |
392 | if (diff > max) |
397 | return 0; |
393 | return 0; |
398 | |
394 | |
399 | while (diff > 1 && max > 0) |
395 | while (diff > 1 && max > 0) |
400 | { |
396 | { |
401 | lastx = x; |
397 | mapxy lastpos = pos; |
402 | lasty = y; |
|
|
403 | lastmap = m; |
|
|
404 | x = lastx + freearr_x[dir]; |
|
|
405 | y = lasty + freearr_y[dir]; |
|
|
406 | |
398 | |
407 | mflags = get_map_flags (m, &m, x, y, &x, &y); |
399 | pos.move (dir); |
408 | blocked = (mflags & P_OUT_OF_MAP) ? MOVE_ALL : GET_MAP_MOVE_BLOCK (m, x, y); |
|
|
409 | |
400 | |
410 | /* Space is blocked - try changing direction a little */ |
401 | /* Space is blocked - try changing direction a little */ |
411 | if ((mflags & P_OUT_OF_MAP) || ((OB_TYPE_MOVE_BLOCK (mon, blocked) || (mflags & P_BLOCKSVIEW)) |
402 | if (!pos.normalise () |
412 | && (m == mon->map && blocked_link (mon, m, x, y)))) |
403 | || (((pos->flags () & P_BLOCKSVIEW) || OB_TYPE_MOVE_BLOCK (mon, pos->move_block)) |
|
|
404 | && blocked_link (mon, pos.m, pos.x, pos.y))) |
413 | { |
405 | { |
414 | /* recalculate direction from last good location. Possible |
406 | /* recalculate direction from last good location. Possible |
415 | * we were not traversing ideal location before. |
407 | * we were not traversing ideal location before. |
416 | */ |
408 | */ |
417 | get_rangevector_from_mapcoord (lastmap, lastx, lasty, pl, &rv, 0); |
409 | get_rangevector_from_mapcoord (lastpos.m, lastpos.x, lastpos.y, pl, &rv, 0); |
418 | if (rv.direction != dir) |
410 | if (rv.direction != dir) |
419 | { |
411 | { |
420 | /* OK - says direction should be different - lets reset the |
412 | /* OK - says direction should be different - lets reset the |
421 | * the values so it will try again. |
413 | * the values so it will try again. |
422 | */ |
414 | */ |
423 | x = lastx; |
|
|
424 | y = lasty; |
|
|
425 | m = lastmap; |
415 | pos = lastpos; |
426 | dir = firstdir = rv.direction; |
416 | dir = firstdir = rv.direction; |
427 | } |
417 | } |
428 | else |
418 | else |
429 | { |
419 | { |
430 | /* direct path is blocked - try taking a side step to |
420 | /* direct path is blocked - try taking a side step to |
… | |
… | |
437 | */ |
427 | */ |
438 | for (i = -DETOUR_AMOUNT; i <= DETOUR_AMOUNT; i++) |
428 | for (i = -DETOUR_AMOUNT; i <= DETOUR_AMOUNT; i++) |
439 | { |
429 | { |
440 | if (i == 0) |
430 | if (i == 0) |
441 | continue; /* already did this, so skip it */ |
431 | continue; /* already did this, so skip it */ |
|
|
432 | |
442 | /* Use lastdir here - otherwise, |
433 | /* Use lastdir here - otherwise, |
443 | * since the direction that the creature should move in |
434 | * since the direction that the creature should move in |
444 | * may change, you could get infinite loops. |
435 | * may change, you could get infinite loops. |
445 | * ie, player is northwest, but monster can only |
436 | * ie, player is northwest, but monster can only |
446 | * move west, so it does that. It goes some distance, |
437 | * move west, so it does that. It goes some distance, |
… | |
… | |
448 | * can't do that, but now finds it can move east, and |
439 | * can't do that, but now finds it can move east, and |
449 | * gets back to its original point. lastdir contains |
440 | * gets back to its original point. lastdir contains |
450 | * the last direction the creature has successfully |
441 | * the last direction the creature has successfully |
451 | * moved. |
442 | * moved. |
452 | */ |
443 | */ |
453 | |
|
|
454 | x = lastx + freearr_x[absdir (lastdir + i)]; |
|
|
455 | y = lasty + freearr_y[absdir (lastdir + i)]; |
|
|
456 | m = lastmap; |
444 | pos = lastpos; |
457 | mflags = get_map_flags (m, &m, x, y, &x, &y); |
445 | pos.move (absdir (lastdir + i)); |
458 | if (mflags & P_OUT_OF_MAP) |
446 | |
|
|
447 | if (!pos.normalise ()) |
459 | continue; |
448 | continue; |
460 | blocked = GET_MAP_MOVE_BLOCK (m, x, y); |
449 | |
461 | if (OB_TYPE_MOVE_BLOCK (mon, blocked)) |
450 | mapspace &ms = *pos; |
|
|
451 | |
|
|
452 | if (ms.flags () & P_BLOCKSVIEW) |
462 | continue; |
453 | continue; |
463 | if (mflags & P_BLOCKSVIEW) |
454 | |
|
|
455 | if (OB_TYPE_MOVE_BLOCK (mon, ms.move_block)) |
464 | continue; |
456 | continue; |
465 | |
457 | |
466 | if (m == mon->map && blocked_link (mon, m, x, y)) |
458 | if (blocked_link (mon, pos.m, pos.x, pos.y)) |
467 | break; |
459 | break; |
468 | } |
460 | } |
|
|
461 | |
469 | /* go through entire loop without finding a valid |
462 | /* go through entire loop without finding a valid |
470 | * sidestep to take - thus, no valid path. |
463 | * sidestep to take - thus, no valid path. |
471 | */ |
464 | */ |
472 | if (i == (DETOUR_AMOUNT + 1)) |
465 | if (i == DETOUR_AMOUNT + 1) |
473 | return 0; |
466 | return 0; |
|
|
467 | |
474 | diff--; |
468 | diff--; |
475 | lastdir = dir; |
469 | lastdir = dir; |
476 | max--; |
470 | max--; |
477 | if (!firstdir) |
471 | if (!firstdir) |
478 | firstdir = dir + i; |
472 | firstdir = dir + i; |
… | |
… | |
482 | { |
476 | { |
483 | /* we moved towards creature, so diff is less */ |
477 | /* we moved towards creature, so diff is less */ |
484 | diff--; |
478 | diff--; |
485 | max--; |
479 | max--; |
486 | lastdir = dir; |
480 | lastdir = dir; |
|
|
481 | |
487 | if (!firstdir) |
482 | if (!firstdir) |
488 | firstdir = dir; |
483 | firstdir = dir; |
489 | } |
484 | } |
490 | |
485 | |
491 | if (diff <= 1) |
486 | if (diff <= 1) |
492 | { |
487 | { |
493 | /* Recalculate diff (distance) because we may not have actually |
488 | /* Recalculate diff (distance) because we may not have actually |
494 | * headed toward player for entire distance. |
489 | * headed toward player for entire distance. |
495 | */ |
490 | */ |
496 | get_rangevector_from_mapcoord (m, x, y, pl, &rv, 0); |
491 | get_rangevector_from_mapcoord (pos.m, pos.x, pos.y, pl, &rv, 0); |
497 | diff = ::max (abs (rv.distance_x), abs (rv.distance_y)); |
492 | diff = ::max (abs (rv.distance_x), abs (rv.distance_y)); |
498 | } |
493 | } |
499 | |
494 | |
500 | if (diff > max) |
495 | if (diff > max) |
501 | return 0; |
496 | return 0; |
… | |
… | |
566 | |
561 | |
567 | /* Give starting characters identified, uncursed, and undamned |
562 | /* Give starting characters identified, uncursed, and undamned |
568 | * items. Just don't identify gold or silver, or it won't be |
563 | * items. Just don't identify gold or silver, or it won't be |
569 | * merged properly. |
564 | * merged properly. |
570 | */ |
565 | */ |
571 | if (need_identify (op)) |
566 | if (op->need_identify ()) |
572 | { |
567 | { |
573 | op->set_flag (FLAG_IDENTIFIED); |
568 | op->set_flag (FLAG_IDENTIFIED); |
574 | op->clr_flag (FLAG_CURSED); |
569 | op->clr_flag (FLAG_CURSED); |
575 | op->clr_flag (FLAG_DAMNED); |
570 | op->clr_flag (FLAG_DAMNED); |
576 | } |
571 | } |
… | |
… | |
2003 | { |
1998 | { |
2004 | if (!op->map || op->map->in_memory != MAP_ACTIVE) |
1999 | if (!op->map || op->map->in_memory != MAP_ACTIVE) |
2005 | return 0; |
2000 | return 0; |
2006 | |
2001 | |
2007 | /* Sanity check: make sure dir is valid */ |
2002 | /* Sanity check: make sure dir is valid */ |
2008 | if (dir < 0 || dir >= 9) |
2003 | if (dir < 0 || dir > 8) |
2009 | { |
2004 | { |
2010 | LOG (llevError, "move_player: invalid direction %d\n", dir); |
2005 | LOG (llevError, "move_player: invalid direction %d\n", dir); |
2011 | return 0; |
2006 | return 0; |
2012 | } |
2007 | } |
2013 | |
2008 | |