DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T s

⟦e6f7455b4⟧ TextFile

    Length: 15955 (0x3e53)
    Types: TextFile
    Names: »suntetris_pw.c.orig«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/Sun/Suntetris/suntetris_pw.c.orig« 

TextFile

#ifndef lint
static char sccsid[] = "@(#)suntetris_pw.c	1.14 3/23/89";
#endif
/*
 *  Copyright 1989, Rick Iwamoto iwamoto@sun.com
 *  Permission is given to copy and distribute for non-profit purposes. 
 */

#include <stdio.h>
#include <suntool/sunview.h>
#include <suntool/canvas.h>
#include "suntetris.h"
#include <pwd.h>
#include <unistd.h>

extern Canvas canvas;
static Pixwin *pw;
static Pixfont *bigfont;
static Pixrect *savepr;
static int incolor;
static int boardmap[BOARDWIDTH][BOARDHEIGHT];

typedef
struct figure  {
    int x[4], y[4];
} Figure;

static Figure fig1a = { { 2, 1, 0, 0 }, { 2, 2, 2, 1 } };
static Figure fig1b = { { 1, 1, 1, 0 }, { 0, 1, 2, 2 } };
static Figure fig1c = { { 0, 1, 2, 2 }, { 1, 1, 1, 2 } };
static Figure fig1d = { { 1, 1, 1, 2 }, { 2, 1, 0, 0 } };
static Figure fig2a = { { 0, 1, 2, 2 }, { 2, 2, 2, 1 } };
static Figure fig2b = { { 1, 1, 1, 0 }, { 2, 1, 0, 0 } };
static Figure fig2c = { { 2, 1, 0, 0 }, { 1, 1, 1, 2 } };
static Figure fig2d = { { 1, 1, 1, 2 }, { 0, 1, 2, 2 } };
static Figure fig3a = { { 0, 1, 2, 1 }, { 2, 2, 2, 1 } };
static Figure fig3b = { { 1, 1, 1, 0 }, { 2, 1, 0, 1 } };
static Figure fig3c = { { 2, 1, 0, 1 }, { 1, 1, 1, 2 } };
static Figure fig3d = { { 1, 1, 1, 2 }, { 0, 1, 2, 1 } };
static Figure fig4a = { { 0, 1, 1, 2 }, { 1, 1, 2, 2 } };
static Figure fig4b = { { 1, 1, 2, 2 }, { 2, 1, 1, 0 } };
static Figure fig5a = { { 0, 1, 1, 2 }, { 2, 2, 1, 1 } };
static Figure fig5b = { { 2, 2, 1, 1 }, { 2, 1, 1, 0 } };
static Figure fig6a = { { 0, 1, 2, 3 }, { 1, 1, 1, 1 } };
static Figure fig6b = { { 2, 2, 2, 2 }, { 3, 2, 1, 0 } };
static Figure fig7 = { { 0, 1, 0, 1 }, { 1, 1, 2, 2 } };


static Figure *figures[7][4] = {
    { &fig1a, &fig1b, &fig1c, &fig1d },	/* backward L */
    { &fig2a, &fig2b, &fig2c, &fig2d },	/* L */
    { &fig3a, &fig3b, &fig3c, &fig3d },	/* T */
    { &fig4a, &fig4b, &fig4a, &fig4b },	/* Z */
    { &fig5a, &fig5b, &fig5a, &fig5b },	/* S */
    { &fig6a, &fig6b, &fig6a, &fig6b },	/* I */
    { &fig7, &fig7, &fig7, &fig7 }	/* Square block */
};


static bordercolor[8] =
    { BLACK, GREEN, LTGREEN, VIOLET, RED, BLUE, YELLOW, CYAN };
static fillcolor[8] =
    { BLACK, RED, GREEN, RED, BLACK, VIOLET, RED, WHITE };

