~humm/crabs9

9d382db5b34a3383c430d076b3b4620177058e35 — Glenda 3 years ago master
initial import
4 files changed, 306 insertions(+), 0 deletions(-)

A README
A crabs.c
A crabs.man
A mkfile
A  => README +16 -0
@@ 1,16 @@
crabs—graphical marine adventure game
=====================================

This is a port of the game *crabs* from Research UNIX to Plan 9.  I
modified the original port [1] (whose origin I don’t know) to behave more
like the paper [2] describes.

To the extend possible under law, I have dedicated all copyright and
related and neighboring rights to my modifications to the original
software to the public domain worldwide.  This software is distributed
without any warranty.

--Humm

[1]: http://9front.org/extra/crabs.tgz
[2]: http://doc.cat-v.org/bell_labs/crabs/technical-memorandum.pdf

A  => crabs.c +223 -0
@@ 1,223 @@
#include <u.h>
#include <libc.h>
#include <draw.h>

typedef struct Crab Crab;
struct Crab
{
	int d;
	int c;
	int v;
	Point p;

	Image *s;
	Image *i;
};

Image *peekimage;
Image *crabimage[4];
Image *greyimage;
Image *greymask;

int wantedcol;

void
initcrabimage(void)
{
	ulong i, j, k;
	uchar b[8];
	char *c =
		"_##_###_"
		"####_###"
		"#______#"
		"#_####_#"
		"_######_"
		"_######_"
		"#_####_#"
		"_#____#_"

		"_###__#_"
		"##__##_#"
		"##_####_"
		"#__####_"
		"_#_####_"
		"##_####_"
		"##__##_#"
		"_###__#_"

		"_#____#_"
		"#_####_#"
		"_######_"
		"_######_"
		"#_####_#"
		"#______#"
		"###_####"
		"_###_##_"

		"_#__###_"
		"#_##__##"
		"_####_##"
		"_####_#_"
		"_####__#"
		"_####_##"
		"#_##__##"
		"_#__###_";

	for(k = 0; k < nelem(crabimage); ++k){
		for(i = 0; i < 8; ++i){
			b[i] = 0;
			for(j = 0; j < 8; ++j){
				b[i] <<= 1;
				if(*c++ == '#')
					b[i] |= 1;
			}
		}
		crabimage[k] = allocimage(display, Rect(0, 0, 8, 8), GREY1, 0, DNofill);
		loadimage(crabimage[k], Rect(0, 0, 8, 8), b, sizeof b);
	}

	c =
		"________"
		"________"
		"___#____"
		"__###___"
		"___#____"
		"________"
		"________"
		"________";

	for(i = 0; i < 8; ++i){
		b[i] = 0;
		for(j = 0; j < 8; ++j){
			b[i] <<= 1;
			if(*c++ == '#')
				b[i] |= 1;
		}
	}

	if((greymask = allocimage(display, Rect(0, 0, 8, 8), GREY1, 0, DNofill)) == nil)
		sysfatal("allocimage: %r");
	if(loadimage(greymask, Rect(0, 0, 8, 8), b, sizeof b) < 0)
		sysfatal("loadimage: %r");

	if((greyimage = allocimage(display, Rect(0, 0, 8, 8), CMAP8, 0, cmap2rgba(wantedcol))) == nil)
		sysfatal("allocimage: %r");
}

int
getcolor(Image *s, Point p)
{
	uchar b[1];

	draw(peekimage, peekimage->r, s, nil, p);
	if(unloadimage(peekimage, peekimage->r, b, sizeof(b)) < 0)
		sysfatal("unloadimage: %r");
	return b[0];
}

void
drawcrab(Image *d, Crab *c)
{
	int col;
	int dodraw = 0;

	if(c->s == nil){
		c->s = allocimage(display, c->i->r, d->chan, 0, 0);
		c->c = getcolor(d, addpt(d->r.min, addpt(c->p, Pt(4, 4))));
	}else
		draw(d, rectaddpt(c->s->r, addpt(d->r.min, c->p)), c->s, nil, c->s->r.min);
	if(c->d == 1 || nrand(16) == 0){
		c->d = 0;
		c->i = crabimage[nrand(4)];
	}

	Point p = c->p;
	if(c->i == crabimage[0])
		p.x -= c->v;
	else if(c->i == crabimage[1])
		p.y += c->v;
	else if(c->i == crabimage[2])
		p.x += c->v;
	else
		p.y -= c->v;
	if(p.y < 0 || p.y + Dy(c->i->r) > Dy(d->r) || p.x < 0 || p.x + Dx(c->i->r) > Dx(d->r))
		c->d = 1;
	else{
		col = getcolor(d, addpt(d->r.min, addpt(p, Pt(3, 3))));
		if(col != wantedcol){
			c->d = 1;
			dodraw = 1;
		}else
			c->p = p;
	}

	draw(c->s, c->s->r, d, nil, addpt(d->r.min, c->p));
	if(dodraw)
		draw(c->s, c->s->r, greyimage, greymask, greyimage->r.min);
	draw(d, rectaddpt(c->i->r, addpt(d->r.min, c->p)), display->black, c->i, c->i->r.min);
}

static void
usage(void)
{
	fprint(2, "usage: %s [-i] [-s duration] [-v velocity] [number]\n", argv0);
	exits("usage");
}

void
main(int argc, char **argv)
{
	Crab *crabs;
	ulong ncrabs, duration, velocity;
	Image *im;
	ulong i;

	ncrabs = 30;
	duration = 0;
	velocity = 5;

	ARGBEGIN{
	case 'i':
		break;
	case 's':
		duration = strtoul(EARGF(usage()), nil, 10);
		break;
	case 'v':
		velocity = strtoul(EARGF(usage()), nil, 10);
		break;
	default:
		usage();
	}ARGEND

	USED(duration);
	USED(velocity);

	if(argc > 1)
		usage();
	if(argc > 0)
		ncrabs = strtoul(argv[0], nil, 10);

	wantedcol = rgb2cmap(0x77, 0x77, 0x77);

	crabs = malloc(sizeof *crabs * ncrabs);

	if(initdraw(nil, nil, argv0) < 0)
		sysfatal("initdraw: %r");
	im = display->image;
	peekimage = allocimage(display, Rect(0, 0, 1, 1), CMAP8, 0, 0);
	initcrabimage();
	memset(crabs, 0, sizeof *crabs * ncrabs);
	for(i = 0; i < ncrabs; ++i){
		crabs[i].i = crabimage[nrand(4)];
		crabs[i].p = Pt(nrand(Dx(im->r)), nrand(Dy(im->r)));
		crabs[i].d = 0;
		crabs[i].v = 1;
	}

	for(;;){	
		for(i = 0; i < ncrabs; ++i)
			drawcrab(im, crabs + i);
		flushimage(display, 1);
		sleep(10);
	}
}

A  => crabs.man +58 -0
@@ 1,58 @@
.TH CRABS 1
.SH NAME
crabs \- graphical marine adventure game
.SH SYNOPSIS
.B crabs
[
.B -i
] [
.B -s
.I duration
] [
.B -v
.I velocity
] [
.I number
]
.SH DESCRIPTION
In
.IR crabs ,
difficult situations are encountered in trying to kill or capture
crustaceans swarming in a murky sea.  You will have to work very
rapidly to keep your territory free of seabed intruders.  At first,
you may even find it hard to keep a clear view of your surroundings,
but later discoveries about the spirit of the game will suggest a
solution.
.PP
There are several options.
.TP 10
.B -i
causes the intruders to play intelligently, allowing them to avoid detection.
.TP
.B -s
simplifies the game for the first
.I duration
time intervals.  Default is 0.  5–10 is recommended for beginners,
although you may want to forgo this option the first time, just to see
how interesting it can get.
.TP
.B -v
adjusts the velocity of the crabs, 1 being fastest. Default is 5.
.PP
.I Number
specifies the number of intruders. Default is 30.
.SH SOURCE
.B
/sys/src/games/crabs
.SH SEE ALSO
Luca Cardelli,
``Crabs: the bitmap terror''.
.SH BUGS
The options
.BR -i ,
.BR -s ,
and
.BR -v
have no effect.
.SH CRUSTACEANS
Can be frustrating.

A  => mkfile +9 -0
@@ 1,9 @@
</$objtype/mkfile

TARG = crabs
OFILES = crabs.$O

BIN = /$objtype/bin/games
MAN = /sys/man/1

</sys/src/cmd/mkone