');
+ $('#playing').button();
+ var slider = $('#seekslider');
+ slider.slider({ max: turns.length-1, slide: function(event, ui) { seekToFrame(ui.value); } });
+
+ var spacing = 100 / turns.length;
+ var deaths = [];
+ for (i in turns[0]) {
+ deaths.push(false);
+ }
+ var percent = 0;
+ for (var f = 0; f < turns.length; f++) {
+ var turn = turns[f];
+ if (percent < (spacing * f)) {
+ percent = spacing * f;
+ }
+ for (var i = 0; i < turn.length; i++) {
+ if (deaths[i]) { continue; }
+ if (!turn[i] || (turn[i][4] & 4)) {
+ deaths[i] = true;
+ // http://stackoverflow.com/questions/8648963/add-tick-marks-to-jquery-slider
+ $('').css('left', percent + '%').css('background-color', game[1][i][0]).appendTo(slider);
+ percent++;
+ break;
+ }
+ }
+ }
+ }
+}
+
diff --git a/docs/_site/history.html b/docs/_site/history.html
new file mode 100644
index 0000000..58284ab
--- /dev/null
+++ b/docs/_site/history.html
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ by
+
+
+
+
History
+
+
This is a port of the “Tanks” program written by Paul Ferrell
+pflarr@clanspum.net in 2009-2010. Paul created the entire game based
+off a brief description I provided him of
+Crobots
+and a vague desire to
+“make something fun for high school kids to learn some programming.” We
+ran Paul’s Tanks as part of a 100-attendee computer security contest in
+February of 2010 and by all accounts it was a huge success. It even
+made the nightly news.
+
+
Paul’s version was written in Python and provided a custom language
+called “Bullet”, which looked like this:
Nick Moffitt played with this original version and convinced me (Neale)
+that something like Forth would be a better language. I added some code
+to accept a scaled-down version of PostScript. The IRC channel we
+frequent collectively agreed to give this new language the derisive name
+“Forf”, which should ideally be followed by punching someone after it is
+spoken aloud. I wrote a Python implementation of Forf, which was slow,
+and then Adam Glasgall wrote a C implementation, which was quick.
+
+
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
+240 MHz MIPS CPU, 16MB RAM, and a 4MB flash disk, along with an
+802.11b/g radio, 4-port 10/100 switch, and an additional 10/100 “uplink”
+port; it’s sold as a home wireless router. I had originally intended to
+run it off a lantern battery just for fun, but eventually thought better
+of it: doing so would be wasteful for no good reason.
+
+
Aaron McPhall amcphall@mcphall.org, my summer intern at the time, got
+OpenWRT and Python onto the box and benchmarked it at about 60 seconds
+for a 16-tank game, after he had profiled the code and optimized a lot
+of the math. That wasn’t bad, it meant we could run a reasonably-sized
+game at one turn per minute, which we knew from past experience was
+about the right rate. But it required a USB thumb drive to hold Python,
+and when we used the Python Forf implementation, the run-time shot up to
+several minutes. I began this C port while Adam Glasgall, another fool
+on the previously-mentioned IRC channel, started work on a C version of
+a Forf interpreter.
+
+
This C version with Forf runs about 6 times faster than the Python
+version with Bullet, on the WL-500gU. A 1GHz Intel Atom runs a 16-tank
+game in about 0.2 seconds.
+
+
What’s so great about Forf?
+
+
Nothing’s great about Forf. It’s a crummy language that only does
+integer math. For this application it’s a good choice, for the
+following reasons:
+
+
+
No library dependencies, not even malloc
+
Runs in fixed size memory
+
Not Turing-complete, I think (impossible to make endless loops)
Dirtbags Tanks is a game in which you pit your coding abilities
+against other hackers. You write a program for your tank, set it out
+on the battlefield, and watch how your program fares against tanks
+written by other players. Dirtbags Tanks is frequently a component of
+Dirtbags Capture The Flag.
+
+
Each tank has a turret-mounted laser, two treads, up to ten sensors,
+and a diagnostic LED. Sensors are used to detect when other tanks are
+inside a given arc. In the examples on this page, “triggered” sensors
+turn black. Most tanks will take some action if a sensor is
+triggered, such as changing speed of the treads, turning the turret,
+or firing.
+
+
Tanks are programmed in Forf, a stack-based language similar to
+PostScript.
+
+
Other Versions
+
+
Everybody loves tanks!
+If you’ve made a port or done something fun with it,
+please let me know and I’ll link it here!
Unfortunately, it’s kind of a mess right now.
+I know there are a few forks of this code,
+and I would love it if someone proposed a merge to clearly illustrate how to run tanks.
+
+
When I spin up a new tanks game,
+typically I run something like:
+
+
while sleep 60; do ./round.sh */; done
+
+
+
+
This assumes all your tanks directories are in the same place as round.sh.
+
+
Included programs
+
+
I tried to stick with the Unix philosophy of one program per task. I
+also tried to avoid doing any string processing in C. The result is a
+hodgepodge of C, Bourne shell, and awk, but at least each piece is
+fairly simple to audit.
+
+
round.sh 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
+to run from cron or whatever.
+
+
forftanks tank1 tank2 …
+
+
A program to run a round of tanks and output a JSON description of the
+game. This is what tanks.js uses to render a game graphically.
+The object printed contains:
');
+ $('#playing').button();
+ var slider = $('#seekslider');
+ slider.slider({ max: turns.length-1, slide: function(event, ui) { seekToFrame(ui.value); } });
+
+ var spacing = 100 / turns.length;
+ var deaths = [];
+ for (i in turns[0]) {
+ deaths.push(false);
+ }
+ var percent = 0;
+ for (var f = 0; f < turns.length; f++) {
+ var turn = turns[f];
+ if (percent < (spacing * f)) {
+ percent = spacing * f;
+ }
+ for (var i = 0; i < turn.length; i++) {
+ if (deaths[i]) { continue; }
+ if (!turn[i] || (turn[i][4] & 4)) {
+ deaths[i] = true;
+ // http://stackoverflow.com/questions/8648963/add-tick-marks-to-jquery-slider
+ $('').css('left', percent + '%').css('background-color', game[1][i][0]).appendTo(slider);
+ percent++;
+ break;
+ }
+ }
+ }
+ }
+}
+
diff --git a/docs/forf.html.m4 b/docs/forf.html.m4
new file mode 100644
index 0000000..65a4de5
--- /dev/null
+++ b/docs/forf.html.m4
@@ -0,0 +1,13 @@
+
+
+
+ Forf Manual
+
+
+
+
+syscmd(markdown forf.txt)
+include(nav.html.inc)
+
+
+
diff --git a/docs/history.md b/docs/history.md
index 3873dbf..d94efc3 100644
--- a/docs/history.md
+++ b/docs/history.md
@@ -1,4 +1,9 @@
-# History
+---
+title: History
+scripts:
+ - assets/js/tanks.js
+ - assets/js/figures.js
+---
This is a port of the "Tanks" program written by Paul Ferrell
in 2009-2010. Paul created the entire game based
@@ -29,6 +34,18 @@ called "Bullet", which looked like this:
sense(2): turretccw();
sense(0): fire();
+
+
"Chashtank" cleans up.
+
+
+
+
+
+
+
+
Nick Moffitt played with this original version and convinced me (Neale)
that something like Forth would be a better language. I added some code
to accept a scaled-down version of PostScript. The IRC channel we
diff --git a/docs/intro.html.m4 b/docs/intro.html.m4
new file mode 100644
index 0000000..6d31e1f
--- /dev/null
+++ b/docs/intro.html.m4
@@ -0,0 +1,147 @@
+
+
+
+ Tanks Introduction
+
+
+
+
+
+
+
Tanks Introduction
+
+
+
"ChashTank" dominates this short round.
+
+
+
+
+
+
+
+
+
+ Tanks is a game in which you pit your coding abilities against
+ other hackers. You write a program for your tank, set it out on
+ the battlefield, and watch how it fares against other tanks while
+ running your program.
+
+
+
+ Each tank has a turret-mounted laser, two treads, up to ten
+ sensors, and a diagnostic LED. Sensors are used to detect when
+ other tanks are inside a given arc. In the examples on this page,
+ "triggered" sensors turn black. Most tanks will take some action
+ if a sensor is triggered, such as changing speed of the treads,
+ turning the turret, or firing.
+
+
+
+ Tanks are programmed in Forf, a stack-based language similar to
+ PostScript. Please read the Forf manual
+ to learn more about forf, and the Tanks
+ procedure reference for a description of Tanks extensions.
+
+
+
Quick Start for the Impatient
+
+
+
"Crashmaster" pwns the lame default tank provided in this
+ section.
+
+
+
+
+
+
+
+
+
+ To get started, head over to the Tank
+ Debugger and enter the following example tank. This tank will
+ move around, turn the turret, and fire if there's something in
+ front of it.
+
+
+
+Sensor 0: 50 0 7 ☑
+Sensor 1: 30 0 90 ☐
+
+get-turret 12 + set-turret! ( Rotate turret )
+37 40 set-speed! ( Go in circles )
+0 sensor? { fire! } if ( Fire if turret sensor triggered )
+1 sensor? { -50 50 set-speed! } if ( Turn if collision sensor triggered )
+
+
+
+ Obviously, this tank could be improved. Studying the examples on
+ this page should give you ideas about how to make a better tank.
+ Don't forget the Forf manual and the
+ Tank procedure reference.
+
+
+
Tank Specifications
+
+
+
"Ant Lion" nails "Rabbit With Gun".
+
+
+
+
+
+
+
+
+
+ Your PF-255 autonomous tank is built to the exacting
+ specifications sent to our factory in New Khavistan. All
+ distances are in meters, angles in degrees.
+
+
+
+
Tank size
+
+ The targettable area of the tank—the part which can be hit by a
+ cannon—is a circle about 7½ meters in radius.
+
+
+
Speed
+
+ Each tread can have a speed between -100 and 100. This is in
+ percentage of total speed for that tread, where total speed is
+ roughly 7 meters per turn.
+
+
+
Sensors
+
+ Each sensor has a maximum range of 100 meters. Of course, you
+ don't have to use the full range. Sensors may be attached to
+ the turret (they turn along with the turret), or left fixed to
+ the tank.
+
+
+
Turret
+
+ Turret angle can be set between -359° and 359°, with 0° directly
+ in front of the tank. Be aware that it takes time for the
+ turret to swing around: the turret can swing about 45° per turn.
+
+
+
Cannon range and recharging
+
+ When the cannon is fired, it obliterates everything for 50
+ meters in front of it. It takes around 20 turns for your cannon
+ to recharge after it's been fired, so only shoot when you feel
+ like you're going to hit something.
+
+
+
+ Good luck blowing everybody up!
+include(nav.html.inc)
+
diff --git a/docs/intro.md b/docs/intro.md
deleted file mode 100644
index add5033..0000000
--- a/docs/intro.md
+++ /dev/null
@@ -1,72 +0,0 @@
-# Tanks Introduction
-
-Tanks is a game in which you pit your coding abilities against
-other hackers. You write a program for your tank, set it out on
-the battlefield, and watch how it fares against other tanks while
-running your program.
-
-Each tank has a turret-mounted laser, two treads, up to ten
-sensors, and a diagnostic LED. Sensors are used to detect when
-other tanks are inside a given arc. In the examples on this page,
-"triggered" sensors turn black. Most tanks will take some action
-if a sensor is triggered, such as changing speed of the treads,
-turning the turret, or firing.
-
-Tanks are programmed in Forf, a stack-based language similar to
-PostScript. Please read the [Forf manual](forf.md) to learn more
-about forf, and the [Tanks procedure reference](procs.html) for a
-description of Tanks extensions.
-
-## Quick Start for the Impatient
-
-To get started, head over to the designer for your game,
-and use the following example tank. This tank will
-move around, turn the turret, and fire if there's something in
-front of it.
-
- Sensor 0: 50 0 7 ☑
- Sensor 1: 30 0 90 ☐
-
- get-turret 12 + set-turret! ( Rotate turret )
- 37 40 set-speed! ( Go in circles )
- 0 sensor? { fire! } if ( Fire if turret sensor triggered )
- 1 sensor? { -50 50 set-speed! } if ( Turn if collision sensor triggered )
-
-Obviously, this tank could be improved.
-Watch other tanks in your game to get ideas about how to improve yours.
-Don't forget the [Forf manual](forf.md) and the
-[Tank procedure reference](procs.html).
-
-## Tank Specifications
-
-Your PF-255 autonomous tank is built to the exacting
-specifications sent to our factory in New Khavistan. All
-distances are in meters, angles in degrees.
-
-
-Tank size
-: The targettable area of the tank—the part which can be hit by a cannon—is a circle about 7½ meters in radius.
-
-Speed
-: Each tread can have a speed between -100 and 100. This is in
- percentage of total speed for that tread, where total speed is
- roughly 7 meters per turn.
-
-Sensors
-: Each sensor has a maximum range of 100 meters. Of course, you
- don't have to use the full range. Sensors may be attached to
- the turret (they turn along with the turret), or left fixed to
- the tank.
-
-Turret
-: Turret angle can be set between -359° and 359°, with 0° directly
- in front of the tank. Be aware that it takes time for the
- turret to swing around: the turret can swing about 45° per turn.
-
-Cannon range and recharging
-: When the cannon is fired, it obliterates everything for 50
- meters in front of it. It takes around 20 turns for your cannon
- to recharge after it's been fired, so only shoot when you feel
- like you're going to hit something.
-
-Good luck blowing everybody up!
diff --git a/docs/nav.html.inc b/docs/nav.html.inc
new file mode 100644
index 0000000..b2ea44f
--- /dev/null
+++ b/docs/nav.html.inc
@@ -0,0 +1,10 @@
+
diff --git a/docs/procs.html.m4 b/docs/procs.html.m4
new file mode 100644
index 0000000..2510df0
--- /dev/null
+++ b/docs/procs.html.m4
@@ -0,0 +1,74 @@
+
+
+
+ Tanks Procedure Reference
+
+
+
+
+
Tanks Procedure Reference
+
+
+ Each tank's program is run once per turn. The data and command
+ stacks are reset at the beginning of each turn, but memory is not,
+ so you can carry data over in memory registers if you want. See
+ the Forf manual for more information about
+ the base language.
+
+
+
+ For tank specifications (sensor range, maximum speeds, etc.), see
+ the introduction.
+
+
+
+
Limits
+
+
+ Forf Tanks has a data stack size of 200, and a command stack size
+ of 500. This means your program cannot have more than 200 data
+ items, or 500 instructions, including 2 instructions for each
+ substack.
+
+
+
+ Forf Tanks provides 10 memory registers (0-9) which persist across
+ invocations of your tank's program.
+
+
+
+
Additional Procedures
+
+
+
fire-ready?
+
Returns 1 if the tank can fire, 0 if not.
+
+
fire!
+
Fires the cannon.
+
+
l r set-speed!
+
Sets the speed of the left and right treads (range: -100 to
+ 100).
+
+
get-turret
+
Returns the current angle of the turret.
+
+
a set-turret!
+
Set the turret to a degrees.
+
+
n sensor?
+
Returns 1 if sensor n is triggered, 0 if not.
+
+
s set-led!
+
Turns off the LED if s is 0, on for any other value.
+
+
n random
+
Returns a random number in the range [0, n). That is, between
+ 0 and n-1, inclusive.
+
+
+include(nav.html.inc)
+
+
+
+
diff --git a/docs/procs.md b/docs/procs.md
deleted file mode 100644
index c003cb5..0000000
--- a/docs/procs.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# Tanks Procedure Reference
-
-Each tank's program is run once per turn. The data and command
-stacks are reset at the beginning of each turn, but memory is not,
-so you can carry data over in memory registers if you want. See
-the [Forf manual](forf.md) for more information about
-the base language.
-
-For tank specifications (sensor range, maximum speeds, etc.), see
-the [introduction](intro.html).
-
-## Limits
-
-Forf Tanks has a data stack size of 200, and a command stack size
-of 500. This means your program cannot have more than 200 data
-items, or 500 instructions, including 2 instructions for each
-substack.
-
-Forf Tanks provides 10 memory registers (0-9) which persist across
-invocations of your tank's program.
-
-
-## Additional Procedures
-
-fire-ready?
-: Returns 1 if the tank can fire, 0 if not.
-
-fire!
-: Fires the cannon.
-
-l r set-speed!
-: Sets the speed of the left and right treads (range: -100 to 100).
-
-get-turret
-: Returns the current angle of the turret, in degrees.
-
-a set-turret!
-: Begin moving the turret to a degrees.
-
-n sensor?
-: Returns 1 if sensor n is triggered, 0 if not.
-
-s set-led!
-: Turns off the LED if s is 0, on for any other value.
-
-n random
-: Returns a random number in the range [0, n). That is, between 0 and n-1, inclusive.
diff --git a/docs/running.md b/docs/running.md
new file mode 100644
index 0000000..66dd857
--- /dev/null
+++ b/docs/running.md
@@ -0,0 +1,73 @@
+---
+title: Running Tanks
+---
+
+Unfortunately, it's kind of a mess right now.
+I know there are a few forks of this code,
+and I would love it if someone proposed a merge to clearly illustrate how to run tanks.
+
+When I spin up a new tanks game,
+typically I run something like:
+
+ while sleep 60; do ./run-tanks */; done
+
+This assumes all your tanks directories are in the same place as `run-tanks`.
+
+
+
+Included programs
+-----------------
+
+I tried to stick with the Unix philosophy of one program per task. I
+also tried to avoid doing any string processing in C. The result is a
+hodgepodge of C, Bourne shell, and awk, but at least each piece is
+fairly simple to audit.
+
+
+### 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
+to run from cron or whatever.
+
+
+### forftanks tank1 tank2 ...
+
+A program to run a round of tanks and output a JSON description of the
+game. This is what tanks.js uses to render a game graphically.
+The object printed contains:
+
+ [[game-width, game-height],
+ [[tank1-color,
+ [[sensor1range, sensor1angle, sensor1width, sensor1turret],
+ ...]],
+ ...],
+ [[
+ [tank1x, tank1y, tank1angle, tank1sensangle,
+ tank1flags, tank1sensors],
+ ...],
+ ...]]
+
+If file descriptor 3 is open for writes, it also outputs the results of
+the round to fd3.
+
+
+### rank.awk
+
+Processes the fd3 output of forftanks to award points and output an
+HTML results table.
+
+
+### summary.awk tank1 tank2
+
+Creates summary.html, linking to all rounds and showing overall
+standing.
+
+
+### designer.cgi
+
+Accepts form input and writes a tank.
+
+
+
+