static short bwdata0[] = {	/* BLACK */
    0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
    0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF
};
mpr_static (bwblock0, BLOCKSIZE, BLOCKSIZE, 1, bwdata0);
static short bwdata1[] = {	/* root middle */
	0x0000,0x0000,0x2220,0x2220,0x0888,0x0888,0x2220,0x2220,
	0x0888,0x0888,0x2220,0x2220,0x0888,0x0888,0x0000,0x0000
};
mpr_static (bwblock1, BLOCKSIZE, BLOCKSIZE, 1, bwdata1);
static short bwdata2[] = {	/* 25 % middle */
	0x0000,0x0000,0x0444,0x1110,0x0888,0x2220,0x0444,0x1110,
	0x0888,0x2220,0x0444,0x1110,0x0888,0x2220,0x0000,0x0000
};
mpr_static (bwblock2, BLOCKSIZE, BLOCKSIZE, 1, bwdata2);
static short bwdata3[] = {	/* 50 % middle */
	0x0000,0x0000,0x2AA8,0x1554,0x2AA8,0x1554,0x2AA8,0x1554,
	0x2AA8,0x1554,0x2AA8,0x1554,0x2AA8,0x1554,0x0000,0x0000
};
mpr_static (bwblock3, BLOCKSIZE, BLOCKSIZE, 1, bwdata3);
static short bwdata4[] = {	/* 75 % middle */
	0x0000,0x0000,0x3BB8,0x2EEC,0x3774,0x1DDC,0x3BB8,0x2EEC,
	0x3774,0x1DDC,0x3BB8,0x2EEC,0x3774,0x1DDC,0x0000,0x0000
};
mpr_static (bwblock4, BLOCKSIZE, BLOCKSIZE, 1, bwdata4);
static short bwdata5[] = {	/* horiz middle */
	0x0000,0x0000,0x3FFC,0x0000,0x3FFC,0x0000,0x3FFC,0x0000,
	0x3FFC,0x0000,0x3FFC,0x0000,0x3FFC,0x0000,0x0000,0x0000
};
mpr_static (bwblock5, BLOCKSIZE, BLOCKSIZE, 1, bwdata5);
static short bwdata6[] = {	/* diag middle */
	0x0000,0x0000,0x2490,0x1248,0x0924,0x2490,0x1248,0x0924,
	0x2490,0x1248,0x0924,0x2490,0x1248,0x0924,0x0000,0x0000
};
mpr_static (bwblock6, BLOCKSIZE, BLOCKSIZE, 1, bwdata6);
static short bwdata7[] = {	/* checker middle */
	0x0000,0x0000,0x3330,0x3330,0x0CCC,0x0CCC,0x3330,0x3330,
	0x0CCC,0x0CCC,0x3330,0x3330,0x0CCC,0x0CCC,0x0000,0x0000
};
mpr_static (bwblock7, BLOCKSIZE, BLOCKSIZE, 1, bwdata7);
static Pixrect *bwblocks[8] = {
    &bwblock0, &bwblock1, &bwblock2, &bwblock3, 
    &bwblock4, &bwblock5, &bwblock6, &bwblock7
};

#define BORDER 2

/* draw_block draws a single block according to color or black&white mode */
#define draw_block(x,y,color) { \
    if (incolor)  { \
	pw_rop (pw, (x), (y), BLOCKSIZE, BLOCKSIZE, \
	    PIX_SRC | PIX_COLOR(bordercolor[color]), 0, 0, 0); \
	pw_rop (pw, (x)+BORDER, (y)+BORDER, \
	    BLOCKSIZE-2*BORDER, BLOCKSIZE-2*BORDER, \
	    PIX_SRC | PIX_COLOR(fillcolor[color]), 0, 0, 0); \
    } else \
	pw_rop (pw, (x), (y), BLOCKSIZE, BLOCKSIZE, \
	    PIX_NOT(PIX_SRC), bwblocks[color], 0, 0); \
    }
    

/* draw_figure draws one of the 7 figures in the specified orientation
   at the location on the canvas */
void
draw_figure (figno, orientation, pix_x, pix_y, color)
int figno, orientation, pix_x, pix_y, color;
{
    int i;

    if (figno > 6 || orientation > 3)  exit (1);
    pw_batch_on (pw);
    for (i = 0; i < 4; i++)
	draw_block (pix_x+(figures[figno][orientation]->x[i])*BLOCKSIZE,
	    pix_y+(figures[figno][orientation]->y[i])*BLOCKSIZE, color)
    pw_batch_off (pw);
}


