diff --git a/.gitignore b/.gitignore
index ce47879..d5c648c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,10 @@
*~
*#
*.o
+*.swp
round-*.html
+results-*.txt
next-round
points
forftanks
@@ -14,3 +16,5 @@ summary.html
designer.html
intro.html
procs.html
+chord.html
+killmatrix.js
diff --git a/Makefile b/Makefile
index fded3c4..0b24b5d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,32 +1,55 @@
BINARIES = forftanks designer.cgi
-HTML = forf.html procs.html intro.html designer.html
+HTML = forf.html procs.html intro.html designer.html chord.html
WWW = style.css grunge.png designer.js figures.js tanks.js nav.html.inc
+SCRIPTS = killmatrix.pl rank.awk summary.awk winner.awk
-CFLAGS = -Wall
+CFLAGS = -Wall -std=gnu90 -g
all: $(BINARIES) $(HTML)
-install:
- install -d $(DESTDIR)/usr/bin
- install run-tanks $(DESTDIR)/usr/bin
- install forftanks $(DESTDIR)/usr/bin
+forftanks: forftanks.o ctanks.o forf.o tankdir.o tankjson.o
+forftanks: LDLIBS = -lm -ljansson
- install -d $(DESTDIR)/usr/lib/tanks
- install designer.cgi $(DESTDIR)/usr/lib/tanks
- install $(HTML) $(DESTDIR)/usr/lib/tanks
- install $(WWW) $(DESTDIR)/usr/lib/tanks
- cp -r examples $(DESTDIR)/usr/lib/tanks/examples
-
-forftanks: forftanks.o ctanks.o forf.o
-forftanks: LDFLAGS = -lm
-
-forftanks.o: forf.h ctanks.h
+forftanks.o: forf.h ctanks.h tankdef.h tankdir.h tankjson.h
forf.o: forf.c forf.h
ctanks.o: ctanks.h
+tankdir.o: tankdef.h tankdir.h
+tankjson.o: tankdef.h tankjson.h
%.html: %.html.m4
m4 $< > $@
+.PHONY: install clean check-env
+install: check-env
+ install -d $(DESTDIR)/bin
+ install run-tanks $(DESTDIR)/bin
+ install forftanks $(DESTDIR)/bin
+ install $(SCRIPTS) $(DESTDIR)/bin
+ install -d $(DOCROOT)
+ install designer.cgi $(CGIBIN)
+ install $(HTML) $(DOCROOT)
+ install $(WWW) $(DOCROOT)
+ cp -r examples $(DOCROOT)/examples
+
clean:
- rm -f *.o next-round round-*.html
+ rm -f *.o next-round round-*.html round-*.json results-*.txt current.html
rm -f $(BINARIES) $(HTML)
+
+check-env:
+ifndef DESTDIR
+ $(error DESTDIR is undefined)
+endif
+ifndef DOCROOT
+ifndef DESTDIR
+ $(error DOCROOT is undefined)
+else
+DOCROOT = $(DESTDIR)
+endif
+endif
+ifndef CGIBIN
+ifndef DESTDIR
+ $(error CGIBIN is undefined)
+else
+CGIBIN = $(DESTDIR)
+endif
+endif
diff --git a/README.txt b/README.txt
index f446fcb..afaf3b5 100644
--- a/README.txt
+++ b/README.txt
@@ -18,7 +18,7 @@ hodgepodge of C, Bourne shell, and awk, but at least each piece is
fairly simple to audit.
-### round.sh tank1 tank2 ...
+### run-tanks tank1 tank2 ...
Runs a single round, awards points with rank.awk, and creates a new
summary.html with summary.awk. This is the main interface that you want
diff --git a/chord.html.m4 b/chord.html.m4
new file mode 100644
index 0000000..9118a5c
--- /dev/null
+++ b/chord.html.m4
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+Killer Chart
+include(nav.html.inc)
+
+
+
diff --git a/ctanks.c b/ctanks.c
index f7d1049..be7a165 100644
--- a/ctanks.c
+++ b/ctanks.c
@@ -105,17 +105,13 @@ rotate_point(float angle, float point[2])
point[1] = new[1];
}
-
static void
-tanks_fire_cannon(struct tanks_game *game,
- struct tank *this,
- struct tank *that,
- float vector[2],
- float dist2)
+tanks_collision_detect(struct tanks_game *game,
+ struct tank *this,
+ struct tank *that,
+ float vector[2],
+ float dist2)
{
- float theta = this->angle + this->turret.current;
- float rpos[2];
-
/* If someone's a crater, this is easy */
if (this->killer || that->killer) {
return;
@@ -128,18 +124,32 @@ tanks_fire_cannon(struct tanks_game *game,
that->killer = this;
that->cause_death = "collision";
+ }
+}
- return;
+static int
+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 rpos[2];
+
+ /* If someone's a crater, this is easy */
+ if (this->killer || that->killer) {
+ return 0;
}
/* No need to check if it's not even firing */
if (! this->turret.firing) {
- return;
+ return 0;
}
/* Also no need to check if it's outside cannon range */
if (dist2 > TANK_CANNON_ADJ2) {
- return;
+ return 0;
}
/* Did this shoot that? Rotate point by turret degrees, and if |y| <
@@ -147,10 +157,7 @@ tanks_fire_cannon(struct tanks_game *game,
rpos[0] = vector[0];
rpos[1] = vector[1];
rotate_point(-theta, rpos);
- if ((rpos[0] > 0) && (fabsf(rpos[1]) < TANK_RADIUS)) {
- that->killer = this;
- that->cause_death = "shot";
- }
+ return ((rpos[0] > 0) && (fabsf(rpos[1]) < TANK_RADIUS));
}
static void
@@ -428,10 +435,21 @@ tanks_run_turn(struct tanks_game *game, struct tank *tanks, int ntanks)
struct tank *that = &tanks[j];
compute_vector(game, vector, &dist2, this, that);
- tanks_fire_cannon(game, this, that, vector, dist2);
+ tanks_collision_detect(game, that, this, vector, dist2);
+ int a,b;
+ a = tanks_fire_cannon(game, this, that, vector, dist2);
vector[0] = -vector[0];
vector[1] = -vector[1];
- tanks_fire_cannon(game, that, this, vector, dist2);
+ b = tanks_fire_cannon(game, that, this, vector, dist2);
+
+ if(a){
+ that->killer = this;
+ that->cause_death = "shot";
+ }
+ if(b){
+ this->killer = that;
+ this->cause_death = "shot";
+ }
}
}
}
diff --git a/forftanks.c b/forftanks.c
index 65205fc..497bc27 100644
--- a/forftanks.c
+++ b/forftanks.c
@@ -20,14 +20,20 @@
#include
#include
#include
+#include
#include "ctanks.h"
#include "forf.h"
#include "dump.h"
+#include "tankdef.h"
+#include "tankdir.h"
+#include "tankjson.h"
#define MAX_TANKS 50
#define ROUNDS 500
#define SPACING 150
+#define MAX_JSON_SIZE 10000
+
#define LENV_SIZE 100
#define DSTACK_SIZE 200
@@ -194,34 +200,6 @@ struct forf_lexical_env tanks_lenv_addons[] = {
* Filesystem stuff
*
*/
-
-int
-ft_read_file(char *ptr, size_t size, char *dir, char *fn)
-{
- char path[256];
- FILE *f = NULL;
- int ret;
- int success = 0;
-
- do {
- snprintf(path, sizeof(path), "%s/%s", dir, fn);
- f = fopen(path, "r");
- if (! f) break;
-
- ret = fread(ptr, 1, size - 1, f);
- ptr[ret] = '\0';
- if (! ret) break;
-
- success = 1;
- } while (0);
-
- if (f) fclose(f);
- if (! success) {
- return 0;
- }
- return 1;
-}
-
void
ft_bricked_tank(struct tank *tank, void *ignored)
{
@@ -244,33 +222,17 @@ ft_run_tank(struct tank *tank, struct forftank *ftank)
}
}
-int
+int //&L Added function
ft_read_program(struct forftank *ftank,
- struct tank *tank,
- struct forf_lexical_env *lenv,
- char *path)
+ struct tank *tank,
+ struct tankdef *tank_def)
{
- char progpath[256];
- FILE *f;
-
- /* Open program */
- snprintf(progpath, sizeof(progpath), "%s/program", path);
- f = fopen(progpath, "r");
- if (! f) return 0;
-
- /* Parse program */
- ftank->error_pos = forf_parse_file(&ftank->env, f);
- fclose(f);
+ ftank->error_pos = forf_parse_string(&ftank->env, tank_def->program);
if (ftank->error_pos) {
return 0;
}
-
- /* Back up the program so we can run it over and over without
- needing to re-parse */
forf_stack_copy(&ftank->_prog, &ftank->_cmd);
-
tank_init(tank, (tank_run_func *)ft_run_tank, ftank);
-
return 1;
}
@@ -292,71 +254,71 @@ ft_tank_init(struct forftank *ftank,
tank);
}
-void
-ft_read_sensors(struct tank *tank,
- char *path)
+void //&L Added function
+ft_read_sensors(struct tank *tank,
+ struct tankdef *tankdef)
{
int i;
for (i = 0; i < TANK_MAX_SENSORS; i += 1) {
- int ret;
- char fn[10];
- char s[20];
- char *p = s;
long range;
- long angle;
- long width;
+ double angle;
+ double width;
long turret;
- snprintf(fn, sizeof(fn), "sensor%d", i);
- ret = ft_read_file(s, sizeof(s), path, fn);
- if (! ret) {
- s[0] = 0;
- }
- range = strtol(p, &p, 0);
- angle = strtol(p, &p, 0);
- width = strtol(p, &p, 0);
- turret = strtol(p, &p, 0);
+ range = tankdef->sensors[i].range;
+ angle = tankdef->sensors[i].angle;
+ width = tankdef->sensors[i].width;
+ turret = tankdef->sensors[i].turret;
tank->sensors[i].range = min(range, TANK_SENSOR_RANGE);
- tank->sensors[i].angle = deg2rad(angle % 360);
- tank->sensors[i].width = deg2rad(width % 360);
+ tank->sensors[i].angle = deg2rad((long)angle % 360);
+ tank->sensors[i].width = deg2rad((long)width % 360);
tank->sensors[i].turret = (0 != turret);
}
}
-int
+char* //&L Added function.
+temp_parse_path(char* tankName)
+{
+ size_t inTankName;
+ size_t inPath;
+ char* retVal = (char*)malloc(strlen(tankName)*sizeof(char));
+ for(inTankName=0, inPath=0; inTankNamepath = path;
-
+ ftank->path = temp_parse_path(tank_def->name); // No path anymore.
/* What is your name? */
- ret = ft_read_file(ftank->name, sizeof(ftank->name), path, "name");
- if (! ret) {
- strncpy(ftank->name, path, sizeof(ftank->name));
- }
-
+ strncpy(ftank->name, tank_def->name, sizeof(ftank->name));
/* What is your quest? */
ft_tank_init(ftank, tank, lenv);
- ret = ft_read_program(ftank, tank, lenv, path);
+ ret = ft_read_program(ftank, tank, tank_def);
if (ret) {
- ft_read_sensors(tank, path);
+ ft_read_sensors(tank, tank_def);
} else {
/* Brick the tank */
tank_init(tank, ft_bricked_tank, NULL);
}
-
/* What is your favorite color? */
- ret = ft_read_file(ftank->color, sizeof(ftank->color), path, "color");
- if (! ret) {
- strncpy(ftank->color, "#808080", sizeof(ftank->color));
- }
-
+ strncpy(ftank->color, tank_def->color, sizeof(ftank->color));
return 1;
}
@@ -469,10 +431,24 @@ print_standings(FILE *f,
}
}
+void
+delete_tank(struct forftank theTank) {
+ free(theTank.path);
+}
+
+void
+delete_tanks(struct forftank* myftanks, const int ntanks) {
+ int i;
+ for(i=0; i 1){
+ /* Every argument is a tank directory */
+ ntanks = argc-1; // argc[0] is program name, not a tank.
+ if(ntanks > MAX_TANKS) {
+ fprintf(stderr, "Too many tanks! Tried to load: %d, Max: %d",
+ ntanks, MAX_TANKS);
+ return 1;
}
+ for (i = 0; i < ntanks; i++) { //&L changed loop.
+ mytankdefs[i] = readTankFromDir(argv[i+1]);
+ }
+ } else { // Expecting JSON on stdin.
+ char* jsonString = malloc(sizeof(char)*MAX_JSON_SIZE);
+ char c;
+ long size = 0;
+ while( (c=fgetc(stdin)) != EOF ) {
+ jsonString[size] = c;
+ size++;
+ if(size>=(MAX_JSON_SIZE-1)) {
+ fprintf(stderr,"Error: JSON text too large.\n");
+ return 1;
+ }
+ }
+ jsonString[size] = '\0';
+ ntanks = jsonArraySize(jsonString); // argc[0] is program name, not a tank.
+ if(ntanks > MAX_TANKS) {
+ fprintf(stderr, "Too many tanks! Tried to load: %d, Max: %d",
+ ntanks, MAX_TANKS);
+ return 1;
+ }
+ readTanksFromJSON(mytankdefs, ntanks, jsonString);
}
-
if (0 == ntanks) {
fprintf(stderr, "No usable tanks!\n");
return 1;
}
+ for(i=0; i < ntanks; i++) {
+ ft_read_tank(&myftanks[i],
+ &mytanks[i],
+ lenv,
+ &mytankdefs[i]);
+ }
/* Calculate the size of the game board */
{
@@ -580,6 +584,8 @@ main(int argc, char *argv[])
print_standings(standings, myftanks, mytanks, ntanks);
}
}
+
+ delete_tanks(myftanks, ntanks);
return 0;
}
diff --git a/killmatrix.pl b/killmatrix.pl
new file mode 100755
index 0000000..1f51db1
--- /dev/null
+++ b/killmatrix.pl
@@ -0,0 +1,55 @@
+#!/usr/bin/perl
+
+foreach $file (@ARGV) {
+ $tanks = {};
+ open FH, "<$file";
+ foreach () {
+ chomp;
+ @tank{"id","path","cause","killer","errorpos","error"} = split;
+ $tanks->{$tank{"id"}} = {%tank};
+ $paths->{$tank{"path"}}++};
+ foreach (values %$tanks) {
+ next if $_->{"killer"} eq "(nil)";
+ next unless $_->{"cause"} eq "shot";
+ $data->{$tanks->{$_->{"killer"}}->{"path"}}->{$_->{"path"}}++
+ }
+ };
+ @paths = keys %$paths;
+ print
+ "var names = [",
+ (join
+ ",",
+ map {
+ open NF, $_."/name";
+ $name = ;
+ chomp $name;"\"$name\""
+ }
+ @paths
+ ),
+ "];\n";
+
+ print "var colors = [",
+ (join
+ ",",
+ map {
+ open CF, $_."/color";
+ $color = ;
+ $color ||= "#c0c0c0";
+ chomp $color;
+ "\"$color\""
+ } @paths
+ ),
+ "];\n";
+
+ print
+ "var matrix = [\n [",
+ (join
+ ("],\n [",
+ map {
+ join(
+ ",",
+ map{$_||=0} @{$data->{$_}}{@paths}
+ )
+ }
+ @paths)
+ ),"]\n];\n";
diff --git a/rank.awk b/rank.awk
index 1ad320a..f7e44ad 100755
--- a/rank.awk
+++ b/rank.awk
@@ -5,9 +5,9 @@ BEGIN {
}
function esc(s) {
- gsub(/&/, "&", s);
- gsub(/, "<", s);
- gsub(/>/, ">", s);
+ gsub(/&/, "\\&", s);
+ gsub(/, "\\<", s);
+ gsub(/>/, "\\>", s);
return s;
}
diff --git a/run-tanks b/run-tanks
index 854aec9..edc5a20 100755
--- a/run-tanks
+++ b/run-tanks
@@ -22,10 +22,13 @@ fi
expr $next + 1 > next-round
fn=$(printf "round-%04d.html" $next)
-rfn=results$$.txt
-
+rfn=$(printf "results-%04d.txt" $next)
+jfn=$(printf "round-%04d.json" $next)
+cfn="current$$.html";
echo -n "Running round $next... "
+$TANKS_GAME $tanks >>$jfn 3>$rfn
+
cat <$fn
@@ -38,7 +41,7 @@ cat <$fn
start("battlefield",
// Start JSON data
EOF
-$TANKS_GAME $tanks >>$fn 3>$rfn
+cat $jfn >> $fn
cat <>$fn
// end JSON data
);
@@ -52,15 +55,56 @@ window.onload = go;
0 fps
EOF
rank.awk $rfn >>$fn
-rm -f $rfn
cat $NAV_HTML_INC >>$fn
cat <>$fn