From 74b9e8e455d245365157a889040a218d0748ae20 Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Tue, 6 Jul 2010 13:53:17 -0600 Subject: [PATCH] Finally got sensors debugged --- Makefile | 7 +- ctanks.c | 207 ++++++++++++++++++++++++++++------------------- ctanks.h | 45 +++++++---- round.html.m4 | 28 +++++++ tanks.js | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++ test-tanks.c | 122 +++++++++++++++++++++++++--- trig.c | 93 --------------------- trig.h | 25 ------ 8 files changed, 520 insertions(+), 226 deletions(-) create mode 100644 round.html.m4 create mode 100644 tanks.js delete mode 100644 trig.c delete mode 100644 trig.h diff --git a/Makefile b/Makefile index 47f2beb..287ebdc 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,11 @@ +LDFLAGS = -lm + all: test test: test-tanks - ./test-tanks + ./test-tanks | m4 round.html.m4 - > round.html test-tanks: test-tanks.o ctanks.o + +clean: + rm -f test-tanks *.o \ No newline at end of file diff --git a/ctanks.c b/ctanks.c index acfe384..47de757 100644 --- a/ctanks.c +++ b/ctanks.c @@ -2,9 +2,22 @@ #include #include #include -#include "trig.h" #include "ctanks.h" +/* Debugging help */ +#define DUMPf(fmt, args...) fprintf(stderr, "%s:%s:%d " fmt "\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#define DUMP() DUMPf("") +#define DUMP_d(v) DUMPf("%s = %d", #v, v) +#define DUMP_x(v) DUMPf("%s = 0x%x", #v, v) +#define DUMP_s(v) DUMPf("%s = %s", #v, v) +#define DUMP_c(v) DUMPf("%s = %c", #v, v) +#define DUMP_f(v) DUMPf("%s = %f", #v, v) +#define DUMP_xy(v) DUMPf("%s = (%f, %f)", #v, v[0], v[1]); +#define DUMP_angle(v) DUMPf("%s = %.3fπ", #v, (v/PI)); + +#define sq(x) ((x) * (x)) + + void tank_init(struct tank *tank, tank_run_func *run, void *udata) { @@ -32,16 +45,16 @@ tank_set_speed(struct tank *tank, float left, float right) tank->speed.desired[1] = right; } -int +float tank_get_turret(struct tank *tank) { return tank->turret.current; } void -tank_set_turret(struct tank *tank, int angle) +tank_set_turret(struct tank *tank, float angle) { - tank->turret.desired = angle; + tank->turret.desired = fmodf(angle, 2*PI); } int @@ -50,7 +63,7 @@ tank_get_sensor(struct tank *tank, int sensor_num) if ((sensor_num < 0) || (sensor_num > TANK_MAX_SENSORS)) { return 0; } - return tank->sensor[sensor_num].triggered; + return tank->sensors[sensor_num].triggered; } void @@ -60,16 +73,19 @@ tank_set_led(struct tank *tank, int active) } static void -rotate_point(int angle, float point[2]) +rotate_point(float angle, float point[2]) { float cos_, sin_; float new[2]; - cos_ = trig_cos(angle); - sin_ = trig_sin(angle); + cos_ = cosf(angle); + sin_ = sinf(angle); - new[0] = point[0]*cos_ + point[1]*sin_; + new[0] = point[0]*cos_ - point[1]*sin_; new[1] = point[0]*sin_ + point[1]*cos_; + + point[0] = new[0]; + point[1] = new[1]; } @@ -95,7 +111,7 @@ tank_sensor_calc(struct tanks_game *game, rpos[0] = tpos[0]; rpos[1] = tpos[1]; - rotate_point(theta, rpos); + rotate_point(-theta, rpos); if (fabsf(rpos[1]) < TANK_RADIUS) { that->killer = this; that->cause_death = "shot"; @@ -103,50 +119,59 @@ tank_sensor_calc(struct tanks_game *game, } /* Calculate sensors */ - for (i = 0; i < this->num_sensors; i += 1) { - int theta; + for (i = 0; i < TANK_MAX_SENSORS; i += 1) { + float theta; float rpos[2]; float m_r, m_s; /* No need to re-check this sensor if it's already firing */ - if (this->sensor[i].triggered) { + if (this->sensors[i].triggered) { continue; } /* If the tank is out of range, don't bother */ - if (dist2 < this->sensor[i].range_adj2) { + if (dist2 > sq(this->sensors[i].range + TANK_RADIUS)) { continue; } /* What is the angle of our sensor? */ - theta = this->angle; - if (this->sensor[i].turret) { + theta = this->angle + this->sensors[i].angle; + if (this->sensors[i].turret) { theta += this->turret.current; } + theta = fmodf(theta, 2*PI); /* Rotate tpos by theta */ rpos[0] = tpos[0]; rpos[1] = tpos[1]; - rotate_point(theta, rpos); + rotate_point(-theta, rpos); - /* Sensor is symmetrical, we can consider only first quadrant */ + /* Sensor is symmetrical, we can consider only top quadrants */ rpos[1] = fabsf(rpos[1]); - /* Compute slopes to tank and of our sensor */ - m_s = tan(theta); - m_r = rpos[1] / rpos[0]; + /* Compute inverse slopes to tank and of our sensor */ + m_s = 1 / tanf(this->sensors[i].width / 2); + m_r = rpos[0] / rpos[1]; - /* If their slope is greater than ours, they're inside the arc */ + if (1 == i) { + DUMP(); + DUMP_angle(this->angle); + DUMP_angle(theta); + DUMP_xy(tpos); + DUMP_xy(rpos); + } + + /* If our inverse slope is less than theirs, they're inside the arc */ if (m_r >= m_s) { - this->sensor[i].triggered = 1; + this->sensors[i].triggered = 1; continue; } /* Now check if the edge of the arc intersects the tank. Do this just like with firing. */ - rotate_point(this->sensor[i].width / 2, rpos); + rotate_point(this->sensors[i].width / -2, rpos); if (fabsf(rpos[1]) < TANK_RADIUS) { - this->sensor[i].triggered = 1; + this->sensors[i].triggered = 1; } } } @@ -156,12 +181,14 @@ do_shit_with(struct tanks_game *game, struct tank *this, struct tank *that) { - float vector[2]; - int dist2; /* Integer to avoid overflow! */ - float tpos; /* Translated position */ - int i; + float vector[2]; + float dist2; /* distance squared */ + float tpos; /* Translated position */ + int i; - /* Don't bother if one is dead */ + /* Don't bother if that is dead */ + /* XXX: If three tanks occupy the same space at the same time, only + the first two will collide. */ if ((this->killer) || (that->killer)) { return; } @@ -171,16 +198,11 @@ do_shit_with(struct tanks_game *game, for (i = 0; i < 2; i += 1) { float halfsize = game->size[i] / 2; - /* XXX: is there a more elegant way to do this? */ - vector[i] = that->position[i] - this->position[i]; - if (2*vector[i] > game->size[i]) { - vector[i] -= game->size[i]; - } else if (2*vector[i] < game->size[i]) { - vector[i] += game->size[i]; - } + vector[i] = halfsize - fabsf(that->position[i] - this->position[i] - halfsize); } + /* Compute distance^2 for range comparisons */ - dist2 = ((vector[0] * vector[0]) + (vector[1] * vector[1])); + dist2 = sq(vector[0]) + sq(vector[1]); /* If they're not within sensor range, there's nothing to do. */ if (dist2 > TANK_SENSOR_ADJ2) { @@ -193,7 +215,7 @@ do_shit_with(struct tanks_game *game, this->cause_death = "collision"; that->killer = this; - this->cause_death = "collision"; + that->cause_death = "collision"; return; } @@ -203,43 +225,51 @@ do_shit_with(struct tanks_game *game, tank_sensor_calc(game, that, this, dist2); } -void -tanks_print_tank(struct tanks_game *game, - struct tank *tank) -{ - printf("%p\n", tank); -} - void tanks_move_tank(struct tanks_game *game, struct tank *tank) { int i; - float movement[2]; - int angle; + float movement; + float angle; + + /* Rotate the turret */ + { + float rot_angle; /* Quickest way there */ + + /* Constrain rot_angle to between -PI and PI */ + rot_angle = tank->turret.desired - tank->turret.current; + while (rot_angle < 0) { + rot_angle += 2*PI; + } + rot_angle = fmodf(PI + rot_angle, 2*PI) - PI; + + rot_angle = min(TANK_MAX_TURRET_ROT, rot_angle); + rot_angle = max(-TANK_MAX_TURRET_ROT, rot_angle); + tank->turret.current = fmodf(tank->turret.current + rot_angle, 2*PI); + } /* Fakey acceleration */ for (i = 0; i < 2; i += 1) { if (tank->speed.current[i] == tank->speed.desired[i]) { /* Do nothing */ } else if (tank->speed.current[i] < tank->speed.desired[i]) { - tank->speed.current[i] = max(tank->speed.current[i] - TANK_MAX_ACCEL, + tank->speed.current[i] = min(tank->speed.current[i] + TANK_MAX_ACCEL, tank->speed.desired[i]); } else { - tank->speed.current[i] = min(tank->speed.current[i] + TANK_MAX_ACCEL, + tank->speed.current[i] = max(tank->speed.current[i] - TANK_MAX_ACCEL, tank->speed.desired[i]); } } /* The simple case */ if (tank->speed.current[0] == tank->speed.current[1]) { - movement[0] = tank->speed.current[0]; - movement[1] = tank->speed.current[1]; - angle = tank->angle; + movement = tank->speed.current[0] * (TANK_TOP_SPEED / 100.0); + angle = 0; } else { /* pflarr's original comment: * - * The tank drives around in a circle of radius r, which is some * + * The tank drives around in a circle of radius r, which is some * offset on a line perpendicular to the tank. The distance it * travels around the circle varies with the speed of each tread, * and is such that each side of the tank moves an equal angle @@ -250,29 +280,25 @@ tanks_move_tank(struct tanks_game *game, float friction; float v[2]; float So, Si; - float w, r; - int theta; + float r; + float theta; int dir; /* The first thing Paul's code does is find "friction", which seems to be a penalty for having the treads go in opposite directions. This probably plays hell with precisely-planned tanks, which I find very ha ha. */ - friction = .25 * (fabsf(tank->speed.current[0] - tank->speed.current[1]) / 200); - - v[0] = tank->speed.current[0] * friction; - v[1] = tank->speed.current[1] * friction; + friction = .75 * (fabsf(tank->speed.current[0] - tank->speed.current[1]) / 200); + v[0] = tank->speed.current[0] * (1 - friction) * (TANK_TOP_SPEED / 100.0); + v[1] = tank->speed.current[1] * (1 - friction) * (TANK_TOP_SPEED / 100.0); /* Outside and inside speeds */ So = max(v[0], v[1]); Si = min(v[0], v[1]); dir = (v[0] > v[1]) ? 1 : -1; - /* Width of tank */ - w = TANK_RADIUS * 2; - /* Radius of circle to outside tread (use similar triangles) */ - r = So * w / (So - Si); + r = So * (TANK_RADIUS * 2) / (So - Si); /* pflarr: @@ -285,28 +311,25 @@ tanks_move_tank(struct tanks_game *game, theta = So/r We multiply it by dir to adjust for the direction of rotation */ - theta = rad2deg(So/r) * dir; + theta = So/r * dir; - /* Translate so the circle's center is 0,0, rotate the point by - theta, then add back in. */ - v[0] = trig_cos(tank->angle + 90*dir) * (TANK_RADIUS - r); - v[1] = trig_sin(tank->angle + 90*dir) * (TANK_RADIUS - r); - - movement[0] = v[0]; - movement[1] = v[1]; - rotate_point(theta, movement); - - movement[0] -= v[0]; - movement[1] -= v[1]; + movement = r * tanf(theta); angle = theta; } /* Now move the tank */ - for (i = 0; i < 2; i += 1) { - tank->position[i] = fmodf(tank->position[i] + movement[i] + game->size[i], - game->size[i]); + tank->angle = fmodf(tank->angle + angle + 2*PI, 2*PI); + { + float m[2]; + + m[0] = cosf(tank->angle) * movement; + m[1] = sinf(tank->angle) * movement; + + for (i = 0; i < 2; i += 1) { + tank->position[i] = fmodf(tank->position[i] + m[i] + game->size[i], + game->size[i]); + } } - tank->angle = (tank->angle + angle + 360) % 360; } void @@ -314,11 +337,31 @@ tanks_run_turn(struct tanks_game *game, struct tank *tanks, int ntanks) { int i, j; + /* Run programs */ + for (i = 0; i < ntanks; i += 1) { + if (! tanks[i].killer) { + tanks[i].run(&tanks[i], &tanks[i].udata); + } + } + + /* Clear sensors */ + for (i = 0; i < ntanks; i += 1) { + for (j = 0; j < TANK_MAX_SENSORS; j += 1) { + tanks[i].sensors[j].triggered = 0; + } + } + + /* Move */ + for (i = 0; i < ntanks; i += 1) { + if (! tanks[i].killer) { + tanks_move_tank(game, &(tanks[i])); + } + } + + /* Sense and fire */ for (i = 0; i < ntanks; i += 1) { for (j = i + 1; j < ntanks; j += 1) { do_shit_with(game, &(tanks[i]), &(tanks[j])); } - tanks_print_tank(game, &(tanks[i])); - tanks_move_tank(game, &(tanks[i])); } } diff --git a/ctanks.h b/ctanks.h index f36e2ec..dd9a2d9 100644 --- a/ctanks.h +++ b/ctanks.h @@ -2,11 +2,15 @@ #define __CTANKS_H__ /* Some useful constants */ -#define TANK_MAX_SENSORS 10 -#define TANK_RADIUS 7.5 -#define TANK_SENSOR_RANGE 100 -#define TANK_CANNON_RANGE (TANK_SENSOR_RANGE / 2) -#define TANK_MAX_ACCEL 35 +#define PI 3.14159265358979323846 + +#define TANK_MAX_SENSORS 10 +#define TANK_RADIUS 7.5 +#define TANK_SENSOR_RANGE 100 +#define TANK_CANNON_RANGE (TANK_SENSOR_RANGE / 2) +#define TANK_MAX_ACCEL 35 +#define TANK_MAX_TURRET_ROT (PI/3) +#define TANK_TOP_SPEED 7 /* (tank radius + tank radius)^2 */ #define TANK_COLLISION_ADJ2 \ @@ -18,6 +22,16 @@ #define TANK_SENSOR_ADJ2 \ ((TANK_SENSOR_RANGE + TANK_RADIUS) * (TANK_SENSOR_RANGE + TANK_RADIUS)) + +#ifndef rad2deg +#define rad2deg(r) ((int)(180*(r)/PI)) +#endif + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + struct tanks_game { float size[2]; /* dimensions of playing field */ }; @@ -25,10 +39,10 @@ struct tanks_game { struct tank; struct sensor { - int angle; - int width; - float range; - float range_adj2; /* (range + TANK_RADIUS)^2 */ + float angle; + float width; + int range; + int range_adj2; /* (range + TANK_RADIUS)^2 */ int turret; /* Mounted to turret? */ int triggered; }; @@ -37,19 +51,18 @@ typedef void tank_run_func(struct tank *, void *); struct tank { float position[2]; /* Current position on the board */ - int angle; /* Current orientation */ + float angle; /* Current orientation */ struct { float current[2]; /* Current tread speed */ float desired[2]; /* Desired tread speed */ } speed; struct { - int current; /* Current turret angle */ - int desired; /* Desired turret angle */ + float current; /* Current turret angle */ + float desired; /* Desired turret angle */ int firing; /* True if firing this turn */ int recharge; /* Turns until gun is recharged */ } turret; - struct sensor sensor[TANK_MAX_SENSORS]; /* Sensor array */ - int num_sensors; /* Number of sensors */ + struct sensor sensors[TANK_MAX_SENSORS]; /* Sensor array */ int led; /* State of the LED */ struct tank *killer; /* Killer, or NULL if alive */ char *cause_death; /* Cause of death */ @@ -76,10 +89,10 @@ void tank_fire(struct tank *tank); void tank_set_speed(struct tank *tank, float left, float right); /** Get the current turret angle */ -int tank_get_turret(struct tank *tank); +float tank_get_turret(struct tank *tank); /** Set the desired turret angle */ -void tank_set_turret(struct tank *tank, int angle); +void tank_set_turret(struct tank *tank, float angle); /** Is a sensor active? */ int tank_get_sensor(struct tank *tank, int sensor_num); diff --git a/round.html.m4 b/round.html.m4 new file mode 100644 index 0000000..e7a827b --- /dev/null +++ b/round.html.m4 @@ -0,0 +1,28 @@ + + + + Tank Game + + + + + +
+