/* safe_move tells when the block will collide with another or when it
   is at the border of the board */
safe_move (figno, orientation, x, y)
int figno, orientation, x, y;
{
    int i, xpos, ypos;

    for (i = 0; i < 4; i++)  {
	xpos = x+figures[figno][orientation]->x[i];
	ypos = y+figures[figno][orientation]->y[i];
	if (xpos < 0 || xpos >= BOARDWIDTH || ypos < 0 || ypos >= BOARDHEIGHT
	    || boardmap[xpos][ypos] != 0)  return (0);
    }
    return (1);
}


/* mark_board logs the specified figure on the boardmap, which keeps track
   of all pieces which have come to rest */
void
mark_board (figno, orientation, x, y)
int figno, orientation, x, y;
{
    int i, xpos, ypos;

    for (i = 0; i < 4; i++)  {
	xpos = x+figures[figno][orientation]->x[i];
	ypos = y+figures[figno][orientation]->y[i];
	boardmap[xpos][ypos] = 1;
    }
}


static struct timeval delay_50ms = { 0, 50000 };

/* reduce_rows checks for solid blocks across rows on the board,
   flashes the rows to be deleted, then deletes them from the board
   as well as the boardmap */
reduce_rows (y)
int y;
{
    int i, j, skip = 0, reducing = 0;
    static int reduce[BOARDHEIGHT] = {
    	0, 0, 0, 0, 0,
    	0, 0, 0, 0, 0,
    	0, 0, 0, 0, 0,
    	0, 0, 0, 0, 0 };

    /* check for solid rows */
    /* log all of the rows which need to be deleted into reduce[] */
    /* At most 4 rows can be deleted at one time */
    for (j = y+3; j >= y; j--)  {
	if (j >= BOARDHEIGHT)  continue;
	    /* for some blocks j can be past bottom */
	reduce[j] = 1;
	for (i = 0; i < BOARDWIDTH && reduce[j]; i++)
	    reduce[j] &= boardmap[i][j];
	reducing |= reduce[j];
	if (reduce[j])	/* save any rows-to-be-reduced for flashing */
	    pw_read (savepr, 0, (j-y)*BLOCKSIZE, BOARDWIDTH*BLOCKSIZE,
		BLOCKSIZE, PIX_SRC, pw, BOARD_X, BOARD_Y+j*BLOCKSIZE);
    }
    if (!reducing)  return (0);
    select (1, 0, 0, 0, &delay_50ms);
    for (i = 0; i < 3; i++)  {	/* flash rows 3 times */
	for (j = y+3; j >= y; j--)  {
	    if (j < BOARDHEIGHT && reduce[j])	/* erase rows */
		pw_writebackground (pw, BOARD_X, BOARD_Y+j*BLOCKSIZE,
		    BOARDWIDTH*BLOCKSIZE, BLOCKSIZE, PIX_CLR);
	}
	select (1, 0, 0, 0, &delay_50ms);
	for (j = y+3; j >= y; j--)  {
	    if (j < BOARDHEIGHT && reduce[j])	/* restore rows */
		pw_rop (pw, BOARD_X, BOARD_Y+j*BLOCKSIZE, BOARDWIDTH*BLOCKSIZE,
		    BLOCKSIZE, PIX_SRC, savepr, 0, (j-y)*BLOCKSIZE);
	}
	select (1, 0, 0, 0, &delay_50ms);
    }
    pw_batch_on (pw);
    /*  next, starting from the bottom of the board,
	we do nothing if the row is to be deleted,
	we copy the non-full row down by how many have been deleted
	under it */
    for (j = y+3; j >= 0; j--)  {	/* remove rows */
	if (j >= BOARDHEIGHT)  continue;
	if (reduce[j])  {
	    skip++;
	    reduce[j] = 0;
	}
	else if (skip > 0)  {
	    for (i = 0; i < BOARDWIDTH; i++)
		boardmap[i][j+skip] = boardmap[i][j];
	    pw_copy (pw, BOARD_X, BOARD_Y+(j+skip)*BLOCKSIZE,
		BLOCKSIZE*BOARDWIDTH, BLOCKSIZE,		/* one row */
		PIX_SRC, pw, BOARD_X, BOARD_Y+j*BLOCKSIZE);
	}
    }
    /* shift remaining blocks down by number of deleted rows */
    pw_writebackground (pw, BOARD_X, BOARD_Y, BLOCKSIZE*BOARDWIDTH,
	BLOCKSIZE*skip, PIX_CLR);
    pw_batch_off (pw);
    return (skip);
}

