|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T s
Length: 15955 (0x3e53) Types: TextFile Names: »suntetris_pw.c.orig«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/Sun/Suntetris/suntetris_pw.c.orig«
#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); }