xenocara/app/xlockmore/modes/mountain.c
2006-11-26 11:07:42 +00:00

293 lines
7.2 KiB
C

/* -*- Mode: C; tab-width: 4 -*- */
/* mountain -- square grid mountains */
#if !defined( lint ) && !defined( SABER )
static const char sccsid[] = "@(#)mountain.c 5.00 2000/11/01 xlockmore";
#endif
/*-
* Copyright (c) 1995 Pascal Pensa <pensa@aurora.unice.fr>
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation.
*
* This file is provided AS IS with no warranties of any kind. The author
* shall have no liability with respect to the infringement of copyrights,
* trade secrets or any patents by this file or any part thereof. In no
* event will the author be liable for any lost revenue or profits or
* other special, indirect and consequential damages.
*
* Revision History:
* 01-Nov-2000: Allocation checks
* 10-May-1997: Compatible with xscreensaver
* 1995: Written
*/
#ifdef STANDALONE
#define MODE_mountain
#define PROGCLASS "Mountain"
#define HACK_INIT init_mountain
#define HACK_DRAW draw_mountain
#define mountain_opts xlockmore_opts
#define DEFAULTS "*delay: 1000 \n" \
"*count: 30 \n" \
"*cycles: 4000 \n" \
"*ncolors: 64 \n" \
"*wireframe: False \n" \
"*fullrandom: False \n"
#define SMOOTH_COLORS
#include "xlockmore.h" /* in xscreensaver distribution */
#else /* STANDALONE */
#include "xlock.h" /* in xlockmore distribution */
#endif /* STANDALONE */
#ifdef MODE_mountain
ModeSpecOpt mountain_opts =
{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
#ifdef USE_MODULES
ModStruct mountain_description =
{"mountain", "init_mountain", "draw_mountain", "release_mountain",
"refresh_mountain", "init_mountain", (char *) NULL, &mountain_opts,
1000, 30, 4000, 1, 64, 1.0, "",
"Shows Papo's mountain range", 0, NULL};
#endif
/* ~ 5000 Max mountain height (1000 - 10000) */
#define MAXHEIGHT (3 * (mp->width + mp->height))
#define WORLDWIDTH 50 /* World size x * y */
#define RANGE_RAND(min,max) ((min) + NRAND((max) - (min)))
typedef struct {
int pixelmode;
int width;
int height;
int x, y;
int offset;
int stage;
int h[WORLDWIDTH][WORLDWIDTH];
long time; /* up time */
Bool wireframe;
Bool joke;
GC stippledGC;
} mountainstruct;
static mountainstruct *mountains = (mountainstruct *) NULL;
static void
spread(int (*m)[50], int x, int y)
{
int x2, y2;
int h = m[x][y];
for (y2 = y - 1; y2 <= y + 1; y2++)
for (x2 = x - 1; x2 <= x + 1; x2++)
if (x2 >= 0 && y2 >= 0 && x2 < WORLDWIDTH && y2 < WORLDWIDTH)
m[x2][y2] = (m[x2][y2] + h) / 2;
}
static void
drawamountain(ModeInfo * mi)
{
Display *display = MI_DISPLAY(mi);
Window window = MI_WINDOW(mi);
GC gc = MI_GC(mi);
mountainstruct *mp = &mountains[MI_SCREEN(mi)];
int x2, y2, x3, y3, y4, y5, c = 0;
XPoint p[5];
if (MI_NPIXELS(mi) > 2) {
c = (mp->h[mp->x][mp->y] + mp->h[mp->x + 1][mp->y] +
mp->h[mp->x][mp->y + 1] + mp->h[mp->x + 1][mp->y + 1]) / 4;
c = (c / 10 + mp->offset) % MI_NPIXELS(mi);
}
x2 = mp->x * (2 * mp->width) / (3 * WORLDWIDTH);
y2 = mp->y * (2 * mp->height) / (3 * WORLDWIDTH);
p[0].x = (x2 - y2 / 2) + (mp->width / 4);
p[0].y = (y2 - mp->h[mp->x][mp->y]) + mp->height / 4;
x3 = (mp->x + 1) * (2 * mp->width) / (3 * WORLDWIDTH);
y3 = mp->y * (2 * mp->height) / (3 * WORLDWIDTH);
p[1].x = (x3 - y3 / 2) + (mp->width / 4);
p[1].y = (y3 - mp->h[mp->x + 1][mp->y]) + mp->height / 4;
y4 = (mp->y + 1) * (2 * mp->height) / (3 * WORLDWIDTH);
p[2].x = (x3 - y4 / 2) + (mp->width / 4);
p[2].y = (y4 - mp->h[mp->x + 1][mp->y + 1]) + mp->height / 4;
y5 = (mp->y + 1) * (2 * mp->height) / (3 * WORLDWIDTH);
p[3].x = (x2 - y5 / 2) + (mp->width / 4);
p[3].y = (y5 - mp->h[mp->x][mp->y + 1]) + mp->height / 4;
p[4].x = p[0].x;
p[4].y = p[0].y;
if (MI_NPIXELS(mi) > 2)
XSetForeground(display, gc, MI_PIXEL(mi, c));
else
XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
if (mp->joke) {
if ((Bool) (LRAND() & 1))
XDrawLines(display, window, gc, p, 5, CoordModeOrigin);
else {
XFillPolygon(display, window, gc, p, 4, Complex, CoordModeOrigin);
if (!mp->pixelmode) {
XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
XDrawLines(display, window, gc, p, 5, CoordModeOrigin);
}
}
} else {
if (mp->wireframe) {
XDrawLines(display, window, gc, p, 5, CoordModeOrigin);
} else {
XFillPolygon(display, window, gc, p, 4, Complex, CoordModeOrigin);
if (!mp->pixelmode) {
XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
XDrawLines(display, window, gc, p, 5, CoordModeOrigin);
}
}
}
mp->x++;
if (mp->x == WORLDWIDTH - 1) {
mp->y++;
mp->x = 0;
}
if (mp->y == WORLDWIDTH - 1)
mp->stage++;
}
void
init_mountain(ModeInfo * mi)
{
int i, j, x, y;
XGCValues gcv;
mountainstruct *mp;
if (mountains == NULL) {
if ((mountains = (mountainstruct *) calloc(MI_NUM_SCREENS(mi),
sizeof (mountainstruct))) == NULL)
return;
}
mp = &mountains[MI_SCREEN(mi)];
mp->width = MI_WIDTH(mi);
mp->height = MI_HEIGHT(mi);
mp->pixelmode = (mp->width + mp->height < 200);
mp->stage = 0;
mp->time = 0;
mp->x = mp->y = 0;
if (MI_IS_FULLRANDOM(mi)) {
mp->joke = (Bool) (NRAND(10) == 0);
mp->wireframe = (Bool) (LRAND() & 1);
} else {
mp->joke = False;
mp->wireframe = MI_IS_WIREFRAME(mi);
}
if (mp->stippledGC == None) {
gcv.foreground = MI_WHITE_PIXEL(mi);
gcv.background = MI_BLACK_PIXEL(mi);
if ((mp->stippledGC = XCreateGC(MI_DISPLAY(mi), MI_WINDOW(mi),
GCForeground | GCBackground, &gcv)) == None)
return;
}
MI_CLEARWINDOW(mi);
for (y = 0; y < (int) WORLDWIDTH; y++)
for (x = 0; x < (int) WORLDWIDTH; x++)
mp->h[x][y] = 0;
j = MI_COUNT(mi);
if (j < 0)
j = NRAND(-j) + 1;
for (i = 0; i < j; i++)
mp->h[RANGE_RAND(1, WORLDWIDTH - 1)][RANGE_RAND(1, WORLDWIDTH - 1)] =
NRAND(MAXHEIGHT);
for (y = 0; y < WORLDWIDTH; y++)
for (x = 0; x < WORLDWIDTH; x++)
spread(mp->h, x, y);
for (y = 0; y < WORLDWIDTH; y++)
for (x = 0; x < WORLDWIDTH; x++) {
mp->h[x][y] = mp->h[x][y] + NRAND(10) - 5;
if (mp->h[x][y] < 10)
mp->h[x][y] = 0;
}
if (MI_NPIXELS(mi) > 2)
mp->offset = NRAND(MI_NPIXELS(mi));
else
mp->offset = 0;
}
void
draw_mountain(ModeInfo * mi)
{
mountainstruct *mp;
if (mountains == NULL)
return;
mp = &mountains[MI_SCREEN(mi)];
if (mp->stippledGC == None)
return;
MI_IS_DRAWN(mi) = True;
switch (mp->stage) {
case 0:
drawamountain(mi);
break;
case 1:
if (++mp->time > MI_CYCLES(mi))
mp->stage++;
break;
case 2:
init_mountain(mi);
break;
}
}
void
release_mountain(ModeInfo * mi)
{
if (mountains != NULL) {
int screen;
for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
mountainstruct *mp = &mountains[screen];
if (mp->stippledGC)
XFreeGC(MI_DISPLAY(mi), mp->stippledGC);
}
free(mountains);
mountains = (mountainstruct *) NULL;
}
}
void
refresh_mountain(ModeInfo * mi)
{
mountainstruct *mp;
if (mountains == NULL)
return;
mp = &mountains[MI_SCREEN(mi)];
MI_CLEARWINDOW(mi);
mp->x = 0;
mp->y = 0;
}
#endif /* MODE_mountain */