#define BORDER_PIXOP (PIX_SRC | PIX_COLOR(RED))
#define TEXT_PIXOP (PIX_SRC | PIX_COLOR(YELLOW))

/* close_board does the closing door effect when the game is over */
void
close_board ()
{
    int i, j;
    static struct timeval delay_100ms = { 0, 100000 };

    for (i = 0; i < BOARDHEIGHT; i++)		/* clear boardmap */
	for (j = 0; j < BOARDWIDTH; j++)  boardmap[j][i] = 0;
    select (1, 0, 0, 0, &delay_100ms);
    for (i = 0; i < BOARDHEIGHT/2; i++)  {
	pw_batch_on (pw);
	for (j = 0; j < BOARDWIDTH; j++)  {
	    draw_block (BOARD_X+j*BLOCKSIZE, BOARD_Y+i*BLOCKSIZE, 2)
	    draw_block (BOARD_X+j*BLOCKSIZE,
		BOARD_Y+(BOARDHEIGHT-1-i)*BLOCKSIZE, 2);
	}
	pw_batch_off (pw);
	select (1, 0, 0, 0, &delay_100ms);
    }
    pw_text (pw, BOARD_X+2*BLOCKSIZE, BOARD_Y+BLOCKSIZE*BOARDHEIGHT/2,
	TEXT_PIXOP, bigfont, "GAME OVER");
    select (1, 0, 0, 0, &delay_100ms);
}


void draw_score (lines, score, level)
int lines, score, level;
{
    char s[10];

    pw_batch_on (pw);
    sprintf (s, "%6d", lines);
    pw_text (pw, 100, LINES_Y, TEXT_PIXOP, bigfont, s);
    sprintf (s, "%6d", score);
    pw_text (pw, 100, SCORE_Y, TEXT_PIXOP, bigfont, s);
    sprintf (s, "%6d", level);
    pw_text (pw, 100, LEVEL_Y, TEXT_PIXOP, bigfont, s);
    pw_batch_off (pw);
}


void
draw_board ()
{
    pw_batch_on (pw);
    pw_writebackground (pw, 0, 0, pw->pw_pixrect->pr_width,
	pw->pw_pixrect->pr_height, PIX_CLR);	/* clear screen */
    pw_writebackground (pw, BOARD_X-4, BOARD_Y-4, 2, BOARDHEIGHT*BLOCKSIZE+8,
	BORDER_PIXOP);
    pw_writebackground (pw, BOARD_X-4, BOARD_Y-4, BOARDWIDTH*BLOCKSIZE+8, 2,
	BORDER_PIXOP);
    pw_writebackground (pw, BOARD_X+BOARDWIDTH*BLOCKSIZE+2, BOARD_Y-4,
	2, BOARDHEIGHT*BLOCKSIZE+8, BORDER_PIXOP);
    pw_writebackground (pw, BOARD_X-4, BOARD_Y+BOARDHEIGHT*BLOCKSIZE+2,
	BOARDWIDTH*BLOCKSIZE+8, 2, BORDER_PIXOP);
    pw_ttext (pw, 20, SCORE_Y, TEXT_PIXOP, bigfont, "SCORE");
    pw_ttext (pw, 20, LINES_Y, TEXT_PIXOP, bigfont, "LINES");
    pw_ttext (pw, 20, LEVEL_Y, TEXT_PIXOP, bigfont, "LEVEL");
    pw_batch_off (pw);
}


