mirror of https://github.com/dirtbags/tanks.git
Output actual JSON, and modernize it a little
This commit is contained in:
parent
49152d5128
commit
a3cb9f8fe1
|
@ -8,6 +8,7 @@ points
|
||||||
forftanks
|
forftanks
|
||||||
|
|
||||||
designer.cgi
|
designer.cgi
|
||||||
|
upload.cgi
|
||||||
|
|
||||||
forf.html
|
forf.html
|
||||||
summary.html
|
summary.html
|
||||||
|
|
25
Makefile
25
Makefile
|
@ -1,21 +1,13 @@
|
||||||
BINARIES = forftanks upload.cgi
|
DESTDIR ?= $(HOME)
|
||||||
HTML = forf.html procs.html intro.html designer.html debugger.html
|
|
||||||
WWW = style.css grunge.png designer.js figures.js tanks.js nav.html.inc jstanks.js
|
|
||||||
|
|
||||||
CFLAGS = -Wall
|
CFLAGS = -Wall
|
||||||
|
|
||||||
all: $(BINARIES) $(HTML)
|
BINARIES = forftanks upload.cgi
|
||||||
|
|
||||||
install:
|
all: $(BINARIES)
|
||||||
install -d $(DESTDIR)/usr/bin
|
|
||||||
install run-tanks $(DESTDIR)/usr/bin
|
|
||||||
install forftanks $(DESTDIR)/usr/bin
|
|
||||||
|
|
||||||
install -d $(DESTDIR)/usr/lib/tanks
|
install: $(BINARIES)
|
||||||
install designer.cgi $(DESTDIR)/usr/lib/tanks
|
install -d $(DESTDIR)$(PREFIX)/bin
|
||||||
install $(HTML) $(DESTDIR)/usr/lib/tanks
|
install $(BINARIES) $(DESTDIR)$(PREFIX)/bin
|
||||||
install $(WWW) $(DESTDIR)/usr/lib/tanks
|
|
||||||
cp -r examples $(DESTDIR)/usr/lib/tanks/examples
|
|
||||||
|
|
||||||
forftanks: forftanks.o ctanks.o forf.o
|
forftanks: forftanks.o ctanks.o forf.o
|
||||||
forftanks: LDLIBS = -lm
|
forftanks: LDLIBS = -lm
|
||||||
|
@ -24,9 +16,6 @@ forftanks.o: forf.h ctanks.h
|
||||||
forf.o: forf.c forf.h
|
forf.o: forf.c forf.h
|
||||||
ctanks.o: ctanks.h
|
ctanks.o: ctanks.h
|
||||||
|
|
||||||
%.html: %.html.m4 nav.html.inc
|
|
||||||
m4 $< > $@
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o next-round round-*.html
|
rm -f *.o next-round round-*.html
|
||||||
rm -f $(BINARIES) $(HTML)
|
rm -f $(BINARIES)
|
||||||
|
|
59
README.md
59
README.md
|
@ -8,15 +8,68 @@ written by other players. Dirtbags Tanks is frequently a component of
|
||||||
[Dirtbags Capture The Flag](https://dirtbags.github.io/contest/).
|
[Dirtbags Capture The Flag](https://dirtbags.github.io/contest/).
|
||||||
|
|
||||||
|
|
||||||
|
Running it
|
||||||
|
============
|
||||||
|
|
||||||
|
forftanks TANKDIR [TANKDIR...]
|
||||||
|
|
||||||
|
`forftanks` will run a round with every tank provided as an argument.
|
||||||
|
It outputs a JSON object describing the round.
|
||||||
|
|
||||||
|
|
||||||
|
Output fields
|
||||||
|
------
|
||||||
|
|
||||||
|
`seed`
|
||||||
|
: Seed used by the random number generator.
|
||||||
|
You can specify your own seed with the environment variable `SEED.
|
||||||
|
If the same seed is used with the same tanks,
|
||||||
|
you will get the same output.
|
||||||
|
|
||||||
|
`field`
|
||||||
|
: Dimensions of the play field.
|
||||||
|
|
||||||
|
`tanks`
|
||||||
|
: Description of each tank.
|
||||||
|
|
||||||
|
`rounds`
|
||||||
|
: List of frames for each round.
|
||||||
|
Each frame is a list of tank state for each tank.
|
||||||
|
Tank state is described below.
|
||||||
|
|
||||||
|
|
||||||
|
Tank state
|
||||||
|
--------
|
||||||
|
|
||||||
|
Tank state is packed more tightly than most modern JSON APIs.
|
||||||
|
Tank state is a tuple of (x position, y position, orientation angle, turret angle, flags, sensor bits).
|
||||||
|
|
||||||
|
x position, y position
|
||||||
|
: Tank's position on the play field.
|
||||||
|
|
||||||
|
orientation angle
|
||||||
|
: Tank's orientation on the play field, in radians.
|
||||||
|
|
||||||
|
turret angle
|
||||||
|
: Turret angle, relative to the tank, in radians.
|
||||||
|
|
||||||
|
flags
|
||||||
|
: Logical or of 1 (firing), 2 (LED on), and 4 (dead)
|
||||||
|
|
||||||
|
sensor bits
|
||||||
|
: Bit field of sensor state (1 = triggered)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
-------------
|
============
|
||||||
|
|
||||||
* [Homepage](https://dirtbags.github.io/tanks/)
|
* [Homepage](https://dirtbags.github.io/tanks/)
|
||||||
* [History](docs/history.md)
|
* [History](docs/history.md)
|
||||||
* [Running](docs/running.md)
|
* [Running](docs/running.md)
|
||||||
|
|
||||||
|
|
||||||
Author
|
Current Maintainer
|
||||||
------
|
=====
|
||||||
|
|
||||||
Neale Pickett <neale@woozle.org>
|
Neale Pickett <neale@woozle.org>
|
||||||
|
|
6
ctanks.h
6
ctanks.h
|
@ -1,5 +1,4 @@
|
||||||
#ifndef __CTANKS_H__
|
#pragma once
|
||||||
#define __CTANKS_H__
|
|
||||||
|
|
||||||
/* τ = 2π */
|
/* τ = 2π */
|
||||||
#define TAU 6.28318530717958647692
|
#define TAU 6.28318530717958647692
|
||||||
|
@ -107,6 +106,3 @@ 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__ */
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ to accept a scaled-down version of PostScript. The IRC channel we
|
||||||
frequent collectively agreed to give this new language the derisive name
|
frequent collectively agreed to give this new language the derisive name
|
||||||
"Forf", which should ideally be followed by punching someone after it is
|
"Forf", which should ideally be followed by punching someone after it is
|
||||||
spoken aloud. I wrote a Python implementation of Forf, which was slow,
|
spoken aloud. I wrote a Python implementation of Forf, which was slow,
|
||||||
and then Adam Glasgall wrote a C implementation, which was quick.
|
and then Anna Glasgall wrote a C implementation, which was quick.
|
||||||
|
|
||||||
I decided to take Tanks to Def Con in July 2010, and just for bragging
|
I decided to take Tanks to Def Con in July 2010, and just for bragging
|
||||||
rights, to have it run on an Asus WL-500gU. This is a $50 device with a
|
rights, to have it run on an Asus WL-500gU. This is a $50 device with a
|
||||||
|
|
|
@ -6,7 +6,7 @@ title: thanks
|
||||||
* Paul Ferrell: Initial implementation
|
* Paul Ferrell: Initial implementation
|
||||||
* Aaron McPhall: Math optimizations
|
* Aaron McPhall: Math optimizations
|
||||||
* Nick Moffitt: Suggestion to use FORTH-like language
|
* Nick Moffitt: Suggestion to use FORTH-like language
|
||||||
* Adam Glasgall: C Forf prototype
|
* Anna Glasgall: C Forf prototype
|
||||||
* Adam Thomas: Various patches
|
* Adam Thomas: Various patches
|
||||||
* Various Australians: Creation of some mind-blowing tanks
|
* Various Australians: Creation of some mind-blowing tanks
|
||||||
* Alyssa Milburn: JS Tanks, Tank Debugger, many more other helpful contributions
|
* Alyssa Milburn: JS Tanks, Tank Debugger, many more other helpful contributions
|
||||||
|
|
4
dump.h
4
dump.h
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __DUMP_H__
|
#pragma once
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
@ -28,5 +28,3 @@
|
||||||
#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)
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
5
forf.h
5
forf.h
|
@ -1,5 +1,4 @@
|
||||||
#ifndef __FORF_H__
|
#pragma once
|
||||||
#define __FORF_H__
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
@ -146,5 +145,3 @@ int forf_eval_once(struct forf_env *env);
|
||||||
|
|
||||||
/** Evaluate the entire command stack */
|
/** Evaluate the entire command stack */
|
||||||
int forf_eval(struct forf_env *env);
|
int forf_eval(struct forf_env *env);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
148
forftanks.c
148
forftanks.c
|
@ -368,38 +368,11 @@ ft_read_tank(struct forftank *ftank,
|
||||||
void
|
void
|
||||||
print_header(FILE *f,
|
print_header(FILE *f,
|
||||||
struct tanks_game *game,
|
struct tanks_game *game,
|
||||||
struct forftank *forftanks,
|
int seed)
|
||||||
struct tank *tanks,
|
|
||||||
int ntanks)
|
|
||||||
{
|
{
|
||||||
int i, j;
|
fprintf(f, "{\n");
|
||||||
|
fprintf(f, " \"seed\": %d,\n", seed);
|
||||||
fprintf(f, "[[%d,%d],[\n",
|
fprintf(f, " \"field\": [%d,%d],\n", (int)game->size[0], (int)game->size[1]);
|
||||||
(int)game->size[0], (int)game->size[1]);
|
|
||||||
for (i = 0; i < ntanks; i += 1) {
|
|
||||||
fprintf(f, " [\"%s\",[", forftanks[i].color);
|
|
||||||
for (j = 0; j < TANK_MAX_SENSORS; j += 1) {
|
|
||||||
struct sensor *s = &(tanks[i].sensors[j]);
|
|
||||||
|
|
||||||
if (! s->range) {
|
|
||||||
fprintf(f, "0,");
|
|
||||||
} else {
|
|
||||||
fprintf(f, "[%d,%.2f,%.2f,%d],",
|
|
||||||
(int)(s->range),
|
|
||||||
s->angle,
|
|
||||||
s->width,
|
|
||||||
s->turret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fprintf(f, "]],\n");
|
|
||||||
}
|
|
||||||
fprintf(f, "],[\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
print_footer(FILE *f)
|
|
||||||
{
|
|
||||||
fprintf(f, "]]\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -408,24 +381,31 @@ print_rounds(FILE *f,
|
||||||
struct tank *tanks,
|
struct tank *tanks,
|
||||||
int ntanks)
|
int ntanks)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
int alive;
|
int alive;
|
||||||
|
|
||||||
|
fprintf(f, " \"rounds\": [\n");
|
||||||
|
|
||||||
/* Run rounds */
|
/* Run rounds */
|
||||||
alive = ntanks;
|
alive = ntanks;
|
||||||
for (i = 0; (alive > 1) && (i < ROUNDS); i += 1) {
|
for (int i = 0; (alive > 1) && (i < ROUNDS); i += 1) {
|
||||||
int j;
|
if (i > 0) {
|
||||||
|
fprintf(f, ",\n");
|
||||||
|
}
|
||||||
|
|
||||||
tanks_run_turn(game, tanks, ntanks);
|
tanks_run_turn(game, tanks, ntanks);
|
||||||
fprintf(f, "[\n");
|
fprintf(f, " [");
|
||||||
alive = ntanks;
|
alive = ntanks;
|
||||||
for (j = 0; j < ntanks; j += 1) {
|
for (int j = 0; j < ntanks; j += 1) {
|
||||||
struct tank *t = &(tanks[j]);
|
struct tank *t = &(tanks[j]);
|
||||||
|
|
||||||
int k;
|
int k;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
int sensors = 0;
|
int sensors = 0;
|
||||||
|
|
||||||
|
if (j > 0) {
|
||||||
|
fprintf(f, ",");
|
||||||
|
}
|
||||||
|
|
||||||
for (k = 0; k < TANK_MAX_SENSORS; k += 1) {
|
for (k = 0; k < TANK_MAX_SENSORS; k += 1) {
|
||||||
if (t->sensors[k].triggered) {
|
if (t->sensors[k].triggered) {
|
||||||
sensors |= (1 << k);
|
sensors |= (1 << k);
|
||||||
|
@ -441,7 +421,7 @@ print_rounds(FILE *f,
|
||||||
alive -= 1;
|
alive -= 1;
|
||||||
flags |= 4;
|
flags |= 4;
|
||||||
}
|
}
|
||||||
fprintf(f, " [%d,%d,%.2f,%.2f,%d,%d],\n",
|
fprintf(f, "[%d,%d,%.2f,%.2f,%d,%d]",
|
||||||
(int)t->position[0],
|
(int)t->position[0],
|
||||||
(int)(t->position[1]),
|
(int)(t->position[1]),
|
||||||
t->angle,
|
t->angle,
|
||||||
|
@ -449,8 +429,10 @@ print_rounds(FILE *f,
|
||||||
flags,
|
flags,
|
||||||
sensors);
|
sensors);
|
||||||
}
|
}
|
||||||
fprintf(f, "],\n");
|
fprintf(f, "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(f, "\n ],\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -459,18 +441,56 @@ print_standings(FILE *f,
|
||||||
struct tank *tanks,
|
struct tank *tanks,
|
||||||
int ntanks)
|
int ntanks)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ntanks; i += 1) {
|
fprintf(f, " \"tanks\": [\n");
|
||||||
/* &tank path cause &killer parse_error_pos lasterr */
|
for (int i = 0; i < ntanks; i += 1) {
|
||||||
fprintf(f, "%p\t%s\t%s\t%p\t%d\t%s\n",
|
int killer = -1;
|
||||||
&(tanks[i]),
|
for (int j = 0; j < ntanks; j += 1) {
|
||||||
ftanks[i].path,
|
if (tanks[i].killer == &(tanks[j])) {
|
||||||
tanks[i].cause_death,
|
killer = j;
|
||||||
tanks[i].killer,
|
|
||||||
ftanks[i].error_pos,
|
|
||||||
forf_error_str[ftanks[i].env.error]);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > 0) {
|
||||||
|
fprintf(f, ",\n");
|
||||||
|
}
|
||||||
|
fprintf(f, " {\n");
|
||||||
|
fprintf(f, " \"color\": \"%s\",\n", ftanks[i].color);
|
||||||
|
fprintf(f, " \"path\": \"%s\",\n", ftanks[i].path);
|
||||||
|
fprintf(f, " \"death\": \"%s\",\n", tanks[i].cause_death);
|
||||||
|
fprintf(f, " \"killer\": %d,\n", killer);
|
||||||
|
fprintf(f, " \"errorPos\": %d,\n", ftanks[i].error_pos);
|
||||||
|
fprintf(f, " \"error\": \"%s\",\n", forf_error_str[ftanks[i].env.error]);
|
||||||
|
fprintf(f, " \"sensors\": [\n");
|
||||||
|
for (int j = 0; j < TANK_MAX_SENSORS; j += 1) {
|
||||||
|
struct sensor *s = &(tanks[i].sensors[j]);
|
||||||
|
|
||||||
|
if (j > 0) {
|
||||||
|
fprintf(f, ",\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! s->range) {
|
||||||
|
fprintf(f, " null");
|
||||||
|
} else {
|
||||||
|
fprintf(f, " {\"range\":%d,\"angle\":%.2f,\"width\":%.2f,\"turret\":%s}",
|
||||||
|
(int)(s->range),
|
||||||
|
s->angle,
|
||||||
|
s->width,
|
||||||
|
s->turret?"true":"false");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(f, "\n ]");
|
||||||
|
fprintf(f, "\n }");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(f, "\n ],\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_footer(FILE *f)
|
||||||
|
{
|
||||||
|
fprintf(f, " \"\": null\n"); // sentry, so everything prior can end with a comma
|
||||||
|
fprintf(f, "}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -483,6 +503,7 @@ main(int argc, char *argv[])
|
||||||
int order[MAX_TANKS];
|
int order[MAX_TANKS];
|
||||||
int ntanks = 0;
|
int ntanks = 0;
|
||||||
int i;
|
int i;
|
||||||
|
int seed;
|
||||||
|
|
||||||
lenv[0].name = NULL;
|
lenv[0].name = NULL;
|
||||||
lenv[0].proc = NULL;
|
lenv[0].proc = NULL;
|
||||||
|
@ -495,14 +516,18 @@ 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");
|
||||||
int seed = atoi(s?s:"");
|
seed = atoi(s?s:"");
|
||||||
|
|
||||||
if (! seed) {
|
if (! seed) {
|
||||||
seed = getpid();
|
seed = getpid();
|
||||||
}
|
}
|
||||||
|
|
||||||
srand(seed);
|
srand(seed);
|
||||||
fprintf(stdout, "// SEED=%d\n", seed);
|
}
|
||||||
|
|
||||||
|
if ((argc < 2) || (argv[1][0] == '-')) {
|
||||||
|
fprintf(stderr, "usage: %s TANKDIR [TANKDIR...]\n", argv[0]);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Every argument is a tank directory */
|
/* Every argument is a tank directory */
|
||||||
|
@ -515,11 +540,6 @@ main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == ntanks) {
|
|
||||||
fprintf(stderr, "No usable tanks!\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate the size of the game board */
|
/* Calculate the size of the game board */
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
|
@ -566,24 +586,10 @@ main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print_header(stdout, &game, myftanks, mytanks, ntanks);
|
print_header(stdout, &game, seed);
|
||||||
print_rounds(stdout, &game, mytanks, ntanks);
|
print_rounds(stdout, &game, mytanks, ntanks);
|
||||||
|
print_standings(stdout, myftanks, 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;
|
||||||
}
|
}
|
||||||
|
|
83
rank.awk
83
rank.awk
|
@ -1,83 +0,0 @@
|
||||||
#! /usr/bin/awk -f
|
|
||||||
|
|
||||||
BEGIN {
|
|
||||||
FS = "\t";
|
|
||||||
}
|
|
||||||
|
|
||||||
function esc(s) {
|
|
||||||
gsub(/&/, "&", s);
|
|
||||||
gsub(/</, "<", s);
|
|
||||||
gsub(/>/, ">", s);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
id = $1;
|
|
||||||
ntanks += 1;
|
|
||||||
tanks[id] = id;
|
|
||||||
if ($4 == "(nil)") {
|
|
||||||
score[id] += 1;
|
|
||||||
} else {
|
|
||||||
reason[id] = $3;
|
|
||||||
killer[id] = $4;
|
|
||||||
kills[$4] += 1;
|
|
||||||
score[$4] += 1;
|
|
||||||
}
|
|
||||||
path[id] = $2;
|
|
||||||
if ($5) {
|
|
||||||
lasterr[id] = $6 " around char " $5;
|
|
||||||
} else {
|
|
||||||
lasterr[id] = $6;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (1 == getline < (path[id] "/name")) {
|
|
||||||
name[id] = esc($0);
|
|
||||||
} else {
|
|
||||||
name[id] = "<i>Unnamed</i>";
|
|
||||||
}
|
|
||||||
|
|
||||||
getline < (path[id] "/color");
|
|
||||||
if (/^#[0-9A-Fa-f]+$/) {
|
|
||||||
color[id] = $0;
|
|
||||||
} else {
|
|
||||||
color[id] = "#c0c0c0";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
END {
|
|
||||||
# Fill in who killed whom
|
|
||||||
for (id in tanks) {
|
|
||||||
if (score[id] > topscore) {
|
|
||||||
winner = id;
|
|
||||||
topscore = score[id];
|
|
||||||
}
|
|
||||||
if (killer[id]) {
|
|
||||||
reason[id] = reason[id] " (<span style='color:" color[killer[id]] ";'>" name[killer[id]] "</span>)";
|
|
||||||
}
|
|
||||||
# XXX: track points a different way
|
|
||||||
# print score[id] >> (path[id] "/points");
|
|
||||||
}
|
|
||||||
|
|
||||||
# Output the table
|
|
||||||
print "<table id=\"results\">";
|
|
||||||
print "<tr><th>Name</th><th>Score</th><th>Cause of Death</th><th>Last Error</th></tr>";
|
|
||||||
for (i = ntanks; i >= 0; i -= 1) {
|
|
||||||
for (me in tanks) {
|
|
||||||
if (score[me] == i) {
|
|
||||||
if (me == winner) {
|
|
||||||
style = "style=\"font-weight: bold; background-color: #666666\"";
|
|
||||||
} else {
|
|
||||||
style = "";
|
|
||||||
}
|
|
||||||
printf("<tr " style ">");
|
|
||||||
printf("<td><span class=\"swatch\" style=\"background-color: " color[me] "\">#</span> " name[me] "</td>");
|
|
||||||
printf("<td>" score[me] "</td>");
|
|
||||||
printf("<td>" reason[me] "</td>");
|
|
||||||
printf("<td>" lasterr[me] "</td>");
|
|
||||||
printf("</tr>\n");
|
|
||||||
printf("<!-- score " path[me] " " i " -->\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
print "</table>";
|
|
||||||
}
|
|
77
summary.awk
77
summary.awk
|
@ -1,77 +0,0 @@
|
||||||
#! /usr/bin/awk -f
|
|
||||||
|
|
||||||
function esc(s) {
|
|
||||||
gsub(/&/, "&", s);
|
|
||||||
gsub(/</, "<", s);
|
|
||||||
gsub(/>/, ">", s);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
BEGIN {
|
|
||||||
ngames = 20;
|
|
||||||
getline rounds < "next-round";
|
|
||||||
|
|
||||||
print "<!DOCTYPE html>";
|
|
||||||
print "<html>";
|
|
||||||
print " <head>";
|
|
||||||
print " <title>Dirtbags Tanks</title>";
|
|
||||||
print " <link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">";
|
|
||||||
print " </head>";
|
|
||||||
print " <body>";
|
|
||||||
print " <h1>Dirtbags Tanks</h1>";
|
|
||||||
|
|
||||||
print " <p>New here? Read the <a href=\"intro.html\">introduction</a>.</p>";
|
|
||||||
print " <p>New round every minute.</p>";
|
|
||||||
print " <h2>Rankings</h2>";
|
|
||||||
print " <p>Over the last " ngames" games only.</p>";
|
|
||||||
print " <ol>";
|
|
||||||
for (i = rounds - ngames - 1; i > 0 && i < rounds; i += 1) {
|
|
||||||
fn = sprintf("round-%04d.html", i)
|
|
||||||
while (getline < fn) {
|
|
||||||
if ($2 == "score") {
|
|
||||||
scores[$3] += $4
|
|
||||||
if (scores[$3] > topscore) {
|
|
||||||
topscore = scores[$3]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (id in scores) {
|
|
||||||
if (1 == getline < (id "/name")) {
|
|
||||||
names[id] = esc($0)
|
|
||||||
} else {
|
|
||||||
names[id] = "<i>Unnamed</i>"
|
|
||||||
}
|
|
||||||
|
|
||||||
getline < (id "/color")
|
|
||||||
if (/^#[0-9A-Fa-f]+$/) {
|
|
||||||
color[id] = $0
|
|
||||||
} else {
|
|
||||||
color[id] = "#c0c0c0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (s = topscore; s >= 0; s -= 1) {
|
|
||||||
for (id in scores) {
|
|
||||||
if (scores[id] == s) {
|
|
||||||
printf("<li><span class=\"swatch\" style=\"background-color: %s;\">#</span> %s (%d points)</li>\n", color[id], names[id], scores[id]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
print " </ol>";
|
|
||||||
|
|
||||||
print " <h2>Rounds</h2>";
|
|
||||||
print " <ul>";
|
|
||||||
for (i = rounds - 1; (i >= rounds - 721) && (i > 0); i -= 1) {
|
|
||||||
printf("<li><a href=\"round-%04d.html\">%04d</a></li>\n", i, i);
|
|
||||||
}
|
|
||||||
print " </ul>";
|
|
||||||
|
|
||||||
while (getline < ENVIRON["NAV_HTML_INC"]) {
|
|
||||||
print;
|
|
||||||
}
|
|
||||||
|
|
||||||
print " </body>";
|
|
||||||
print "</html>";
|
|
||||||
}
|
|
32
winner.awk
32
winner.awk
|
@ -1,32 +0,0 @@
|
||||||
#! /usr/bin/awk -f
|
|
||||||
|
|
||||||
BEGIN {
|
|
||||||
FS = "\t";
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
tanks[$1] = $2;
|
|
||||||
if ($4 == "(nil)") {
|
|
||||||
p = $1;
|
|
||||||
} else {
|
|
||||||
p = $4;
|
|
||||||
}
|
|
||||||
score[p] += 1;
|
|
||||||
if (score[p] == topscore) {
|
|
||||||
winners += 1;
|
|
||||||
} else if (score[p] > topscore) {
|
|
||||||
winners = 1;
|
|
||||||
topscore = score[p];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
END {
|
|
||||||
if (winners > 1) {
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
for (id in tanks) {
|
|
||||||
if (score[id] == topscore) {
|
|
||||||
print tanks[id];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue