[comp.sources.games] v06i030: crabs - visual display for 630 MTG and 5620 DMD

games@tekred.CNA.TEK.COM (03/22/89)

Submitted-by: gwyn%smoke.brl.mil@CUNYVM.CUNY.EDU (Doug Gwyn)
Posting-number: Volume 6, Issue 30
Archive-name: crabs

	[This program is display device specific.  I don't have either
	 of these guys so I couldn't try it out - you're on your own. -br]

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  crabs.c
# Wrapped by billr@saab on Tue Mar 21 10:44:38 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'crabs.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'crabs.c'\"
else
echo shar: Extracting \"'crabs.c'\" \(12000 characters\)
sed "s/^X//" >'crabs.c' <<'END_OF_FILE'
X/*
X    crabs -- see September 1985 Scientific American pages 18..23
X
X    last edit:    89/02/25    D A Gwyn
X
X    SCCS ID:    @(#)crabs.c    1.3    for 5620 DMD and 630 MTG
X
XTo compile:
X    $ dmdcc -o crabs.m crabs.c    # -g -O also recommended
X
XTo run:
X    $ dmdld crabs.m            # runs only in mpx mode
Xor
X    $ dmdld crabs.m -        # for invisible crabs
X*/
X
X#ifndef lint
Xstatic char    SCCS_ID[] = "@(#)crabs.c    1.3 89/02/25";    /* for "what"
X utility */
X#endif
X
X
X#include    <dmd.h>
X
X#ifdef DMD630
X
X#define    texture16    texture
X
X#else    /* 5620 */
X
Xstatic Texture16    T_background =        /* background texture */
X    {
X    0x1111, 0x4444, 0x1111, 0x4444,
X    0x1111, 0x4444, 0x1111, 0x4444,
X    0x1111, 0x4444, 0x1111, 0x4444,
X    0x1111, 0x4444, 0x1111, 0x4444
X    };
X
Xstatic Bitmap    physical =        /* full screen definition */
X    {
X    (Word *)0x700000L,        /* DMD screen image base address */
X    (XMAX + 31) / 32,        /* bitmap width in 32-bit Words */
X    0, 0, XMAX, YMAX        /* screen rectangle within bitmap */
X    };
X
X#endif
X
X
X#define    NCRABS    32            /* total number of crabs (1..32) */
X
X#define    MAXVEL    8            /* abs. bound on velocity component */
X
X#define    PERIOD    2            /* sleep time (ticks) per cycle */
X
X
Xtypedef int    bool;            /* Boolean data type */
X#define    false    0
X#define    true    1
X
X
Xstatic bool    visible;        /* true if crabs are to be shown */
X
Xstatic struct
X    {
X    Point    ulc;            /* upper left corner screen coords */
X    Point    vel;            /* velocity (pixels/cycle) */
X    }    crab[NCRABS];        /* keeps track of crabs' state */
X/* We rely on this forcing the following arrays to be Word-aligned! */
X
X/* There are 4 possible crab orientations, each of which
X   has 4 possible relationships with the grey background.
X   (Scientific American article says 8, but it's wrong.) */
X
X/* Crab images XORed with grey background texture at various offsets: */
X
Xstatic short    upcrab[] =        /* facing up */
X    {
X    0x6E4C, 0x2A66,
X    0xB377, 0xE6D5,
X    0x8081, 0x8101,
X    0xB935, 0xAC9D,
X    0x6E5C, 0x3A76,
X    0x3A76, 0x6E5C,
X    0xAC9D, 0xB935,
X    0x0242, 0x4240
X    };
X
Xstatic short    downcrab[] =        /* facing down */
X    {
X    0x4240, 0x0242,
X    0xB935, 0xAC9D,
X    0x6E5C, 0x3A76,
X    0x3A76, 0x6E5C,
X    0xAC9D, 0xB935,
X    0x8101, 0x8081,
X    0xEECD, 0xAB67,
X    0x3276, 0x6654
X    };
X
Xstatic short    rightcrab[] =        /* facing right */
X    {
X    0x4E4C, 0x0A46,
X    0xB333, 0xA291,
X    0x6A59, 0x3B73,
X    0x3A72, 0x6A58,
X    0x6859, 0x3971,
X    0x3B73, 0x6A59,
X    0xA291, 0xB333,
X    0x0A46, 0x4E4C
X    };
X
Xstatic short    leftcrab[] =        /* facing left */
X    {
X    0x6250, 0x3272,
X    0x8945, 0xCCCD,
X    0xCEDC, 0x9A56,
X    0x9A16, 0x8E9C,
X    0x4E5C, 0x1A56,
X    0x9A56, 0xCEDC,
X    0xCCCD, 0x8945,
X    0x3272, 0x6250
X    };
X
X/* The bitmaps for the four orientations: */
X
Xstatic Bitmap    upmap = { (Word *)upcrab, 32/WORDSIZE, 0, 0, 32, 8 };
Xstatic Bitmap    downmap = { (Word *)downcrab, 32/WORDSIZE, 0, 0, 32, 8 };
Xstatic Bitmap    rightmap = { (Word *)rightcrab, 32/WORDSIZE, 0, 0, 32, 8 };
Xstatic Bitmap    leftmap = { (Word *)leftcrab, 32/WORDSIZE, 0, 0, 32, 8 };
X
X/* Crab "vicinities" are recorded in the following
X   global map; see Collide() and Draw() for details: */
X
Xstatic long    vicinity[(XMAX + 31) / 32 + 2][(YMAX + 31) / 32 + 2];
X                    /* includes margins all around */
X
Xstatic void    Cycle(), DrawCrab(), HideCrabs(), Init(), ModVel(), NewVel();
Xstatic int    RandInt();
Xstatic long    Collide();
X
Xmain( argc, argv )
X    int    argc;
X    char    *argv[];
X    {
X    Init( argc, argv );        /* set up initial grey crab layer */
X
X    for ( ; ; )            /* no way out! */
X        {
X        sleep( PERIOD );    /* relinquish the processor */
X
X        Cycle();        /* move the crabs */
X        }
X    /*NOTREACHED*/
X    }
X
X
Xstatic void
XInit( argc, argv )            /* set up initial crab layer */
X    int    argc;
X    char    *argv[];
X    {
X    int    i;            /* crab # */
X
X    visible = argc <= 1;        /* default is to show crabs */
X
X    texture16( &display, display.rect, &T_background, F_STORE );
X                    /* crab layer */
X
X    /* Create initial set of crabs: */
X
X    for ( i = 0; i < NCRABS; ++i )
X        {
X        /* Assign random position within "crabs" layer: */
X
X        crab[i].ulc.x = RandInt( display.rect.origin.x,
X                     display.rect.corner.x - 8
X                       );
X        crab[i].ulc.y = RandInt( display.rect.origin.y,
X                     display.rect.corner.y - 8
X                       );
X
X        /* Assign random velocity: */
X
X        NewVel( i );
X
X        /* Draw crab at initial position (within "crabs" layer): */
X
X        if ( visible )
X            DrawCrab( i );
X        }
X
X/* DEBUG
X    display.rect.corner = display.rect.origin;    /* make unpickable */
X    }
X
X
Xstatic void
XCycle()                    /* one motion cycle for all crabs */
X    {
X    static long    old[8];        /* old contents of new crab position */
X    static Bitmap    oldmap = { (Word *)old, 32/WORDSIZE, 0, 0, 8, 8 };
X    Point        p;        /* new crab upper left corner */
X    Rectangle    r;        /* new crab area */
X    long        syndrome;    /* crab collision mask */
X    int        i;        /* crab # */
X    int        w;        /* index for old[.] */
X
X    for ( i = 0; i < NCRABS; ++i )
X        {
X        DrawCrab( i );        /* erase crab from previous position */
X
X        for ( ; ; )        /* determine a new position */
X            {
X            p.x = crab[i].ulc.x + crab[i].vel.x;    /* motion */
X            p.y = crab[i].ulc.y + crab[i].vel.y;
X
X            if ( p.x >= 0 && p.x < XMAX - 8
X              && p.y >= 0 && p.y < YMAX - 8
X               )
X                break;    /* on-screen, proceed */
X
X            /* Bounce off edge of screen: */
X
X            NewVel( i );    /* assign new velocity */
X            }
X
X        r.origin = p;
X        r.corner.x = p.x + 8;
X        r.corner.y = p.y + 8;
X
X        /* Check for collision with other crabs;
X           if you don't worry about this, you get
X           crud left behind from crab collisions
X           (visible in Scientific American article).
X           (Note that crab # i has been removed.) */
X
X        /* The strategy is: only undraw possibly colliding crabs.
X           The obvious alternative, not showing any crabs until
X           all locations have been painted, would probably cause
X           the set of crabs to flicker or to appear too faint. */
X
X        if ( (syndrome = Collide( p )) != 0L )
X            HideCrabs( syndrome );    /* save from following code */
X
X        /* Save old contents of new crab location: */
X
X        bitblt( &physical, r, &oldmap, Pt( 0, 0 ), F_STORE );
X
X        /* Paint the new location grey: */
X
X        texture16( &physical, r, &T_background, F_STORE );
X
X        /* Determine if new location used to be grey: */
X
X        bitblt( &physical, r, &oldmap, Pt( 0, 0 ), F_XOR );
X
X        for ( w = 0; w < 8; ++w )
X            if ( old[w] != 0L )
X                {    /* this location has been nibbled */
X                p = crab[i].ulc;    /* reset position */
X
X                NewVel( i );    /* bounce away from bite */
X
X                break;
X                }
X
X        if ( syndrome != 0L )
X            HideCrabs( syndrome );    /* bring them back */
X
X        /* Draw the crab in its new position: */
X
X        crab[i].ulc = p;
X
X        ModVel( i );        /* randomly alter crab velocity */
X
X        DrawCrab( i );
X        }
X    }
X
X
Xstatic long
XCollide( p )                /* return syndrome for crab collision */
X    Point    p;            /* crab upper left corner */
X    {
X    long    syndrome;        /* accumulate syndrome here */
X    bool    right = p.x % 32 > 32 - 8,
X        down = p.y % 32 > 32 - 8;    /* more than one vicinity? */
X    int    x32 = p.x / 32,
X        y32 = p.y / 32;        /* vicinity array indices */
X
X    /* "Or" in crabs from overlapping vicinities: */
X
X    syndrome = vicinity[x32 + 1][y32 + 1];
X    if ( right )
X        syndrome |= vicinity[x32 + 1 + 1][y32 + 1];
X    if ( down )
X        syndrome |= vicinity[x32 + 1][y32 + 1 + 1];
X    if ( right && down )
X        syndrome |= vicinity[x32 + 1 + 1][y32 + 1 + 1];
X
X    return syndrome;
X    }
X
X
Xstatic void
XHideCrabs( syndrome )            /* draw crabs contained in syndrome */
X    long    syndrome;        /* syndrome (crab bit flags) */
X    {
X    int    i;            /* indexes crab[.] */
X    long    m;            /* bit mask for crab # i */
X
X    for ( m = 1L, i = 0; i < NCRABS; m <<= 1, ++i )
X        if ( (m & syndrome) != 0L )    /* crab contained in syndrome */
X            DrawCrab( i );    /* toggle crab */
X    }
X
X
Xstatic void
XDrawCrab( i )                /* draw specified crab */
X    int    i;            /* crab # (0..NCRABS-1) */
X    {
X    Point    p;            /* upper left corner for crab image */
X    Point    v;            /* crab velocity */
X    Bitmap    *whichmap;        /* -> 1 of 4 possible orientations */
X    int    index;            /* selects 1 of 4 offsets wrt grey */
X    int    x32, y32;        /* vicinity array indices */
X    bool    right, down;        /* more than one vicinity? */
X    long    syn_bit;        /* crab possible-occupancy bit */
X
X    if ( visible )
X        {
X        p = crab[i].ulc;
X        v = crab[i].vel;
X
X        if ( abs( v.x ) >= abs( v.y ) )
X            if ( v.x > 0 )
X                whichmap = &upmap;
X            else
X                whichmap = &downmap;
X        else
X            if ( v.y > 0 )
X                whichmap = &rightmap;
X            else
X                whichmap = &leftmap;
X
X        index = (p.x + p.y * 2) % 4 * 8;
X        bitblt( whichmap,
X            Rect( index, 0, index + 8, 8 ),
X            &physical,
X            p,
X            F_XOR
X              );
X
X        /* A crab's vicinities are the disjoint 32x32 regions
X           that contain any piece of the crab's 8x8 square.
X           On the average, 9 out of 16 crabs occupy just 1
X           vicinity; 6 out of 16 crabs occupy 2 vicinities,
X           and 1 out of every 16 crabs occupies 4 vicinities. */
X
X        x32 = p.x / 32;
X        y32 = p.y / 32;        /* coords for upper left vicinity */
X
X        right = p.x % 32 > 32 - 8;    /* also next vicinity right? */
X        down = p.y % 32 > 32 - 8;    /* also next vicinty down? */
X
X        /* Toggle crab's occupancy bit in all occupied vicinities: */
X
X        syn_bit = i == 0 ? 1L : 1L << i;
X
X        vicinity[x32 + 1][y32 + 1] ^= syn_bit;
X        if ( right )
X            vicinity[x32 + 1 + 1][y32 + 1] ^= syn_bit;
X        if ( down )
X            vicinity[x32 + 1][y32 + 1 + 1] ^= syn_bit;
X        if ( right && down )
X            vicinity[x32 + 1 + 1][y32 + 1 + 1] ^= syn_bit;
X        }
X    /* else nibble away but don't show crabs */
X    }
X
X
Xstatic void
XNewVel( i )                /* assign new velocity to crab */
X    int    i;            /* crab # */
X    {
X    crab[i].vel.x = RandInt( 1 - MAXVEL, MAXVEL );
X    crab[i].vel.y = RandInt( 1 - MAXVEL, MAXVEL );
X
X    /* Velocity (0,0) is okay since we repeatedly modify all velocities. */
X    }
X
X
Xstatic void
XModVel( i )                /* randomly modify crab velocity */
X    int    i;            /* crab # */
X    {
X    int    d;            /* increment */
X
X    if ( crab[i].vel.x >= MAXVEL - 1 )
X        d = RandInt( -1, 1 );
X    else if ( crab[i].vel.x <= 1 - MAXVEL )
X        d = RandInt( 0, 2 );
X    else
X        d = RandInt( -1, 2 );
X
X    crab[i].vel.x += d;
X
X    if ( crab[i].vel.y >= MAXVEL - 1 )
X        d = RandInt( -1, 1 );
X    else if ( crab[i].vel.y <= 1 - MAXVEL )
X        d = RandInt( 0, 2 );
X    else
X        d = RandInt( -1, 2 );
X
X    crab[i].vel.y += d;
X    }
X
X
Xstatic int
XRandInt( lo, hi )            /* generate random integer in range */
X    int    lo, hi;            /* range lo..hi-1 */
X    {
X    return lo + (int)((long)(hi - lo) * (long)(rand() & 0x7FFF) / 32768L);
X    }
X
X
X
END_OF_FILE
if test 12000 -ne `wc -c <'crabs.c'`; then
    echo shar: \"'crabs.c'\" unpacked with wrong size!
fi
# end of 'crabs.c'
fi
echo shar: End of shell archive.
exit 0