/* init_pw gets the pixwin from the canvas and sets up the colormap */
void
init_pw (forcebw)
int forcebw;
{
    u_char red[TETRISCMSSIZE], green[TETRISCMSSIZE], blue[TETRISCMSSIZE];

    bigfont = pf_open ("/usr/lib/fonts/fixedwidthfonts/gallant.r.19");
    pw = (Pixwin *) window_get (canvas, WIN_PIXWIN);
    incolor = (pw->pw_pixrect->pr_depth == 8);
    if (forcebw)  incolor = 0;
    tetris_cms(red, green, blue)
    pw_setcmsname (pw, "suntetris");
    pw_putcolormap (pw, 0, TETRISCMSSIZE, red, green, blue);
    pw = canvas_pixwin (canvas);
    pw_setcmsname (pw, "suntetris");
    pw_putcolormap (pw, 0, TETRISCMSSIZE, red, green, blue);
    savepr = mem_create (BOARDWIDTH*BLOCKSIZE, 4*BLOCKSIZE,
		 incolor?8:1);
}


/* rand_blocks draws a random assortment of blocks to the specified height
   on the board and logs them into the boardmap */
void
rand_blocks (height)
int height;
{
    int x, y, r;

    pw_batch_on (pw);
    for (y = BOARDHEIGHT-height; y < BOARDHEIGHT; y++)  {
	for (x = 0; x < BOARDWIDTH; x ++)  {
	    r = random ();
	    if (r % 4 == 0)  {
		boardmap[x][y] = 1;
		draw_block (BOARD_X+x*BLOCKSIZE,
		    BOARD_Y+y*BLOCKSIZE, (r/4) % 7 + 1)
	    }
	}
    }
    pw_batch_off (pw);
}


#define BOXSIZE 32
#define CHOICE_PIXOP PIX_NOT(PIX_SRC)
#define CADJX 10
#define CADJY BOXSIZE-8
#define LVX 50
#define HTX 260
#define LVY BOARD_Y+10
#define HTY BOARD_Y+10

/* display_choices draws the level selection and height selection boxes */
void
display_choices ()
{
    int i;

    pw_batch_on (pw);
    pw_writebackground (pw, 0, 0, pw->pw_pixrect->pr_width,
	pw->pw_pixrect->pr_height, PIX_CLR);	/* clear screen */
    pw_text (pw, LVX, BOARD_Y, PIX_SRC, bigfont, "LEVEL");
    pw_text (pw, HTX, BOARD_Y, PIX_SRC, bigfont, "HEIGHT");
    for (i = 0; i < 6; i++)
	pw_writebackground (pw, LVX+i*BOXSIZE, LVY, 2, 2*BOXSIZE, PIX_SET);
    for (i = 0; i < 4; i++)
	pw_writebackground (pw, HTX+i*BOXSIZE, HTY, 2, 2*BOXSIZE, PIX_SET);
    for (i = 0; i < 3; i++)  {
	pw_writebackground (pw, LVX, LVY+i*BOXSIZE, 5*BOXSIZE+2, 2,
	    PIX_SET);
	pw_writebackground (pw, HTX, HTY+i*BOXSIZE, 3*BOXSIZE+2, 2,
	    PIX_SET);
    }
    for (i = 0; i <= 9; i++)
	pw_char (pw, LVX+(i%5)*32+CADJX, LVY+(i/5)*32+CADJY, PIX_SRC,
	    bigfont, i+'0');
    pw_char (pw, HTX+CADJX, HTY+CADJY, PIX_SRC, bigfont, '0');
    pw_char (pw, HTX+BOXSIZE+CADJX, HTY+CADJY, PIX_SRC, bigfont, '4');
    pw_char (pw, HTX+2*BOXSIZE+CADJX, HTY+CADJY, PIX_SRC, bigfont, '7');
    pw_text (pw, HTX-6+CADJX, HTY+BOXSIZE+CADJY, PIX_SRC, bigfont, "10");
    pw_text (pw, HTX-6+BOXSIZE+CADJX, HTY+BOXSIZE+CADJY, PIX_SRC, bigfont,
	"13");
    pw_text (pw, HTX-6+2*BOXSIZE+CADJX, HTY+BOXSIZE+CADJY, PIX_SRC, bigfont,
	">>");
    pw_batch_off (pw);
}


