758 lines
21 KiB
C
758 lines
21 KiB
C
/* bmatrix.c Matrix Module for blib
|
|
*
|
|
* Copyright (c) 2002 Simon Budig <simon@gimp.org>,
|
|
* 1999 Jamie Zawinski <jwz@jwz.org>
|
|
*
|
|
* Inspired/Ripped off from the Matrix hack from the xscreensaver package.
|
|
*
|
|
* Due to the very hackish nature of this hack no warranties for the
|
|
* quality of the code are given. Sorry.
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
* documentation for any purpose is hereby granted without fee, provided that
|
|
* the above copyright notice appear in all copies and that both that
|
|
* copyright notice and this permission notice appear in supporting
|
|
* documentation. No representations are made about the suitability of this
|
|
* software for any purpose. It is provided "as is" without express or
|
|
* implied warranty.
|
|
*
|
|
* Matrix -- simulate the text scrolls from the movie "The Matrix".
|
|
*
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <glib.h>
|
|
#include <gmodule.h>
|
|
|
|
#include <blib/blib.h>
|
|
|
|
|
|
#define TIMEOUT 60
|
|
#define MATRIX_DENSITY 40 /* Average density of used pixels */
|
|
#define MATRIX_INSERT "both" /* "top" "bottom" "both" */
|
|
#define MATRIX_ACTION 0 /* special effects - flashing, errors, etc. */
|
|
#define MATRIX_SPINNER 0 /* number of stationary flashing pixels */
|
|
|
|
/* Uncomment this for 2 pixels wide columns
|
|
#define MATRIX_WIDE
|
|
*/
|
|
|
|
#define B_TYPE_MATRIX (b_type_matrix)
|
|
#define B_MATRIX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), B_TYPE_MATRIX, BMatrix))
|
|
#define B_MATRIX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), B_TYPE_MATRIX, BMatrixClass))
|
|
#define B_IS_MATRIX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), B_TYPE_MATRIX))
|
|
|
|
typedef struct _BMatrix BMatrix;
|
|
typedef struct _BMatrixClass BMatrixClass;
|
|
|
|
typedef struct _BMatrixCell BMatrixCell;
|
|
typedef struct _BMatrixFeeder BMatrixFeeder;
|
|
|
|
|
|
struct _BMatrixCell
|
|
{
|
|
guint glyph : 8;
|
|
gint glow : 8;
|
|
guint changed : 1;
|
|
guint spinner : 1;
|
|
};
|
|
|
|
struct _BMatrixFeeder
|
|
{
|
|
gint remaining;
|
|
gint throttle;
|
|
gint y;
|
|
gint failure;
|
|
gint fail_type;
|
|
};
|
|
|
|
struct _BMatrix
|
|
{
|
|
BModule parent_instance;
|
|
|
|
gint grid_width, grid_height;
|
|
gint flash_x, flash_y, flash_count;
|
|
gint failcount;
|
|
BMatrixCell *cells;
|
|
BMatrixFeeder *feeders;
|
|
gint action_p;
|
|
gint insert_top_p, insert_bottom_p;
|
|
gint density;
|
|
gint density_param;
|
|
|
|
gint image_width, image_height;
|
|
gint nglyphs;
|
|
};
|
|
|
|
struct _BMatrixClass
|
|
{
|
|
BModuleClass parent_class;
|
|
};
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
PROP_LINES
|
|
};
|
|
|
|
static gint densitizer (BMatrix *state);
|
|
static void init_spinners (BMatrix *state);
|
|
static void draw_matrix (BMatrix *state);
|
|
|
|
|
|
static guchar intensities[] =
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
3, 4, 5, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
|
|
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15
|
|
};
|
|
|
|
static GType b_matrix_get_type (GTypeModule *module);
|
|
static void b_matrix_class_init (BMatrixClass *klass);
|
|
static gboolean b_matrix_query (gint width,
|
|
gint height,
|
|
gint channels,
|
|
gint maxval);
|
|
static gboolean b_matrix_prepare (BModule *module,
|
|
GError **error);
|
|
static void b_matrix_relax (BModule *module);
|
|
static void b_matrix_start (BModule *module);
|
|
static gint b_matrix_tick (BModule *module);
|
|
static void b_matrix_describe (BModule *module,
|
|
const gchar **title,
|
|
const gchar **description,
|
|
const gchar **author);
|
|
|
|
static GType b_type_matrix = 0;
|
|
|
|
|
|
G_MODULE_EXPORT gboolean
|
|
b_module_register (GTypeModule *module)
|
|
{
|
|
b_matrix_get_type (module);
|
|
return TRUE;
|
|
}
|
|
|
|
GType
|
|
b_matrix_get_type (GTypeModule *module)
|
|
{
|
|
if (!b_type_matrix)
|
|
{
|
|
static const GTypeInfo matrix_info =
|
|
{
|
|
sizeof (BMatrixClass),
|
|
NULL, /* base_init */
|
|
NULL, /* base_finalize */
|
|
(GClassInitFunc) b_matrix_class_init,
|
|
NULL, /* class_finalize */
|
|
NULL, /* class_data */
|
|
sizeof (BMatrix),
|
|
0, /* n_preallocs */
|
|
NULL /* instance_init */
|
|
};
|
|
|
|
b_type_matrix = g_type_module_register_type (module,
|
|
B_TYPE_MODULE, "BMatrix",
|
|
&matrix_info, 0);
|
|
}
|
|
|
|
return b_type_matrix;
|
|
}
|
|
|
|
static void
|
|
b_matrix_class_init (BMatrixClass *klass)
|
|
{
|
|
BModuleClass *module_class;
|
|
|
|
module_class = B_MODULE_CLASS (klass);
|
|
|
|
module_class->query = b_matrix_query;
|
|
module_class->prepare = b_matrix_prepare;
|
|
module_class->relax = b_matrix_relax;
|
|
module_class->start = b_matrix_start;
|
|
module_class->tick = b_matrix_tick;
|
|
module_class->describe = b_matrix_describe;
|
|
}
|
|
|
|
static gboolean
|
|
b_matrix_query (gint width,
|
|
gint height,
|
|
gint channels,
|
|
gint maxval)
|
|
{
|
|
return (width > 0 && height > 0 && maxval == 255 && channels == 1);
|
|
}
|
|
|
|
static gboolean
|
|
b_matrix_prepare (BModule *module,
|
|
GError **error)
|
|
{
|
|
BMatrix *state = B_MATRIX (module);
|
|
gchar *insert = NULL;
|
|
|
|
state->nglyphs = 15;
|
|
|
|
#ifdef MATRIX_WIDE
|
|
state->grid_width = (module->width + 1) / 3;
|
|
#else
|
|
state->grid_width = module->width;
|
|
#endif
|
|
state->grid_height = module->height;
|
|
|
|
state->flash_count = -rand() % 1000;
|
|
|
|
state->cells = g_new0 (BMatrixCell, state->grid_width * state->grid_height);
|
|
state->feeders = g_new0 (BMatrixFeeder, state->grid_width);
|
|
|
|
state->density = MATRIX_DENSITY;
|
|
if (state->density < 0) state->density = 0;
|
|
if (state->density > 100) state->density = 100;
|
|
state->density_param = densitizer (state);
|
|
|
|
insert = MATRIX_INSERT;
|
|
if (insert && !strcmp(insert, "top"))
|
|
{
|
|
state->insert_top_p = TRUE;
|
|
state->insert_bottom_p = FALSE;
|
|
}
|
|
else if (insert && !strcmp(insert, "bottom"))
|
|
{
|
|
state->insert_top_p = FALSE;
|
|
state->insert_bottom_p = TRUE;
|
|
}
|
|
else if (insert && !strcmp(insert, "both"))
|
|
{
|
|
state->insert_top_p = TRUE;
|
|
state->insert_bottom_p = TRUE;
|
|
}
|
|
else
|
|
{
|
|
/* if (insert && *insert)
|
|
fprintf (stderr,
|
|
"%s: `insert' must be `top', `bottom', or `both', not `%s'\n",
|
|
"bmatrix", insert); */
|
|
state->insert_top_p = FALSE;
|
|
state->insert_bottom_p = TRUE;
|
|
}
|
|
|
|
state->action_p = MATRIX_ACTION;
|
|
|
|
init_spinners (state);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
b_matrix_relax (BModule *module)
|
|
{
|
|
BMatrix *matrix = B_MATRIX (module);
|
|
|
|
if (matrix->cells)
|
|
{
|
|
g_free (matrix->cells);
|
|
matrix->cells = NULL;
|
|
}
|
|
if (matrix->feeders)
|
|
{
|
|
g_free (matrix->feeders);
|
|
matrix->feeders = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
b_matrix_start (BModule *module)
|
|
{
|
|
b_module_fill (module, 0);
|
|
b_module_ticker_start (module, TIMEOUT);
|
|
}
|
|
|
|
static gint
|
|
b_matrix_tick (BModule *module)
|
|
{
|
|
BMatrix *matrix = B_MATRIX (module);
|
|
|
|
draw_matrix (matrix);
|
|
b_module_paint (module);
|
|
|
|
return TIMEOUT;
|
|
}
|
|
|
|
static void
|
|
b_matrix_describe (BModule *module,
|
|
const gchar **title,
|
|
const gchar **description,
|
|
const gchar **author)
|
|
{
|
|
*title = "BMatrix";
|
|
*description = "Matrix hack";
|
|
*author = "Simon Budig, Jamie Zawinski";
|
|
}
|
|
|
|
static gint
|
|
densitizer (BMatrix *state)
|
|
{
|
|
/* Horrid kludge that converts percentages (density of screen coverage)
|
|
to the parameter that actually controls this. I got this mapping
|
|
empirically, on a 1024x768 screen. Sue me. */
|
|
/* Used to determine a reasonable starting value, xmatrix tries to
|
|
adjust this parameter while running. */
|
|
if (state->density < 10) return 85;
|
|
else if (state->density < 15) return 60;
|
|
else if (state->density < 20) return 45;
|
|
else if (state->density < 25) return 25;
|
|
else if (state->density < 30) return 20;
|
|
else if (state->density < 35) return 15;
|
|
else if (state->density < 45) return 10;
|
|
else if (state->density < 50) return 8;
|
|
else if (state->density < 55) return 7;
|
|
else if (state->density < 65) return 5;
|
|
else if (state->density < 80) return 3;
|
|
else if (state->density < 90) return 2;
|
|
else return 1;
|
|
}
|
|
|
|
|
|
static void
|
|
init_spinners (BMatrix *state)
|
|
{
|
|
gint i = MATRIX_SPINNER;
|
|
gint x, y;
|
|
BMatrixCell *cell;
|
|
|
|
for (y = 0; y < state->grid_height; y++)
|
|
for (x = 0; x < state->grid_width; x++)
|
|
{
|
|
cell = &state->cells[state->grid_width * y + x];
|
|
cell->spinner = 0;
|
|
}
|
|
|
|
while (--i > 0)
|
|
{
|
|
x = rand() % state->grid_width;
|
|
y = rand() % state->grid_height;
|
|
cell = &state->cells[state->grid_width * y + x];
|
|
cell->spinner = 1;
|
|
}
|
|
}
|
|
|
|
static void
|
|
insert_glyph (BMatrix *state, gint glyph, gint x, gint y)
|
|
{
|
|
gint bottom_feeder_p = (y >= 0);
|
|
BMatrixCell *from, *to;
|
|
|
|
if (y >= state->grid_height)
|
|
return;
|
|
|
|
if (bottom_feeder_p)
|
|
{
|
|
to = &state->cells[state->grid_width * y + x];
|
|
}
|
|
else
|
|
{
|
|
for (y = state->grid_height-1; y > 0; y--)
|
|
{
|
|
from = &state->cells[state->grid_width * (y-1) + x];
|
|
to = &state->cells[state->grid_width * y + x];
|
|
to->glyph = from->glyph;
|
|
to->glow = from->glow;
|
|
to->changed = 1;
|
|
}
|
|
to = &state->cells[x];
|
|
}
|
|
|
|
to->glyph = glyph;
|
|
to->changed = 1;
|
|
|
|
if (!to->glyph)
|
|
;
|
|
else if (bottom_feeder_p)
|
|
to->glow = 1 + (rand() % 2);
|
|
else
|
|
to->glow = 0;
|
|
}
|
|
|
|
|
|
static void
|
|
feed_matrix (BMatrix *state)
|
|
{
|
|
gint x;
|
|
|
|
/* Update according to current feeders. */
|
|
for (x = 0; x < state->grid_width; x++)
|
|
{
|
|
BMatrixFeeder *f = &state->feeders[x];
|
|
|
|
if (f->throttle) /* this is a delay tick, synced to frame. */
|
|
{
|
|
f->throttle--;
|
|
}
|
|
else if (f->remaining > 0) /* how many items are in the pipe */
|
|
{
|
|
gint g = (rand() % state->nglyphs) + 1;
|
|
insert_glyph (state, g, x, f->y);
|
|
f->remaining--;
|
|
if (f->y >= 0) /* bottom_feeder_p */
|
|
f->y++;
|
|
}
|
|
else /* if pipe is empty, insert spaces */
|
|
{
|
|
insert_glyph (state, 0, x, f->y);
|
|
if (f->y >= 0) /* bottom_feeder_p */
|
|
f->y++;
|
|
}
|
|
|
|
if ((rand() % 10) == 0) /* randly change throttle speed */
|
|
{
|
|
f->throttle = ((rand() % 5) + (rand() % 5));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
hack_matrix (BMatrix *state)
|
|
{
|
|
gint x;
|
|
|
|
/* Glow some characters. */
|
|
if (!state->insert_bottom_p)
|
|
{
|
|
gint i = rand() % (state->grid_width / 2);
|
|
while (--i > 0)
|
|
{
|
|
gint x = rand() % state->grid_width;
|
|
gint y = rand() % state->grid_height;
|
|
BMatrixCell *cell = &state->cells[state->grid_width * y + x];
|
|
if (cell->glyph && cell->glow == 0)
|
|
{
|
|
cell->glow = rand() % 10;
|
|
cell->changed = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Change some of the feeders. */
|
|
|
|
state->failcount = 0;
|
|
|
|
for (x = 0; x < state->grid_width; x++)
|
|
{
|
|
BMatrixFeeder *f = &state->feeders[x];
|
|
gint bottom_feeder_p;
|
|
|
|
if (state->action_p)
|
|
/* failure of some columns is controlled by a counter:
|
|
f->failure == 0: normal operation,
|
|
f->failure < -1: flickering, will black out soon,
|
|
f->failure == -1: black out
|
|
f->failure > 1: still black out...
|
|
f->failure == 1: resuming operation
|
|
*/
|
|
{
|
|
if (f->failure != 0)
|
|
{
|
|
f->failure += (f->failure < 0 ? 1 : -1);
|
|
state->failcount++;
|
|
}
|
|
|
|
if (f->failure < -1)
|
|
{
|
|
gint y;
|
|
gint r = rand() % 10;
|
|
BMatrixCell *cell;
|
|
f->fail_type = r > 2 ? 1 : 2;
|
|
if (f->fail_type == 2)
|
|
for (y=0; y < state->grid_height; y++)
|
|
{
|
|
cell = &state->cells[state->grid_width * y + x];
|
|
if (cell->glyph)
|
|
{
|
|
cell->glow = 1;
|
|
cell->changed = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (f->failure == -1)
|
|
{
|
|
f->failure += 150; /* This should be variable, but equal
|
|
for failing neighbours */
|
|
f->fail_type = 1;
|
|
}
|
|
|
|
if (f->failure == 1)
|
|
{
|
|
gint y;
|
|
BMatrixCell *cell;
|
|
|
|
f->fail_type = 0;
|
|
for (y=0; y < state->grid_height; y++)
|
|
{
|
|
cell = &state->cells[state->grid_width * y + x];
|
|
if (cell->glyph)
|
|
{
|
|
cell->glow = 1;
|
|
cell->changed = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (f->remaining > 0) /* never change if pipe isn't empty */
|
|
continue;
|
|
|
|
/* if ((rand() % densitizer(state)) != 0) then change N% of the time */
|
|
if ((rand() % state->density_param) != 0) /* then change N% of the time */
|
|
continue;
|
|
|
|
f->remaining = 3 + (rand() % state->grid_height);
|
|
f->throttle = ((rand() % 5) + (rand() % 5));
|
|
|
|
if ((rand() % 4) != 0)
|
|
f->remaining = 0;
|
|
|
|
if (state->insert_top_p && state->insert_bottom_p)
|
|
bottom_feeder_p = (rand() & 1);
|
|
else
|
|
bottom_feeder_p = state->insert_bottom_p;
|
|
|
|
if (bottom_feeder_p)
|
|
f->y = rand() % (state->grid_height / 2);
|
|
else
|
|
f->y = -1;
|
|
}
|
|
|
|
if (state->action_p)
|
|
{
|
|
/* Some columns may fail - they typically infect their neighbours */
|
|
gint failtimeout = (rand() % 12) + 3;
|
|
|
|
if (!(rand() % 200) && state->failcount <= state->grid_width / 6)
|
|
{
|
|
gint w = rand() % (1 + state->grid_width / 12);
|
|
gint i;
|
|
|
|
x = (rand() % state->grid_width);
|
|
|
|
for (i = -w; i <= w ; i++)
|
|
{
|
|
if (x+i >= 0 &&
|
|
x+i < state->grid_width &&
|
|
!(state->feeders[x+i].failure))
|
|
{
|
|
state->feeders[x+i].failure =
|
|
-failtimeout - w + (rand() % (abs(i/3)+1));
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Sometimes a flash (expanding square of glowing glyphs) will appear.
|
|
state->flash_count < 0: Count up to next flash
|
|
state->flash_count >= 0: radius of flash
|
|
*/
|
|
if (state->flash_count <= state->grid_width + state->grid_height)
|
|
state->flash_count++;
|
|
else
|
|
state->flash_count = - 1000 + rand() % 800;
|
|
|
|
if (state->flash_count == 0)
|
|
{
|
|
BMatrixCell *cell;
|
|
state->flash_x = rand() % state->grid_width;
|
|
state->flash_y = rand() % state->grid_height;
|
|
cell =
|
|
&state->cells[state->grid_width * state->flash_y + state->flash_x];
|
|
if (cell->glyph && !(cell->glow > 0))
|
|
{
|
|
cell->glow = 1;
|
|
cell->changed = 1;
|
|
}
|
|
}
|
|
|
|
if (state->flash_count > 0)
|
|
{
|
|
BMatrixCell *cell;
|
|
gint j, k, x, y;
|
|
k = state->flash_count + state->flash_count / 4;
|
|
for (; state->flash_count < k; state->flash_count++)
|
|
{
|
|
for (j=0; j <= 2 * state->flash_count; j += 1)
|
|
{
|
|
x = state->flash_x - state->flash_count + j;
|
|
y = state->flash_y - state->flash_count;
|
|
if (x >= 0 && x < state->grid_width && y >= 0 &&
|
|
y < state->grid_height)
|
|
{
|
|
cell = &state->cells[state->grid_width * y + x];
|
|
if (cell->glyph) { cell->glow+=2; cell->changed = 1; }
|
|
}
|
|
y = state->flash_y + state->flash_count;
|
|
if (x >= 0 && x < state->grid_width && y >= 0 &&
|
|
y < state->grid_height)
|
|
{
|
|
cell = &state->cells[state->grid_width * y + x];
|
|
if (cell->glyph) { cell->glow+=2; cell->changed = 1; }
|
|
}
|
|
y = state->flash_y - state->flash_count + j;
|
|
x = state->flash_x - state->flash_count;
|
|
if (x >= 0 && x < state->grid_width && y >= 0 &&
|
|
y < state->grid_height)
|
|
{
|
|
cell = &state->cells[state->grid_width * y + x];
|
|
if (cell->glyph) { cell->glow+=2; cell->changed = 1; }
|
|
}
|
|
x = state->flash_x + state->flash_count;
|
|
if (x >= 0 && x < state->grid_width && y >= 0 &&
|
|
y < state->grid_height)
|
|
{
|
|
cell = &state->cells[state->grid_width * y + x];
|
|
if (cell->glyph) { cell->glow+=2; cell->changed = 1; }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (! (rand() % 500))
|
|
init_spinners (state);
|
|
}
|
|
|
|
static void
|
|
draw_matrix (BMatrix *state)
|
|
{
|
|
gint x, y, i;
|
|
gint count = 0;
|
|
BModule *module = B_MODULE (state);
|
|
|
|
# define WINDOW 25
|
|
gint dens;
|
|
static gint ndens = 0;
|
|
static gint tdens = 0;
|
|
static gint *densities = NULL;
|
|
static gint *parameters = NULL;
|
|
static gint dens_sum, param_sum;
|
|
|
|
feed_matrix (state);
|
|
hack_matrix (state);
|
|
|
|
for (x = 0; x < state->grid_width; x++)
|
|
{
|
|
/* BMatrixFeeder *f = &(state->feeders[x]); */
|
|
|
|
for (y = 0; y < state->grid_height; y++)
|
|
{
|
|
BMatrixCell *cell = &state->cells[state->grid_width * y + x];
|
|
|
|
if (cell->glyph)
|
|
count++;
|
|
|
|
if (!cell->changed)
|
|
continue;
|
|
|
|
#ifdef MATRIX_WIDE
|
|
if (cell->glyph == 0)
|
|
{
|
|
b_module_draw_point (module, x*3, y, 0);
|
|
b_module_draw_point (module, x*3+1, y, 0);
|
|
}
|
|
else
|
|
{
|
|
b_module_draw_point (module, x*3, y, 17 * intensities[
|
|
((cell->glow > 0 || cell->spinner) ?
|
|
cell->glyph + 30
|
|
: (cell->glow == 0
|
|
? cell->glyph + 15
|
|
: cell->glyph)) -1]);
|
|
b_module_draw_point (module, x*3+1, y, 17 * intensities[
|
|
((cell->glow > 0 || cell->spinner) ?
|
|
cell->glyph + 30
|
|
: (cell->glow == 0
|
|
? cell->glyph + 15
|
|
: cell->glyph)) -1]);
|
|
}
|
|
#else
|
|
if (cell->glyph == 0)
|
|
{
|
|
b_module_draw_point (module, x, y, 0);
|
|
}
|
|
else
|
|
{
|
|
b_module_draw_point (module, x, y, 17 * intensities[
|
|
((cell->glow > 0 || cell->spinner) ?
|
|
cell->glyph + 30
|
|
: (cell->glow == 0
|
|
? cell->glyph + 15
|
|
: cell->glyph)) -1]);
|
|
}
|
|
#endif
|
|
|
|
cell->changed = 0;
|
|
|
|
if (cell->glow > 0)
|
|
{
|
|
cell->glow--;
|
|
cell->changed = 1;
|
|
}
|
|
else if (cell->glow < 0)
|
|
{
|
|
cell->glow++;
|
|
if (cell->glow == 0)
|
|
cell->glyph = 0;
|
|
cell->changed = 1;
|
|
}
|
|
|
|
if (cell->spinner)
|
|
{
|
|
cell->glyph = rand() % state->nglyphs;
|
|
cell->changed = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Adjust density-parameter */
|
|
dens = (100 * count) / (state->grid_width * state->grid_height);
|
|
|
|
if (!densities) {
|
|
densities = g_new (gint, WINDOW);
|
|
for (i = 0; i < WINDOW; i++) densities[i] = state->density;
|
|
dens_sum = state->density * WINDOW;
|
|
}
|
|
if (!parameters) {
|
|
parameters = g_new (gint, WINDOW);
|
|
for (i = 0; i < WINDOW; i++) parameters[i] = state->density_param;
|
|
param_sum = state->density_param * WINDOW;
|
|
}
|
|
|
|
/* collect the last WINDOW density/parameter values */
|
|
|
|
dens_sum -= densities [ndens % WINDOW];
|
|
param_sum -= parameters [ndens % WINDOW];
|
|
|
|
densities [ndens % WINDOW] = dens;
|
|
parameters [ndens % WINDOW] = state->density_param;
|
|
|
|
dens_sum += densities [ndens % WINDOW];
|
|
param_sum += parameters [ndens % WINDOW];
|
|
|
|
tdens += dens;
|
|
ndens++;
|
|
|
|
/* assume, that the average parameter results in the average density
|
|
* and adjust the parameter accordingly +- 1 */
|
|
|
|
if (dens_sum <= (state->density - 5) * WINDOW &&
|
|
state->density_param > 1)
|
|
state->density_param = param_sum / WINDOW - 1;
|
|
|
|
if (dens_sum >= (state->density + 5) * WINDOW)
|
|
state->density_param = param_sum / WINDOW + 2;
|
|
/* +2 to jump over the rounding error */
|
|
|
|
#if 0
|
|
printf ("density: %d%% (%d%%), param: %d\n",
|
|
dens, (tdens / ndens), state->density_param);
|
|
#endif
|
|
}
|