* Walk a path from src_cc to dest_cc, calling a proc for each location * except the starting one. If the proc returns FALSE, stop walking * and return FALSE. If stopped early, dest_cc will be the location * before the failed callback. */
| 653 | * before the failed callback. |
| 654 | */ |
| 655 | boolean |
| 656 | walk_path( |
| 657 | coord *src_cc, coord *dest_cc, |
| 658 | boolean (*check_proc)(genericptr_t, coordxy, coordxy), |
| 659 | genericptr_t arg) |
| 660 | { |
| 661 | int err; |
| 662 | coordxy x, y, dx, dy, x_change, y_change, i, prev_x, prev_y; |
| 663 | boolean keep_going = TRUE; |
| 664 | |
| 665 | /* Use Bresenham's Line Algorithm to walk from src to dest. |
| 666 | * |
| 667 | * This should be replaced with a more versatile algorithm |
| 668 | * since it handles slanted moves in a suboptimal way. |
| 669 | * Going from 'x' to 'y' needs to pass through 'z', and will |
| 670 | * fail if there's an obstacle there, but it could choose to |
| 671 | * pass through 'Z' instead if that way imposes no obstacle. |
| 672 | * ..y .Zy |
| 673 | * xz. vs x.. |
| 674 | * Perhaps we should check both paths and accept whichever |
| 675 | * one isn't blocked. But then multiple zigs and zags could |
| 676 | * potentially produce a meandering path rather than the best |
| 677 | * attempt at a straight line. And (*check_proc)() would |
| 678 | * need to work more like 'travel', distinguishing between |
| 679 | * testing a possible move and actually attempting that move. |
| 680 | */ |
| 681 | dx = dest_cc->x - src_cc->x; |
| 682 | dy = dest_cc->y - src_cc->y; |
| 683 | prev_x = x = src_cc->x; |
| 684 | prev_y = y = src_cc->y; |
| 685 | |
| 686 | if (dx < 0) { |
| 687 | x_change = -1; |
| 688 | dx = -dx; |
| 689 | } else { |
| 690 | x_change = 1; |
| 691 | } |
| 692 | if (dy < 0) { |
| 693 | y_change = -1; |
| 694 | dy = -dy; |
| 695 | } else { |
| 696 | y_change = 1; |
| 697 | } |
| 698 | i = err = 0; |
| 699 | if (dx < dy) { |
| 700 | while (i++ < dy) { |
| 701 | prev_x = x; |
| 702 | prev_y = y; |
| 703 | y += y_change; |
| 704 | err += dx << 1; |
| 705 | if (err > dy) { |
| 706 | x += x_change; |
| 707 | err -= dy << 1; |
| 708 | } |
| 709 | /* check for early exit condition */ |
| 710 | if (!(keep_going = (*check_proc)(arg, x, y))) |
| 711 | break; |
| 712 | } |
no outgoing calls
no test coverage detected