/* select_level inverts the box corresponding to the specified level */
void
select_level (level)
int level;
{
    pw_copy (pw, LVX+(level%5)*BOXSIZE+2, LVY+(level/5)*BOXSIZE+2,
	BOXSIZE-2, BOXSIZE-2, PIX_NOT(PIX_SRC),
	pw, LVX+(level%5)*BOXSIZE+2, LVY+(level/5)*BOXSIZE+2);
}


/* select_height inverts the box corresponding to the specified height
   position onscreen (0-5) not the actual height (0,4,7,10,13,>>) */
void
select_height (height)
int height;
{
    pw_copy (pw, HTX+(height%3)*BOXSIZE+2, HTY+(height/3)*BOXSIZE+2,
	BOXSIZE-2, BOXSIZE-2, PIX_NOT(PIX_SRC),
	pw, HTX+(height%3)*BOXSIZE+2, HTY+(height/3)*BOXSIZE+2);
}


static struct highscores  {
    char name[16];
    int level, score;
} highs[10] =  {
    "nobody", 0, 0,
    "nobody", 0, 0,
    "nobody", 0, 0,
    "nobody", 0, 0,
    "nobody", 0, 0,
    "nobody", 0, 0,
    "nobody", 0, 0,
    "nobody", 0, 0,
    "nobody", 0, 0,
    "nobody", 0, 0,
};

#define SPACING 32
#define HIGHS_X 30
#define HIGHS_Y 80

void
display_hs ()
{
    int i;
    char s[8];

    pw_batch_on (pw);
    pw_writebackground (pw, 0, 0, pw->pw_pixrect->pr_width,
	pw->pw_pixrect->pr_height, PIX_CLR);	/* clear screen */
    pw_text (pw, HIGHS_X, HIGHS_Y-SPACING, PIX_SRC, bigfont, "NAME");
    pw_text (pw, HIGHS_X+160, HIGHS_Y-SPACING, PIX_SRC, bigfont, "LEVEL");
    pw_text (pw, HIGHS_X+270, HIGHS_Y-SPACING, PIX_SRC, bigfont, "SCORE");
    for (i = 0; i < 10; i++)  {
	pw_text (pw, HIGHS_X, HIGHS_Y+i*SPACING, PIX_SRC, bigfont,
	    highs[i].name);
	pw_char (pw, HIGHS_X+180, HIGHS_Y+i*SPACING, PIX_SRC, bigfont,
	    highs[i].level+'0');
	sprintf (s, "%5d", highs[i].score);
	pw_text (pw, HIGHS_X+270, HIGHS_Y+i*SPACING, PIX_SRC, bigfont, s);
    }
    pw_batch_off (pw);
}


#ifndef HIGHSCOREFILE
#define HIGHSCOREFILE suntetris.hs
#endif HIGHSCOREFILE

/* The file locking here isn't foolproof */
/* We have an unsecured highscore file */
void
update_hs (score, level)
int score, level;
{
    FILE *fp;
    int i, j;
    struct passwd *passwd = getpwuid (getuid ());

    if ((fp = fopen (HIGHSCOREFILE, "r")) != NULL)  {	/* read old scores */
	lockf (fileno (fp), F_LOCK, 0);
	while (i < 10 && (fscanf(fp, "%s %d %d", highs[i].name,
			  &highs[i].level, &highs[i].score) != EOF))  i++;
	fclose (fp);
    }
    for (i = 10; i > 0 && score > highs[i-1].score; i--) ;
    if (i > 9)  return;
    if ((fp = fopen (HIGHSCOREFILE, "w")) == NULL)  return;
    lockf (fileno (fp), F_LOCK, 0);
    for (j = 9; j > i; j--)  {
	strcpy (highs[j].name, highs[j-1].name);
	highs[j].level = highs[j-1].level;
	highs[j].score = highs[j-1].score;
    }
    strcpy (highs[i].name, passwd->pw_name);
    highs[i].level = level;
    highs[i].score = score;
    for (i = 0; i < 10; i++)
	fprintf (fp, "%s %d %d\n", highs[i].name, highs[i].level,
		 highs[i].score);
    fclose (fp);
}