mirror of https://github.com/dirtbags/tanks.git
clang-format
This commit is contained in:
parent
9d3cce9bf6
commit
ffc7d07214
139
ctanks.c
139
ctanks.c
|
@ -1,11 +1,13 @@
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include "ctanks.h"
|
#include "ctanks.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
/* Debugging help */
|
/* Debugging help */
|
||||||
#define DUMPf(fmt, args...) fprintf(stderr, "%s:%s:%d " fmt "\n", __FILE__, __FUNCTION__, __LINE__, ##args)
|
#define DUMPf(fmt, args...) \
|
||||||
|
fprintf(stderr, "%s:%s:%d " fmt "\n", __FILE__, __FUNCTION__, __LINE__, \
|
||||||
|
##args)
|
||||||
#define DUMP() DUMPf("")
|
#define DUMP() DUMPf("")
|
||||||
#define DUMP_d(v) DUMPf("%s = %d", #v, v)
|
#define DUMP_d(v) DUMPf("%s = %d", #v, v)
|
||||||
#define DUMP_x(v) DUMPf("%s = 0x%x", #v, v)
|
#define DUMP_x(v) DUMPf("%s = 0x%x", #v, v)
|
||||||
|
@ -14,94 +16,63 @@
|
||||||
#define DUMP_f(v) DUMPf("%s = %f", #v, v)
|
#define DUMP_f(v) DUMPf("%s = %f", #v, v)
|
||||||
#define DUMP_p(v) DUMPf("%s = %p", #v, v)
|
#define DUMP_p(v) DUMPf("%s = %p", #v, v)
|
||||||
#define DUMP_xy(v) DUMPf("%s = (%f, %f)", #v, v[0], v[1]);
|
#define DUMP_xy(v) DUMPf("%s = (%f, %f)", #v, v[0], v[1]);
|
||||||
#define DUMP_angle(v) DUMPf("%s = %.3fτ", #v, (v/TAU));
|
#define DUMP_angle(v) DUMPf("%s = %.3fτ", #v, (v / TAU));
|
||||||
|
|
||||||
#define sq(x) ((x) * (x))
|
#define sq(x) ((x) * (x))
|
||||||
|
|
||||||
|
void tank_init(struct tank *tank, tank_run_func *run, void *udata) {
|
||||||
void
|
|
||||||
tank_init(struct tank *tank, tank_run_func *run, void *udata)
|
|
||||||
{
|
|
||||||
memset(tank, 0, sizeof(*tank));
|
memset(tank, 0, sizeof(*tank));
|
||||||
tank->run = run;
|
tank->run = run;
|
||||||
tank->udata = udata;
|
tank->udata = udata;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int tank_fire_ready(struct tank *tank) { return (!tank->turret.recharge); }
|
||||||
tank_fire_ready(struct tank *tank)
|
|
||||||
{
|
|
||||||
return (! tank->turret.recharge);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void tank_fire(struct tank *tank) {
|
||||||
tank_fire(struct tank *tank)
|
|
||||||
{
|
|
||||||
tank->turret.firing = tank_fire_ready(tank);
|
tank->turret.firing = tank_fire_ready(tank);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void tank_set_speed(struct tank *tank, float left, float right) {
|
||||||
tank_set_speed(struct tank *tank, float left, float right)
|
|
||||||
{
|
|
||||||
tank->speed.desired[0] = min(max(left, -100), 100);
|
tank->speed.desired[0] = min(max(left, -100), 100);
|
||||||
tank->speed.desired[1] = min(max(right, -100), 100);
|
tank->speed.desired[1] = min(max(right, -100), 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
float tank_get_turret(struct tank *tank) { return tank->turret.current; }
|
||||||
tank_get_turret(struct tank *tank)
|
|
||||||
{
|
|
||||||
return tank->turret.current;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void tank_set_turret(struct tank *tank, float angle) {
|
||||||
tank_set_turret(struct tank *tank, float angle)
|
|
||||||
{
|
|
||||||
tank->turret.desired = fmodf(angle, TAU);
|
tank->turret.desired = fmodf(angle, TAU);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int tank_get_sensor(struct tank *tank, int sensor_num) {
|
||||||
tank_get_sensor(struct tank *tank, int sensor_num)
|
|
||||||
{
|
|
||||||
if ((sensor_num < 0) || (sensor_num > TANK_MAX_SENSORS)) {
|
if ((sensor_num < 0) || (sensor_num > TANK_MAX_SENSORS)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return tank->sensors[sensor_num].triggered;
|
return tank->sensors[sensor_num].triggered;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void tank_set_led(struct tank *tank, int active) { tank->led = active; }
|
||||||
tank_set_led(struct tank *tank, int active)
|
|
||||||
{
|
|
||||||
tank->led = active;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void rotate_point(float angle, float point[2]) {
|
||||||
rotate_point(float angle, float point[2])
|
|
||||||
{
|
|
||||||
float cos_, sin_;
|
float cos_, sin_;
|
||||||
float new[2];
|
float new[2];
|
||||||
|
|
||||||
cos_ = cosf(angle);
|
cos_ = cosf(angle);
|
||||||
sin_ = sinf(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_;
|
new[1] = point[0] * sin_ + point[1] * cos_;
|
||||||
|
|
||||||
point[0] = new[0];
|
point[0] = new[0];
|
||||||
point[1] = new[1];
|
point[1] = new[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tanks_fire_cannon(struct tanks_game *game, struct tank *this,
|
||||||
static void
|
struct tank *that, float vector[2], float dist2) {
|
||||||
tanks_fire_cannon(struct tanks_game *game,
|
|
||||||
struct tank *this,
|
|
||||||
struct tank *that,
|
|
||||||
float vector[2],
|
|
||||||
float dist2)
|
|
||||||
{
|
|
||||||
float theta = this->angle + this->turret.current;
|
float theta = this->angle + this->turret.current;
|
||||||
float rpos[2];
|
float rpos[2];
|
||||||
|
|
||||||
/* If someone's a crater, this is easy (unless we were just killed by the other one, in which case
|
/* If someone's a crater, this is easy (unless we were just killed by the
|
||||||
we have to check the other direction) */
|
other one, in which case we have to check the other direction) */
|
||||||
if ((this->killer && this->killer != that) || that->killer) {
|
if ((this->killer && this->killer != that) || that->killer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -118,7 +89,7 @@ tanks_fire_cannon(struct tanks_game *game,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No need to check if it's not even firing */
|
/* No need to check if it's not even firing */
|
||||||
if (! this->turret.firing) {
|
if (!this->turret.firing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,13 +109,8 @@ tanks_fire_cannon(struct tanks_game *game,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void tanks_sensor_calc(struct tanks_game *game, struct tank *this,
|
||||||
tanks_sensor_calc(struct tanks_game *game,
|
struct tank *that, float vector[2], float dist2) {
|
||||||
struct tank *this,
|
|
||||||
struct tank *that,
|
|
||||||
float vector[2],
|
|
||||||
float dist2)
|
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* If someone's a crater, this is easy */
|
/* If someone's a crater, this is easy */
|
||||||
|
@ -211,13 +177,8 @@ tanks_sensor_calc(struct tanks_game *game,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void compute_vector(struct tanks_game *game, float vector[2], float *dist2,
|
||||||
compute_vector(struct tanks_game *game,
|
struct tank *this, struct tank *that) {
|
||||||
float vector[2],
|
|
||||||
float *dist2,
|
|
||||||
struct tank *this,
|
|
||||||
struct tank *that)
|
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Establish shortest vector from center of this to center of that,
|
/* Establish shortest vector from center of this to center of that,
|
||||||
|
@ -228,8 +189,7 @@ compute_vector(struct tanks_game *game,
|
||||||
vector[i] = that->position[i] - this->position[i];
|
vector[i] = that->position[i] - this->position[i];
|
||||||
if (vector[i] > halfsize) {
|
if (vector[i] > halfsize) {
|
||||||
vector[i] = vector[i] - game->size[i];
|
vector[i] = vector[i] - game->size[i];
|
||||||
}
|
} else if (vector[i] < -halfsize) {
|
||||||
else if (vector[i] < -halfsize) {
|
|
||||||
vector[i] = game->size[i] + vector[i];
|
vector[i] = game->size[i] + vector[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,10 +198,7 @@ compute_vector(struct tanks_game *game,
|
||||||
*dist2 = sq(vector[0]) + sq(vector[1]);
|
*dist2 = sq(vector[0]) + sq(vector[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void tanks_move_tank(struct tanks_game *game, struct tank *tank) {
|
||||||
tanks_move_tank(struct tanks_game *game,
|
|
||||||
struct tank *tank)
|
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
float movement;
|
float movement;
|
||||||
float angle;
|
float angle;
|
||||||
|
@ -268,11 +225,11 @@ tanks_move_tank(struct tanks_game *game,
|
||||||
if (tank->speed.current[i] == tank->speed.desired[i]) {
|
if (tank->speed.current[i] == tank->speed.desired[i]) {
|
||||||
/* Do nothing */
|
/* Do nothing */
|
||||||
} else if (tank->speed.current[i] < tank->speed.desired[i]) {
|
} else if (tank->speed.current[i] < tank->speed.desired[i]) {
|
||||||
tank->speed.current[i] = min(tank->speed.current[i] + TANK_MAX_ACCEL,
|
tank->speed.current[i] =
|
||||||
tank->speed.desired[i]);
|
min(tank->speed.current[i] + TANK_MAX_ACCEL, tank->speed.desired[i]);
|
||||||
} else {
|
} else {
|
||||||
tank->speed.current[i] = max(tank->speed.current[i] - TANK_MAX_ACCEL,
|
tank->speed.current[i] =
|
||||||
tank->speed.desired[i]);
|
max(tank->speed.current[i] - TANK_MAX_ACCEL, tank->speed.desired[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +258,8 @@ tanks_move_tank(struct tanks_game *game,
|
||||||
to be a penalty for having the treads go in opposite directions.
|
to be a penalty for having the treads go in opposite directions.
|
||||||
This probably plays hell with precisely-planned tanks, which I
|
This probably plays hell with precisely-planned tanks, which I
|
||||||
find very ha ha. */
|
find very ha ha. */
|
||||||
friction = TANK_FRICTION * (fabsf(tank->speed.current[0] - tank->speed.current[1]) / 200);
|
friction = TANK_FRICTION *
|
||||||
|
(fabsf(tank->speed.current[0] - tank->speed.current[1]) / 200);
|
||||||
v[0] = tank->speed.current[0] * (1 - friction) * (TANK_TOP_SPEED / 100.0);
|
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);
|
v[1] = tank->speed.current[1] * (1 - friction) * (TANK_TOP_SPEED / 100.0);
|
||||||
|
|
||||||
|
@ -330,7 +288,7 @@ tanks_move_tank(struct tanks_game *game,
|
||||||
theta = So/r
|
theta = So/r
|
||||||
We multiply it by dir to adjust for the direction of rotation
|
We multiply it by dir to adjust for the direction of rotation
|
||||||
*/
|
*/
|
||||||
theta = So/r * dir;
|
theta = So / r * dir;
|
||||||
|
|
||||||
movement = r * tanf(theta);
|
movement = r * tanf(theta);
|
||||||
angle = theta;
|
angle = theta;
|
||||||
|
@ -345,15 +303,13 @@ tanks_move_tank(struct tanks_game *game,
|
||||||
m[1] = sinf(tank->angle) * movement * dir;
|
m[1] = sinf(tank->angle) * movement * dir;
|
||||||
|
|
||||||
for (i = 0; i < 2; i += 1) {
|
for (i = 0; i < 2; i += 1) {
|
||||||
tank->position[i] = fmodf(tank->position[i] + m[i] + game->size[i],
|
tank->position[i] =
|
||||||
game->size[i]);
|
fmodf(tank->position[i] + m[i] + game->size[i], game->size[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void tanks_run_turn(struct tanks_game *game, struct tank *tanks, int ntanks) {
|
||||||
tanks_run_turn(struct tanks_game *game, struct tank *tanks, int ntanks)
|
|
||||||
{
|
|
||||||
int i, j;
|
int i, j;
|
||||||
float vector[2];
|
float vector[2];
|
||||||
float dist2; /* distance squared */
|
float dist2; /* distance squared */
|
||||||
|
@ -369,7 +325,8 @@ tanks_run_turn(struct tanks_game *game, struct tank *tanks, int ntanks)
|
||||||
tanks[i].turret.firing = 0;
|
tanks[i].turret.firing = 0;
|
||||||
tanks[i].turret.recharge = TANK_CANNON_RECHARGE;
|
tanks[i].turret.recharge = TANK_CANNON_RECHARGE;
|
||||||
}
|
}
|
||||||
if (tanks[i].killer) continue;
|
if (tanks[i].killer)
|
||||||
|
continue;
|
||||||
if (tanks[i].turret.recharge) {
|
if (tanks[i].turret.recharge) {
|
||||||
tanks[i].turret.recharge -= 1;
|
tanks[i].turret.recharge -= 1;
|
||||||
}
|
}
|
||||||
|
@ -380,13 +337,15 @@ tanks_run_turn(struct tanks_game *game, struct tank *tanks, int ntanks)
|
||||||
|
|
||||||
/* Move tanks */
|
/* Move tanks */
|
||||||
for (i = 0; i < ntanks; i += 1) {
|
for (i = 0; i < ntanks; i += 1) {
|
||||||
if (tanks[i].killer) continue;
|
if (tanks[i].killer)
|
||||||
|
continue;
|
||||||
tanks_move_tank(game, &(tanks[i]));
|
tanks_move_tank(game, &(tanks[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Probe sensors */
|
/* Probe sensors */
|
||||||
for (i = 0; i < ntanks; i += 1) {
|
for (i = 0; i < ntanks; i += 1) {
|
||||||
if (tanks[i].killer) continue;
|
if (tanks[i].killer)
|
||||||
|
continue;
|
||||||
for (j = i + 1; j < ntanks; j += 1) {
|
for (j = i + 1; j < ntanks; j += 1) {
|
||||||
struct tank *this = &tanks[i];
|
struct tank *this = &tanks[i];
|
||||||
struct tank *that = &tanks[j];
|
struct tank *that = &tanks[j];
|
||||||
|
@ -401,13 +360,15 @@ tanks_run_turn(struct tanks_game *game, struct tank *tanks, int ntanks)
|
||||||
|
|
||||||
/* Run programs */
|
/* Run programs */
|
||||||
for (i = 0; i < ntanks; i += 1) {
|
for (i = 0; i < ntanks; i += 1) {
|
||||||
if (tanks[i].killer) continue;
|
if (tanks[i].killer)
|
||||||
|
continue;
|
||||||
tanks[i].run(&tanks[i], tanks[i].udata);
|
tanks[i].run(&tanks[i], tanks[i].udata);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fire cannons and check for crashes */
|
/* Fire cannons and check for crashes */
|
||||||
for (i = 0; i < ntanks; i += 1) {
|
for (i = 0; i < ntanks; i += 1) {
|
||||||
if (tanks[i].killer) continue;
|
if (tanks[i].killer)
|
||||||
|
continue;
|
||||||
for (j = i + 1; j < ntanks; j += 1) {
|
for (j = i + 1; j < ntanks; j += 1) {
|
||||||
struct tank *this = &tanks[i];
|
struct tank *this = &tanks[i];
|
||||||
struct tank *that = &tanks[j];
|
struct tank *that = &tanks[j];
|
||||||
|
|
11
ctanks.h
11
ctanks.h
|
@ -11,7 +11,7 @@
|
||||||
#define TANK_CANNON_RECHARGE 20 /* Turns to recharge cannon */
|
#define TANK_CANNON_RECHARGE 20 /* Turns to recharge cannon */
|
||||||
#define TANK_CANNON_RANGE (TANK_SENSOR_RANGE / 2)
|
#define TANK_CANNON_RANGE (TANK_SENSOR_RANGE / 2)
|
||||||
#define TANK_MAX_ACCEL 35
|
#define TANK_MAX_ACCEL 35
|
||||||
#define TANK_MAX_TURRET_ROT (TAU/8)
|
#define TANK_MAX_TURRET_ROT (TAU / 8)
|
||||||
#define TANK_TOP_SPEED 7
|
#define TANK_TOP_SPEED 7
|
||||||
#define TANK_FRICTION 0.75
|
#define TANK_FRICTION 0.75
|
||||||
|
|
||||||
|
@ -29,13 +29,13 @@
|
||||||
((TANK_CANNON_RANGE + TANK_RADIUS) * (TANK_CANNON_RANGE + TANK_RADIUS))
|
((TANK_CANNON_RANGE + TANK_RADIUS) * (TANK_CANNON_RANGE + TANK_RADIUS))
|
||||||
|
|
||||||
#ifndef rad2deg
|
#ifndef rad2deg
|
||||||
#define rad2deg(r) ((int)(360*(r)/TAU))
|
#define rad2deg(r) ((int)(360 * (r) / TAU))
|
||||||
#define deg2rad(r) ((r*TAU)/360)
|
#define deg2rad(r) ((r * TAU) / 360)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef max
|
#ifndef max
|
||||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct tanks_game {
|
struct tanks_game {
|
||||||
|
@ -79,7 +79,6 @@ struct tank {
|
||||||
void tank_init(struct tank *tank, tank_run_func *run, void *udata);
|
void tank_init(struct tank *tank, tank_run_func *run, void *udata);
|
||||||
void tanks_run_turn(struct tanks_game *game, struct tank *tanks, int ntanks);
|
void tanks_run_turn(struct tanks_game *game, struct tank *tanks, int ntanks);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Tanks API for scripts
|
* Tanks API for scripts
|
||||||
|
|
12
dump.h
12
dump.h
|
@ -7,7 +7,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Debugging */
|
/* Debugging */
|
||||||
#define DUMPf(fmt, args...) fprintf(stderr, "%s:%s:%d " fmt "\n", __FILE__, __FUNCTION__, __LINE__, ##args)
|
#define DUMPf(fmt, args...) \
|
||||||
|
fprintf(stderr, "%s:%s:%d " fmt "\n", __FILE__, __FUNCTION__, __LINE__, \
|
||||||
|
##args)
|
||||||
#define DUMP() DUMPf("")
|
#define DUMP() DUMPf("")
|
||||||
#define DUMP_d(v) DUMPf("%s = %d", #v, v)
|
#define DUMP_d(v) DUMPf("%s = %d", #v, v)
|
||||||
#define DUMP_x(v) DUMPf("%s = 0x%x", #v, v)
|
#define DUMP_x(v) DUMPf("%s = 0x%x", #v, v)
|
||||||
|
@ -16,15 +18,17 @@
|
||||||
#define DUMP_f(v) DUMPf("%s = %f", #v, v)
|
#define DUMP_f(v) DUMPf("%s = %f", #v, v)
|
||||||
#define DUMP_p(v) DUMPf("%s = %p", #v, v)
|
#define DUMP_p(v) DUMPf("%s = %p", #v, v)
|
||||||
#define DUMP_xy(v) DUMPf("%s = (%f, %f)", #v, v[0], v[1]);
|
#define DUMP_xy(v) DUMPf("%s = (%f, %f)", #v, v[0], v[1]);
|
||||||
#define DUMP_angle(v) DUMPf("%s = %.3fτ", #v, (v/TAU));
|
#define DUMP_angle(v) DUMPf("%s = %.3fτ", #v, (v / TAU));
|
||||||
|
|
||||||
/* Tektronix 4014 drawing */
|
/* Tektronix 4014 drawing */
|
||||||
#define TEK_ENABLE "\033[?38h"
|
#define TEK_ENABLE "\033[?38h"
|
||||||
#define TEK_DISABLE "\033\003"
|
#define TEK_DISABLE "\033\003"
|
||||||
#define TEK(fmt, args...) fprintf(stderr, TEK_ENABLE fmt TEK_DISABLE, ##args)
|
#define TEK(fmt, args...) fprintf(stderr, TEK_ENABLE fmt TEK_DISABLE, ##args)
|
||||||
#define TEK_coord(x, y) ((int)y/32)+32,((int)y%32)+96,((int)x/32)+32,((int)x%32)+64
|
#define TEK_coord(x, y) \
|
||||||
|
((int)y / 32) + 32, ((int)y % 32) + 96, ((int)x / 32) + 32, ((int)x % 32) + 64
|
||||||
|
|
||||||
#define TEK_cls() TEK("\033\014")
|
#define TEK_cls() TEK("\033\014")
|
||||||
#define TEK_line(x1, y1, x2, y2) TEK("\035%c%c%c%c%c%c%c%c", TEK_coord(x1, y1), TEK_coord(x2, y2))
|
#define TEK_line(x1, y1, x2, y2) \
|
||||||
|
TEK("\035%c%c%c%c%c%c%c%c", TEK_coord(x1, y1), TEK_coord(x2, y2))
|
||||||
#define TEK_point(x, y) TEK("\034%c%c%c%c", TEK_coord(x, y))
|
#define TEK_point(x, y) TEK("\034%c%c%c%c", TEK_coord(x, y))
|
||||||
#define TEK_text(x, y, s) TEK("\035%c%c%c%c\037%s", TEK_coord(x, y), s)
|
#define TEK_text(x, y, s) TEK("\035%c%c%c%c\037%s", TEK_coord(x, y), s)
|
||||||
|
|
275
forf.c
275
forf.c
|
@ -27,28 +27,22 @@
|
||||||
* and not new stack types.
|
* and not new stack types.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#include "forf.h"
|
|
||||||
#include "dump.h"
|
#include "dump.h"
|
||||||
|
#include "forf.h"
|
||||||
|
|
||||||
#ifndef max
|
#ifndef max
|
||||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char *forf_error_str[] = {
|
char *forf_error_str[] = {
|
||||||
"None",
|
"None", "Runtime", "Parse", "Underflow", "Overflow",
|
||||||
"Runtime",
|
"Type", "No such procedure", "Divide by zero",
|
||||||
"Parse",
|
|
||||||
"Underflow",
|
|
||||||
"Overflow",
|
|
||||||
"Type",
|
|
||||||
"No such procedure",
|
|
||||||
"Divide by zero",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -56,47 +50,29 @@ char *forf_error_str[] = {
|
||||||
* Memory manipulation
|
* Memory manipulation
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void
|
void forf_memory_init(struct forf_memory *m, long *values, size_t size) {
|
||||||
forf_memory_init(struct forf_memory *m,
|
|
||||||
long *values,
|
|
||||||
size_t size)
|
|
||||||
{
|
|
||||||
m->mem = values;
|
m->mem = values;
|
||||||
m->size = size;
|
m->size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Stack manipulation
|
* Stack manipulation
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void forf_stack_init(struct forf_stack *s, struct forf_value *values,
|
||||||
forf_stack_init(struct forf_stack *s,
|
size_t size) {
|
||||||
struct forf_value *values,
|
|
||||||
size_t size)
|
|
||||||
{
|
|
||||||
s->stack = values;
|
s->stack = values;
|
||||||
s->size = size;
|
s->size = size;
|
||||||
s->top = 0;
|
s->top = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void forf_stack_reset(struct forf_stack *s) { s->top = 0; }
|
||||||
forf_stack_reset(struct forf_stack *s)
|
|
||||||
{
|
|
||||||
s->top = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
size_t forf_stack_len(struct forf_stack *s) { return s->top; }
|
||||||
forf_stack_len(struct forf_stack *s)
|
|
||||||
{
|
|
||||||
return s->top;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int forf_stack_push(struct forf_stack *s, struct forf_value *v) {
|
||||||
forf_stack_push(struct forf_stack *s, struct forf_value *v)
|
|
||||||
{
|
|
||||||
if (s->top == s->size) {
|
if (s->top == s->size) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -104,9 +80,7 @@ forf_stack_push(struct forf_stack *s, struct forf_value *v)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int forf_stack_pop(struct forf_stack *s, struct forf_value *v) {
|
||||||
forf_stack_pop(struct forf_stack *s, struct forf_value *v)
|
|
||||||
{
|
|
||||||
if (0 == s->top) {
|
if (0 == s->top) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -114,23 +88,18 @@ forf_stack_pop(struct forf_stack *s, struct forf_value *v)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void forf_stack_copy(struct forf_stack *dst, struct forf_stack *src) {
|
||||||
forf_stack_copy(struct forf_stack *dst, struct forf_stack *src)
|
|
||||||
{
|
|
||||||
int top = min(dst->size, src->top);
|
int top = min(dst->size, src->top);
|
||||||
|
|
||||||
dst->top = top;
|
dst->top = top;
|
||||||
memcpy(dst->stack, src->stack, sizeof(*dst->stack) * top);
|
memcpy(dst->stack, src->stack, sizeof(*dst->stack) * top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void forf_stack_reverse(struct forf_stack *s) {
|
||||||
void
|
|
||||||
forf_stack_reverse(struct forf_stack *s)
|
|
||||||
{
|
|
||||||
struct forf_value val;
|
struct forf_value val;
|
||||||
size_t pos;
|
size_t pos;
|
||||||
|
|
||||||
for (pos = 0; pos < (s->top)/2; pos += 1) {
|
for (pos = 0; pos < (s->top) / 2; pos += 1) {
|
||||||
size_t qos = s->top - pos - 1;
|
size_t qos = s->top - pos - 1;
|
||||||
|
|
||||||
val = s->stack[pos];
|
val = s->stack[pos];
|
||||||
|
@ -139,12 +108,10 @@ forf_stack_reverse(struct forf_stack *s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long
|
long forf_pop_num(struct forf_env *env) {
|
||||||
forf_pop_num(struct forf_env *env)
|
|
||||||
{
|
|
||||||
struct forf_value val;
|
struct forf_value val;
|
||||||
|
|
||||||
if (! forf_stack_pop(env->data, &val)) {
|
if (!forf_stack_pop(env->data, &val)) {
|
||||||
env->error = forf_error_underflow;
|
env->error = forf_error_underflow;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -156,19 +123,16 @@ forf_pop_num(struct forf_env *env)
|
||||||
return val.v.i;
|
return val.v.i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void forf_push_num(struct forf_env *env, long i) {
|
||||||
forf_push_num(struct forf_env *env, long i)
|
|
||||||
{
|
|
||||||
struct forf_value val;
|
struct forf_value val;
|
||||||
|
|
||||||
val.type = forf_type_number;
|
val.type = forf_type_number;
|
||||||
val.v.i = i;
|
val.v.i = i;
|
||||||
if (! forf_stack_push(env->data, &val)) {
|
if (!forf_stack_push(env->data, &val)) {
|
||||||
env->error = forf_error_overflow;
|
env->error = forf_error_overflow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Pop an entire stack
|
/* Pop an entire stack
|
||||||
*
|
*
|
||||||
* DANGER WILL ROBINSON
|
* DANGER WILL ROBINSON
|
||||||
|
@ -177,14 +141,12 @@ forf_push_num(struct forf_env *env, long i)
|
||||||
* finished with this stack before you push anything onto the data
|
* finished with this stack before you push anything onto the data
|
||||||
* stack, otherwise your returned stack will be corrupted.
|
* stack, otherwise your returned stack will be corrupted.
|
||||||
*/
|
*/
|
||||||
struct forf_stack
|
struct forf_stack forf_pop_stack(struct forf_env *env) {
|
||||||
forf_pop_stack(struct forf_env *env)
|
struct forf_stack s = {0, 0, NULL};
|
||||||
{
|
|
||||||
struct forf_stack s = { 0, 0, NULL };
|
|
||||||
struct forf_value val;
|
struct forf_value val;
|
||||||
size_t depth = 1;
|
size_t depth = 1;
|
||||||
|
|
||||||
if (! forf_stack_pop(env->data, &val)) {
|
if (!forf_stack_pop(env->data, &val)) {
|
||||||
env->error = forf_error_underflow;
|
env->error = forf_error_underflow;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
@ -198,7 +160,7 @@ forf_pop_stack(struct forf_env *env)
|
||||||
s.size = -1;
|
s.size = -1;
|
||||||
while (depth) {
|
while (depth) {
|
||||||
s.size += 1;
|
s.size += 1;
|
||||||
if (! forf_stack_pop(env->data, &val)) {
|
if (!forf_stack_pop(env->data, &val)) {
|
||||||
/* You should never underflow here, there should at least be a
|
/* You should never underflow here, there should at least be a
|
||||||
stack begin marker. */
|
stack begin marker. */
|
||||||
env->error = forf_error_runtime;
|
env->error = forf_error_runtime;
|
||||||
|
@ -223,13 +185,11 @@ forf_pop_stack(struct forf_env *env)
|
||||||
|
|
||||||
/* Push an entire stack onto another stack.
|
/* Push an entire stack onto another stack.
|
||||||
*/
|
*/
|
||||||
int
|
int forf_push_stack(struct forf_stack *dst, struct forf_stack *src) {
|
||||||
forf_push_stack(struct forf_stack *dst, struct forf_stack *src)
|
|
||||||
{
|
|
||||||
struct forf_value val;
|
struct forf_value val;
|
||||||
|
|
||||||
while (forf_stack_pop(src, &val)) {
|
while (forf_stack_pop(src, &val)) {
|
||||||
if (! forf_stack_push(dst, &val)) {
|
if (!forf_stack_push(dst, &val)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,10 +200,8 @@ forf_push_stack(struct forf_stack *dst, struct forf_stack *src)
|
||||||
*
|
*
|
||||||
* This is meant to work with the return value from forf_pop_stack.
|
* This is meant to work with the return value from forf_pop_stack.
|
||||||
*/
|
*/
|
||||||
int
|
int forf_push_to_command_stack(struct forf_env *env, struct forf_stack *src) {
|
||||||
forf_push_to_command_stack(struct forf_env *env, struct forf_stack *src)
|
if (!forf_push_stack(env->command, src)) {
|
||||||
{
|
|
||||||
if (! forf_push_stack(env->command, src)) {
|
|
||||||
env->error = forf_error_overflow;
|
env->error = forf_error_overflow;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -259,24 +217,21 @@ forf_push_to_command_stack(struct forf_env *env, struct forf_stack *src)
|
||||||
* always have "reversed" substacks, and everything else will have them
|
* always have "reversed" substacks, and everything else will have them
|
||||||
* in the right order.
|
* in the right order.
|
||||||
*/
|
*/
|
||||||
int
|
int forf_stack_move_value(struct forf_env *env, struct forf_stack *dst,
|
||||||
forf_stack_move_value(struct forf_env *env,
|
struct forf_stack *src) {
|
||||||
struct forf_stack *dst,
|
|
||||||
struct forf_stack *src)
|
|
||||||
{
|
|
||||||
struct forf_value val;
|
struct forf_value val;
|
||||||
size_t depth = 0;
|
size_t depth = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* Pop from src */
|
/* Pop from src */
|
||||||
if (! forf_stack_pop(env->command, &val)) {
|
if (!forf_stack_pop(env->command, &val)) {
|
||||||
env->error = forf_error_underflow;
|
env->error = forf_error_underflow;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Push to dst (or discard if dst is NULL) */
|
/* Push to dst (or discard if dst is NULL) */
|
||||||
if (dst) {
|
if (dst) {
|
||||||
if (! forf_stack_push(env->data, &val)) {
|
if (!forf_stack_push(env->data, &val)) {
|
||||||
env->error = forf_error_overflow;
|
env->error = forf_error_overflow;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -296,10 +251,8 @@ forf_stack_move_value(struct forf_env *env,
|
||||||
} while (depth > 0);
|
} while (depth > 0);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Procedures
|
* Procedures
|
||||||
|
@ -307,45 +260,28 @@ forf_stack_move_value(struct forf_env *env,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define unproc(name, op) \
|
#define unproc(name, op) \
|
||||||
static void \
|
static void forf_proc_##name(struct forf_env *env) { \
|
||||||
forf_proc_ ## name(struct forf_env *env) \
|
|
||||||
{ \
|
|
||||||
long a = forf_pop_num(env); \
|
long a = forf_pop_num(env); \
|
||||||
\
|
\
|
||||||
forf_push_num(env, op a); \
|
forf_push_num(env, op a); \
|
||||||
}
|
}
|
||||||
|
|
||||||
unproc(inv, ~)
|
unproc(inv, ~) unproc(not, !)
|
||||||
unproc(not, !)
|
|
||||||
|
|
||||||
#define binproc(name, op) \
|
#define binproc(name, op) \
|
||||||
static void \
|
static void forf_proc_##name(struct forf_env *env) { \
|
||||||
forf_proc_ ## name(struct forf_env *env) \
|
|
||||||
{ \
|
|
||||||
long a = forf_pop_num(env); \
|
long a = forf_pop_num(env); \
|
||||||
long b = forf_pop_num(env); \
|
long b = forf_pop_num(env); \
|
||||||
\
|
\
|
||||||
forf_push_num(env, b op a); \
|
forf_push_num(env, b op a); \
|
||||||
}
|
}
|
||||||
|
|
||||||
binproc(add, +)
|
binproc(add, +) binproc(sub, -) binproc(mul, *) binproc(and, &)
|
||||||
binproc(sub, -)
|
binproc(or, |) binproc(xor, ^) binproc(lshift, <<) binproc(rshift, >>)
|
||||||
binproc(mul, *)
|
binproc(gt, >) binproc(ge, >=) binproc(lt, <) binproc(le, <=)
|
||||||
binproc(and, &)
|
binproc(eq, ==) binproc(ne, !=)
|
||||||
binproc(or, |)
|
|
||||||
binproc(xor, ^)
|
|
||||||
binproc(lshift, <<)
|
|
||||||
binproc(rshift, >>)
|
|
||||||
binproc(gt, >)
|
|
||||||
binproc(ge, >=)
|
|
||||||
binproc(lt, <)
|
|
||||||
binproc(le, <=)
|
|
||||||
binproc(eq, ==)
|
|
||||||
binproc(ne, !=)
|
|
||||||
|
|
||||||
static void
|
static void forf_proc_div(struct forf_env *env) {
|
||||||
forf_proc_div(struct forf_env *env)
|
|
||||||
{
|
|
||||||
long a = forf_pop_num(env);
|
long a = forf_pop_num(env);
|
||||||
long b = forf_pop_num(env);
|
long b = forf_pop_num(env);
|
||||||
|
|
||||||
|
@ -356,9 +292,7 @@ forf_proc_div(struct forf_env *env)
|
||||||
forf_push_num(env, b / a);
|
forf_push_num(env, b / a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void forf_proc_mod(struct forf_env *env) {
|
||||||
forf_proc_mod(struct forf_env *env)
|
|
||||||
{
|
|
||||||
long a = forf_pop_num(env);
|
long a = forf_pop_num(env);
|
||||||
long b = forf_pop_num(env);
|
long b = forf_pop_num(env);
|
||||||
|
|
||||||
|
@ -369,30 +303,20 @@ forf_proc_mod(struct forf_env *env)
|
||||||
forf_push_num(env, b % a);
|
forf_push_num(env, b % a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void forf_proc_abs(struct forf_env *env) {
|
||||||
forf_proc_abs(struct forf_env *env)
|
|
||||||
{
|
|
||||||
forf_push_num(env, abs(forf_pop_num(env)));
|
forf_push_num(env, abs(forf_pop_num(env)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void forf_proc_dup(struct forf_env *env) {
|
||||||
forf_proc_dup(struct forf_env *env)
|
|
||||||
{
|
|
||||||
long a = forf_pop_num(env);
|
long a = forf_pop_num(env);
|
||||||
|
|
||||||
forf_push_num(env, a);
|
forf_push_num(env, a);
|
||||||
forf_push_num(env, a);
|
forf_push_num(env, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void forf_proc_pop(struct forf_env *env) { forf_pop_num(env); }
|
||||||
forf_proc_pop(struct forf_env *env)
|
|
||||||
{
|
|
||||||
forf_pop_num(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void forf_proc_exch(struct forf_env *env) {
|
||||||
forf_proc_exch(struct forf_env *env)
|
|
||||||
{
|
|
||||||
long a = forf_pop_num(env);
|
long a = forf_pop_num(env);
|
||||||
long b = forf_pop_num(env);
|
long b = forf_pop_num(env);
|
||||||
|
|
||||||
|
@ -400,9 +324,7 @@ forf_proc_exch(struct forf_env *env)
|
||||||
forf_push_num(env, b);
|
forf_push_num(env, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void forf_proc_if(struct forf_env *env) {
|
||||||
forf_proc_if(struct forf_env *env)
|
|
||||||
{
|
|
||||||
struct forf_stack ifclause = forf_pop_stack(env);
|
struct forf_stack ifclause = forf_pop_stack(env);
|
||||||
long cond = forf_pop_num(env);
|
long cond = forf_pop_num(env);
|
||||||
|
|
||||||
|
@ -411,9 +333,7 @@ forf_proc_if(struct forf_env *env)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void forf_proc_ifelse(struct forf_env *env) {
|
||||||
forf_proc_ifelse(struct forf_env *env)
|
|
||||||
{
|
|
||||||
struct forf_stack elseclause = forf_pop_stack(env);
|
struct forf_stack elseclause = forf_pop_stack(env);
|
||||||
struct forf_stack ifclause = forf_pop_stack(env);
|
struct forf_stack ifclause = forf_pop_stack(env);
|
||||||
long cond = forf_pop_num(env);
|
long cond = forf_pop_num(env);
|
||||||
|
@ -425,9 +345,7 @@ forf_proc_ifelse(struct forf_env *env)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void forf_proc_memset(struct forf_env *env) {
|
||||||
forf_proc_memset(struct forf_env *env)
|
|
||||||
{
|
|
||||||
long pos = forf_pop_num(env);
|
long pos = forf_pop_num(env);
|
||||||
long a = forf_pop_num(env);
|
long a = forf_pop_num(env);
|
||||||
|
|
||||||
|
@ -439,9 +357,7 @@ forf_proc_memset(struct forf_env *env)
|
||||||
env->memory->mem[pos] = a;
|
env->memory->mem[pos] = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void forf_proc_memget(struct forf_env *env) {
|
||||||
forf_proc_memget(struct forf_env *env)
|
|
||||||
{
|
|
||||||
long pos = forf_pop_num(env);
|
long pos = forf_pop_num(env);
|
||||||
|
|
||||||
if (pos >= env->memory->size) {
|
if (pos >= env->memory->size) {
|
||||||
|
@ -457,8 +373,7 @@ forf_proc_memget(struct forf_env *env)
|
||||||
* Lexical environment
|
* Lexical environment
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct forf_lexical_env forf_base_lexical_env[] = {
|
struct forf_lexical_env forf_base_lexical_env[] = {{"~", forf_proc_inv},
|
||||||
{"~", forf_proc_inv},
|
|
||||||
{"!", forf_proc_not},
|
{"!", forf_proc_not},
|
||||||
{"+", forf_proc_add},
|
{"+", forf_proc_add},
|
||||||
{"-", forf_proc_sub},
|
{"-", forf_proc_sub},
|
||||||
|
@ -484,39 +399,33 @@ struct forf_lexical_env forf_base_lexical_env[] = {
|
||||||
{"ifelse", forf_proc_ifelse},
|
{"ifelse", forf_proc_ifelse},
|
||||||
{"mset", forf_proc_memset},
|
{"mset", forf_proc_memset},
|
||||||
{"mget", forf_proc_memget},
|
{"mget", forf_proc_memget},
|
||||||
{NULL, NULL}
|
{NULL, NULL}};
|
||||||
};
|
|
||||||
|
|
||||||
/** Extend a lexical environment */
|
/** Extend a lexical environment */
|
||||||
int
|
int forf_extend_lexical_env(struct forf_lexical_env *dest,
|
||||||
forf_extend_lexical_env(struct forf_lexical_env *dest,
|
struct forf_lexical_env *src, size_t size) {
|
||||||
struct forf_lexical_env *src,
|
|
||||||
size_t size)
|
|
||||||
{
|
|
||||||
int base, i;
|
int base, i;
|
||||||
|
|
||||||
for (base = 0; dest[base].name; base += 1);
|
for (base = 0; dest[base].name; base += 1)
|
||||||
for (i = 0; (base+i < size) && (src[i].name); i += 1) {
|
;
|
||||||
dest[base+i] = src[i];
|
for (i = 0; (base + i < size) && (src[i].name); i += 1) {
|
||||||
|
dest[base + i] = src[i];
|
||||||
}
|
}
|
||||||
if (base + i == size) {
|
if (base + i == size) {
|
||||||
/* Not enough room */
|
/* Not enough room */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
dest[base+i].name = NULL;
|
dest[base + i].name = NULL;
|
||||||
dest[base+i].proc = NULL;
|
dest[base + i].proc = NULL;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Parsing
|
* Parsing
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int
|
static int forf_push_token(struct forf_env *env, char *token, size_t tokenlen) {
|
||||||
forf_push_token(struct forf_env *env, char *token, size_t tokenlen)
|
|
||||||
{
|
|
||||||
long i;
|
long i;
|
||||||
char s[MAX_TOKEN_LEN + 1];
|
char s[MAX_TOKEN_LEN + 1];
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
@ -549,7 +458,7 @@ forf_push_token(struct forf_env *env, char *token, size_t tokenlen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! forf_stack_push(env->command, &val)) {
|
if (!forf_stack_push(env->command, &val)) {
|
||||||
env->error = forf_error_overflow;
|
env->error = forf_error_overflow;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -558,11 +467,8 @@ forf_push_token(struct forf_env *env, char *token, size_t tokenlen)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse an input stream onto the command stack */
|
/* Parse an input stream onto the command stack */
|
||||||
int
|
int forf_parse_stream(struct forf_env *env, forf_getch_func *getch,
|
||||||
forf_parse_stream(struct forf_env *env,
|
void *datum) {
|
||||||
forf_getch_func *getch,
|
|
||||||
void *datum)
|
|
||||||
{
|
|
||||||
int running = 1;
|
int running = 1;
|
||||||
long pos = 0;
|
long pos = 0;
|
||||||
char token[MAX_TOKEN_LEN];
|
char token[MAX_TOKEN_LEN];
|
||||||
|
@ -574,7 +480,8 @@ forf_parse_stream(struct forf_env *env,
|
||||||
#define _tokenize() \
|
#define _tokenize() \
|
||||||
do { \
|
do { \
|
||||||
if (tokenlen) { \
|
if (tokenlen) { \
|
||||||
if (! forf_push_token(env, token, tokenlen)) return pos; \
|
if (!forf_push_token(env, token, tokenlen)) \
|
||||||
|
return pos; \
|
||||||
tokenlen = 0; \
|
tokenlen = 0; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -616,7 +523,7 @@ forf_parse_stream(struct forf_env *env,
|
||||||
case '{':
|
case '{':
|
||||||
_tokenize();
|
_tokenize();
|
||||||
val.type = forf_type_stack_begin;
|
val.type = forf_type_stack_begin;
|
||||||
if (! forf_stack_push(env->command, &val)) {
|
if (!forf_stack_push(env->command, &val)) {
|
||||||
env->error = forf_error_overflow;
|
env->error = forf_error_overflow;
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
@ -625,7 +532,7 @@ forf_parse_stream(struct forf_env *env,
|
||||||
case '}':
|
case '}':
|
||||||
_tokenize();
|
_tokenize();
|
||||||
val.type = forf_type_stack_end;
|
val.type = forf_type_stack_end;
|
||||||
if (! forf_stack_push(env->command, &val)) {
|
if (!forf_stack_push(env->command, &val)) {
|
||||||
env->error = forf_error_overflow;
|
env->error = forf_error_overflow;
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
@ -657,20 +564,14 @@ struct forf_char_stream {
|
||||||
size_t pos;
|
size_t pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int forf_string_getch(struct forf_char_stream *stream) {
|
||||||
forf_string_getch(struct forf_char_stream *stream)
|
|
||||||
{
|
|
||||||
if (stream->pos >= stream->len) {
|
if (stream->pos >= stream->len) {
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
return stream->buf[stream->pos++];
|
return stream->buf[stream->pos++];
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int forf_parse_buffer(struct forf_env *env, char *buf, size_t len) {
|
||||||
forf_parse_buffer(struct forf_env *env,
|
|
||||||
char *buf,
|
|
||||||
size_t len)
|
|
||||||
{
|
|
||||||
struct forf_char_stream stream;
|
struct forf_char_stream stream;
|
||||||
|
|
||||||
stream.buf = buf;
|
stream.buf = buf;
|
||||||
|
@ -680,35 +581,23 @@ forf_parse_buffer(struct forf_env *env,
|
||||||
return forf_parse_stream(env, (forf_getch_func *)forf_string_getch, &stream);
|
return forf_parse_stream(env, (forf_getch_func *)forf_string_getch, &stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int forf_parse_string(struct forf_env *env, char *str) {
|
||||||
forf_parse_string(struct forf_env *env,
|
|
||||||
char *str)
|
|
||||||
{
|
|
||||||
return forf_parse_buffer(env, str, strlen(str));
|
return forf_parse_buffer(env, str, strlen(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int forf_parse_file(struct forf_env *env, FILE *f) {
|
||||||
forf_parse_file(struct forf_env *env,
|
|
||||||
FILE *f)
|
|
||||||
{
|
|
||||||
return forf_parse_stream(env, (forf_getch_func *)fgetc, f);
|
return forf_parse_stream(env, (forf_getch_func *)fgetc, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Forf environment
|
* Forf environment
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void forf_env_init(struct forf_env *env, struct forf_lexical_env *lenv,
|
||||||
forf_env_init(struct forf_env *env,
|
struct forf_stack *data, struct forf_stack *cmd,
|
||||||
struct forf_lexical_env *lenv,
|
struct forf_memory *mem, void *udata) {
|
||||||
struct forf_stack *data,
|
|
||||||
struct forf_stack *cmd,
|
|
||||||
struct forf_memory *mem,
|
|
||||||
void *udata)
|
|
||||||
{
|
|
||||||
env->lenv = lenv;
|
env->lenv = lenv;
|
||||||
env->data = data;
|
env->data = data;
|
||||||
env->command = cmd;
|
env->command = cmd;
|
||||||
|
@ -716,13 +605,10 @@ forf_env_init(struct forf_env *env,
|
||||||
env->udata = udata;
|
env->udata = udata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int forf_eval_once(struct forf_env *env) {
|
||||||
int
|
|
||||||
forf_eval_once(struct forf_env *env)
|
|
||||||
{
|
|
||||||
struct forf_value val;
|
struct forf_value val;
|
||||||
|
|
||||||
if (! forf_stack_pop(env->command, &val)) {
|
if (!forf_stack_pop(env->command, &val)) {
|
||||||
env->error = forf_error_underflow;
|
env->error = forf_error_underflow;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -731,7 +617,8 @@ forf_eval_once(struct forf_env *env)
|
||||||
case forf_type_stack_begin:
|
case forf_type_stack_begin:
|
||||||
// Push back on command stack, then move it
|
// Push back on command stack, then move it
|
||||||
forf_stack_push(env->command, &val);
|
forf_stack_push(env->command, &val);
|
||||||
if (! forf_stack_move_value(env, env->data, env->command)) return 0;
|
if (!forf_stack_move_value(env, env->data, env->command))
|
||||||
|
return 0;
|
||||||
break;
|
break;
|
||||||
case forf_type_proc:
|
case forf_type_proc:
|
||||||
(val.v.p)(env);
|
(val.v.p)(env);
|
||||||
|
@ -743,15 +630,13 @@ forf_eval_once(struct forf_env *env)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int forf_eval(struct forf_env *env) {
|
||||||
forf_eval(struct forf_env *env)
|
|
||||||
{
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
env->error = forf_error_none;
|
env->error = forf_error_none;
|
||||||
while (env->command->top) {
|
while (env->command->top) {
|
||||||
ret = forf_eval_once(env);
|
ret = forf_eval_once(env);
|
||||||
if ((! ret) || (env->error)) {
|
if ((!ret) || (env->error)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
43
forf.h
43
forf.h
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#define MAX_TOKEN_LEN 20
|
#define MAX_TOKEN_LEN 20
|
||||||
#define MAX_CMDSTACK 200
|
#define MAX_CMDSTACK 200
|
||||||
|
@ -28,7 +28,7 @@ enum forf_error_type {
|
||||||
|
|
||||||
extern char *forf_error_str[];
|
extern char *forf_error_str[];
|
||||||
|
|
||||||
typedef void (forf_proc)(struct forf_env *);
|
typedef void(forf_proc)(struct forf_env *);
|
||||||
|
|
||||||
struct forf_value {
|
struct forf_value {
|
||||||
enum forf_value_type type;
|
enum forf_value_type type;
|
||||||
|
@ -63,7 +63,6 @@ struct forf_env {
|
||||||
void *udata;
|
void *udata;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Main entry points
|
* Main entry points
|
||||||
|
@ -71,13 +70,10 @@ struct forf_env {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** Initialize a memory structure, given an array of longs */
|
/** Initialize a memory structure, given an array of longs */
|
||||||
void forf_memory_init(struct forf_memory *m,
|
void forf_memory_init(struct forf_memory *m, long *values, size_t size);
|
||||||
long *values,
|
|
||||||
size_t size);
|
|
||||||
|
|
||||||
/** Initialize a stack, given an array of values */
|
/** Initialize a stack, given an array of values */
|
||||||
void forf_stack_init(struct forf_stack *s,
|
void forf_stack_init(struct forf_stack *s, struct forf_value *values,
|
||||||
struct forf_value *values,
|
|
||||||
size_t size);
|
size_t size);
|
||||||
|
|
||||||
void forf_stack_reset(struct forf_stack *s);
|
void forf_stack_reset(struct forf_stack *s);
|
||||||
|
@ -94,51 +90,40 @@ void forf_push_num(struct forf_env *env, long i);
|
||||||
/** Pop a whole stack */
|
/** Pop a whole stack */
|
||||||
struct forf_stack forf_pop_stack(struct forf_env *env);
|
struct forf_stack forf_pop_stack(struct forf_env *env);
|
||||||
|
|
||||||
|
|
||||||
/** The base lexical environment */
|
/** The base lexical environment */
|
||||||
extern struct forf_lexical_env forf_base_lexical_env[];
|
extern struct forf_lexical_env forf_base_lexical_env[];
|
||||||
|
|
||||||
/** Extend a lexical environment */
|
/** Extend a lexical environment */
|
||||||
int
|
int forf_extend_lexical_env(struct forf_lexical_env *dest,
|
||||||
forf_extend_lexical_env(struct forf_lexical_env *dest,
|
struct forf_lexical_env *src, size_t size);
|
||||||
struct forf_lexical_env *src,
|
|
||||||
size_t size);
|
|
||||||
|
|
||||||
/** Initialize a forf runtime environment.
|
/** Initialize a forf runtime environment.
|
||||||
*
|
*
|
||||||
* data, cmd, and mem should have already been initialized
|
* data, cmd, and mem should have already been initialized
|
||||||
*/
|
*/
|
||||||
void forf_env_init(struct forf_env *env,
|
void forf_env_init(struct forf_env *env, struct forf_lexical_env *lenv,
|
||||||
struct forf_lexical_env *lenv,
|
struct forf_stack *data, struct forf_stack *cmd,
|
||||||
struct forf_stack *data,
|
struct forf_memory *mem, void *udata);
|
||||||
struct forf_stack *cmd,
|
|
||||||
struct forf_memory *mem,
|
|
||||||
void *udata);
|
|
||||||
|
|
||||||
/** The type of a getch function (used for parsing) */
|
/** The type of a getch function (used for parsing) */
|
||||||
typedef int (forf_getch_func)(void *);
|
typedef int(forf_getch_func)(void *);
|
||||||
|
|
||||||
/** Parse something by calling getch(datum)
|
/** Parse something by calling getch(datum)
|
||||||
*
|
*
|
||||||
* Returns the character at which an error was encountered, or
|
* Returns the character at which an error was encountered, or
|
||||||
* 0 for successful parse.
|
* 0 for successful parse.
|
||||||
*/
|
*/
|
||||||
int forf_parse_stream(struct forf_env *env,
|
int forf_parse_stream(struct forf_env *env, forf_getch_func *getch,
|
||||||
forf_getch_func *getch,
|
|
||||||
void *datum);
|
void *datum);
|
||||||
|
|
||||||
/** Parse a buffer */
|
/** Parse a buffer */
|
||||||
int forf_parse_buffer(struct forf_env *env,
|
int forf_parse_buffer(struct forf_env *env, char *buf, size_t len);
|
||||||
char *buf,
|
|
||||||
size_t len);
|
|
||||||
|
|
||||||
/** Parse a string */
|
/** Parse a string */
|
||||||
int forf_parse_string(struct forf_env *env,
|
int forf_parse_string(struct forf_env *env, char *str);
|
||||||
char *str);
|
|
||||||
|
|
||||||
/** Parse a FILE * */
|
/** Parse a FILE * */
|
||||||
int forf_parse_file(struct forf_env *env,
|
int forf_parse_file(struct forf_env *env, FILE *f);
|
||||||
FILE *f);
|
|
||||||
|
|
||||||
/** Evaluate the topmost value on the command stack */
|
/** Evaluate the topmost value on the command stack */
|
||||||
int forf_eval_once(struct forf_env *env);
|
int forf_eval_once(struct forf_env *env);
|
||||||
|
|
211
forftanks.c
211
forftanks.c
|
@ -1,13 +1,13 @@
|
||||||
#include <sys/types.h>
|
#include "ctanks.h"
|
||||||
#include <sys/stat.h>
|
#include "dump.h"
|
||||||
#include <unistd.h>
|
#include "forf.h"
|
||||||
#include <string.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <string.h>
|
||||||
#include "ctanks.h"
|
#include <sys/stat.h>
|
||||||
#include "forf.h"
|
#include <sys/types.h>
|
||||||
#include "dump.h"
|
#include <unistd.h>
|
||||||
|
|
||||||
#define MAX_TANKS 50
|
#define MAX_TANKS 50
|
||||||
#define ROUNDS 500
|
#define ROUNDS 500
|
||||||
|
@ -37,11 +37,8 @@ struct forftank {
|
||||||
long _memvals[MEMORY_SIZE];
|
long _memvals[MEMORY_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifndef NODEBUG
|
#ifndef NODEBUG
|
||||||
void
|
void forf_print_val(struct forf_value *val) {
|
||||||
forf_print_val(struct forf_value *val)
|
|
||||||
{
|
|
||||||
switch (val->type) {
|
switch (val->type) {
|
||||||
case forf_type_number:
|
case forf_type_number:
|
||||||
printf("%ld", val->v.i);
|
printf("%ld", val->v.i);
|
||||||
|
@ -58,9 +55,7 @@ forf_print_val(struct forf_value *val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void forf_print_stack(struct forf_stack *s) {
|
||||||
forf_print_stack(struct forf_stack *s)
|
|
||||||
{
|
|
||||||
size_t pos;
|
size_t pos;
|
||||||
|
|
||||||
for (pos = 0; pos < s->top; pos += 1) {
|
for (pos = 0; pos < s->top; pos += 1) {
|
||||||
|
@ -69,9 +64,7 @@ forf_print_stack(struct forf_stack *s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void forf_dump_stack(struct forf_stack *s) {
|
||||||
forf_dump_stack(struct forf_stack *s)
|
|
||||||
{
|
|
||||||
printf("Stack at %p: ", s);
|
printf("Stack at %p: ", s);
|
||||||
forf_print_stack(s);
|
forf_print_stack(s);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
@ -85,27 +78,21 @@ forf_dump_stack(struct forf_stack *s)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** Has the turret recharged? */
|
/** Has the turret recharged? */
|
||||||
void
|
void forf_tank_fire_ready(struct forf_env *env) {
|
||||||
forf_tank_fire_ready(struct forf_env *env)
|
|
||||||
{
|
|
||||||
struct tank *tank = (struct tank *)env->udata;
|
struct tank *tank = (struct tank *)env->udata;
|
||||||
|
|
||||||
forf_push_num(env, tank_fire_ready(tank));
|
forf_push_num(env, tank_fire_ready(tank));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Fire! */
|
/** Fire! */
|
||||||
void
|
void forf_tank_fire(struct forf_env *env) {
|
||||||
forf_tank_fire(struct forf_env *env)
|
|
||||||
{
|
|
||||||
struct tank *tank = (struct tank *)env->udata;
|
struct tank *tank = (struct tank *)env->udata;
|
||||||
|
|
||||||
tank_fire(tank);
|
tank_fire(tank);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set desired speed */
|
/** Set desired speed */
|
||||||
void
|
void forf_tank_set_speed(struct forf_env *env) {
|
||||||
forf_tank_set_speed(struct forf_env *env)
|
|
||||||
{
|
|
||||||
struct tank *tank = (struct tank *)env->udata;
|
struct tank *tank = (struct tank *)env->udata;
|
||||||
long right = forf_pop_num(env);
|
long right = forf_pop_num(env);
|
||||||
long left = forf_pop_num(env);
|
long left = forf_pop_num(env);
|
||||||
|
@ -114,9 +101,7 @@ forf_tank_set_speed(struct forf_env *env)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the current turret angle */
|
/** Get the current turret angle */
|
||||||
void
|
void forf_tank_get_turret(struct forf_env *env) {
|
||||||
forf_tank_get_turret(struct forf_env *env)
|
|
||||||
{
|
|
||||||
struct tank *tank = (struct tank *)env->udata;
|
struct tank *tank = (struct tank *)env->udata;
|
||||||
float angle = tank_get_turret(tank);
|
float angle = tank_get_turret(tank);
|
||||||
|
|
||||||
|
@ -124,9 +109,7 @@ forf_tank_get_turret(struct forf_env *env)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the desired turret angle */
|
/** Set the desired turret angle */
|
||||||
void
|
void forf_tank_set_turret(struct forf_env *env) {
|
||||||
forf_tank_set_turret(struct forf_env *env)
|
|
||||||
{
|
|
||||||
struct tank *tank = (struct tank *)env->udata;
|
struct tank *tank = (struct tank *)env->udata;
|
||||||
long angle = forf_pop_num(env);
|
long angle = forf_pop_num(env);
|
||||||
|
|
||||||
|
@ -134,9 +117,7 @@ forf_tank_set_turret(struct forf_env *env)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Is a sensor active? */
|
/** Is a sensor active? */
|
||||||
void
|
void forf_tank_get_sensor(struct forf_env *env) {
|
||||||
forf_tank_get_sensor(struct forf_env *env)
|
|
||||||
{
|
|
||||||
struct tank *tank = (struct tank *)env->udata;
|
struct tank *tank = (struct tank *)env->udata;
|
||||||
long sensor_num = forf_pop_num(env);
|
long sensor_num = forf_pop_num(env);
|
||||||
|
|
||||||
|
@ -144,9 +125,7 @@ forf_tank_get_sensor(struct forf_env *env)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the LED state */
|
/** Set the LED state */
|
||||||
void
|
void forf_tank_set_led(struct forf_env *env) {
|
||||||
forf_tank_set_led(struct forf_env *env)
|
|
||||||
{
|
|
||||||
struct tank *tank = (struct tank *)env->udata;
|
struct tank *tank = (struct tank *)env->udata;
|
||||||
long active = forf_pop_num(env);
|
long active = forf_pop_num(env);
|
||||||
|
|
||||||
|
@ -154,9 +133,7 @@ forf_tank_set_led(struct forf_env *env)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Pick a random number */
|
/** Pick a random number */
|
||||||
void
|
void forf_proc_random(struct forf_env *env) {
|
||||||
forf_proc_random(struct forf_env *env)
|
|
||||||
{
|
|
||||||
long max = forf_pop_num(env);
|
long max = forf_pop_num(env);
|
||||||
|
|
||||||
if (max < 1) {
|
if (max < 1) {
|
||||||
|
@ -177,8 +154,7 @@ struct forf_lexical_env tanks_lenv_addons[] = {
|
||||||
{"sensor?", forf_tank_get_sensor},
|
{"sensor?", forf_tank_get_sensor},
|
||||||
{"set-led!", forf_tank_set_led},
|
{"set-led!", forf_tank_set_led},
|
||||||
{"random", forf_proc_random},
|
{"random", forf_proc_random},
|
||||||
{NULL, NULL}
|
{NULL, NULL}};
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
|
@ -186,9 +162,7 @@ struct forf_lexical_env tanks_lenv_addons[] = {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int ft_read_file(char *ptr, size_t size, char *dir, char *fn) {
|
||||||
ft_read_file(char *ptr, size_t size, char *dir, char *fn)
|
|
||||||
{
|
|
||||||
char path[256];
|
char path[256];
|
||||||
FILE *f = NULL;
|
FILE *f = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -197,57 +171,52 @@ ft_read_file(char *ptr, size_t size, char *dir, char *fn)
|
||||||
do {
|
do {
|
||||||
snprintf(path, sizeof(path), "%s/%s", dir, fn);
|
snprintf(path, sizeof(path), "%s/%s", dir, fn);
|
||||||
f = fopen(path, "r");
|
f = fopen(path, "r");
|
||||||
if (! f) break;
|
if (!f)
|
||||||
|
break;
|
||||||
|
|
||||||
ret = fread(ptr, 1, size - 1, f);
|
ret = fread(ptr, 1, size - 1, f);
|
||||||
ptr[ret] = '\0';
|
ptr[ret] = '\0';
|
||||||
if (! ret) break;
|
if (!ret)
|
||||||
|
break;
|
||||||
|
|
||||||
success = 1;
|
success = 1;
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
if (f) fclose(f);
|
if (f)
|
||||||
if (! success) {
|
fclose(f);
|
||||||
|
if (!success) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ft_bricked_tank(struct tank *tank, void *ignored) {
|
||||||
ft_bricked_tank(struct tank *tank, void *ignored)
|
|
||||||
{
|
|
||||||
/* Do nothing, the tank is comatose */
|
/* Do nothing, the tank is comatose */
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ft_run_tank(struct tank *tank, struct forftank *ftank) {
|
||||||
ft_run_tank(struct tank *tank, struct forftank *ftank)
|
|
||||||
{
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Copy program into command stack */
|
/* Copy program into command stack */
|
||||||
forf_stack_copy(&ftank->_cmd, &ftank->_prog);
|
forf_stack_copy(&ftank->_cmd, &ftank->_prog);
|
||||||
forf_stack_reset(&ftank->_data);
|
forf_stack_reset(&ftank->_data);
|
||||||
ret = forf_eval(&ftank->env);
|
ret = forf_eval(&ftank->env);
|
||||||
if (! ret) {
|
if (!ret) {
|
||||||
fprintf(stderr, "Error in %s: %s\n",
|
fprintf(stderr, "Error in %s: %s\n", ftank->path,
|
||||||
ftank->path,
|
|
||||||
forf_error_str[ftank->env.error]);
|
forf_error_str[ftank->env.error]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int ft_read_program(struct forftank *ftank, struct tank *tank,
|
||||||
ft_read_program(struct forftank *ftank,
|
struct forf_lexical_env *lenv, char *path) {
|
||||||
struct tank *tank,
|
|
||||||
struct forf_lexical_env *lenv,
|
|
||||||
char *path)
|
|
||||||
{
|
|
||||||
char progpath[256];
|
char progpath[256];
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
/* Open program */
|
/* Open program */
|
||||||
snprintf(progpath, sizeof(progpath), "%s/program", path);
|
snprintf(progpath, sizeof(progpath), "%s/program", path);
|
||||||
f = fopen(progpath, "r");
|
f = fopen(progpath, "r");
|
||||||
if (! f) return 0;
|
if (!f)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Parse program */
|
/* Parse program */
|
||||||
ftank->error_pos = forf_parse_file(&ftank->env, f);
|
ftank->error_pos = forf_parse_file(&ftank->env, f);
|
||||||
|
@ -265,28 +234,18 @@ ft_read_program(struct forftank *ftank,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ft_tank_init(struct forftank *ftank, struct tank *tank,
|
||||||
ft_tank_init(struct forftank *ftank,
|
struct forf_lexical_env *lenv) {
|
||||||
struct tank *tank,
|
|
||||||
struct forf_lexical_env *lenv)
|
|
||||||
{
|
|
||||||
/* Set up forf environment */
|
/* Set up forf environment */
|
||||||
forf_stack_init(&ftank->_prog, ftank->_progvals, CSTACK_SIZE);
|
forf_stack_init(&ftank->_prog, ftank->_progvals, CSTACK_SIZE);
|
||||||
forf_stack_init(&ftank->_cmd, ftank->_cmdvals, CSTACK_SIZE);
|
forf_stack_init(&ftank->_cmd, ftank->_cmdvals, CSTACK_SIZE);
|
||||||
forf_stack_init(&ftank->_data, ftank->_datavals, DSTACK_SIZE);
|
forf_stack_init(&ftank->_data, ftank->_datavals, DSTACK_SIZE);
|
||||||
forf_memory_init(&ftank->_mem, ftank->_memvals, MEMORY_SIZE);
|
forf_memory_init(&ftank->_mem, ftank->_memvals, MEMORY_SIZE);
|
||||||
forf_env_init(&ftank->env,
|
forf_env_init(&ftank->env, lenv, &ftank->_data, &ftank->_cmd, &ftank->_mem,
|
||||||
lenv,
|
|
||||||
&ftank->_data,
|
|
||||||
&ftank->_cmd,
|
|
||||||
&ftank->_mem,
|
|
||||||
tank);
|
tank);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ft_read_sensors(struct tank *tank, char *path) {
|
||||||
ft_read_sensors(struct tank *tank,
|
|
||||||
char *path)
|
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < TANK_MAX_SENSORS; i += 1) {
|
for (i = 0; i < TANK_MAX_SENSORS; i += 1) {
|
||||||
|
@ -301,7 +260,7 @@ ft_read_sensors(struct tank *tank,
|
||||||
|
|
||||||
snprintf(fn, sizeof(fn), "sensor%d", i);
|
snprintf(fn, sizeof(fn), "sensor%d", i);
|
||||||
ret = ft_read_file(s, sizeof(s), path, fn);
|
ret = ft_read_file(s, sizeof(s), path, fn);
|
||||||
if (! ret) {
|
if (!ret) {
|
||||||
s[0] = 0;
|
s[0] = 0;
|
||||||
}
|
}
|
||||||
range = strtol(p, &p, 0);
|
range = strtol(p, &p, 0);
|
||||||
|
@ -316,12 +275,8 @@ ft_read_sensors(struct tank *tank,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int ft_read_tank(struct forftank *ftank, struct tank *tank,
|
||||||
ft_read_tank(struct forftank *ftank,
|
struct forf_lexical_env *lenv, char *path) {
|
||||||
struct tank *tank,
|
|
||||||
struct forf_lexical_env *lenv,
|
|
||||||
char *path)
|
|
||||||
{
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ftank->path = path;
|
ftank->path = path;
|
||||||
|
@ -338,7 +293,7 @@ ft_read_tank(struct forftank *ftank,
|
||||||
|
|
||||||
/* What is your name? */
|
/* What is your name? */
|
||||||
ret = ft_read_file(ftank->name, sizeof(ftank->name), path, "name");
|
ret = ft_read_file(ftank->name, sizeof(ftank->name), path, "name");
|
||||||
if (! ret) {
|
if (!ret) {
|
||||||
snprintf(ftank->name, sizeof(ftank->name), "i:%x", ftank->uid);
|
snprintf(ftank->name, sizeof(ftank->name), "i:%x", ftank->uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,29 +309,21 @@ ft_read_tank(struct forftank *ftank,
|
||||||
|
|
||||||
/* What is your favorite color? */
|
/* What is your favorite color? */
|
||||||
ret = ft_read_file(ftank->color, sizeof(ftank->color), path, "color");
|
ret = ft_read_file(ftank->color, sizeof(ftank->color), path, "color");
|
||||||
if (! ret) {
|
if (!ret) {
|
||||||
strncpy(ftank->color, "#808080", sizeof(ftank->color));
|
strncpy(ftank->color, "#808080", sizeof(ftank->color));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void print_header(FILE *f, struct tanks_game *game, int seed) {
|
||||||
print_header(FILE *f,
|
|
||||||
struct tanks_game *game,
|
|
||||||
int seed)
|
|
||||||
{
|
|
||||||
fprintf(f, "{\n");
|
fprintf(f, "{\n");
|
||||||
fprintf(f, " \"seed\": %d,\n", seed);
|
fprintf(f, " \"seed\": %d,\n", seed);
|
||||||
fprintf(f, " \"field\": [%d,%d],\n", (int)game->size[0], (int)game->size[1]);
|
fprintf(f, " \"field\": [%d,%d],\n", (int)game->size[0], (int)game->size[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void print_rounds(FILE *f, struct tanks_game *game, struct tank *tanks,
|
||||||
print_rounds(FILE *f,
|
int ntanks) {
|
||||||
struct tanks_game *game,
|
|
||||||
struct tank *tanks,
|
|
||||||
int ntanks)
|
|
||||||
{
|
|
||||||
int alive;
|
int alive;
|
||||||
|
|
||||||
fprintf(f, " \"rounds\": [\n");
|
fprintf(f, " \"rounds\": [\n");
|
||||||
|
@ -417,12 +364,8 @@ print_rounds(FILE *f,
|
||||||
alive -= 1;
|
alive -= 1;
|
||||||
flags |= 4;
|
flags |= 4;
|
||||||
}
|
}
|
||||||
fprintf(f, "[%d,%d,%.2f,%.2f,%d,%d]",
|
fprintf(f, "[%d,%d,%.2f,%.2f,%d,%d]", (int)t->position[0],
|
||||||
(int)t->position[0],
|
(int)(t->position[1]), t->angle, t->turret.current, flags,
|
||||||
(int)(t->position[1]),
|
|
||||||
t->angle,
|
|
||||||
t->turret.current,
|
|
||||||
flags,
|
|
||||||
sensors);
|
sensors);
|
||||||
}
|
}
|
||||||
fprintf(f, "]");
|
fprintf(f, "]");
|
||||||
|
@ -431,12 +374,8 @@ print_rounds(FILE *f,
|
||||||
fprintf(f, "\n ],\n");
|
fprintf(f, "\n ],\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void print_standings(FILE *f, struct forftank *ftanks, struct tank *tanks,
|
||||||
print_standings(FILE *f,
|
int ntanks) {
|
||||||
struct forftank *ftanks,
|
|
||||||
struct tank *tanks,
|
|
||||||
int ntanks)
|
|
||||||
{
|
|
||||||
|
|
||||||
fprintf(f, " \"tanks\": [\n");
|
fprintf(f, " \"tanks\": [\n");
|
||||||
for (int i = 0; i < ntanks; i += 1) {
|
for (int i = 0; i < ntanks; i += 1) {
|
||||||
|
@ -462,7 +401,8 @@ print_standings(FILE *f,
|
||||||
fprintf(f, " \"killer\": %d,\n", killer);
|
fprintf(f, " \"killer\": %d,\n", killer);
|
||||||
fprintf(f, " \"kills\": %d,\n", kills);
|
fprintf(f, " \"kills\": %d,\n", kills);
|
||||||
fprintf(f, " \"errorPos\": %d,\n", ftanks[i].error_pos);
|
fprintf(f, " \"errorPos\": %d,\n", ftanks[i].error_pos);
|
||||||
fprintf(f, " \"error\": \"%s\",\n", forf_error_str[ftanks[i].env.error]);
|
fprintf(f, " \"error\": \"%s\",\n",
|
||||||
|
forf_error_str[ftanks[i].env.error]);
|
||||||
fprintf(f, " \"sensors\": [\n");
|
fprintf(f, " \"sensors\": [\n");
|
||||||
for (int j = 0; j < TANK_MAX_SENSORS; j += 1) {
|
for (int j = 0; j < TANK_MAX_SENSORS; j += 1) {
|
||||||
struct sensor *s = &(tanks[i].sensors[j]);
|
struct sensor *s = &(tanks[i].sensors[j]);
|
||||||
|
@ -471,14 +411,14 @@ print_standings(FILE *f,
|
||||||
fprintf(f, ",\n");
|
fprintf(f, ",\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! s->range) {
|
if (!s->range) {
|
||||||
fprintf(f, " null");
|
fprintf(f, " null");
|
||||||
} else {
|
} else {
|
||||||
fprintf(f, " {\"range\":%d,\"angle\":%.2f,\"width\":%.2f,\"turret\":%s}",
|
fprintf(f,
|
||||||
(int)(s->range),
|
" "
|
||||||
s->angle,
|
"{\"range\":%d,\"angle\":%.2f,\"width\":%.2f,\"turret\":%s}",
|
||||||
s->width,
|
(int)(s->range), s->angle, s->width,
|
||||||
s->turret?"true":"false");
|
s->turret ? "true" : "false");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(f, "\n ]");
|
fprintf(f, "\n ]");
|
||||||
|
@ -488,16 +428,13 @@ print_standings(FILE *f,
|
||||||
fprintf(f, "\n ],\n");
|
fprintf(f, "\n ],\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void print_footer(FILE *f) {
|
||||||
print_footer(FILE *f)
|
fprintf(f,
|
||||||
{
|
" \"\": null\n"); // sentry, so everything prior can end with a comma
|
||||||
fprintf(f, " \"\": null\n"); // sentry, so everything prior can end with a comma
|
|
||||||
fprintf(f, "}\n");
|
fprintf(f, "}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int main(int argc, char *argv[]) {
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
struct tanks_game game;
|
struct tanks_game game;
|
||||||
struct forftank myftanks[MAX_TANKS];
|
struct forftank myftanks[MAX_TANKS];
|
||||||
struct tank mytanks[MAX_TANKS];
|
struct tank mytanks[MAX_TANKS];
|
||||||
|
@ -509,8 +446,8 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
lenv[0].name = NULL;
|
lenv[0].name = NULL;
|
||||||
lenv[0].proc = NULL;
|
lenv[0].proc = NULL;
|
||||||
if ((! forf_extend_lexical_env(lenv, forf_base_lexical_env, LENV_SIZE)) ||
|
if ((!forf_extend_lexical_env(lenv, forf_base_lexical_env, LENV_SIZE)) ||
|
||||||
(! forf_extend_lexical_env(lenv, tanks_lenv_addons, LENV_SIZE))) {
|
(!forf_extend_lexical_env(lenv, tanks_lenv_addons, LENV_SIZE))) {
|
||||||
fprintf(stderr, "Unable to initialize lexical environment.\n");
|
fprintf(stderr, "Unable to initialize lexical environment.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -518,9 +455,9 @@ main(int argc, char *argv[])
|
||||||
/* We only need slightly random numbers */
|
/* We only need slightly random numbers */
|
||||||
{
|
{
|
||||||
char *s = getenv("SEED");
|
char *s = getenv("SEED");
|
||||||
seed = atoi(s?s:"");
|
seed = atoi(s ? s : "");
|
||||||
|
|
||||||
if (! seed) {
|
if (!seed) {
|
||||||
seed = getpid();
|
seed = getpid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,10 +471,7 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
/* Every argument is a tank directory */
|
/* Every argument is a tank directory */
|
||||||
for (i = 1; ntanks < MAX_TANKS && i < argc; i += 1) {
|
for (i = 1; ntanks < MAX_TANKS && i < argc; i += 1) {
|
||||||
if (ft_read_tank(&myftanks[ntanks],
|
if (ft_read_tank(&myftanks[ntanks], &mytanks[ntanks], lenv, argv[i])) {
|
||||||
&mytanks[ntanks],
|
|
||||||
lenv,
|
|
||||||
argv[i])) {
|
|
||||||
ntanks += 1;
|
ntanks += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -546,7 +480,8 @@ main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
for (x = 1; x * x < ntanks; x += 1);
|
for (x = 1; x * x < ntanks; x += 1)
|
||||||
|
;
|
||||||
y = ntanks / x;
|
y = ntanks / x;
|
||||||
if (ntanks % x) {
|
if (ntanks % x) {
|
||||||
y += 1;
|
y += 1;
|
||||||
|
@ -570,8 +505,8 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
/* Position tanks */
|
/* Position tanks */
|
||||||
{
|
{
|
||||||
int x = SPACING/2;
|
int x = SPACING / 2;
|
||||||
int y = SPACING/2;
|
int y = SPACING / 2;
|
||||||
|
|
||||||
for (i = 0; i < ntanks; i += 1) {
|
for (i = 0; i < ntanks; i += 1) {
|
||||||
mytanks[order[i]].position[0] = (float)x;
|
mytanks[order[i]].position[0] = (float)x;
|
||||||
|
|
Loading…
Reference in New Issue