# Another version of BLA

From RogueBasin

Revision as of 17:04, 26 October 2012 by Hari Seldon (Talk | contribs)

/* Adapted from the code displayed at RogueBasin's "Bresenham's Line * Algorithm" article, this function checks for an unobstructed line * of sight between two locations using Bresenham's line algorithm to * draw a line from one point to the other. Returns true if there is * line of sight, false if there is no line of sight. */ int los (int los_x_1, int los_y_1, int los_x_2, int los_y_2, int level) { int delta_x, delta_y, move_x, move_y, error; /* Calculate deltas. */ delta_x = abs (los_x_2 - los_x_1) << 1; delta_y = abs (los_y_2 - los_y_1) << 1; /* Calculate signs. */ move_x = los_x_2 >= los_x_1 ? 1 : -1; move_y = los_y_2 >= los_y_1 ? 1 : -1; /* There is an automatic line of sight, of course, between a * location and the same location or directly adjacent * locations. */ if (abs (los_x_2 - los_x_1) < 2 && abs (los_y_2 - los_y_1) < 2) { /* Return. */ return true; } /* Ensure that the line will not extend too long. */ if (((los_x_2 - los_x_1) * (los_x_2 - los_x_1)) + ((los_y_2 - los_y_1) * (los_y_2 - los_y_1)) > LOS_DISTANCE * LOS_DISTANCE) { /* Return. */ return false; } /* "Draw" the line, checking for obstructions. */ if (delta_x >= delta_y) { /* Calculate the error factor, which may go below zero. */ error = delta_y - (delta_x >> 1); /* Search the line. */ while (los_x_1 != los_x_2) { /* Check for an obstruction. If the obstruction can be "moved * around", it isn't really an obstruction. */ if (feature_data (dungeon (los_x_1, los_y_1, level).feature).obstruction && (((los_y_1 - move_y >= 1 && los_y_1 - move_y <= DUNGEON_HEIGHT) && feature_data (dungeon (los_x_1, los_y_1 - move_y, level).feature).obstruction) || (los_y_1 != los_y_2 || !(delta_y)))) { /* Return. */ return false; } /* Update values. */ if (error > 0) { if (error || (move_x > 0)) { los_y_1 += move_y; error -= delta_x; } } los_x_1 += move_x; error += delta_y; } } else { /* Calculate the error factor, which may go below zero. */ error = delta_x - (delta_y >> 1); /* Search the line. */ while (los_y_1 != los_y_2) { /* Check for an obstruction. If the obstruction can be "moved * around", it isn't really an obstruction. */ if (feature_data (dungeon (los_x_1, los_y_1, level).feature).obstruction && (((los_x_1 - move_x >= 1 && los_x_1 - move_x <= DUNGEON_WIDTH) && feature_data (dungeon (los_x_1 - move_x, los_y_1, level).feature).obstruction) || (los_x_1 != los_x_2 || !(delta_x)))) { /* Return. */ return false; } /* Update values. */ if (error > 0) { if (error || (move_y > 0)) { los_x_1 += move_x; error -= delta_y; } } los_y_1 += move_y; error += delta_x; } } /* Return. */ return true; }