mirror of https://github.com/dirtbags/tanks.git
Fix up designer cgi
This commit is contained in:
parent
39169bf352
commit
ea84c67517
5
Makefile
5
Makefile
|
@ -1,6 +1,7 @@
|
||||||
|
CFLAGS = -Wall
|
||||||
LDFLAGS = -lm
|
LDFLAGS = -lm
|
||||||
|
|
||||||
all: test
|
all: run-tanks
|
||||||
|
|
||||||
test: test-tanks
|
test: test-tanks
|
||||||
./test-tanks | m4 round.html.m4 - > round.html
|
./test-tanks | m4 round.html.m4 - > round.html
|
||||||
|
@ -10,4 +11,4 @@ test-tanks: test-tanks.o ctanks.o
|
||||||
run-tanks: run-tanks.o ctanks.o cforf.o
|
run-tanks: run-tanks.o ctanks.o cforf.o
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f test-tanks *.o
|
rm -f test-tanks run-tanks *.o
|
4
cforf.c
4
cforf.c
|
@ -211,6 +211,8 @@ forf_pop_stack(struct forf_env *env)
|
||||||
case forf_type_stack_begin:
|
case forf_type_stack_begin:
|
||||||
depth -= 1;
|
depth -= 1;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.top = s.size;
|
s.top = s.size;
|
||||||
|
@ -287,6 +289,8 @@ forf_stack_move_value(struct forf_env *env,
|
||||||
case forf_type_stack_end:
|
case forf_type_stack_end:
|
||||||
depth -= 1;
|
depth -= 1;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} while (depth > 0);
|
} while (depth > 0);
|
||||||
|
|
||||||
|
|
6
cforf.h
6
cforf.h
|
@ -119,7 +119,11 @@ void forf_env_init(struct forf_env *env,
|
||||||
/** 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
|
||||||
|
* 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);
|
||||||
|
|
5
ctanks.h
5
ctanks.h
|
@ -10,7 +10,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 (PI/3)
|
#define TANK_MAX_TURRET_ROT (PI/10)
|
||||||
#define TANK_TOP_SPEED 7
|
#define TANK_TOP_SPEED 7
|
||||||
|
|
||||||
/* (tank radius + tank radius)^2 */
|
/* (tank radius + tank radius)^2 */
|
||||||
|
@ -75,6 +75,8 @@ 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);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
|
@ -103,4 +105,5 @@ int tank_get_sensor(struct tank *tank, int sensor_num);
|
||||||
/** Set the LED state */
|
/** Set the LED state */
|
||||||
void tank_set_led(struct tank *tank, int active);
|
void tank_set_led(struct tank *tank, int active);
|
||||||
|
|
||||||
|
|
||||||
#endif /* __CTANKS_H__ */
|
#endif /* __CTANKS_H__ */
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define BASE_PATH "/tmp/"
|
||||||
|
|
||||||
struct string {
|
struct string {
|
||||||
char *s;
|
char *s;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
@ -71,6 +74,8 @@ read_item(FILE *f, struct string *str)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
|
str->len = 0;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
c = fgetc(f);
|
c = fgetc(f);
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
@ -100,6 +105,7 @@ read_pair(FILE *f, struct string *key, struct string *val)
|
||||||
return read_item(f, val);
|
return read_item(f, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is ugly and I dislike it. */
|
||||||
#define new_string(name, size) \
|
#define new_string(name, size) \
|
||||||
char _##name[size]; \
|
char _##name[size]; \
|
||||||
struct string name = {_##name, size, 0 }
|
struct string name = {_##name, size, 0 }
|
||||||
|
@ -111,13 +117,58 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
new_string(key, 20);
|
new_string(key, 20);
|
||||||
new_string(val, 8192);
|
new_string(val, 8192);
|
||||||
|
new_string(token, 40);
|
||||||
new_string(name, 20);
|
new_string(name, 20);
|
||||||
new_string(author, 20);
|
new_string(author, 60);
|
||||||
|
new_string(color, 10);
|
||||||
|
new_string(program, 8192);
|
||||||
|
|
||||||
printf("Content-type: text/plain\n\n");
|
printf("Content-type: text/plain\n\n");
|
||||||
|
|
||||||
while (! feof(stdin)) {
|
while (! feof(stdin)) {
|
||||||
read_pair(stdin, &key, &val);
|
read_pair(stdin, &key, &val);
|
||||||
|
if (0 == string_cmp(&key, "token", 5)) {
|
||||||
|
string_cpy(&token, &key);
|
||||||
|
} else if (0 == string_cmp(&key, "name", 4)) {
|
||||||
|
string_cpy(&name, &key);
|
||||||
|
} else if (0 == string_cmp(&key, "author", 6)) {
|
||||||
|
string_cpy(&author, &key);
|
||||||
|
} else if (0 == string_cmp(&key, "color", 5)) {
|
||||||
|
string_cpy(&color, &key);
|
||||||
|
} else if (0 == string_cmp(&key, "program", 7)) {
|
||||||
|
string_cpy(&program, &key);
|
||||||
|
} else if ((3 == key.len) && ('s' == key.s[0])) {
|
||||||
|
/* sensor dealie, key = "s[0-9][rawt]" */
|
||||||
|
int n = key.s[1] - '0';
|
||||||
|
int i;
|
||||||
|
int p;
|
||||||
|
|
||||||
|
if (! (n >= 0) && (n <= 9)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (val.len > 3) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
val.s[val.len] = '\0';
|
||||||
|
i = atoi(val.s);
|
||||||
|
|
||||||
|
switch (key.s[2]) {
|
||||||
|
case 'r':
|
||||||
|
p = 0;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
p = 1;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
p = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
p = 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sensor[n][p] = i;
|
||||||
|
}
|
||||||
write(1, key.s, key.len);
|
write(1, key.s, key.len);
|
||||||
write(1, "=", 1);
|
write(1, "=", 1);
|
||||||
write(1, val.s, val.len);
|
write(1, val.s, val.len);
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
BEGIN {
|
||||||
|
FS = "\t";
|
||||||
|
}
|
||||||
|
|
||||||
|
function esc(s) {
|
||||||
|
gsub(/&/, "&", s);
|
||||||
|
gsub(/</, "<", s);
|
||||||
|
gsub(/>/, ">", s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
tanks[i++] = $1;
|
||||||
|
reason[$1] = $3;
|
||||||
|
killer[$1] = $4;
|
||||||
|
errchar[$1] = $5;
|
||||||
|
lasterr[$1] = $6;
|
||||||
|
kills[$4] += 1;
|
||||||
|
|
||||||
|
getline < ($2 "/name");
|
||||||
|
name[$1] = $0;
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
print "<table id=\"results\">";
|
||||||
|
print "<tr><th>Name</th><th>Kills</th><th>Cause of Death</th><th>Killer</th><th>Last Error</th><th>Parse error @</th></tr>";
|
||||||
|
for (me in name) {
|
||||||
|
print "<tr>";
|
||||||
|
print "<td>" esc(name[me]) "</td>";
|
||||||
|
print "<td>" kills[me] "</td>";
|
||||||
|
print "<td>" reason[me] "</td>";
|
||||||
|
print "<td>" esc(name[killer[me]]) "</td>";
|
||||||
|
print "<td>" lasterr[me] "</td>";
|
||||||
|
print "<td>" errchar[me] "</td>";
|
||||||
|
print "</tr>";
|
||||||
|
}
|
||||||
|
print "</table>";
|
||||||
|
}
|
66
run-tanks.c
66
run-tanks.c
|
@ -20,8 +20,10 @@
|
||||||
|
|
||||||
struct forftank {
|
struct forftank {
|
||||||
struct forf_env env;
|
struct forf_env env;
|
||||||
|
int error_pos;
|
||||||
char color[7]; /* "ff0088" */
|
char color[7]; /* "ff0088" */
|
||||||
char name[50];
|
char name[50];
|
||||||
|
char *path;
|
||||||
|
|
||||||
struct forf_stack _prog;
|
struct forf_stack _prog;
|
||||||
struct forf_value _progvals[CSTACK_SIZE];
|
struct forf_value _progvals[CSTACK_SIZE];
|
||||||
|
@ -40,7 +42,7 @@ forf_print_val(struct forf_value *val)
|
||||||
{
|
{
|
||||||
switch (val->type) {
|
switch (val->type) {
|
||||||
case forf_type_number:
|
case forf_type_number:
|
||||||
printf("%d", val->v.i);
|
printf("%ld", val->v.i);
|
||||||
break;
|
break;
|
||||||
case forf_type_proc:
|
case forf_type_proc:
|
||||||
printf("[proc %p]", val->v.p);
|
printf("[proc %p]", val->v.p);
|
||||||
|
@ -232,7 +234,6 @@ ft_read_program(struct forftank *ftank,
|
||||||
struct forf_lexical_env *lenv,
|
struct forf_lexical_env *lenv,
|
||||||
char *path)
|
char *path)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
char progpath[256];
|
char progpath[256];
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
|
@ -242,13 +243,9 @@ ft_read_program(struct forftank *ftank,
|
||||||
if (! f) return 0;
|
if (! f) return 0;
|
||||||
|
|
||||||
/* Parse program */
|
/* Parse program */
|
||||||
ret = forf_parse_file(&ftank->env, f);
|
ftank->error_pos = forf_parse_file(&ftank->env, f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
if (ret) {
|
if (ftank->error_pos) {
|
||||||
fprintf(stderr, "Parse error in %s, character %d: %s\n",
|
|
||||||
progpath,
|
|
||||||
ret,
|
|
||||||
forf_error_str[ftank->env.error]);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,6 +317,8 @@ ft_read_tank(struct forftank *ftank,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
ftank->path = path;
|
||||||
|
|
||||||
/* 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) {
|
||||||
|
@ -384,7 +383,6 @@ print_footer(FILE *f)
|
||||||
void
|
void
|
||||||
print_rounds(FILE *f,
|
print_rounds(FILE *f,
|
||||||
struct tanks_game *game,
|
struct tanks_game *game,
|
||||||
struct forftank *forftanks,
|
|
||||||
struct tank *tanks,
|
struct tank *tanks,
|
||||||
int ntanks)
|
int ntanks)
|
||||||
{
|
{
|
||||||
|
@ -396,15 +394,15 @@ print_rounds(FILE *f,
|
||||||
for (i = 0; (alive > 1) && (i < ROUNDS); i += 1) {
|
for (i = 0; (alive > 1) && (i < ROUNDS); i += 1) {
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
tanks_run_turn(&game, mytanks, ntanks);
|
tanks_run_turn(game, tanks, ntanks);
|
||||||
fprintf(stdout, "[\n");
|
fprintf(f, "[\n");
|
||||||
alive = ntanks;
|
alive = ntanks;
|
||||||
for (j = 0; j < ntanks; j += 1) {
|
for (j = 0; j < ntanks; j += 1) {
|
||||||
struct tank *t = &(mytanks[j]);
|
struct tank *t = &(tanks[j]);
|
||||||
|
|
||||||
if (t->killer) {
|
if (t->killer) {
|
||||||
alive -= 1;
|
alive -= 1;
|
||||||
fprintf(stdout, " 0,\n");
|
fprintf(f, " 0,\n");
|
||||||
} else {
|
} else {
|
||||||
int k;
|
int k;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
@ -421,7 +419,7 @@ print_rounds(FILE *f,
|
||||||
if (t->led) {
|
if (t->led) {
|
||||||
flags |= 2;
|
flags |= 2;
|
||||||
}
|
}
|
||||||
fprintf(stdout, " [%d,%d,%.2f,%.2f,%d,%d],\n",
|
fprintf(f, " [%d,%d,%.2f,%.2f,%d,%d],\n",
|
||||||
(int)(t->position[0]),
|
(int)(t->position[0]),
|
||||||
(int)(t->position[1]),
|
(int)(t->position[1]),
|
||||||
t->angle,
|
t->angle,
|
||||||
|
@ -430,7 +428,27 @@ print_rounds(FILE *f,
|
||||||
sensors);
|
sensors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(stdout, "],\n");
|
fprintf(f, "],\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_standings(FILE *f,
|
||||||
|
struct forftank *ftanks,
|
||||||
|
struct tank *tanks,
|
||||||
|
int ntanks)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ntanks; i += 1) {
|
||||||
|
/* &tank path cause &killer parse_error_pos lasterr */
|
||||||
|
fprintf(f, "%p\t%s\t%s\t%p\t%d\t%s\n",
|
||||||
|
&(tanks[i]),
|
||||||
|
ftanks[i].path,
|
||||||
|
tanks[i].cause_death,
|
||||||
|
tanks[i].killer,
|
||||||
|
ftanks[i].error_pos,
|
||||||
|
forf_error_str[ftanks[i].env.error]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,9 +545,23 @@ main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
print_header(stdout, &game, myftanks, mytanks, ntanks);
|
print_header(stdout, &game, myftanks, mytanks, ntanks);
|
||||||
print_rounds(stdout, &game, myftanks, mytanks, ntanks);
|
print_rounds(stdout, &game, mytanks, ntanks);
|
||||||
|
|
||||||
print_footer(stdout);
|
print_footer(stdout);
|
||||||
|
|
||||||
|
/* Output standings to fd3.
|
||||||
|
*
|
||||||
|
* fd 3 is normally closed, so this won't normally do anything.
|
||||||
|
* To output to fd3 from the shell, you'll need to do something like this:
|
||||||
|
*
|
||||||
|
* ./run-tanks 3>standing
|
||||||
|
**/
|
||||||
|
{
|
||||||
|
FILE *standings = fdopen(3, "w");
|
||||||
|
|
||||||
|
if (standings) {
|
||||||
|
print_standings(standings, myftanks, mytanks, ntanks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue