End-user documentation

This commit is contained in:
Neale Pickett 2010-07-20 15:39:10 -06:00
parent 7c7acc5ffe
commit 4e8934377e
19 changed files with 486 additions and 1078 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*~
*#
*.o

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "forf"]
path = forf
url = woozle.org:projects/forf

View File

@ -1,14 +1,23 @@
CFLAGS = -Wall
LDFLAGS = -lm
all: run-tanks
all: html run-tanks designer.cgi
html: forf.html
test: test-tanks
./test-tanks | m4 round.html.m4 - > round.html
run-tanks: run-tanks.o ctanks.o forf.o
run-tanks: LDFLAGS = -lm
test-tanks: test-tanks.o ctanks.o
run-tanks.o: forf.h ctanks.h
forf.o: forf.c forf.h
ctanks.o: ctanks.h
run-tanks: run-tanks.o ctanks.o cforf.o
forf.html: forf.html.sh forf/forf.txt
./forf.html.sh > $@
forf.%: forf/forf.%
cp forf/$@ $@
forf/%:
git submodule update --init
clean:
rm -f test-tanks run-tanks *.o
rm -f run-tanks designer.cgi *.o forf.c forf.h
rm -f next-round round-*.html summary.html forf.html

752
cforf.c
View File

@ -1,752 +0,0 @@
/* forf: a crappy Forth implementation
* Copyright (C) 2010 Adam Glasgall
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Notes
* -------------------------------------------------------
*
* This is intended to be implemented as a library. As such, it doesn't
* use the libc memory allocation functions. This may be a different
* programming style than you're used to.
*
* There are two data types: numbers and stacks. Because we can't
* allocate memory, stacks are implemented with begin and end markers
* and not new stack types.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cforf.h"
#include "dump.h"
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
char *forf_error_str[] = {
"None",
"Runtime",
"Parse",
"Underflow",
"Overflow",
"Type",
"No such procedure",
"Divide by zero",
};
/*
*
* Memory manipulation
*
*/
void
forf_memory_init(struct forf_memory *m,
long *values,
size_t size)
{
m->mem = values;
m->size = size;
}
/*
*
* Stack manipulation
*
*/
void
forf_stack_init(struct forf_stack *s,
struct forf_value *values,
size_t size)
{
s->stack = values;
s->size = size;
s->top = 0;
}
void
forf_stack_reset(struct forf_stack *s)
{
s->top = 0;
}
size_t
forf_stack_len(struct forf_stack *s)
{
return s->top;
}
int
forf_stack_push(struct forf_stack *s, struct forf_value *v)
{
if (s->top == s->size) {
return 0;
}
s->stack[(s->top)++] = *v;
return 1;
}
int
forf_stack_pop(struct forf_stack *s, struct forf_value *v)
{
if (0 == s->top) {
return 0;
}
*v = s->stack[--(s->top)];
return 1;
}
void
forf_stack_copy(struct forf_stack *dst, struct forf_stack *src)
{
int top = min(dst->size, src->top);
dst->top = top;
memcpy(dst->stack, src->stack, sizeof(*dst->stack) * top);
}
void
forf_stack_reverse(struct forf_stack *s)
{
struct forf_value val;
size_t pos;
for (pos = 0; pos < (s->top)/2; pos += 1) {
size_t qos = s->top - pos - 1;
val = s->stack[pos];
s->stack[pos] = s->stack[qos];
s->stack[qos] = val;
}
}
long
forf_pop_num(struct forf_env *env)
{
struct forf_value val;
if (! forf_stack_pop(env->data, &val)) {
env->error = forf_error_underflow;
return 0;
}
if (forf_type_number != val.type) {
forf_stack_push(env->data, &val);
env->error = forf_error_type;
return 0;
}
return val.v.i;
}
void
forf_push_num(struct forf_env *env, long i)
{
struct forf_value val;
val.type = forf_type_number;
val.v.i = i;
if (! forf_stack_push(env->data, &val)) {
env->error = forf_error_overflow;
}
}
/* Pop an entire stack
*
* DANGER WILL ROBINSON
*
* This returned stack points to values on the data stack. You must be
* finished with this stack before you push anything onto the data
* stack, otherwise your returned stack will be corrupted.
*/
struct forf_stack
forf_pop_stack(struct forf_env *env)
{
struct forf_stack s = { 0, 0, NULL };
struct forf_value val;
size_t depth = 1;
if (! forf_stack_pop(env->data, &val)) {
env->error = forf_error_underflow;
return s;
}
if (forf_type_stack_end != val.type) {
forf_stack_push(env->data, &val);
env->error = forf_error_type;
return s;
}
/* Duplicate just the stack onto s. Begin with -1 to account for the
end of list marker. */
s.size = -1;
while (depth) {
s.size += 1;
if (! forf_stack_pop(env->data, &val)) {
/* You should never underflow here, there should at least be a
stack begin marker. */
env->error = forf_error_runtime;
s.size = 0;
return s;
}
switch (val.type) {
case forf_type_stack_end:
depth += 1;
break;
case forf_type_stack_begin:
depth -= 1;
break;
default:
break;
}
}
s.top = s.size;
s.stack = (env->data->stack) + (env->data->top + 1);
return s;
}
/* Push an entire stack onto another stack.
*/
int
forf_push_stack(struct forf_stack *dst, struct forf_stack *src)
{
struct forf_value val;
while (forf_stack_pop(src, &val)) {
if (! forf_stack_push(dst, &val)) {
return 0;
}
}
return 1;
}
/* Push an entire stack onto the command stack.
*
* This is meant to work with the return value from forf_pop_stack.
*/
int
forf_push_to_command_stack(struct forf_env *env, struct forf_stack *src)
{
if (! forf_push_stack(env->command, src)) {
env->error = forf_error_overflow;
return 0;
}
return 1;
}
/* Move one value from src to dst. Note that one value could mean a
* whole substack, in which case dst gets the stack in reverse! dst can
* also be NULL, in which case a value is just discarded.
*
* Because of the reversing thing, it's important to make sure that the
* data stack is either src or dst. This way, the data stack will
* always have "reversed" substacks, and everything else will have them
* in the right order.
*/
int
forf_stack_move_value(struct forf_env *env,
struct forf_stack *dst,
struct forf_stack *src)
{
struct forf_value val;
size_t depth = 0;
do {
/* Pop from src */
if (! forf_stack_pop(env->command, &val)) {
env->error = forf_error_underflow;
return 0;
}
/* Push to dst (or discard if dst is NULL) */
if (dst) {
if (! forf_stack_push(env->data, &val)) {
env->error = forf_error_overflow;
return 0;
}
}
/* Deal with it being a substack marker */
switch (val.type) {
case forf_type_stack_begin:
depth += 1;
break;
case forf_type_stack_end:
depth -= 1;
break;
default:
break;
}
} while (depth > 0);
return 1;
}
/*
*
* Procedures
*
*/
#define unproc(name, op) \
static void \
forf_proc_ ## name(struct forf_env *env) \
{ \
long a = forf_pop_num(env); \
\
forf_push_num(env, op a); \
}
unproc(inv, ~)
unproc(not, !)
#define binproc(name, op) \
static void \
forf_proc_ ## name(struct forf_env *env) \
{ \
long a = forf_pop_num(env); \
long b = forf_pop_num(env); \
\
forf_push_num(env, b op a); \
}
binproc(add, +)
binproc(sub, -)
binproc(mul, *)
binproc(and, &)
binproc(or, |)
binproc(xor, ^)
binproc(lshift, <<)
binproc(rshift, >>)
binproc(gt, >)
binproc(ge, >=)
binproc(lt, <)
binproc(le, <=)
binproc(eq, ==)
binproc(ne, !=)
static void
forf_proc_div(struct forf_env *env)
{
long a = forf_pop_num(env);
long b = forf_pop_num(env);
if (0 == a) {
env->error = forf_error_divzero;
return;
}
forf_push_num(env, b / a);
}
static void
forf_proc_mod(struct forf_env *env)
{
long a = forf_pop_num(env);
long b = forf_pop_num(env);
if (0 == a) {
env->error = forf_error_divzero;
return;
}
forf_push_num(env, b % a);
}
static void
forf_proc_abs(struct forf_env *env)
{
forf_push_num(env, abs(forf_pop_num(env)));
}
static void
forf_proc_dup(struct forf_env *env)
{
long a = forf_pop_num(env);
forf_push_num(env, a);
forf_push_num(env, a);
}
static void
forf_proc_pop(struct forf_env *env)
{
forf_pop_num(env);
}
static void
forf_proc_exch(struct forf_env *env)
{
long a = forf_pop_num(env);
long b = forf_pop_num(env);
forf_push_num(env, a);
forf_push_num(env, b);
}
static void
forf_proc_if(struct forf_env *env)
{
struct forf_stack ifclause = forf_pop_stack(env);
long cond = forf_pop_num(env);
if (cond) {
forf_push_to_command_stack(env, &ifclause);
}
}
static void
forf_proc_ifelse(struct forf_env *env)
{
struct forf_stack elseclause = forf_pop_stack(env);
struct forf_stack ifclause = forf_pop_stack(env);
long cond = forf_pop_num(env);
if (cond) {
forf_push_to_command_stack(env, &ifclause);
} else {
forf_push_to_command_stack(env, &elseclause);
}
}
static void
forf_proc_memset(struct forf_env *env)
{
long pos = forf_pop_num(env);
long a = forf_pop_num(env);
if (pos >= env->memory->size) {
env->error = forf_error_overflow;
return;
}
env->memory->mem[pos] = a;
}
static void
forf_proc_memget(struct forf_env *env)
{
long pos = forf_pop_num(env);
if (pos >= env->memory->size) {
env->error = forf_error_overflow;
return;
}
forf_push_num(env, env->memory->mem[pos]);
}
/*
*
* Lexical environment
*
*/
struct forf_lexical_env forf_base_lexical_env[] = {
{"~", forf_proc_inv},
{"!", forf_proc_not},
{"+", forf_proc_add},
{"-", forf_proc_sub},
{"*", forf_proc_mul},
{"/", forf_proc_div},
{"%", forf_proc_mod},
{"&", forf_proc_and},
{"|", forf_proc_or},
{"^", forf_proc_xor},
{"<<", forf_proc_lshift},
{">>", forf_proc_rshift},
{">", forf_proc_gt},
{">=", forf_proc_ge},
{"<", forf_proc_lt},
{"<=", forf_proc_le},
{"=", forf_proc_eq},
{"<>", forf_proc_ne},
{"abs", forf_proc_abs},
{"dup", forf_proc_dup},
{"pop", forf_proc_pop},
{"exch", forf_proc_exch},
{"if", forf_proc_if},
{"ifelse", forf_proc_ifelse},
{"mset", forf_proc_memset},
{"mget", forf_proc_memget},
{NULL, NULL}
};
/** Extend a lexical environment */
int
forf_extend_lexical_env(struct forf_lexical_env *dest,
struct forf_lexical_env *src,
size_t size)
{
int base, i;
for (base = 0; dest[base].name; base += 1);
for (i = 0; (base+i < size) && (src[i].name); i += 1) {
dest[base+i] = src[i];
}
if (base + i == size) {
/* Not enough room */
return 0;
}
dest[base+i].name = NULL;
dest[base+i].proc = NULL;
return 1;
}
/*
*
* Parsing
*
*/
static int
forf_push_token(struct forf_env *env, char *token, size_t tokenlen)
{
long i;
char s[MAX_TOKEN_LEN + 1];
char *endptr;
struct forf_value val;
/* Zero-length token yields int:0 from strtol */
/* NUL-terminate it */
memcpy(s, token, tokenlen);
s[tokenlen] = '\0';
/* Try to make in an integer */
i = strtol(s, &endptr, 0);
if ('\0' == *endptr) {
/* Was an int */
val.type = forf_type_number;
val.v.i = i;
} else {
/* If not an int, a procedure name */
val.type = forf_type_proc;
for (i = 0; NULL != env->lenv[i].name; i += 1) {
if (0 == strcmp(s, env->lenv[i].name)) {
val.v.p = env->lenv[i].proc;
break;
}
}
if (NULL == env->lenv[i].name) {
env->error = forf_error_noproc;
return 0;
}
}
if (! forf_stack_push(env->command, &val)) {
env->error = forf_error_overflow;
return 0;
}
return 1;
}
/* Parse an input stream onto the command stack */
int
forf_parse_stream(struct forf_env *env,
forf_getch_func *getch,
void *datum)
{
int running = 1;
long pos = 0;
char token[MAX_TOKEN_LEN];
size_t tokenlen = 0;
struct forf_value val;
size_t stack_depth = 0;
int comment = 0;
#define _tokenize() \
do { \
if (tokenlen) { \
if (! forf_push_token(env, token, tokenlen)) return pos; \
tokenlen = 0; \
} \
} while (0)
while (running) {
int c;
c = getch(datum);
pos += 1;
/* Handle comments */
if (comment) {
if (')' == c) {
comment = 0;
}
continue;
}
switch (c) {
case EOF:
running = 0;
break;
case '(':
comment = 1;
break;
case ' ':
case '\f':
case '\n':
case '\r':
case '\t':
case '\v':
_tokenize();
break;
case '{':
_tokenize();
val.type = forf_type_stack_begin;
if (! forf_stack_push(env->command, &val)) {
env->error = forf_error_overflow;
return pos;
}
stack_depth += 1;
break;
case '}':
_tokenize();
val.type = forf_type_stack_end;
if (! forf_stack_push(env->command, &val)) {
env->error = forf_error_overflow;
return pos;
}
stack_depth -= 1;
break;
default:
if (tokenlen < sizeof(token)) {
token[tokenlen++] = c;
}
break;
}
}
_tokenize();
if (0 != stack_depth) {
env->error = forf_error_parse;
return pos;
}
// The first thing we read should be the first thing we do
forf_stack_reverse(env->command);
return 0;
}
struct forf_char_stream {
char *buf;
size_t len;
size_t pos;
};
static int
forf_string_getch(struct forf_char_stream *stream)
{
if (stream->pos >= stream->len) {
return EOF;
}
return stream->buf[stream->pos++];
}
int
forf_parse_buffer(struct forf_env *env,
char *buf,
size_t len)
{
struct forf_char_stream stream;
stream.buf = buf;
stream.len = len;
stream.pos = 0;
return forf_parse_stream(env, (forf_getch_func *)forf_string_getch, &stream);
}
int
forf_parse_string(struct forf_env *env,
char *str)
{
return forf_parse_buffer(env, str, strlen(str));
}
int
forf_parse_file(struct forf_env *env,
FILE *f)
{
return forf_parse_stream(env, (forf_getch_func *)fgetc, f);
}
/*
*
* Forf environment
*
*/
void
forf_env_init(struct forf_env *env,
struct forf_lexical_env *lenv,
struct forf_stack *data,
struct forf_stack *cmd,
struct forf_memory *mem,
void *udata)
{
env->lenv = lenv;
env->data = data;
env->command = cmd;
env->memory = mem;
env->udata = udata;
}
int
forf_eval_once(struct forf_env *env)
{
struct forf_value val;
if (! forf_stack_pop(env->command, &val)) {
env->error = forf_error_underflow;
return 0;
}
switch (val.type) {
case forf_type_number:
case forf_type_stack_begin:
// Push back on command stack, then move it
forf_stack_push(env->command, &val);
if (! forf_stack_move_value(env, env->data, env->command)) return 0;
break;
case forf_type_proc:
(val.v.p)(env);
break;
default:
env->error = forf_error_runtime;
return 0;
}
return 1;
}
int
forf_eval(struct forf_env *env)
{
int ret;
while (env->command->top) {
ret = forf_eval_once(env);
if ((! ret) || (env->error)) {
return 0;
}
}
return 1;
}

150
cforf.h
View File

@ -1,150 +0,0 @@
#ifndef __CFORF_H__
#define __CFORF_H__
#include <stdio.h>
#include <inttypes.h>
#define MAX_TOKEN_LEN 20
#define MAX_CMDSTACK 200
struct forf_env;
enum forf_value_type {
forf_type_number,
forf_type_proc,
forf_type_stack_begin,
forf_type_stack_end,
};
enum forf_error_type {
forf_error_none,
forf_error_runtime,
forf_error_parse,
forf_error_underflow,
forf_error_overflow,
forf_error_type,
forf_error_noproc,
forf_error_divzero,
};
extern char *forf_error_str[];
typedef void (forf_proc)(struct forf_env *);
struct forf_value {
enum forf_value_type type;
union {
forf_proc *p;
long i;
} v;
};
struct forf_stack {
size_t size;
size_t top;
struct forf_value *stack;
};
struct forf_memory {
size_t size;
long *mem;
};
struct forf_lexical_env {
char *name;
forf_proc *proc;
};
struct forf_env {
enum forf_error_type error;
struct forf_lexical_env *lenv;
struct forf_stack *data;
struct forf_stack *command;
struct forf_memory *memory;
void *udata;
};
/*
*
* Main entry points
*
*/
/** Initialize a memory structure, given an array of longs */
void forf_memory_init(struct forf_memory *m,
long *values,
size_t size);
/** Initialize a stack, given an array of values */
void forf_stack_init(struct forf_stack *s,
struct forf_value *values,
size_t size);
void forf_stack_reset(struct forf_stack *s);
void forf_stack_copy(struct forf_stack *dst, struct forf_stack *src);
int forf_stack_push(struct forf_stack *s, struct forf_value *v);
int forf_stack_pop(struct forf_stack *s, struct forf_value *v);
/** Pop a number off the data stack */
long forf_pop_num(struct forf_env *env);
/** Push a number onto the data stack */
void forf_push_num(struct forf_env *env, long i);
/** Pop a whole stack */
struct forf_stack forf_pop_stack(struct forf_env *env);
/** The base lexical environment */
extern struct forf_lexical_env forf_base_lexical_env[];
/** Extend a lexical environment */
int
forf_extend_lexical_env(struct forf_lexical_env *dest,
struct forf_lexical_env *src,
size_t size);
/** Initialize a forf runtime environment.
*
* data, cmd, and mem should have already been initialized
*/
void forf_env_init(struct forf_env *env,
struct forf_lexical_env *lenv,
struct forf_stack *data,
struct forf_stack *cmd,
struct forf_memory *mem,
void *udata);
/** The type of a getch function (used for parsing) */
typedef int (forf_getch_func)(void *);
/** 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);
/** Parse a buffer */
int forf_parse_buffer(struct forf_env *env,
char *buf,
size_t len);
/** Parse a string */
int forf_parse_string(struct forf_env *env,
char *str);
/** Parse a FILE * */
int forf_parse_file(struct forf_env *env,
FILE *f);
/** Evaluate the topmost value on the command stack */
int forf_eval_once(struct forf_env *env);
/** Evaluate the entire command stack */
int forf_eval(struct forf_env *env);
#endif

View File

@ -2,7 +2,22 @@
<html>
<head>
<title>Tank Designer</title>
<link rel="stylesheet" href="tanks.css" type="text/css">
<link rel="stylesheet" href="dirtbags.css" type="text/css">
<style type="text/css">
#preview {
float: right;
}
#sensors input {
width: 5em;
}
#program textarea {
width: 100%;
min-height: 20em;
}
td {
text-align: left;
}
</style>
<script type="application/javascript" src="tanks.js"></script>
<script type="application/javascript" src="designer.js"></script>
<script type="application/javascript">
@ -10,6 +25,7 @@
</script>
</head>
<body>
<h1>Tank Designer</h1>
<div id="preview"><canvas id="design"></canvas><p id="debug"></p></div>
<form>
<fieldset id="metadata">

201
dirtbags.css Normal file
View File

@ -0,0 +1,201 @@
/**** document ****/
html {
background: #222 url(grunge.png) repeat-x;
}
body {
font-family: sans-serif;
color: #fff;
margin: 50px 0 0 110px;
padding: 10px;
max-width: 700px;
}
/**** heading ****/
h1:first-child {
text-transform: lowercase;
font-size: 1.6em;
/* background-color: #222; */
/* opacity: 0.9; */
padding: 3px;
color: #2a2;
margin: 0 0 1em 70px;
}
h1:first-child:before {
color: #fff;
letter-spacing: -0.1em;
content: "Dirtbags: ";
}
/*** left side bar ***/
#navigation {
position: absolute;
background: #222;
opacity: 0.9;
top: 80px;
left: 0px;
padding: 0;
}
#navigation h3 {
font-size: 100%;
border-bottom: 2px solid #444;
}
#navigation ul {
list-style: none;
padding: 0;
margin: 0;
}
#navigation li a {
display: block;
height: 25px;
width: 90px;
padding: 5px;
margin: 5px;
background: inherit;
border-right: 4px solid #444;
color: #999;
text-transform: lowercase;
font-size: 0.9em;
}
#navigation li a:hover {
color: #f4f4f4;
background: #333;
border-right: 4px solid #2a2;
}
#navigation li .active {
color: #999;
background: #333;
border-right: 4px solid #444;
}
/**** body ****/
a img {
border: 0px;
}
a {
text-decoration: none;
color: #2a2;
font-weight: bold;
}
a:hover {
color: #fff;
background: #2a2;
font-weight: bold;
}
h1, h2, h3 {
color: #999;
letter-spacing: -0.05em;
clear: both;
}
.readme {
color: #fff;
background-color: #555;
margin: 1em;
}
pre {
color: #fff;
background-color: #222;
border: solid #ccc 2px;
padding: 0.25em;
}
th {
vertical-align: top;
text-align: center;
}
td {
vertical-align: top;
text-align: right;
}
p {
line-height: 1.4em;
margin-bottom: 20px;
color: #f4f4f4;
}
hr {
border: 1px solid #444;
}
dt {
white-space: pre;
background-color: #333;
padding: 5px;
border: 2px solid green;
border-bottom: none;
font-weight: bold;
}
dd {
border: 2px solid green;
margin: 0px;
padding: 5px;
background-color: #282828;
}
/**** special cases ****/
.wide {
max-width: inherit;
}
.figure {
margin: 0.5em 1em;
float: right;
font-size: small;
text-align: center;
caption-side: bottom;
}
.left {
float: left;
}
.scoreboard {
background: #222;
}
.scoreboard td {
height: 400px;
}
#battlefield {
border: 2px solid green;
}
.solved {
text-decoration: line-through;
}
table.pollster {
margin-left: 5em;
}
table.pollster td {
padding: 2px 1em 2px 5px;
}
table.pollster thead {
font-weight: bold;
}

5
figures.js Normal file
View File

@ -0,0 +1,5 @@
default_ = [[300, 150, 50],[["#a08080",[[50, 0.00, 0.14, 1],[30, 0.00, 0.87, 0],[50, 0.00, 0.17, 0],[100, 5.50, 1.75, 1],[100, 0.79, 1.75, 1],[60, 3.14, 3.14, 0],]], ["#808080",[[50, 0.00, 0.12, 1],[30, 0.00, 1.57, 0],]],],[[[75,75,3.86,0.96,2,0], [225,75,4.26,0.49,0,0],], [[73,73,3.86,0.65,2,0], [223,72,4.26,0.68,0,0],], [[69,70,3.86,0.33,2,0], [222,70,4.24,0.87,0,0],], [[65,66,3.86,0.02,2,0], [221,67,4.23,1.06,0,0],], [[61,62,3.86,-0.00,2,0], [220,65,4.22,1.27,0,0],], [[56,59,3.86,0.00,2,0], [218,63,4.20,1.48,0,0],], [[52,55,3.86,-0.00,2,0], [217,60,4.19,1.68,0,0],], [[48,51,3.86,-0.00,2,0], [215,58,4.18,1.88,0,0],], [[44,48,3.86,0.00,2,0], [214,55,4.16,2.09,0,0],], [[39,44,3.86,-0.00,2,0], [213,53,4.15,2.30,0,0],], [[35,41,3.77,0.00,2,0], [211,51,4.13,2.51,0,0],], [[31,38,3.68,-0.00,2,0], [209,48,4.12,2.72,0,0],], [[26,36,3.60,-0.00,2,0], [208,46,4.11,2.93,0,0],], [[21,34,3.51,0.00,2,0], [206,44,4.09,3.14,0,0],], [[16,33,3.43,-0.00,2,0], [205,42,4.08,3.35,0,0],], [[11,32,3.34,-0.00,2,0], [203,39,4.06,3.56,0,0],], [[6,31,3.25,0.00,2,8], [201,37,4.05,3.77,0,0],], [[2,31,3.11,-0.31,2,16], [200,35,4.04,3.98,0,0],], [[299,31,3.25,0.00,2,24], [198,33,4.02,4.19,0,0],], [[293,29,3.39,-0.00,2,8], [196,31,4.01,4.40,0,0],], [[289,28,3.39,-0.31,2,24], [194,29,4.00,4.59,0,0],], [[283,27,3.39,-0.31,2,24], [192,27,3.98,4.80,0,0],], [[276,25,3.39,-0.31,2,24], [190,25,3.97,4.99,0,0],], [[269,23,3.39,-0.30,2,24], [189,23,3.95,5.18,0,0],], [[262,21,3.39,-0.28,2,24], [187,21,3.94,5.39,0,0],], [[255,20,3.39,-0.26,2,24], [185,19,3.93,5.59,0,0],], [[249,18,3.39,-0.24,2,24], [183,17,3.91,5.78,0,0],], [[242,16,3.39,-0.23,2,24], [181,15,3.90,5.99,0,0],], [[235,14,3.39,-0.21,3,25], 0,],]];
antlion = [[300, 150, 50],[["#808080",[[50, 0.00, 0.00, 1],[70, 0.00, 0.87, 0],]], ["#ff8844",[[50, 0.00, 0.09, 1],[100, 4.68, 3.09, 1],[100, 1.61, 3.11, 1],[60, 0.00, 2.09, 0],[60, 2.09, 2.09, 0],[60, 4.19, 2.09, 0],[100, 0.00, 0.09, 1],]],],[[[75,75,5.78,2.71,0,0], [225,75,3.28,1.95,0,0],], [[77,73,5.78,3.02,0,0], [225,75,3.28,2.06,0,0],], [[81,71,5.78,3.14,0,0], [225,75,3.28,2.16,0,0],], [[87,68,5.78,3.14,0,0], [225,75,3.28,2.25,0,0],], [[93,64,5.78,3.14,0,0], [225,75,3.28,2.34,0,0],], [[99,61,5.78,3.14,0,0], [225,75,3.28,2.44,0,0],], [[105,57,5.78,3.14,0,0], [225,75,3.28,2.53,0,0],], [[112,54,5.78,3.14,0,0], [225,75,3.28,2.62,0,0],], [[118,51,5.78,3.14,0,0], [225,75,3.28,2.71,0,0],], [[124,47,5.78,3.14,0,0], [225,75,3.28,2.79,0,2],], [[130,44,5.78,3.14,0,0], [225,75,3.28,2.48,0,2],], [[136,40,5.78,3.14,0,0], [225,75,3.28,2.16,0,2],], [[142,37,5.78,3.14,0,0], [225,75,3.28,1.85,0,2],], [[148,34,5.78,3.14,0,0], [225,75,3.28,1.54,0,2],], [[154,30,5.78,3.14,0,0], [225,75,3.28,1.22,0,2],], [[160,28,5.90,3.14,0,0], [225,75,3.28,0.91,0,2],], [[167,25,5.90,3.14,0,0], [225,75,3.28,0.59,0,70],], [[173,23,5.90,3.14,0,0], [225,75,3.28,0.28,0,4],], [[180,20,5.90,3.14,0,0], [225,75,3.28,0.59,0,68],], [[186,17,5.90,3.14,0,0], [225,75,3.28,0.28,0,4],], [[193,15,5.90,3.14,0,0], [225,75,3.28,0.59,0,4],], [[199,12,5.90,3.14,0,0], [225,75,3.28,0.91,0,92],], [[206,10,5.90,3.14,0,0], [222,74,3.24,0.59,0,20],], [[212,7,5.90,3.14,0,0], [218,74,3.15,0.91,0,20],], [[218,4,5.78,3.14,0,0], [212,75,2.96,1.22,0,4],], [[224,1,5.78,3.14,0,0], [208,77,2.77,1.54,0,2],], [[230,147,5.78,3.14,0,0], [207,78,2.65,1.22,0,2],], [[236,144,5.78,3.14,0,0], [207,78,2.65,0.91,0,2],], [[242,140,5.78,3.14,0,0], [207,78,2.65,0.59,0,2],], [[248,137,5.78,3.14,0,0], [207,78,2.65,0.28,0,2],], [[254,134,5.78,3.14,0,0], [207,78,2.65,-0.03,0,2],], [[260,130,5.78,3.14,0,0], [207,78,2.65,-0.35,0,2],], [[267,127,5.78,3.14,0,0], [207,78,2.65,-0.66,0,2],], [[273,123,5.78,3.14,0,0], [207,78,2.65,-0.98,0,2],], [[279,120,5.78,3.14,0,0], [207,78,2.65,-1.29,0,2],], [[285,117,5.78,3.14,0,0], [207,78,2.65,-1.61,0,2],], [[291,113,5.78,3.14,0,0], [207,78,2.65,-1.92,0,2],], [[297,110,5.78,3.14,0,0], [207,78,2.65,-2.23,0,66],], [[3,106,5.78,3.14,0,0], [207,78,2.65,-1.92,0,2],], [[9,103,5.78,3.14,0,0], [207,78,2.65,-2.23,0,2],], [[16,100,5.78,3.14,0,0], [207,78,2.65,-2.55,0,0],], [[22,96,5.78,3.14,0,0], [207,78,2.65,-2.44,0,0],], [[28,93,5.78,3.14,0,0], [207,78,2.65,-2.32,0,0],], [[34,90,5.78,3.14,0,0], [207,78,2.65,-2.20,0,0],], [[40,86,5.78,3.14,0,0], [207,78,2.65,-2.08,0,0],], [[46,84,5.90,3.14,0,0], [207,78,2.65,-1.95,0,0],], [[52,81,5.90,3.14,0,0], [207,78,2.65,-1.85,0,0],], [[59,79,5.90,3.14,0,0], [207,78,2.65,-1.75,0,0],], [[65,76,5.90,3.14,0,0], [207,78,2.65,-1.64,0,0],], [[72,73,5.90,3.14,0,0], [207,78,2.65,-1.54,0,0],], [[78,71,5.90,3.14,0,0], [207,78,2.65,-1.43,0,0],], [[85,68,5.90,3.14,0,0], [207,78,2.65,-1.33,0,0],], [[91,66,5.90,3.14,0,0], [207,78,2.65,-1.20,0,0],], [[98,63,5.90,3.14,0,0], [207,78,2.65,-1.08,0,0],], [[104,60,5.90,3.14,0,0], [207,78,2.65,-0.96,0,4],], [[111,58,5.90,3.14,0,0], [207,78,2.65,-0.65,0,4],], [[117,56,6.03,3.14,0,0], [207,78,2.65,-0.33,0,4],], [[124,54,6.03,3.14,0,0], [207,78,2.65,-0.02,0,4],], [[130,53,6.03,3.14,0,0], [207,78,2.65,0.30,0,4],], [[137,51,6.03,3.14,0,0], [207,78,2.65,0.61,0,4],], [[144,49,6.03,3.14,0,0], [207,78,2.65,0.93,0,70],], [[151,47,6.03,3.14,0,0], [207,78,2.65,0.61,0,28],], [[157,45,6.03,3.14,0,0], [205,79,2.65,0.93,0,28],], [0, [201,81,2.56,1.24,1,85],],]];
shortround = [[300, 300, 50],[["#80f0c0",[[50, 0.00, 0.17, 1],[35, 0.00, 1.57, 0],[100, 0.52, 1.03, 0],[100, 5.76, 1.03, 0],[70, 3.14, 3.14, 0],[100, 1.57, 1.03, 0],[100, 4.71, 1.03, 0],[100, 0.00, 0.09, 1],[55, 0.87, 1.55, 0],[55, 5.41, 1.55, 0],]], ["#ff8844",[[50, 0.00, 0.09, 1],[100, 4.68, 3.09, 1],[100, 1.61, 3.11, 1],[60, 0.00, 2.09, 0],[60, 2.09, 2.09, 0],[60, 4.19, 2.09, 0],[100, 0.00, 0.09, 1],]], ["#ff0033",[[50, 0.00, 0.17, 1],[100, 1.57, 2.62, 1],[100, 4.71, 2.62, 1],]], ["#a08080",[[50, 0.00, 0.14, 1],[30, 0.00, 0.87, 0],[50, 0.00, 0.17, 0],[100, 5.50, 1.75, 1],[100, 0.79, 1.75, 1],[60, 3.14, 3.14, 0],]],],[[[75,75,0.87,0.02,2,0], [225,75,0.24,1.41,0,0], [75,225,5.64,2.15,0,0], [225,225,0.35,-0.00,2,0],], [[76,76,0.87,-0.00,2,0], [225,75,0.24,1.50,0,0], [75,225,5.64,1.83,0,0], [227,225,0.35,0.00,2,0],], [[79,80,0.87,0.00,2,0], [225,75,0.24,1.61,0,0], [75,225,5.64,1.52,0,0], [231,227,0.35,-0.00,2,0],], [[83,85,0.87,-0.00,2,0], [225,75,0.24,1.71,0,0], [75,225,5.64,1.20,0,0], [237,229,0.35,-0.00,2,0],], [[87,90,0.87,-0.00,2,0], [225,75,0.24,1.82,0,0], [75,225,5.64,0.89,0,0], [242,231,0.35,0.00,2,0],], [[91,95,0.87,0.00,2,0], [225,75,0.24,1.92,0,0], [75,225,5.64,0.58,0,0], [247,233,0.35,-0.00,2,0],], [[95,100,0.96,-0.00,2,0], [225,75,0.24,2.02,0,0], [75,225,5.64,0.26,0,0], [252,235,0.35,0.00,2,0],], [[98,105,1.05,-0.00,2,0], [225,75,0.24,2.11,0,0], [75,225,5.64,0.00,0,0], [258,237,0.35,-0.00,2,0],], [[101,111,1.13,0.00,2,0], [225,75,0.24,2.20,0,0], [75,225,5.64,-0.00,0,0], [263,239,0.35,-0.00,2,0],], [[103,116,1.13,-0.00,2,0], [225,75,0.24,2.29,0,0], [75,225,5.64,0.00,0,4], [268,240,0.35,0.00,2,8],], [[105,122,1.22,0.00,2,4], [225,75,0.24,2.37,0,0], [75,225,5.64,-0.31,0,4], [272,242,0.28,-0.31,2,24],], [[106,127,1.38,-0.00,2,4], [225,75,0.24,2.46,0,0], [75,225,5.64,-0.63,0,4], [278,243,0.22,-0.30,2,24],], [[106,131,1.63,-0.00,2,4], [225,75,0.24,2.55,0,0], [75,225,5.64,-0.94,0,6], [285,244,0.22,-0.28,2,24],], [[105,134,1.93,0.00,2,140], [225,75,0.24,2.65,0,0], [75,225,5.64,-1.26,0,6], [292,246,0.22,-0.26,2,8],], [[102,138,2.22,-0.00,2,8], [225,75,0.24,2.74,0,0], [75,225,5.64,-1.57,0,6], [296,247,0.22,-0.58,2,24],], [[99,141,2.32,-0.00,2,8], [225,75,0.24,2.83,0,0], [75,225,5.64,-1.88,0,6], [3,248,0.22,-0.58,2,24],], [[97,144,2.15,0.00,2,8], [225,75,0.24,2.91,0,0], [75,225,5.64,-2.20,0,6], [10,250,0.22,-0.56,2,24],], [[96,148,1.88,-0.00,2,140], [225,75,0.24,3.00,0,0], [75,225,5.64,-2.51,0,6], [17,251,0.22,-0.54,2,24],], [[95,153,1.64,-0.00,2,4], [225,75,0.24,3.09,0,0], [75,225,5.64,-2.83,0,6], [24,253,0.22,-0.54,2,24],], [[95,158,1.64,0.00,2,4], [225,75,0.24,3.18,0,0], [75,225,5.64,-3.14,1,3], 0,], [[94,162,1.82,-0.00,2,140], [225,75,0.24,3.26,0,0], [75,225,5.64,-2.83,0,2], 0,], [[92,168,1.97,0.00,2,652], [225,75,0.24,3.37,0,0], [75,225,5.64,-2.51,0,2], 0,], [[89,175,1.97,-0.00,3,653], [225,75,0.24,3.46,0,0], 0, 0,], [[86,181,1.97,-0.00,0,0], [225,75,0.24,3.54,0,0], 0, 0,], [[84,187,1.97,0.00,0,0], [225,75,0.24,3.63,0,0], 0, 0,], [[81,193,1.97,-0.00,0,0], [225,75,0.24,3.72,0,0], 0, 0,], [[78,198,2.05,-0.00,0,0], [225,75,0.24,3.80,0,0], 0, 0,], [[76,204,2.05,0.00,0,0], [225,75,0.24,3.89,0,0], 0, 0,], [[73,209,2.05,-0.00,0,0], [225,75,0.24,3.98,0,0], 0, 0,], [[70,215,2.05,0.00,0,0], [225,75,0.24,4.08,0,0], 0, 0,], [[67,220,2.05,-0.00,0,0], [225,75,0.24,4.19,0,0], 0, 0,], [[64,226,2.05,-0.00,0,0], [225,75,0.24,4.29,0,0], 0, 0,], [[61,231,2.14,0.00,0,0], [225,75,0.24,4.40,0,0], 0, 0,], [[57,237,2.14,-0.00,0,0], [225,75,0.24,4.49,0,0], 0, 0,], [[54,242,2.14,-0.00,0,0], [225,75,0.24,4.57,0,0], 0, 0,], [[50,247,2.14,0.00,0,0], [225,75,0.24,4.66,0,0], 0, 0,], [[47,252,2.14,-0.00,0,0], [225,75,0.24,4.75,0,0], 0, 0,], [[44,258,2.14,-0.00,0,0], [225,75,0.24,4.83,0,0], 0, 0,], [[40,263,2.14,0.00,0,0], [225,75,0.24,4.92,0,0], 0, 0,], [[37,268,2.14,-0.00,0,0], [225,75,0.24,5.01,0,0], 0, 0,], [[33,274,2.14,0.00,0,0], [225,75,0.24,5.10,0,0], 0, 0,], [[30,279,2.23,-0.00,0,0], [225,75,0.24,5.20,0,0], 0, 0,], [[26,284,2.23,-0.00,2,0], [225,75,0.24,5.31,0,0], 0, 0,], [[22,289,2.23,0.00,2,0], [225,75,0.24,5.39,0,0], 0, 0,], [[18,294,2.23,-0.00,2,0], [225,75,0.24,5.48,0,0], 0, 0,], [[14,299,2.23,-0.00,2,0], [225,75,0.24,5.57,0,0], 0, 0,], [[10,3,2.31,0.00,2,0], [225,75,0.24,5.65,0,0], 0, 0,], [[6,8,2.31,-0.00,2,4], [225,75,0.24,5.74,0,2], 0, 0,], [[2,11,2.42,-0.00,2,140], [225,75,0.24,5.43,0,66], 0, 0,], [[297,15,2.46,0.00,2,140], [225,75,0.24,5.74,0,2], 0, 0,], [[291,20,2.46,-0.00,2,140], [225,75,0.24,5.43,0,66], 0, 0,], [[286,24,2.46,0.00,2,140], [225,75,0.24,5.74,0,2], 0, 0,], [[280,29,2.46,-0.00,2,140], [225,75,0.24,5.43,0,66], 0, 0,], [[275,33,2.46,-0.00,2,140], [225,75,0.24,5.74,0,10], 0, 0,], [[270,37,2.46,0.00,2,908], [222,74,0.24,5.43,0,78], 0, 0,], [[264,42,2.46,-0.00,3,397], 0, 0, 0,],]];

1
forf Submodule

@ -0,0 +1 @@
Subproject commit fb482e222f4357553d717a0cb9daac1721973d23

16
forf.html.sh Executable file
View File

@ -0,0 +1,16 @@
#! /bin/sh
cat <<EOF
<html>
<head>
<title>Forf Manual</title>
<meta charset="utf-8">
<link rel="stylesheet" href="dirtbags.css" type="text/css">
</head>
<body>
EOF
markdown forf/forf.txt
cat <<EOF
</body>
</html>
EOF

BIN
grunge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

146
intro.html Normal file
View File

@ -0,0 +1,146 @@
<!DOCTYPE html>
<html>
<head>
<title>Tanks Introduction</title>
<meta charset="utf-8">
<link rel="stylesheet" href="dirtbags.css" type="text/css">
<script type="application/javascript" src="tanks.js"></script>
<script type="application/javascript" src="figures.js"></script>
</head>
<body>
<h1>Tanks Introduction</h1>
<table class="figure">
<caption>"ChashTank" dominates this short round.</caption>
<tr>
<td>
<canvas id="shortround"></canvas>
<script type="text/javascript">
start("shortround", shortround);
</script>
</td>
</tr>
</table>
<p>
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.
</p>
<p>
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.
</p>
<p>
Tanks are programmed in Forf, a stack-based language similar to
PostScript. Please read the <a href="forf.html">Forf manual</a>
to learn more about forf, and the <a href="procs.html">Tanks
procedure reference</a> for a description of Tanks extensions.
</p>
<h2>Quick Start for the Impatient</h2>
<table class="figure left">
<caption>"Crashmaster" pwns the lame default tank provided in this
section.</caption>
<tr>
<td>
<canvas id="default"></canvas>
<script type="text/javascript">
start("default", default_);
</script>
</td>
</tr>
</table>
<p>
To get started, head over to the <a href="design.html">Tank
Designer</a> and enter the following example tank. This tank will
move around, turn the turret, and fire if there's something in
front of it.
</p>
<pre style="clear: both;">
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 )
</pre>
<p>
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 <a href="forf.html">Forf manual</a> and the
<a href="procs.html">Tank procedure reference</a>.
</p>
<h2>Tank Specifications</h2>
<table class="figure">
<caption>"Ant Lion" nails "Rabbit With Gun".</caption>
<tr>
<td>
<canvas id="antlion"></canvas>
<script type="text/javascript">
start("antlion", antlion);
</script>
</td>
</tr>
</table>
<p>
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.
</p>
<dl style="clear: both;">
<dt>Tank size</dt>
<dd>
The targettable area of the tank—the part which can be hit by a
cannon—is a circle about 7½ meters in radius.
</dd>
<dt>Speed</dt>
<dd>
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.
</dd>
<dt>Sensors</dt>
<dd>
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.
</dd>
<dt>Turret</dt>
<dd>
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 60° per turn.
</dd>
<dt>Cannon range and recharging</dt>
<dd>
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.
</dd>
</dl>
Good luck blowing everybody up!
</html>

72
procs.html Normal file
View File

@ -0,0 +1,72 @@
<!DOCTYPE html>
<html>
<head>
<title>Tanks Procedure Reference</title>
<meta charset="utf-8">
<link rel="stylesheet" href="dirtbags.css" type="text/css">
</head>
<body>
<h1>Tanks Procedure Reference</h1>
<p>
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 <a href="forf.html">Forf manual</a> for more information about
the base language.
</p>
<p>
For tank specifications (sensor range, maximum speeds, etc.), see
the <a href="intro.html">introduction</a>.
</p>
<h2>Limits</h2>
<p>
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.
</p>
<p>
Forf Tanks provides 10 memory registers (0-9) which persist across
invocations of your tank's program.
</p>
<h2>Additional Procedures</h2>
<dl>
<dt>fire-ready?</dt>
<dd>Returns 1 if the tank can fire, 0 if not.</dd>
<dt>fire!</dt>
<dd>Fires the cannon.</dd>
<dt>l r set-speed!</dt>
<dd>Sets the speed of the left and right treads (range: -100 to
100).</dd>
<dt>get-turret</dt>
<dd>Returns the current angle of the turret.</dd>
<dt>a set-turret!</dt>
<dd>Set the turret to a degrees.</dd>
<dt>n sensor?</dt>
<dd>Returns 1 if sensor n is triggered, 0 if not.</dd>
<dt>s set-led!</dt>
<dd>Turns off the LED if s is 0, on for any other value.</dd>
<dt>n random</dt>
<dd>Returns a random number in the range [0, n). That is, between
0 and n-1, inclusive.</dd>
</dl>
</body>
</html>

