/* raptor.c * Plots out tragectory of three raptors targeting a victim at the center * of an equilateral triangle. Raptors/person can be set to any initial * coordinates by editing the source. * Options are available to display (crummy) graphical output. * * See http://xkcd.com/135/ * * Have fun! * * Copyright 2009 Andrew Poelstra * Do what you want, but please leave my name attached * to this code for as long as it's reasonably intact. */ #include #include #include /* Don't set DRAW_GRAPHIC and CHECK_ALL ANGLES; you'll regret it. */ #define DRAW_GRAPHIC 1 #define CHECK_ALL_ANGLES 0 #define ANGLE_STEP 0.1 #define DEFAULT_ANGLE 54.4 #define G_WIDTH 200 #define G_HEIGHT 200 #define MIN_DISPLAY_TIME 3500 /* Minimum time needed to output "Caught at (x, y) message */ #define DISPLAY_STEP 5 /* Number of ms required to add another space before the | for the bar-graph display */ typedef struct raptor { double x; double y; double vx; double vy; double v; } Raptor; long magnitude(long x, long y) { return sqrt(x * x + y * y); } void print_raptor(Raptor *r) { printf("At (%f, %f), velocity (%f, %f)\nTotal velocity %f\n\n", r->x, r->y, r->vx, r->vy, r->v); } /* Units used are mm and msec */ int main(void) { size_t i, x, y; double angle; double x_ratio, y_ratio; unsigned long time_elapsed = 0; char marks[G_WIDTH][G_HEIGHT]; Raptor r[3], you; /* Blank out graphic */ for(x = 0; x < G_WIDTH; ++x) for(y = 0; y < G_HEIGHT; ++y) marks[x][y] = ' '; /* try all angles */ #if CHECK_ALL_ANGLES for(angle = 0; angle <= 360; angle += ANGLE_STEP) { #else angle = DEFAULT_ANGLE; { #endif /* Set nobody moving initially */ r[0].vx = r[0].vy = r[0].v = r[1].vx = r[1].vy = r[1].v = r[2].vx = r[2].vy = r[2].v = you.vx = you.vy = you.v = 0; /* Place raptors */ /* For 20m sides, use coordinates * (0, 0) * (0, 11547) * (10000, -5773) * (-10000, -5773) * For 20m between self and raptors, use * (0, 0) * (0, 20000) * (17321, -10000) * (-17321, -10000) */ you.x = 0; you.y = 0; r[0].x = 0; r[0].y = 11547; r[1].x = 10000; r[1].y = -5773; r[2].x = -10000; r[2].y = -5773; /* Set victim velocity based on angle */ you.v = 6000; you.vx = you.v * sin(angle * 3.141592 / 180); you.vy = you.v * cos(angle * 3.141592 / 180); /* Step for 5 000 msec */ time_elapsed = 0; while(time_elapsed < 5000) { /* Set accelleration */ r[0].v += 4 * (r[0].v < 10000); r[1].v += 4 * (r[1].v < 25000); r[2].v += 4 * (r[2].v < 25000); /* Set velocity */ if(magnitude(r[0].x - you.x, r[0].y - you.y) < 100 || magnitude(r[1].x - you.x, r[1].y - you.y) < 100 || magnitude(r[2].x - you.x, r[2].y - you.y) < 100) { break; } x_ratio = (you.x - r[0].x) / magnitude(r[0].x - you.x, r[0].y - you.y); y_ratio = (you.y - r[0].y) / magnitude(r[0].x - you.x, r[0].y - you.y); r[0].vx = r[0].v * x_ratio; r[0].vy = r[0].v * y_ratio; x_ratio = (you.x - r[1].x) / magnitude(r[1].x - you.x, r[1].y - you.y); y_ratio = (you.y - r[1].y) / magnitude(r[1].x - you.x, r[1].y - you.y); r[1].vx = r[1].v * x_ratio; r[1].vy = r[1].v * y_ratio; x_ratio = (you.x - r[2].x) / magnitude(r[2].x - you.x, r[2].y - you.y); y_ratio = (you.y - r[2].y) / magnitude(r[2].x - you.x, r[2].y - you.y); r[2].vx = r[2].v * x_ratio; r[2].vy = r[2].v * y_ratio; /* Move raptors */ r[0].x += r[0].vx / 1000; r[0].y += r[0].vy / 1000; r[1].x += r[1].vx / 1000; r[1].y += r[1].vy / 1000; r[2].x += r[2].vx / 1000; r[2].y += r[2].vy / 1000; /* Move you */ you.x += you.vx / 1000; you.y += you.vy / 1000; /* mark everybody */ #if DRAW_GRAPHIC if(time_elapsed % 10 == 0) { marks[(int) (G_WIDTH / 2 + r[0].x / 3 / G_WIDTH)][(int) (G_HEIGHT / 3 - r[0].y / 2 / G_HEIGHT)] = '1'; marks[(int) (G_WIDTH / 2 + r[1].x / 3 / G_WIDTH)][(int) (G_HEIGHT / 3 - r[1].y / 2 / G_HEIGHT)] = '2'; marks[(int) (G_WIDTH / 2 + r[2].x / 3 / G_WIDTH)][(int) (G_HEIGHT / 3 - r[2].y / 2 / G_HEIGHT)] = '3'; marks[(int) (G_WIDTH / 2 + you.x / 3 / G_WIDTH)][(int) (G_HEIGHT / 3 - you.y / 2 / G_HEIGHT)] = 'y'; } #endif ++time_elapsed; } if(time_elapsed > MIN_DISPLAY_TIME) { printf("Caught at (%.2f, %.2f) \tAngle: %.2f\tTime elapsed: %ld", you.x / 1000, you.y / 1000, angle, time_elapsed); for(i = MIN_DISPLAY_TIME; i < time_elapsed; i += DISPLAY_STEP) printf(" "); puts("|"); } /* end try all angles */ } #if DRAW_GRAPHIC printf("You are at %3f, %3f.\n", you.x / 1000, you.y / 1000); for(y = 0; y < G_HEIGHT; ++y) { for(x = 0; x < G_WIDTH; ++x) { printf("%c", marks[x][y]); } puts(""); } #endif return 0; }