home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume6
/
sun-tetris1
/
suntetris_pw.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-07-06
|
16KB
|
507 lines
#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);
}