0 fps

+ + +divert(0) diff --git a/tanks.js b/tanks.js new file mode 100644 index 0000000..78c29d7 --- /dev/null +++ b/tanks.js @@ -0,0 +1,219 @@ +function dbg(o) { + e = document.getElementById("debug"); + e.innerHTML = o; +} + +function torgba(color, alpha) { + var r = parseInt(color.substring(1,3), 16); + var g = parseInt(color.substring(3,5), 16); + var b = parseInt(color.substring(5,7), 16); + + return "rgba(" + r + "," + g + "," + b + "," + alpha + ")"; +} + +function Tank(ctx, width, height, color, sensors) { + var craterStroke = torgba(color, 0.5); + var craterFill = torgba(color, 0.2); + var sensorStroke = torgba(color, 0.4); + var maxlen = 0; + + this.x = 0; + this.y = 0; + this.rotation = 0; + this.turret = 0; + + // Do all the yucky math up front + this.sensors = new Array(); + for (i in sensors) { + var s = sensors[i]; + // r, angle, width, turret + this.sensors[i] = new Array(); + this.sensors[i][0] = s[0]; + this.sensors[i][1] = s[1] - s[2]/2; + this.sensors[i][2] = s[1] + s[2]/2; + this.sensors[i][3] = s[3]?1:0; + if (s[0] > maxlen) { + maxlen = s[0]; + } + } + + // Set up our state, for later interleaved draw requests + this.set_state = function(x, y, rotation, turret, flags, sensor_state) { + this.x = x; + this.y = y; + this.rotation = rotation; + this.turret = turret; + if (flags & 1) { + this.fire = 5; + } + this.led = flags & 2; + this.sensor_state = sensor_state; + } + + this.draw_crater = function() { + var points = 7; + var angle = Math.PI / points; + + ctx.save(); + ctx.translate(this.x, this.y); + ctx.rotate(this.rotation); + + ctx.lineWidth = 2; + ctx.strokeStyle = craterStroke; + ctx.fillStyle = craterFill; + ctx.beginPath(); + ctx.moveTo(12, 0); + for (i = 0; i < points; i += 1) { + ctx.rotate(angle); + ctx.lineTo(6, 0); + ctx.rotate(angle); + ctx.lineTo(12, 0); + } + ctx.closePath() + ctx.stroke(); + ctx.fill(); + + ctx.restore(); + } + + this.draw_sensors = function() { + ctx.save(); + ctx.translate(this.x, this.y); + ctx.rotate(this.rotation); + + ctx.lineWidth = 1; + for (i in this.sensors) { + var s = this.sensors[i]; + var adj = this.turret * s[3]; + + if (this.sensor_state & (1 << i)) { + // Sensor is triggered + ctx.strokeStyle = "#000"; + } else { + ctx.strokeStyle = sensorStroke; + } + ctx.beginPath(); + ctx.moveTo(0, 0); + ctx.arc(0, 0, s[0], s[1] + adj, s[2] + adj, false); + ctx.closePath(); + ctx.stroke(); + } + + ctx.restore(); + } + + this.draw_tank = function() { + ctx.save(); + ctx.translate(this.x, this.y); + ctx.rotate(this.rotation); + + ctx.fillStyle = color; + ctx.fillRect(-5, -4, 10, 8); + ctx.fillStyle = "#777"; + ctx.fillRect(-7, -9, 15, 5); + ctx.fillRect(-7, 4, 15, 5); + ctx.rotate(this.turret); + if (this.fire) { + ctx.fillStyle = ("rgba(68,204,68," + this.fire/5 +")"); + ctx.fillRect(0, -1, 45, 2); + this.fire -= 1; + } else { + if (this.led) { + ctx.fillStyle = "#f00"; + } else { + ctx.fillStyle = "#000"; + } + ctx.fillRect(0, -1, 10, 2); + } + + ctx.restore(); + } + + this.draw_wrap_sensors = function() { + var orig_x = this.x; + var orig_y = this.y; + for (x = this.x - width; x < width + maxlen; x += width) { + for (y = this.y - height; y < height + maxlen; y += height) { + if ((-maxlen < x) && (x < width + maxlen) && + (-maxlen < y) && (y < height + maxlen)) { + this.x = x; + this.y = y; + this.draw_sensors(); + } + } + } + this.x = orig_x; + this.y = orig_y; + } +} + +function start(game) { + var canvas = document.getElementById('battlefield'); + var ctx = canvas.getContext('2d'); + var loop_id; + + canvas.width = game[0][0]; + canvas.height = game[0][1]; + // game[2] is tank descriptions + var turns = game[2]; + + // Set up tanks + var tanks = new Array(); + for (i in game[1]) { + var desc = game[1][i]; + tanks[i] = new Tank(ctx, game[0][0], game[0][1], desc[0], desc[1]); + } + + var frame = 0; + var lastframe = 0; + var fps = document.getElementById('fps'); + + function update_fps() { + fps.innerHTML = (frame - lastframe); + lastframe = frame; + } + + function update() { + var idx = frame % (turns.length + 20); + var turn; + + frame += 1; + if (idx >= turns.length) { + return; + } + + canvas.width = canvas.width; + turn = turns[idx]; + + // Draw craters first + for (i in turn) { + t = turn[i]; + if (! t) { + tanks[i].draw_crater(); + } + } + // Then sensors + for (i in turn) { + t = turn[i]; + if (t) { + // Surely there's a better way to do this. + tanks[i].set_state(t[0], t[1], t[2], t[3], t[4], t[5]); + tanks[i].draw_wrap_sensors(); + } + } + // Then tanks + for (i in turn) { + t = turn[i]; + if (t) { + tanks[i].draw_tank() + } + } + } + + //loop_id = setInterval(update, 66); + loop_id = setInterval(update, 200); + if (fps) { + setInterval(update_fps, 1000); + } +} + diff --git a/test-tanks.c b/test-tanks.c index 7babfd4..03c967d 100644 --- a/test-tanks.c +++ b/test-tanks.c @@ -2,24 +2,128 @@ #include #include "ctanks.h" +#define NTANKS 2 + void test_run(struct tank *tank, void *unused) { - tank_set_speed(tank, 30, 50); - tank_set_turret(tank, fmod(tank->turret.desired + 0.2, 2*PI)); + tank_set_speed(tank, 61, 60); + tank_set_turret(tank, 0); +} + +void +sitting_duck(struct tank *tank, void *unused) +{ + tank_set_turret(tank, tank->turret.desired + PI/15); } int main(int argc, char *argv[]) { - struct tank mytank; - int i; + struct tanks_game game; + struct tank mytanks[NTANKS]; + int i; - tank_init(&mytank, test_run, NULL); - printf("hi\n"); - for (i = 0; i < 4; i += 1) { - printf("%f\n", mytank.turret.desired); - mytank.run(&mytank, mytank.udata); + game.size[0] = 600; + game.size[1] = 600; + + printf("[\n"); + printf("[%d, %d, %d],\n", + (int)game.size[0], (int)game.size[1], TANK_CANNON_RANGE); + printf("[\n"); + for (i = 0; i < NTANKS; i += 1) { + if (i == 1) { + printf(" [\"#888888\",["); + tank_init(&mytanks[i], sitting_duck, NULL); + } else { + int j; + + printf(" [\"#ff4444\",["); + tank_init(&mytanks[i], test_run, NULL); + + mytanks[i].sensors[0].angle = 0; + mytanks[i].sensors[0].width = PI/10; + mytanks[i].sensors[0].range = 50; + mytanks[i].sensors[0].turret = 1; + + mytanks[i].sensors[1].angle = 0*PI/2; + mytanks[i].sensors[1].width = PI/3; + mytanks[i].sensors[1].range = 100; + mytanks[i].sensors[1].turret = 1; + + mytanks[i].sensors[2].angle = 1*PI/2; + mytanks[i].sensors[2].width = PI/3; + mytanks[i].sensors[2].range = 100; + mytanks[i].sensors[2].turret = 1; + + mytanks[i].sensors[3].angle = 2*PI/2; + mytanks[i].sensors[3].width = PI/3; + mytanks[i].sensors[3].range = 100; + mytanks[i].sensors[3].turret = 1; + + mytanks[i].sensors[4].angle = 3*PI/2; + mytanks[i].sensors[4].width = PI/3; + mytanks[i].sensors[4].range = 100; + mytanks[i].sensors[4].turret = 1; + + for (j = 0; j < TANK_MAX_SENSORS; j += 1) { + struct sensor *s = &(mytanks[i].sensors[j]); + + if (s->range) { + printf("[%d, %.2f, %.2f, %d],", + (int)(s->range), + s->angle, + s->width, + s->turret); + } + } + } + mytanks[i].position[0] = (game.size[0] / NTANKS) * i + 50; + mytanks[i].position[1] = 50; + /* XXX: print sensors */ + printf("]],\n"); } + printf("],\n"); + printf("// Rounds\n"); + printf("[\n"); + + for (i = 0; i < 200; i += 1) { + int j; + + tanks_run_turn(&game, mytanks, NTANKS); + printf("[\n"); + for (j = 0; j < NTANKS; j += 1) { + struct tank *t = &(mytanks[j]); + + if (t->killer) { + printf(" 0,\n"); + } else { + int k; + int flags = 0; + int sensors = 0; + + for (k = 0; k < TANK_MAX_SENSORS; k += 1) { + if (t->sensors[k].triggered) { + sensors |= (1 << k); + } + } + if (t->turret.firing) { + flags |= 1; + } + if (t->led) { + flags |= 2; + } + printf(" [%d,%d,%.2f,%.2f,%d,%d],\n", + (int)(t->position[0]), + (int)(t->position[1]), + t->angle, + t->turret.current, + flags, + sensors); + } + } + printf("],\n"); + } + printf("]]\n"); return 0; } diff --git a/trig.c b/trig.c deleted file mode 100644 index d45e7f8..0000000 --- a/trig.c +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include -#include "trig.h" - -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -static float trig_cos_table[] = { - 1.000000, 0.999848, 0.999391, 0.998630, 0.997564, 0.996195, - 0.994522, 0.992546, 0.990268, 0.987688, 0.984808, 0.981627, - 0.978148, 0.974370, 0.970296, 0.965926, 0.961262, 0.956305, - 0.951057, 0.945519, 0.939693, 0.933580, 0.927184, 0.920505, - 0.913545, 0.906308, 0.898794, 0.891007, 0.882948, 0.874620, - 0.866025, 0.857167, 0.848048, 0.838671, 0.829038, 0.819152, - 0.809017, 0.798636, 0.788011, 0.777146, 0.766044, 0.754710, - 0.743145, 0.731354, 0.719340, 0.707107, 0.694658, 0.681998, - 0.669131, 0.656059, 0.642788, 0.629320, 0.615661, 0.601815, - 0.587785, 0.573576, 0.559193, 0.544639, 0.529919, 0.515038, - 0.500000, 0.484810, 0.469472, 0.453990, 0.438371, 0.422618, - 0.406737, 0.390731, 0.374607, 0.358368, 0.342020, 0.325568, - 0.309017, 0.292372, 0.275637, 0.258819, 0.241922, 0.224951, - 0.207912, 0.190809, 0.173648, 0.156434, 0.139173, 0.121869, - 0.104528, 0.087156, 0.069756, 0.052336, 0.034899, 0.017452, - 0.000000, -}; - -float -trig_cos(int angle) -{ - int a; - float ret; - - a = abs(angle) % 180; - if (a > 90) { - a = 180 - a; - } - ret = trig_cos_table[a]; - a = abs(angle) % 360; - if ((a > 90) && (a < 270)) { - ret = -ret; - } - return ret; -} - -float -trig_sin(int angle) -{ - return trig_cos(90 - angle); -} - -float -trig_tan(int angle) -{ - return trig_sin(angle) / trig_cos(angle); -} - -int -trig_asin(float x) -{ - return rad2deg(asinf(x)); -} - -int -trig_acos(float x) -{ - return rad2deg(acosf(x)); -} - -int -trig_atan2(float y, float x) -{ - return rad2deg(atan2f(y, x)); -} - - -#if 0 -#include - -int -main() -{ - int i, j; - float f; - int t; - - for (i = 0; i < 600; i += 1) { - printf("%-04d %-0.6f %-0.6f\n", i, trig_cos(i), cosf(deg2rad(i))); - } - return 0; -} -#endif diff --git a/trig.h b/trig.h deleted file mode 100644 index e3ce00c..0000000 --- a/trig.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __TRIG_H__ -#define __TRIG_H__ - -/** Trigonometry in degrees - * - * It's just a library to do discrete(-ish) trig, using degrees. It - * uses a lookup table to make sin, cos, and tan really fast. - * Everything is as slow as normal :) - */ - -/* Just to make it clear what scale these functions are dealing with */ -#define PI 3.14159265358979323846 - -#define rad2deg(rad) ((int)(rad * 180 / PI)) -#define deg2rad(deg) ((float)(deg * PI / 180)) - -float trig_cos(int angle); -float trig_sin(int angle); -float trig_atan(int angle); - -int trig_acos(float angle); -int trig_asin(float angle); -int trig_atan2(float y, float x); - -#endif /* __TRIG_H__ */