// distance - compare various distance calculations (something *not* to // be figured out during a 7DRL) // // CFLAGS="-lm -lncurses" make distance && ./distance #include #include #include #include #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define ABS(a) ((a) < 0 ? -(a) : (a)) typedef struct { int yy; int xx; } coord; int chebyshev(coord *p1, coord *p2); int distance(coord *p1, coord *p2); int taxicab(coord *p1, coord *p2); // this romanizes into various different spellings. "standard 8-way // distance metric" (so will get you a square field of view) int chebyshev(coord *p1, coord *p2) { int dy = ABS(p2->yy - p1->yy); int dx = ABS(p2->xx - p1->xx); return MAX(dy, dx); } // Pythagorean, or the bean haters. may vary depending on how the value // is rounded. rounding up to a number outside of the level map might // be bad, while always rounding towards zero might be bad for // different reasons int distance(coord *p1, coord *p2) { int dy = p2->yy - p1->yy; int dx = p2->xx - p1->xx; return lround(sqrt(dx * dx + dy * dy)); } // or the "Manhattan" distance int taxicab(coord *p1, coord *p2) { return ABS(p2->yy - p1->yy) + ABS(p2->xx - p1->xx); } // Bresenham's line algorithm (from Rosetta Code) int line(coord *p1, coord *p2) { int y0 = p1->yy; int x0 = p1->xx; const int dx = abs(p2->xx - x0), sx = x0 < p2->xx ? 1 : -1; const int dy = abs(p2->yy - y0), sy = y0 < p2->yy ? 1 : -1; int err = (dx > dy ? dx : -dy) / 2, e2; int distance = 0; while (1) { if (x0 == p2->xx && y0 == p2->yy) break; distance++; mvaddch(y0, x0, '.'); e2 = err; if (e2 > -dx) { err -= dy; x0 += sx; } if (e2 < dy) { err += dx; y0 += sy; } } return distance; } int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); initscr(); curs_set(FALSE); keypad(stdscr, TRUE); leaveok(stdscr, TRUE); meta(stdscr, TRUE); //nodelay(stdscr, TRUE); noecho(); nonl(); raw(); // where the HERO (Hapless Explorer of Random Orthographies) is coord hero; hero.yy = 1; hero.xx = 1; coord kitten; kitten.yy = LINES / 2; kitten.xx = COLS / 2; mvaddstr(0, 0, "use h j k l or arrows to move, q or Q to quit"); int running = 1; while (running) { int dirty = 0; mvaddch(kitten.yy, kitten.xx, 'M'); // 'M' is for 'mlatu' mvaddch(hero.yy, hero.xx, '@'); int ch = getch(); switch (ch) { case 'h': hero.xx -= 1; if (hero.xx < 0) hero.xx = 0; dirty = 1; break; case KEY_DOWN: case 'j': hero.yy += 1; if (hero.yy >= LINES) hero.yy = LINES - 1; dirty = 1; break; case KEY_UP: case 'k': hero.yy -= 1; if (hero.yy < 1) hero.yy = 1; dirty = 1; break; case KEY_RIGHT: case 'l': hero.xx += 1; if (hero.xx >= COLS) hero.xx = COLS - 1; dirty = 1; break; case 'y': hero.xx -= 1; if (hero.xx < 0) hero.xx = 0; hero.yy -= 1; if (hero.yy < 1) hero.yy = 1; dirty = 1; break; case 'u': hero.xx += 1; if (hero.xx >= COLS) hero.xx = COLS - 1; hero.yy -= 1; if (hero.yy < 1) hero.yy = 1; dirty = 1; break; case 'b': hero.xx -= 1; if (hero.xx < 0) hero.xx = 0; hero.yy += 1; if (hero.yy >= LINES) hero.yy = LINES - 1; dirty = 1; break; case 'n': hero.xx += 1; if (hero.xx >= COLS) hero.xx = COLS - 1; hero.yy += 1; if (hero.yy >= LINES) hero.yy = LINES - 1; dirty = 1; break; case 'Q': case 'q': running = 0; break; default:; } if (dirty) { clear(); int bdist = line(&hero, &kitten); move(0, 0); clrtoeol(); char *msg; if (asprintf(&msg, "8way %d bres %d taxi %d pyth %d", chebyshev(&hero, &kitten), bdist, taxicab(&hero, &kitten), distance(&hero, &kitten)) >= 0) { addstr(msg); free(msg); } } } endwin(); } gemini://thrig.me/blog/2024/03/16/distance.c

-- Leo's gemini proxy

-- Connecting to thrig.me:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/plain

-- Response ended

-- Page fetched on Sun May 19 09:12:35 2024