You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
3.6 KiB
194 lines
3.6 KiB
#include <stdlib.h>
|
|
#include "things.h"
|
|
#include "tinygl.h"
|
|
|
|
|
|
/* Number of initial objects. */
|
|
#define THINGS_NUM 6
|
|
|
|
#define SAFE_DISTANCE 3
|
|
|
|
#define ANXIETY_LEVEL 2
|
|
|
|
#define PANIC_LEVEL 50
|
|
|
|
#define MOVE_ATTEMPTS 12
|
|
|
|
|
|
typedef struct thing_struct
|
|
{
|
|
tinygl_point_t pos;
|
|
uint8_t anxiety;
|
|
bool alive;
|
|
} thing_t;
|
|
|
|
|
|
static thing_t things[THINGS_NUM];
|
|
|
|
|
|
bool things_killed_p (void)
|
|
{
|
|
uint8_t i;
|
|
|
|
for (i = 1; i < THINGS_NUM; i++)
|
|
{
|
|
if (things[i].alive)
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int8_t thing_find (tinygl_point_t pos)
|
|
{
|
|
uint8_t i;
|
|
|
|
for (i = 0; i < THINGS_NUM; i++)
|
|
{
|
|
if (things[i].pos.x == pos.x
|
|
&& things[i].pos.y == pos.y
|
|
&& things[i].alive)
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
static uint8_t thing_distance_squared (thing_t *things, uint8_t this)
|
|
{
|
|
int8_t dx;
|
|
int8_t dy;
|
|
|
|
dx = things[this].pos.x - things[0].pos.x;
|
|
dy = things[this].pos.y - things[0].pos.y;
|
|
|
|
return dx * dx + dy * dy;
|
|
}
|
|
|
|
|
|
static bool thing_inbounds_p (tinygl_point_t pos)
|
|
{
|
|
return pos.x >= 0 && pos.x < TINYGL_WIDTH
|
|
&& pos.y >= 0 && pos.y < TINYGL_HEIGHT;
|
|
}
|
|
|
|
|
|
static bool thing_position_valid_p (tinygl_point_t pos)
|
|
{
|
|
return thing_inbounds_p (pos) && thing_find (pos) == -1;
|
|
}
|
|
|
|
|
|
void things_monster_move (int8_t dx, int8_t dy)
|
|
{
|
|
int8_t other;
|
|
tinygl_point_t newpos;
|
|
|
|
newpos = tinygl_point (things[0].pos.x + dx, things[0].pos.y + dy);
|
|
if (!thing_inbounds_p (newpos))
|
|
return;
|
|
|
|
other = thing_find (newpos);
|
|
if (other != -1)
|
|
things[other].alive = 0;
|
|
|
|
tinygl_draw_point (things[0].pos, 0);
|
|
things[0].pos = newpos;
|
|
tinygl_draw_point (newpos, 1);
|
|
}
|
|
|
|
|
|
void things_monster_toggle (void)
|
|
{
|
|
tinygl_pixel_set (things[0].pos, ! tinygl_pixel_get (things[0].pos));
|
|
}
|
|
|
|
|
|
|
|
static void thing_move (uint8_t this)
|
|
{
|
|
uint8_t i;
|
|
uint8_t distsq;
|
|
uint8_t panic;
|
|
tinygl_point_t pos;
|
|
|
|
tinygl_draw_point (things[this].pos, 0);
|
|
|
|
distsq = thing_distance_squared (things, this);
|
|
pos = things[this].pos;
|
|
|
|
if (thing_distance_squared (things, this) <= SAFE_DISTANCE * SAFE_DISTANCE)
|
|
things[this].anxiety++;
|
|
else
|
|
things[this].anxiety = 0;
|
|
|
|
panic = things[this].anxiety > ANXIETY_LEVEL
|
|
&& (rand () % 100 > (100 - PANIC_LEVEL));
|
|
|
|
for (i = 0; i < MOVE_ATTEMPTS; i++)
|
|
{
|
|
int8_t dx;
|
|
int8_t dy;
|
|
tinygl_point_t newpos;
|
|
|
|
dx = (rand () % 3) - 1;
|
|
dy = (rand () % 3) - 1;
|
|
|
|
newpos = tinygl_point (pos.x + dx, pos.y + dy);
|
|
|
|
if ((dx || dy) && ! thing_position_valid_p (newpos))
|
|
continue;
|
|
|
|
things[this].pos = newpos;
|
|
|
|
if (panic || thing_distance_squared (things, this) > distsq)
|
|
break;
|
|
}
|
|
|
|
/* Stay put if cannot find better position. */
|
|
if (i == MOVE_ATTEMPTS)
|
|
things[this].pos = pos;
|
|
|
|
tinygl_draw_point (things[this].pos, 1);
|
|
}
|
|
|
|
|
|
void things_move (void)
|
|
{
|
|
uint8_t i;
|
|
|
|
for (i = 1; i < THINGS_NUM; i++)
|
|
if (things[i].alive)
|
|
thing_move (i);
|
|
}
|
|
|
|
|
|
void things_create (void)
|
|
{
|
|
uint8_t i;
|
|
|
|
things[0].pos.x = 0;
|
|
things[0].pos.y = 0;
|
|
things[0].alive = 1;
|
|
tinygl_draw_point (things[0].pos, 1);
|
|
|
|
for (i = 1; i < THINGS_NUM; i++)
|
|
{
|
|
uint8_t x;
|
|
uint8_t y;
|
|
|
|
do
|
|
{
|
|
x = rand () % TINYGL_WIDTH;
|
|
y = rand () % TINYGL_HEIGHT;
|
|
} while (thing_find (tinygl_point (x, y)) != -1);
|
|
|
|
things[i].pos.x = x;
|
|
things[i].pos.y = y;
|
|
things[i].alive = 1;
|
|
|
|
tinygl_draw_point (things[i].pos, 1);
|
|
}
|
|
}
|
|
|