diff --git a/Makefile b/Makefile index e0359c2..c60606d 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ +CFLAGS = -Wall LDFLAGS = -lm -all: test +all: run-tanks test: test-tanks ./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 clean: - rm -f test-tanks *.o \ No newline at end of file + rm -f test-tanks run-tanks *.o \ No newline at end of file diff --git a/cforf.c b/cforf.c index 34d329a..76196a2 100644 --- a/cforf.c +++ b/cforf.c @@ -211,6 +211,8 @@ forf_pop_stack(struct forf_env *env) case forf_type_stack_begin: depth -= 1; break; + default: + break; } } s.top = s.size; @@ -287,6 +289,8 @@ forf_stack_move_value(struct forf_env *env, case forf_type_stack_end: depth -= 1; break; + default: + break; } } while (depth > 0); diff --git a/cforf.h b/cforf.h index c399f64..ca8e384 100644 --- a/cforf.h +++ b/cforf.h @@ -119,7 +119,11 @@ void forf_env_init(struct forf_env *env, /** The type of a getch function (used for parsing) */ 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, forf_getch_func *getch, void *datum); diff --git a/ctanks.h b/ctanks.h index 243ce59..7c3cbfa 100644 --- a/ctanks.h +++ b/ctanks.h @@ -10,7 +10,7 @@ #define TANK_CANNON_RECHARGE 20 /* Turns to recharge cannon */ #define TANK_CANNON_RANGE (TANK_SENSOR_RANGE / 2) #define TANK_MAX_ACCEL 35 -#define TANK_MAX_TURRET_ROT (PI/3) +#define TANK_MAX_TURRET_ROT (PI/10) #define TANK_TOP_SPEED 7 /* (tank radius + tank radius)^2 */ @@ -75,6 +75,8 @@ struct tank { }; 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 */ void tank_set_led(struct tank *tank, int active); + #endif /* __CTANKS_H__ */ diff --git a/designer.cgi.c b/designer.cgi.c index 17ae09d..68be8b6 100644 --- a/designer.cgi.c +++ b/designer.cgi.c @@ -1,7 +1,10 @@ #include +#include #include #include +#define BASE_PATH "/tmp/" + struct string { char *s; size_t size; @@ -71,6 +74,8 @@ read_item(FILE *f, struct string *str) { int c; + str->len = 0; + while (1) { c = fgetc(f); switch (c) { @@ -100,6 +105,7 @@ read_pair(FILE *f, struct string *key, struct string *val) return read_item(f, val); } +/* This is ugly and I dislike it. */ #define new_string(name, size) \ char _##name[size]; \ struct string name = {_##name, size, 0 } @@ -111,13 +117,58 @@ main(int argc, char *argv[]) new_string(key, 20); new_string(val, 8192); + new_string(token, 40); 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"); while (! feof(stdin)) { 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, "=", 1); write(1, val.s, val.len); diff --git a/rank.awk b/rank.awk new file mode 100644 index 0000000..30a6007 --- /dev/null +++ b/rank.awk @@ -0,0 +1,38 @@ +BEGIN { + FS = "\t"; +} + +function esc(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 ""; + print ""; + for (me in name) { + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + } + print "
NameKillsCause of DeathKillerLast ErrorParse error @
" esc(name[me]) "" kills[me] "" reason[me] "" esc(name[killer[me]]) "" lasterr[me] "" errchar[me] "
"; +} \ No newline at end of file diff --git a/run-tanks.c b/run-tanks.c index 7b28770..ff1566e 100644 --- a/run-tanks.c +++ b/run-tanks.c @@ -20,8 +20,10 @@ struct forftank { struct forf_env env; + int error_pos; char color[7]; /* "ff0088" */ char name[50]; + char *path; struct forf_stack _prog; struct forf_value _progvals[CSTACK_SIZE]; @@ -40,7 +42,7 @@ forf_print_val(struct forf_value *val) { switch (val->type) { case forf_type_number: - printf("%d", val->v.i); + printf("%ld", val->v.i); break; case forf_type_proc: printf("[proc %p]", val->v.p); @@ -232,7 +234,6 @@ ft_read_program(struct forftank *ftank, struct forf_lexical_env *lenv, char *path) { - int ret; char progpath[256]; FILE *f; @@ -242,13 +243,9 @@ ft_read_program(struct forftank *ftank, if (! f) return 0; /* Parse program */ - ret = forf_parse_file(&ftank->env, f); + ftank->error_pos = forf_parse_file(&ftank->env, f); fclose(f); - if (ret) { - fprintf(stderr, "Parse error in %s, character %d: %s\n", - progpath, - ret, - forf_error_str[ftank->env.error]); + if (ftank->error_pos) { return 0; } @@ -320,6 +317,8 @@ ft_read_tank(struct forftank *ftank, { int ret; + ftank->path = path; + /* What is your name? */ ret = ft_read_file(ftank->name, sizeof(ftank->name), path, "name"); if (! ret) { @@ -384,7 +383,6 @@ print_footer(FILE *f) void print_rounds(FILE *f, struct tanks_game *game, - struct forftank *forftanks, struct tank *tanks, int ntanks) { @@ -396,15 +394,15 @@ print_rounds(FILE *f, for (i = 0; (alive > 1) && (i < ROUNDS); i += 1) { int j; - tanks_run_turn(&game, mytanks, ntanks); - fprintf(stdout, "[\n"); + tanks_run_turn(game, tanks, ntanks); + fprintf(f, "[\n"); alive = ntanks; for (j = 0; j < ntanks; j += 1) { - struct tank *t = &(mytanks[j]); + struct tank *t = &(tanks[j]); if (t->killer) { alive -= 1; - fprintf(stdout, " 0,\n"); + fprintf(f, " 0,\n"); } else { int k; int flags = 0; @@ -421,7 +419,7 @@ print_rounds(FILE *f, if (t->led) { 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[1]), t->angle, @@ -430,7 +428,27 @@ print_rounds(FILE *f, 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_rounds(stdout, &game, myftanks, mytanks, ntanks); - + print_rounds(stdout, &game, mytanks, ntanks); 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; }