mirror of https://github.com/dirtbags/tanks.git
End-user documentation
This commit is contained in:
parent
7c7acc5ffe
commit
4e8934377e
|
@ -0,0 +1,3 @@
|
||||||
|
*~
|
||||||
|
*#
|
||||||
|
*.o
|
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "forf"]
|
||||||
|
path = forf
|
||||||
|
url = woozle.org:projects/forf
|
23
Makefile
23
Makefile
|
@ -1,14 +1,23 @@
|
||||||
CFLAGS = -Wall
|
CFLAGS = -Wall
|
||||||
LDFLAGS = -lm
|
|
||||||
|
|
||||||
all: run-tanks
|
all: html run-tanks designer.cgi
|
||||||
|
html: forf.html
|
||||||
|
|
||||||
test: test-tanks
|
run-tanks: run-tanks.o ctanks.o forf.o
|
||||||
./test-tanks | m4 round.html.m4 - > round.html
|
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:
|
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
752
cforf.c
|
@ -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
150
cforf.h
|
@ -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
|
|
|
@ -2,7 +2,22 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Tank Designer</title>
|
<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="tanks.js"></script>
|
||||||
<script type="application/javascript" src="designer.js"></script>
|
<script type="application/javascript" src="designer.js"></script>
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
|
@ -10,6 +25,7 @@
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<h1>Tank Designer</h1>
|
||||||
<div id="preview"><canvas id="design"></canvas><p id="debug"></p></div>
|
<div id="preview"><canvas id="design"></canvas><p id="debug"></p></div>
|
||||||
<form>
|
<form>
|
||||||
<fieldset id="metadata">
|
<fieldset id="metadata">
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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,],]];
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit fb482e222f4357553d717a0cb9daac1721973d23
|
|
@ -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
|
Binary file not shown.
After Width: | Height: | Size: 6.6 KiB |
|
@ -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>
|
|
@ -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>
|
||||||
|
|
||||||
|
|
2
round.sh
2
round.sh
|
@ -21,7 +21,7 @@ cat <<EOF >$fn
|
||||||
<link rel="stylesheet" href="tanks.css" type="text/css">
|
<link rel="stylesheet" href="tanks.css" type="text/css">
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
function go() {
|
function go() {
|
||||||
start(
|
start("battlefield",
|
||||||
// Start JSON data
|
// Start JSON data
|
||||||
EOF
|
EOF
|
||||||
./run-tanks players/* >>$fn 3>$rfn
|
./run-tanks players/* >>$fn 3>$rfn
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "ctanks.h"
|
#include "ctanks.h"
|
||||||
#include "cforf.h"
|
#include "forf.h"
|
||||||
#include "dump.h"
|
#include "dump.h"
|
||||||
|
|
||||||
#define MAX_TANKS 50
|
#define MAX_TANKS 50
|
||||||
|
|
|
@ -19,8 +19,9 @@ BEGIN {
|
||||||
|
|
||||||
print " <h2>Resources</h2>";
|
print " <h2>Resources</h2>";
|
||||||
print " <ul>";
|
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=\"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 " <li><a href=\"designer.html\">Tanks designer</a></li>";
|
||||||
print " </ul>";
|
print " </ul>";
|
||||||
|
|
||||||
|
|
26
tanks.css
26
tanks.css
|
@ -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;
|
|
||||||
}
|
|
4
tanks.js
4
tanks.js
|
@ -147,8 +147,8 @@ function Tank(ctx, width, height, color, sensors) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function start(game) {
|
function start(id, game) {
|
||||||
var canvas = document.getElementById('battlefield');
|
var canvas = document.getElementById(id);
|
||||||
var ctx = canvas.getContext('2d');
|
var ctx = canvas.getContext('2d');
|
||||||
var loop_id;
|
var loop_id;
|
||||||
|
|
||||||
|
|
137
test-tanks.c
137
test-tanks.c
|
@ -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;
|
|
||||||
}
|
|
Loading…
Reference in New Issue