546N/A/*
546N/A * Copyright (c) 1988-91 by Patrick J. Naughton.
546N/A *
546N/A * Permission to use, copy, modify, and distribute this software and its
546N/A * documentation for any purpose and without fee is hereby granted,
546N/A * provided that the above copyright notice appear in all copies and that
546N/A * both that copyright notice and this permission notice appear in
546N/A * supporting documentation.
546N/A *
546N/A * This file is provided AS IS with no warranties of any kind. The author
546N/A * shall have no liability with respect to the infringement of copyrights,
546N/A * trade secrets or any patents by this file or any part thereof. In no
546N/A * event will the author be liable for any lost revenue or profits or
546N/A * other special, indirect and consequential damages.
546N/A */
546N/A
546N/A/*
1007N/A * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
546N/A *
546N/A * Permission is hereby granted, free of charge, to any person obtaining a
919N/A * copy of this software and associated documentation files (the "Software"),
919N/A * to deal in the Software without restriction, including without limitation
919N/A * the rights to use, copy, modify, merge, publish, distribute, sublicense,
919N/A * and/or sell copies of the Software, and to permit persons to whom the
919N/A * Software is furnished to do so, subject to the following conditions:
546N/A *
919N/A * The above copyright notice and this permission notice (including the next
919N/A * paragraph) shall be included in all copies or substantial portions of the
919N/A * Software.
546N/A *
919N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
919N/A * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
919N/A * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
919N/A * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
919N/A * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
919N/A * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
919N/A * DEALINGS IN THE SOFTWARE.
546N/A */
546N/A
546N/A/*-
546N/A * life.c - Conway's game of Life for xlock, the X Window System lockscreen.
546N/A *
546N/A * Copyright (c) 1991 by Patrick J. Naughton.
546N/A *
546N/A * See xlock.c for copying information.
546N/A *
546N/A * Revision History:
546N/A * 24-May-91: Added wraparound code from johnson@bugs.comm.mot.com.
546N/A * Made old cells stay blue.
546N/A * Made batchcount control the number of generations till restart.
546N/A * 29-Jul-90: support for multiple screens.
546N/A * 07-Feb-90: remove bogus semi-colon after #include line.
546N/A * 15-Dec-89: Fix for proper skipping of {White,Black}Pixel() in colors.
546N/A * 08-Oct-89: Moved seconds() to an extern.
546N/A * 20-Sep-89: Written (life algorithm courtesy of Jim Graham, flar@sun.com).
546N/A */
546N/A
546N/A#include "xlock.h"
546N/A#include "lifeicon.bit"
546N/A
546N/A#ifdef SYSV
546N/A#ifndef bcopy
546N/A#define bcopy(a,b,c) memmove(b,a,c)
546N/A#endif
546N/A#ifndef bzero
546N/A#define bzero(a,b) memset(a,0,b)
546N/A#endif
546N/A#endif
546N/A
546N/Astatic XImage logo = {
546N/A 0, 0, /* width, height */
546N/A 0, XYBitmap, 0, /* xoffset, format, data */
546N/A LSBFirst, 8, /* byte-order, bitmap-unit */
546N/A LSBFirst, 8, 1 /* bitmap-bit-order, bitmap-pad, depth */
546N/A};
546N/A#define min(a, b) ((a)<(b)?(a):(b))
546N/A#define MAXROWS 155
546N/A#define MAXCOLS 144
546N/A#define TIMEOUT 30
546N/A
546N/Atypedef struct {
546N/A int pixelmode;
546N/A int xs;
546N/A int ys;
546N/A int xb;
546N/A int yb;
546N/A int generation;
546N/A long shooterTime;
546N/A int nrows;
546N/A int ncols;
546N/A int width;
546N/A int height;
546N/A unsigned char buffer[(MAXROWS + 2) * (MAXCOLS + 2) + 2];
546N/A unsigned char tempbuf[MAXCOLS * 2];
546N/A unsigned char lastbuf[MAXCOLS];
546N/A unsigned char agebuf[(MAXROWS + 2) * (MAXCOLS + 2)];
546N/A} lifestruct;
546N/A
546N/Aextern XColor ssblack[];
546N/Aextern XColor sswhite[];
546N/A
546N/Astatic lifestruct lifes[MAXSCREENS];
546N/Astatic int icon_width, icon_height;
546N/A
546N/A/* Buffer stores the data for each cell. Each cell is stored as
546N/A * 8 bits representing the presence of a critter in each of it's
546N/A * surrounding 8 cells. There is an empty row and column around
546N/A * the whole array to allow stores without bounds checking as well
546N/A * as an extra row at the end for the fetches into tempbuf.
546N/A *
546N/A * Tempbuf stores the data for the next two rows so that we know
546N/A * the state of those critter before he was modified by the fate
546N/A * of the critters that have already been processed.
546N/A *
546N/A * Agebuf stores the age of each critter.
546N/A */
546N/A
546N/A#define UPLT 0x01
546N/A#define UP 0x02
546N/A#define UPRT 0x04
546N/A#define LT 0x08
546N/A#define RT 0x10
546N/A#define DNLT 0x20
546N/A#define DN 0x40
546N/A#define DNRT 0x80
546N/A
546N/A/* Fates is a lookup table for the fate of a critter. The 256
546N/A * entries represent the 256 possible combinations of the 8
546N/A * neighbor cells. Each entry is one of BIRTH (create a cell
546N/A * or leave one alive), SAME (leave the cell alive or dead),
546N/A * or DEATH (kill anything in the cell).
546N/A */
546N/A#define BIRTH 0
546N/A#define SAME 1
546N/A#define DEATH 2
546N/Astatic unsigned char fates[256];
546N/Astatic int initialized = 0;
546N/A
546N/Astatic int patterns[][128] = {
546N/A { /* EIGHT */
546N/A -3, -3, -2, -3, -1, -3,
546N/A -3, -2, -2, -2, -1, -2,
546N/A -3, -1, -2, -1, -1, -1,
546N/A 0, 0, 1, 0, 2, 0,
546N/A 0, 1, 1, 1, 2, 1,
546N/A 0, 2, 1, 2, 2, 2,
546N/A 99
546N/A },
546N/A { /* PULSAR */
546N/A 1, 1, 2, 1, 3, 1, 4, 1, 5, 1,
546N/A 1, 2, 5, 2,
546N/A 99
546N/A },
546N/A { /* BARBER */
546N/A -7, -7, -6, -7,
546N/A -7, -6, -5, -6,
546N/A -5, -4, -3, -4,
546N/A -3, -2, -1, -2,
546N/A -1, 0, 1, 0,
546N/A 1, 2, 3, 2,
546N/A 3, 4, 5, 4,
546N/A 4, 5, 5, 5,
546N/A 99
546N/A },
546N/A { /* HERTZ */
546N/A -2, -6, -1, -6,
546N/A -2, -5, -1, -5,
546N/A -7, -3, -6, -3, -2, -3, -1, -3, 0, -3, 1, -3, 5, -3, 6, -3,
546N/A -7, -2, -5, -2, -3, -2, 2, -2, 4, -2, 6, -2,
546N/A -5, -1, -3, -1, -2, -1, 2, -1, 4, -1,
546N/A -7, 0, -5, 0, -3, 0, 2, 0, 4, 0, 6, 0,
546N/A -7, 1, -6, 1, -2, 1, -1, 1, 0, 1, 1, 1, 5, 1, 6, 1,
546N/A -2, 3, -1, 3,
546N/A -2, 4, -1, 4,
546N/A 99
546N/A },
546N/A { /* TUMBLER */
546N/A -6, -6, -5, -6, 6, -6, 7, -6,
546N/A -6, -5, -5, -5, 6, -5, 7, -5,
546N/A -5, 5, 6, 5,
546N/A -7, 6, -5, 6, 6, 6, 8, 6,
546N/A -7, 7, -5, 7, 6, 7, 8, 7,
546N/A -7, 8, -6, 8, 7, 8, 8, 8,
546N/A 99
546N/A },
546N/A { /* PERIOD4 */
546N/A -5, -8, -4, -8,
546N/A -7, -7, -5, -7,
546N/A -8, -6, -2, -6,
546N/A -7, -5, -3, -5, -2, -5,
546N/A -5, -3, -3, -3,
546N/A -4, -2,
546N/A 99
546N/A },
546N/A { /* PERIOD5 */
546N/A -5, -8, -4, -8,
546N/A -6, -7, -3, -7,
546N/A -7, -6, -2, -6,
546N/A -8, -5, -1, -5,
546N/A -8, -4, -1, -4,
546N/A -7, -3, -2, -3,
546N/A -6, -2, -3, -2,
546N/A -5, -1, -4, -1,
546N/A 99
546N/A },
546N/A { /* PERIOD6 */
546N/A -4, -8, -3, -8,
546N/A -8, -7, -7, -7, -5, -7,
546N/A -8, -6, -7, -6, -4, -6, -1, -6,
546N/A -3, -5, -1, -5,
546N/A -2, -4,
546N/A -3, -2, -2, -2,
546N/A -3, -1, -2, -1,
546N/A 99
546N/A },
546N/A { /* PINWHEEL */
546N/A -4, -8, -3, -8,
546N/A -4, -7, -3, -7,
546N/A -4, -5, -3, -5, -2, -5, -1, -5,
546N/A -5, -4, -3, -4, 0, -4, 2, -4, 3, -4,
546N/A -5, -3, -1, -3, 0, -3, 2, -3, 3, -3,
546N/A -8, -2, -7, -2, -5, -2, -2, -2, 0, -2,
546N/A -8, -1, -7, -1, -5, -1, 0, -1,
546N/A -4, 0, -3, 0, -2, 0, -1, 0,
546N/A -2, 2, -1, 2,
546N/A -2, 3, -1, 3,
546N/A 99
546N/A },
546N/A { /* ] */
546N/A -1, -1, 0, -1, 1, -1,
546N/A 0, 0, 1, 0,
546N/A -1, 1, 0, 1, 1, 1,
546N/A 99
546N/A },
546N/A { /* cc: */
546N/A -3, -1, -2, -1, -1, -1, 1, -1, 2, -1, 3, -1,
546N/A -3, 0, -2, 0, 1, 0, 2, 0,
546N/A -3, 1, -2, 1, -1, 1, 1, 1, 2, 1, 3, 1,
546N/A 99
546N/A },
546N/A { /* DOLBY */
546N/A -3, -1, -2, -1, -1, -1, 1, -1, 2, -1, 3, -1,
546N/A -3, 0, -2, 0, 2, 0, 3, 0,
546N/A -3, 1, -2, 1, -1, 1, 1, 1, 2, 1, 3, 1,
546N/A 99
546N/A },
546N/A { /* HORIZON */
546N/A -15, 0, -14, 0, -13, 0, -12, 0, -11, 0,
546N/A -10, 0, -9, 0, -8, 0, -7, 0, -6, 0,
546N/A -5, 0, -4, 0, -3, 0, -2, 0, -1, 0,
546N/A 4, 0, 3, 0, 2, 0, 1, 0, 0, 0,
546N/A 9, 0, 8, 0, 7, 0, 6, 0, 5, 0,
546N/A 14, 0, 13, 0, 12, 0, 11, 0, 10, 0,
546N/A 99
546N/A },
546N/A { /* SHEAR */
546N/A -7, -2, -6, -2, -5, -2, -4, -2, -3, -2,
546N/A -2, -2, -1, -2, 0, -2, 1, -2, 2, -2,
546N/A -5, -1, -4, -1, -3, -1, -2, -1, -1, -1,
546N/A 0, -1, 1, -1, 2, -1, 3, -1, 4, -1,
546N/A -3, 0, -2, 0, -1, 0, 0, 0, 1, 0,
546N/A 2, 0, 3, 0, 4, 0, 5, 0, 6, 0,
546N/A -10, 1, -9, 1, -8, 1, -7, 1, -6, 1,
546N/A -5, 1, -4, 1, -3, 1, -2, 1, -1, 1,
546N/A -10, 2, -9, 2, -8, 2, -7, 2, -6, 2,
546N/A -5, 2, -4, 2, -3, 2, -2, 2, -1, 2,
546N/A 99
546N/A },
546N/A { /* VERTIGO */
546N/A 0, -7,
546N/A 0, -6,
546N/A 0, -5,
546N/A 0, -4,
546N/A 0, -3,
546N/A 0, -2,
546N/A 0, -1,
546N/A 0, 0,
546N/A 0, 7,
546N/A 0, 6,
546N/A 0, 5,
546N/A 0, 4,
546N/A 0, 3,
546N/A 0, 2,
546N/A 0, 1,
546N/A 99
546N/A },
546N/A { /* CROSSBAR */
546N/A -5, 0, -4, 0, -3, 0, -2, 0, -1, 0, 4, 0, 3, 0, 2, 0, 1, 0, 0, 0,
546N/A 99
546N/A },
546N/A { /* GOALPOSTS */
546N/A -8, -7, 8, -7,
546N/A -8, -6, 8, -6,
546N/A -8, -5, 8, -5,
546N/A -8, -4, 8, -4,
546N/A -8, -3, 8, -3,
546N/A -8, -2, 8, -2,
546N/A -8, -1, 8, -1,
546N/A -8, 0, 8, 0,
546N/A -8, 1, 8, 1,
546N/A -8, 2, 8, 2,
546N/A -8, 3, 8, 3,
546N/A -8, 4, 8, 4,
546N/A -8, 5, 8, 5,
546N/A -8, 6, 8, 6,
546N/A -8, 7, 8, 7,
546N/A 99
546N/A },
546N/A { /* \ */
546N/A -8, -8, -7, -8,
546N/A -7, -7, -6, -7,
546N/A -6, -6, -5, -6,
546N/A -5, -5, -4, -5,
546N/A -4, -4, -3, -4,
546N/A -3, -3, -2, -3,
546N/A -2, -2, -1, -2,
546N/A -1, -1, 0, -1,
546N/A 0, 0, 1, 0,
546N/A 1, 1, 2, 1,
546N/A 2, 2, 3, 2,
546N/A 3, 3, 4, 3,
546N/A 4, 4, 5, 4,
546N/A 5, 5, 6, 5,
546N/A 6, 6, 7, 6,
546N/A 7, 7, 8, 7,
546N/A 99
546N/A },
546N/A { /* LABYRINTH */
546N/A -4, -4, -3, -4, -2, -4, -1, -4, 0, -4, 1, -4, 2, -4, 3, -4, 4, -4,
546N/A -4, -3, 0, -3, 4, -3,
546N/A -4, -2, -2, -2, -1, -2, 0, -2, 1, -2, 2, -2, 4, -2,
546N/A -4, -1, -2, -1, 2, -1, 4, -1,
546N/A -4, 0, -2, 0, -1, 0, 0, 0, 1, 0, 2, 0, 4, 0,
546N/A -4, 1, -2, 1, 2, 1, 4, 1,
546N/A -4, 2, -2, 2, -1, 2, 0, 2, 1, 2, 2, 2, 4, 2,
546N/A -4, 3, 0, 3, 4, 3,
546N/A -4, 4, -3, 4, -2, 4, -1, 4, 0, 4, 1, 4, 2, 4, 3, 4, 4, 4,
546N/A 99
546N/A }
546N/A};
546N/A
546N/A#define NPATS (sizeof patterns / sizeof patterns[0])
546N/A
546N/A
546N/Astatic void
546N/Adrawcell(win, row, col)
546N/A Window win;
546N/A int row, col;
546N/A{
546N/A lifestruct *lp = &lifes[screen];
546N/A
546N/A XSetForeground(dsp, Scr[screen].gc, sswhite[screen].pixel);
546N/A if (!mono && Scr[screen].npixels > 2) {
546N/A unsigned char *loc = lp->buffer + ((row + 1) * (lp->ncols + 2)) + col + 1;
546N/A unsigned char *ageptr = lp->agebuf + (loc - lp->buffer);
546N/A unsigned char age = *ageptr;
546N/A
546N/A /* if we aren't up to blue yet, then keep aging the cell. */
546N/A if (age < Scr[screen].npixels * 0.7)
546N/A ++age;
546N/A
546N/A XSetForeground(dsp, Scr[screen].gc, Scr[screen].pixels[age]);
546N/A *ageptr = age;
546N/A }
546N/A if (lp->pixelmode)
546N/A XFillRectangle(dsp, win, Scr[screen].gc,
546N/A lp->xb + lp->xs * col, lp->yb + lp->ys * row, lp->xs, lp->ys);
546N/A else
546N/A XPutImage(dsp, win, Scr[screen].gc, &logo,
546N/A 0, 0, lp->xb + lp->xs * col, lp->yb + lp->ys * row,
546N/A icon_width, icon_height);
546N/A}
546N/A
546N/A
546N/Astatic void
546N/Aerasecell(win, row, col)
546N/A Window win;
546N/A int row, col;
546N/A{
546N/A lifestruct *lp = &lifes[screen];
546N/A XSetForeground(dsp, Scr[screen].gc, ssblack[screen].pixel);
546N/A XFillRectangle(dsp, win, Scr[screen].gc,
546N/A lp->xb + lp->xs * col, lp->yb + lp->ys * row, lp->xs, lp->ys);
546N/A}
546N/A
546N/A
546N/Astatic void
546N/Aspawn(loc)
546N/A unsigned char *loc;
546N/A{
546N/A lifestruct *lp = &lifes[screen];
546N/A unsigned char *ulloc, *ucloc, *urloc, *clloc, *crloc, *llloc, *lcloc, *lrloc,
546N/A *arloc;
546N/A int off, row, col, lastrow;
546N/A
546N/A lastrow = (lp->nrows) * (lp->ncols + 2);
546N/A off = loc - lp->buffer;
546N/A col = off % (lp->ncols + 2);
546N/A row = (off - col) / (lp->ncols + 2);
546N/A ulloc = loc - lp->ncols - 3;
546N/A ucloc = loc - lp->ncols - 2;
546N/A urloc = loc - lp->ncols - 1;
546N/A clloc = loc - 1;
546N/A crloc = loc + 1;
546N/A arloc = loc + 1;
546N/A llloc = loc + lp->ncols + 1;
546N/A lcloc = loc + lp->ncols + 2;
546N/A lrloc = loc + lp->ncols + 3;
546N/A if (row == 1) {
546N/A ulloc += lastrow;
546N/A ucloc += lastrow;
546N/A urloc += lastrow;
546N/A }
546N/A if (row == lp->nrows) {
546N/A llloc -= lastrow;
546N/A lcloc -= lastrow;
546N/A lrloc -= lastrow;
546N/A }
546N/A if (col == 1) {
546N/A ulloc += lp->ncols;
546N/A clloc += lp->ncols;
546N/A llloc += lp->ncols;
546N/A }
546N/A if (col == lp->ncols) {
546N/A urloc -= lp->ncols;
546N/A crloc -= lp->ncols;
546N/A lrloc -= lp->ncols;
546N/A }
546N/A *ulloc |= UPLT;
546N/A *ucloc |= UP;
546N/A *urloc |= UPRT;
546N/A *clloc |= LT;
546N/A *crloc |= RT;
546N/A *arloc |= RT;
546N/A *llloc |= DNLT;
546N/A *lcloc |= DN;
546N/A *lrloc |= DNRT;
546N/A
546N/A *(lp->agebuf + (loc - lp->buffer)) = 0;
546N/A}
546N/A
546N/A
546N/Astatic void
1007N/Akillcell(loc)
546N/A unsigned char *loc;
546N/A{
546N/A lifestruct *lp = &lifes[screen];
546N/A
546N/A unsigned char *ulloc, *ucloc, *urloc, *clloc, *crloc, *llloc, *lcloc,
546N/A *lrloc, *arloc;
546N/A int off, row, col, lastrow;
546N/A
546N/A lastrow = (lp->nrows) * (lp->ncols + 2);
546N/A off = loc - lp->buffer;
546N/A row = off / (lp->ncols + 2);
546N/A col = off % (lp->ncols + 2);
546N/A row = (off - col) / (lp->ncols + 2);
546N/A ulloc = loc - lp->ncols - 3;
546N/A ucloc = loc - lp->ncols - 2;
546N/A urloc = loc - lp->ncols - 1;
546N/A clloc = loc - 1;
546N/A crloc = loc + 1;
546N/A arloc = loc + 1;
546N/A llloc = loc + lp->ncols + 1;
546N/A lcloc = loc + lp->ncols + 2;
546N/A lrloc = loc + lp->ncols + 3;
546N/A if (row == 1) {
546N/A ulloc += lastrow;
546N/A ucloc += lastrow;
546N/A urloc += lastrow;
546N/A }
546N/A if (row == lp->nrows) {
546N/A llloc -= lastrow;
546N/A lcloc -= lastrow;
546N/A lrloc -= lastrow;
546N/A }
546N/A if (col == 1) {
546N/A ulloc += lp->ncols;
546N/A clloc += lp->ncols;
546N/A llloc += lp->ncols;
546N/A }
546N/A if (col == lp->ncols) {
546N/A urloc -= lp->ncols;
546N/A crloc -= lp->ncols;
546N/A lrloc -= lp->ncols;
546N/A }
546N/A *ulloc &= ~UPLT;
546N/A *ucloc &= ~UP;
546N/A *urloc &= ~UPRT;
546N/A *clloc &= ~LT;
546N/A *crloc &= ~RT;
546N/A *arloc &= ~RT;
546N/A *llloc &= ~DNLT;
546N/A *lcloc &= ~DN;
546N/A *lrloc &= ~DNRT;
546N/A}
546N/A
546N/A
546N/Astatic void
546N/Asetcell(win, row, col)
546N/A Window win;
546N/A int row;
546N/A int col;
546N/A{
546N/A lifestruct *lp = &lifes[screen];
546N/A unsigned char *loc;
546N/A
546N/A loc = lp->buffer + ((row + 1) * (lp->ncols + 2)) + col + 1;
546N/A spawn(loc);
546N/A drawcell(win, row, col);
546N/A}
546N/A
546N/A
546N/Astatic void
546N/Ainit_fates()
546N/A{
546N/A int i, bits, neighbors;
546N/A
546N/A for (i = 0; i < 256; i++) {
546N/A neighbors = 0;
546N/A for (bits = i; bits; bits &= (bits - 1))
546N/A neighbors++;
546N/A if (neighbors == 3)
546N/A fates[i] = BIRTH;
546N/A else if (neighbors == 2)
546N/A fates[i] = SAME;
546N/A else
546N/A fates[i] = DEATH;
546N/A }
546N/A}
546N/A
546N/A
546N/Avoid
546N/Ainitlife(win)
546N/A Window win;
546N/A{
546N/A int row, col;
546N/A int *patptr;
546N/A XWindowAttributes xgwa;
546N/A lifestruct *lp = &lifes[screen];
546N/A
546N/A lp->generation = 0;
546N/A lp->shooterTime = seconds();
546N/A icon_width = lifeicon_width;
546N/A icon_height = lifeicon_height;
546N/A
546N/A if (!initialized) {
546N/A initialized = 1;
546N/A init_fates();
546N/A logo.data = (char *) lifeicon_bits;
546N/A logo.width = icon_width;
546N/A logo.height = icon_height;
546N/A logo.bytes_per_line = (icon_width + 7) / 8;
546N/A }
546N/A XGetWindowAttributes(dsp, win, &xgwa);
546N/A lp->width = xgwa.width;
546N/A lp->height = xgwa.height;
546N/A lp->pixelmode = (lp->width < 4 * icon_width);
546N/A if (lp->pixelmode) {
546N/A lp->ncols = 32;
546N/A lp->nrows = 32;
546N/A } else {
546N/A lp->ncols = min(lp->width / icon_width, MAXCOLS);
546N/A lp->nrows = min(lp->height / icon_height, MAXROWS);
546N/A }
546N/A lp->xs = lp->width / lp->ncols;
546N/A lp->ys = lp->height / lp->nrows;
546N/A lp->xb = (lp->width - lp->xs * lp->ncols) / 2;
546N/A lp->yb = (lp->height - lp->ys * lp->nrows) / 2;
546N/A
546N/A XSetForeground(dsp, Scr[screen].gc, ssblack[screen].pixel);
546N/A XFillRectangle(dsp, win, Scr[screen].gc, 0, 0, lp->width, lp->height);
546N/A
546N/A bzero(lp->buffer, sizeof(lp->buffer));
546N/A patptr = &patterns[random() % NPATS][0];
546N/A while ((col = *patptr++) != 99) {
546N/A row = *patptr++;
546N/A col += lp->ncols / 2;
546N/A row += lp->nrows / 2;
546N/A setcell(win, row, col);
546N/A }
546N/A}
546N/A
546N/A
546N/Avoid
546N/Adrawlife(win)
546N/A Window win;
546N/A{
546N/A unsigned char *loc, *temploc, *lastloc;
546N/A int row, col;
546N/A unsigned char fate;
546N/A lifestruct *lp = &lifes[screen];
546N/A
546N/A loc = lp->buffer + lp->ncols + 2 + 1;
546N/A temploc = lp->tempbuf;
546N/A /* copy the first 2 rows to the tempbuf */
546N/A bcopy(loc, temploc, lp->ncols);
546N/A bcopy(loc + lp->ncols + 2, temploc + lp->ncols, lp->ncols);
546N/A
546N/A lastloc = lp->lastbuf;
546N/A /* copy the last row to another buffer for wraparound */
546N/A bcopy(loc + ((lp->nrows - 1) * (lp->ncols + 2)), lastloc, lp->ncols);
546N/A
546N/A for (row = 0; row < lp->nrows; ++row) {
546N/A for (col = 0; col < lp->ncols; ++col) {
546N/A fate = fates[*temploc];
546N/A *temploc = (row == (lp->nrows - 3)) ?
546N/A *(lastloc + col) :
546N/A *(loc + (lp->ncols + 2) * 2);
546N/A switch (fate) {
546N/A case BIRTH:
546N/A if (!(*(loc + 1) & RT)) {
546N/A spawn(loc);
546N/A }
546N/A /* NO BREAK */
546N/A case SAME:
546N/A if (*(loc + 1) & RT) {
546N/A drawcell(win, row, col);
546N/A }
546N/A break;
546N/A case DEATH:
546N/A if (*(loc + 1) & RT) {
1007N/A killcell(loc);
546N/A erasecell(win, row, col);
546N/A }
546N/A break;
546N/A }
546N/A loc++;
546N/A temploc++;
546N/A }
546N/A loc += 2;
546N/A if (temploc >= lp->tempbuf + lp->ncols * 2)
546N/A temploc = lp->tempbuf;
546N/A }
546N/A
546N/A if (++lp->generation > batchcount)
546N/A initlife(win);
546N/A
546N/A /*
546N/A * generate a randomized shooter aimed roughly toward the center of the
546N/A * screen after timeout.
546N/A */
546N/A
546N/A if (seconds() - lp->shooterTime > TIMEOUT) {
546N/A int hsp = random() % (lp->ncols - 5) + 3;
546N/A int vsp = random() % (lp->nrows - 5) + 3;
546N/A int hoff = 1;
546N/A int voff = 1;
546N/A if (vsp > lp->nrows / 2)
546N/A voff = -1;
546N/A if (hsp > lp->ncols / 2)
546N/A hoff = -1;
546N/A setcell(win, vsp + 0 * voff, hsp + 2 * hoff);
546N/A setcell(win, vsp + 1 * voff, hsp + 2 * hoff);
546N/A setcell(win, vsp + 2 * voff, hsp + 2 * hoff);
546N/A setcell(win, vsp + 2 * voff, hsp + 1 * hoff);
546N/A setcell(win, vsp + 1 * voff, hsp + 0 * hoff);
546N/A lp->shooterTime = seconds();
546N/A }
546N/A}