/* zombies */
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <draw.h>
#include <mouse.h>
#define NCOLORS 200
#define MINX -1.0
#define MAXX 1.0
#define MINY -1.0
#define MAXY 1.0
typedef struct Pos Pos;
typedef struct Person Person;
int ppl = 400;
int wlkrs = 10;
struct Pos
{
double x, y;
};
struct Person
{
Pos;
int speed, dead;
int health;
int die, ref, targref;
};
Person *persons;
Mousectl *mctl;
Image *col[NCOLORS];
Image *grey;
Image *red;
long sync;
/* stolen from packet.c */
u32int
randomcol(void)
{
int c[3] = {0, 255, 0};
int *j, t;
c[2] = rand() % 256;
j = c + rand() % 3;
t = c[2];
c[2] = *j;
*j = t;
if(rand()%2){
t = c[1];
c[1] = c[0];
c[0] = t;
}
return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | 0xFF;
}
Point
convert(Pos* p)
{
return (Point){
screen->r.min.x + (screen->r.max.x - screen->r.min.x) *
((p->x - MINX) / (MAXX - MINX)),
screen->r.min.y + (screen->r.max.y - screen->r.min.y) *
((p->y - MINX) / (MAXX - MINX))};
}
Pos
deconvert(Point p)
{
return (Pos){
MINX + (MAXX - MINX) *
((double)(p.x - screen->r.min.x) / (screen->r.max.x - screen->r.min.x)),
MINY + (MAXY - MINY) *
((double)(p.y - screen->r.min.y) / (screen->r.max.y - screen->r.min.y))};
}
void *
emallocz(int size)
{
void *v;
v = mallocz(size, 1);
if(v == nil)
sysfatal("malloc: %r");
setmalloctag(v, getcallerpc(&size));
return v;
}
void
createperson(Pos p)
{
int i, j;
j = ppl;
for(i = 0; i < ppl; i++) {
if(persons[i].Pos.x == p.x && persons[i].Pos.y == p.y)
return;
if(persons[i].die == 3 && j == ppl)
j = i;
}
persons[j].Pos = p;
persons[j].die = 0;
persons[j].ref = 0;
persons[j].targref = 0;
}
void
createworld(void)
{
int i, j;
for(i = 0; i < NCOLORS; i++)
col[i] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, randomcol());
grey = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x888888FF);
red = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xFF0000FF);
persons = emallocz(sizeof(*persons) * ppl);
for(i = 0; i < ppl; i++) {
persons[i].x = frand() * (MAXX - MINX) + MINX;
persons[i].y = frand() * (MAXY - MINY) + MINY;
}
for(i = 0; i < wlkrs; i++) {
persons[i].dead = 1;
}
}
void
rect(Pos *p, int size, Image *col)
{
Point poi;
Rectangle r;
poi = convert(p);
r = insetrect(Rpt(poi, poi), -size);
draw(screen, r, col, nil, ZP);
}
void
domouse(void)
{
static Mouse m;
int lastbut, i;
double dx, dy, d;
Point poi;
if(nbrecv(mctl->resizec, &i) == 1)
if(getwindow(display, Refnone) < 0)
sysfatal("getwindow: %r");
lastbut = m.buttons;
nbrecv(mctl->c, &m);
if(lastbut & 4 && !(m.buttons & 4))
for(i = 0; i < ppl; i++){
poi = convert(&persons[i]);
dx = poi.x - m.xy.x;
dy = poi.y - m.xy.y;
d = sqrt(dx * dx + dy * dy);
if(d < 5){
persons[i].die = 1;
break;
}
}
if(lastbut & 1 && !(m.buttons & 1))
createperson(deconvert(m.xy));
}
void
movepersons()
{
int i;
sleep(600);
for(i = 0; i < ppl; i++) {
persons[i].x = frand() * (MAXX - MINX) + MINX;
persons[i].y = frand() * (MAXY - MINY) + MINY;
}
}
void
timing()
{
for(;;){
semrelease(&sync, 1);
sleep(30);
}
}
void
usage(void)
{
fprint(2, "usage: %s [-D] [-z walkers] [-p ppl]\n", argv0);
exits("usage");
}
void
threadmain(int argc, char **argv)
{
int i, j;
Person *n;
ARGBEGIN {
case 'D': break;
case 'z': wlkrs = atoi(EARGF(usage())); break;
case 'p': ppl = atoi(EARGF(usage())); break;
default: usage();
} ARGEND;
initdraw(nil, nil, nil);
mctl = initmouse(nil, screen);
createworld();
proccreate(timing, nil, mainstacksize);
for(;;) {
domouse();
draw(screen, screen->r, display->white, nil, ZP);
for(n = persons; n < ppl + persons; n++) {
if(!n->die || n->ref)
rect(n, 3, n->die ? grey : display->black);
if(n->dead)
rect(n, 3, n->die ? grey : red);
}
movepersons();
flushimage(display, 1);
semacquire(&sync, 1);
}
}
|