View File

@ -21,7 +21,7 @@ cat <<EOF >$fn
<link rel="stylesheet" href="tanks.css" type="text/css">
<script type="application/javascript">
function go() {
start(
start("battlefield",
// Start JSON data
EOF
./run-tanks players/* >>$fn 3>$rfn

View File

@ -5,7 +5,7 @@
#include <stdlib.h>
#include <math.h>
#include "ctanks.h"
#include "cforf.h"
#include "forf.h"
#include "dump.h"
#define MAX_TANKS 50

View File

@ -19,8 +19,9 @@ BEGIN {
print " <h2>Resources</h2>";
print " <ul>";
print " <li><a href=\"intro.html\">Introduction</a></li>";
print " <li><a href=\"forf.html\">Forf manual</a></li>";
print " <li><a href=\"tanksprocs.html\">Tanks procedures</a></li>";
print " <li><a href=\"procs.html\">Tanks procedures</a></li>";
print " <li><a href=\"designer.html\">Tanks designer</a></li>";
print " </ul>";

View File

@ -1,26 +0,0 @@
body {
background-color: #444444;
color: #c0c0c0;
}
table {
border-collapse: collapse;
}
td {
border: solid 1px #c0c0c0;
}
.swatch {
color: #000000;
}
#preview {
float: right;
}
#sensors input {
width: 5em;
}
#program textarea {
width: 100%;
min-height: 20em;
}
a {
color: #00c080;
}

View File

@ -147,8 +147,8 @@ function Tank(ctx, width, height, color, sensors) {
}
}
function start(game) {
var canvas = document.getElementById('battlefield');
function start(id, game) {
var canvas = document.getElementById(id);
var ctx = canvas.getContext('2d');
var loop_id;

View File

@ -1,137 +0,0 @@
#include <stdio.h>
#include <math.h>
#include "ctanks.h"
#define NTANKS 2
void
test_run(struct tank *tank, void *unused)
{
tank_set_speed(tank, -60, -61);
tank_set_turret(tank, tank->turret.desired + PI/15);
if (tank->sensors[0].triggered) {
tank_fire(tank);
}
}
void
sitting_duck(struct tank *tank, void *unused)
{
tank_set_turret(tank, tank->turret.desired + PI/15);
}
int
main(int argc, char *argv[])
{
struct tanks_game game;
struct tank mytanks[NTANKS];
int i;
game.size[0] = 600;
game.size[1] = 200;
printf("[\n");
printf("[%d, %d, %d],\n",
(int)game.size[0], (int)game.size[1], TANK_CANNON_RANGE);
printf("[\n");
for (i = 0; i < NTANKS; i += 1) {
if (i == 1) {
printf(" [\"#888888\",[");
tank_init(&mytanks[i], sitting_duck, NULL);
} else {
int j;
printf(" [\"#ff4444\",[");
tank_init(&mytanks[i], test_run, NULL);
mytanks[i].sensors[0].angle = 0;
mytanks[i].sensors[0].width = PI/10;
mytanks[i].sensors[0].range = 50;
mytanks[i].sensors[0].turret = 1;
mytanks[i].sensors[1].angle = 0*PI/2;
mytanks[i].sensors[1].width = PI/3;
mytanks[i].sensors[1].range = 100;
mytanks[i].sensors[1].turret = 1;
mytanks[i].sensors[2].angle = 1*PI/2;
mytanks[i].sensors[2].width = PI/3;
mytanks[i].sensors[2].range = 100;
mytanks[i].sensors[2].turret = 1;
mytanks[i].sensors[3].angle = 2*PI/2;
mytanks[i].sensors[3].width = PI/3;
mytanks[i].sensors[3].range = 100;
mytanks[i].sensors[3].turret = 1;
mytanks[i].sensors[4].angle = 3*PI/2;
mytanks[i].sensors[4].width = PI/3;
mytanks[i].sensors[4].range = 100;
mytanks[i].sensors[4].turret = 1;
mytanks[i].sensors[5].angle = 0;
mytanks[i].sensors[5].width = PI*1.99;
mytanks[i].sensors[5].range = 80;
mytanks[i].sensors[5].turret = 0;
for (j = 0; j < TANK_MAX_SENSORS; j += 1) {
struct sensor *s = &(mytanks[i].sensors[j]);
if (s->range) {
printf("[%d, %.2f, %.2f, %d],",
(int)(s->range),
s->angle,
s->width,
s->turret);
}
}
}
mytanks[i].position[0] = (game.size[0] / NTANKS) * i + 50;
mytanks[i].position[1] = 50;
/* XXX: print sensors */
printf("]],\n");
}
printf("],\n");
printf("// Rounds\n");
printf("[\n");
for (i = 0; i < 100; i += 1) {
int j;
tanks_run_turn(&game, mytanks, NTANKS);
printf("[\n");
for (j = 0; j < NTANKS; j += 1) {
struct tank *t = &(mytanks[j]);
if (t->killer) {
printf(" 0,\n");
} else {
int k;
int flags = 0;
int sensors = 0;
for (k = 0; k < TANK_MAX_SENSORS; k += 1) {
if (t->sensors[k].triggered) {
sensors |= (1 << k);
}
}
if (t->turret.firing) {
flags |= 1;
}
if (t->led) {
flags |= 2;
}
printf(" [%d,%d,%.2f,%.2f,%d,%d],\n",
(int)(t->position[0]),
(int)(t->position[1]),
t->angle,
t->turret.current,
flags,
sensors);
}
}
printf("],\n");
}
printf("]]\n");
return 0;
}