home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume15
/
gtetris3
/
part01
/
utils.c
< prev
Wrap
C/C++ Source or Header
|
1993-01-27
|
18KB
|
652 lines
/*
# GENERIC X-WINDOW-BASED TETRIS
#
# utils.c
#
###
#
# Copyright (C) 1992, 1993 Qiang Alex Zhao, azhao@cs.arizona.edu
# Computer Science Dept, University of Arizona
#
# All Rights Reserved
#
# Permission to use, copy, modify, and distribute this software and
# its documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and
# that both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of the author not be
# used in advertising or publicity pertaining to distribution of the
# software without specific, written prior permission.
#
# This program is distributed in the hope that it will be "playable",
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
*/
#include "tetris.h"
#include "bitmaps/ticon.xbm"
#include "bitmaps/rot00.xbm"
#include "bitmaps/rot01.xbm"
#include "bitmaps/rot02.xbm"
#include "bitmaps/rot03.xbm"
#include "bitmaps/rot04.xbm"
#include "bitmaps/rot05.xbm"
#include "bitmaps/rot06.xbm"
#include "bitmaps/rot07.xbm"
#include "bitmaps/rot08.xbm"
#include "bitmaps/rot09.xbm"
#include "bitmaps/rot10.xbm"
#include "bitmaps/rot11.xbm"
#include "bitmaps/rot12.xbm"
#include "bitmaps/rot13.xbm"
#include "bitmaps/rot14.xbm"
Atom delw;
static GC revGC, bigGC, tinyGC, xorGC;
static GC thingGCs[NUM_THINGS];
static char *winName = "GENERIC TETRIS";
static char *iconName = "TETRIS";
static int titleLen, titleWidth, authorLen, authorWidth;
static int titleX, titleY, authorX, authorY;
static int sX;
static int sLevelY, sRowsY, sScoreY;
static int topRWidth, topWidth, topHeight, topMidX, topMidY;
static int frameX, frameY, frameW, frameH;
static char *bitmap_data[NUM_BITMAPS] = {
rot00_bits, rot01_bits, rot02_bits, rot03_bits, rot04_bits, rot05_bits,
rot06_bits, rot07_bits, rot08_bits, rot09_bits, rot10_bits, rot11_bits,
rot12_bits, rot13_bits, rot14_bits
};
static thing_t possible[][4] = {
{
{{{0, 0, 0, 0}, {4, 5, 5, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 4, 0, 0},
{{{0, 2, 0, 0}, {0, 10, 0, 0}, {0, 10, 0, 0}, {0, 8, 0, 0}}, 0, 0, 4, 0, 1},
{{{0, 0, 0, 0}, {4, 5, 5, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 4, 0, 2},
{{{0, 2, 0, 0}, {0, 10, 0, 0}, {0, 10, 0, 0}, {0, 8, 0, 0}}, 0, 0, 4, 0, 3}
},
{
{{{0, 2, 0, 0}, {0, 10, 0, 0}, {4, 9, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 1, 0},
{{{2, 0, 0, 0}, {12, 5, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 1, 1},
{{{6, 1, 0, 0}, {10, 0, 0, 0}, {8, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 1, 2},
{{{4, 5, 3, 0}, {0, 0, 8, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 1, 3}
},
{
{{{2, 0, 0, 0}, {10, 0, 0, 0}, {12, 1, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 2, 0},
{{{6, 5, 1, 0}, {8, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 2, 1},
{{{4, 3, 0, 0}, {0, 10, 0, 0}, {0, 8, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 2, 2},
{{{0, 0, 2, 0}, {4, 5, 9, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 2, 3}
},
{
{{{0, 2, 0, 0}, {4, 11, 0, 0}, {0, 8, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 3, 0},
{{{0, 2, 0, 0}, {4, 13, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 3, 1},
{{{2, 0, 0, 0}, {14, 1, 0, 0}, {8, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 3, 2},
{{{4, 7, 1, 0}, {0, 8, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 3, 3}
},
{
{{{2, 0, 0, 0}, {12, 3, 0, 0}, {0, 8, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 4, 0},
{{{0, 6, 1, 0}, {4, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 4, 1},
{{{2, 0, 0, 0}, {12, 3, 0, 0}, {0, 8, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 4, 2},
{{{0, 6, 1, 0}, {4, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 4, 3}
},
{
{{{0, 2, 0, 0}, {6, 9, 0, 0}, {8, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 5, 0},
{{{4, 3, 0, 0}, {0, 12, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 5, 1},
{{{0, 2, 0, 0}, {6, 9, 0, 0}, {8, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 5, 2},
{{{4, 3, 0, 0}, {0, 12, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 5, 3}
},
{
{{{6, 3, 0, 0}, {12, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 2, 6, 0},
{{{6, 3, 0, 0}, {12, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 2, 6, 1},
{{{6, 3, 0, 0}, {12, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 2, 6, 2},
{{{6, 3, 0, 0}, {12, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 2, 6, 3}
}
};
static char *thingFGs[NUM_THINGS] = {
"Magenta", "ForestGreen", "Blue", "Red", "DarkTurquoise", "Black", "Brown"
};
static Pixmap pms[NUM_BITMAPS];
static thing_t curThing, nextThing;
static struct {
int pm_num, cid;
} field[ROWS][COLS];
/* ------------------------------------------------------------------ */
static int
nrand(n)
int n;
{
return (int) (LRAND() % n);
}
/* ------------------------------------------------------------------ */
unsigned long
getColor(name)
char name[];
{
XColor tmp;
if (!useColor) {
return BlackPixel(display, screen_num);
}
if (XParseColor(display, colormap, name, &tmp) == 0) {
(void) fprintf(stderr, "Tetris: invalid color '%s'.\n", name);
return BlackPixel(display, screen_num);
}
if (XAllocColor(display, colormap, &tmp) == 0) {
(void) fprintf(stderr, "Tetris: can't allocate color '%s'.\n", name);
return BlackPixel(display, screen_num);
}
return tmp.pixel;
}
/* ------------------------------------------------------------------ */
void
inits(argc, argv)
int argc;
char *argv[];
{
XSetWindowAttributes att;
unsigned int attvm;
XTextProperty wName, iName;
XClassHint classhints;
XEvent ev;
XGCValues gcv;
unsigned long gcvm;
int i, j;
SRAND(time(NULL));
for (i = 0; i < COLS; i++)
for (j = 0; j < ROWS; j++)
if ((j >= ROWS - prefilled) && (nrand(2) == 0)) {
field[j][i].pm_num = 0;
field[j][i].cid = nrand(NUM_THINGS);
} else {
field[j][i].pm_num = -1;
field[j][i].cid = 0;
}
titleLen = strlen(MSG_TITLE);
titleWidth = XTextWidth(bigFont, MSG_TITLE, titleLen);
authorLen = strlen(MSG_AUTHOR);
authorWidth = XTextWidth(tinyFont, MSG_AUTHOR, authorLen);
frameW = BOXSIZE * COLS;
frameH = BOXSIZE * ROWS;
topRWidth = BOXSIZE * THINGSIZE + OFFSET * 2;
topHeight = frameH + OFFSET * 2 + 4;
if (titleWidth > topRWidth)
topRWidth = titleWidth;
if (authorWidth > topRWidth)
topRWidth = authorWidth;
topMidX = frameW + OFFSET * 2 + 4;
topMidY = topHeight / 2 + bigFont->ascent;
topWidth = topMidX + topRWidth;
frameX = frameY = OFFSET + 2;
titleX = (topRWidth - titleWidth) / 2 + topMidX;
titleY = OFFSET + 2 + bigFont->ascent;
authorX = (topRWidth - authorWidth) / 2 + topMidX;
authorY = OFFSET + 2 + bigFont->ascent + bigFont->descent + tinyFont->ascent;
sX = topMidX + OFFSET;
sScoreY = topHeight - OFFSET - 2 - tinyFont->descent;
sRowsY = sScoreY - tinyFont->descent - tinyFont->ascent - 2;
sLevelY = sRowsY - tinyFont->descent - tinyFont->ascent - 2;
sizehints.width = (sizehints.min_width =
(sizehints.max_width = topWidth));
sizehints.height = (sizehints.min_height =
(sizehints.max_height = topHeight));
theCursor = XCreateFontCursor(display, XC_exchange);
/* arrow keys */
XRebindKeysym(display, XK_R10, NULL, 0,
(unsigned char *) "j", sizeof(unsigned char));
XRebindKeysym(display, XK_Left, NULL, 0,
(unsigned char *) "j", sizeof(unsigned char));
XRebindKeysym(display, XK_R11, NULL, 0,
(unsigned char *) "k", sizeof(unsigned char));
XRebindKeysym(display, XK_R12, NULL, 0,
(unsigned char *) "l", sizeof(unsigned char));
XRebindKeysym(display, XK_Right, NULL, 0,
(unsigned char *) "l", sizeof(unsigned char));
/* create windows */
attvm = CWBackPixel | CWEventMask | CWDontPropagate | CWCursor;
att.background_pixel = bg;
att.event_mask = ExposureMask | KeyPressMask |
StructureNotifyMask | FocusChangeMask;
att.do_not_propagate_mask = KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
ButtonMotionMask | Button1MotionMask | Button2MotionMask |
Button3MotionMask | Button4MotionMask | Button5MotionMask;
att.cursor = theCursor;
mainWin = XCreateWindow(display, DefaultRootWindow(display),
sizehints.x, sizehints.y, topWidth, topHeight, 0,
CopyFromParent, InputOutput, CopyFromParent, attvm, &att);
attvm = CWBackPixel | CWBorderPixel | CWEventMask;
att.border_pixel = fg;
att.event_mask = ExposureMask;
blockWin = XCreateWindow(display, mainWin,
frameX-2, frameY-2, frameW, frameH, 2,
CopyFromParent, InputOutput, CopyFromParent, attvm, &att);
/* WM hints */
XStringListToTextProperty(&winName, 1, &wName);
XStringListToTextProperty(&iconName, 1, &iName);
wmhints.icon_pixmap = XCreateBitmapFromData(display,
mainWin, ticon_bits, ticon_width, ticon_height);
classhints.res_name = "tetris";
classhints.res_class = "Tetris";
XSetWMProperties(display, mainWin, &wName, &iName,
argv, argc, &sizehints, &wmhints, &classhints);
delw = XInternAtom(display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, mainWin, &delw, 1);
/* GC's */
gcvm = GCForeground | GCBackground | GCFunction |
GCFont | GCGraphicsExposures;
gcv.function = GXcopy;
gcv.foreground = fg;
gcv.background = bg;
gcv.font = bigFont->fid;
gcv.graphics_exposures = False;
bigGC = XCreateGC(display, mainWin, gcvm, &gcv);
gcv.font = tinyFont->fid;
tinyGC = XCreateGC(display, mainWin, gcvm, &gcv);
gcv.foreground = bg;
gcv.background = fg;
revGC = XCreateGC(display, mainWin, gcvm, &gcv);
gcv.background = bg;
for (i = 0; i < NUM_THINGS; i++) {
gcv.foreground = getColor(thingFGs[i]);
if (gcv.foreground == bg)
gcv.foreground = fg;
thingGCs[i] = XCreateGC(display, blockWin, gcvm, &gcv);
}
gcv.foreground = fg;
gcv.function = GXxor;
xorGC = XCreateGC(display, blockWin, gcvm, &gcv);
/* pixmaps */
for (i = 0; i < NUM_BITMAPS; i++) {
pms[i] = (Pixmap) XCreateBitmapFromData(display, blockWin,
bitmap_data[i], BOXSIZE, BOXSIZE);
}
/* new things */
newThing();
newThing();
/* the last thing is to wait for mapped */
XMapWindow(display, blockWin);
XMapRaised(display, mainWin);
XNextEvent(display, &ev);
sleep(1);
}
/* ------------------------------------------------------------------ */
void
newThing()
{
curThing = nextThing;
nextThing = possible[nrand(NUM_THINGS)][nrand(4)];
nextThing.xpos = nrand(COLS - nextThing.size + 1);
}
/* ------------------------------------------------------------------ */
void
drawTitle()
{
XDrawString(display, mainWin, bigGC,
titleX, titleY, MSG_TITLE, titleLen);
XDrawString(display, mainWin, tinyGC,
authorX, authorY, MSG_AUTHOR, authorLen);
}
/* ------------------------------------------------------------------ */
void
drawStatus()
{
char buf[30];
(void) sprintf(buf, "Score: %d", score);
XDrawImageString(display, mainWin, tinyGC, sX, sScoreY, buf, strlen(buf));
(void) sprintf(buf, "Level: %d ", level);
XDrawImageString(display, mainWin, tinyGC, sX, sLevelY, buf, strlen(buf));
(void) sprintf(buf, "Rows: %d", rows);
XDrawImageString(display, mainWin, tinyGC, sX, sRowsY, buf, strlen(buf));
}
/* ------------------------------------------------------------------ */
static void
drawBox(win, pmid, cid, x, y)
Window win;
int pmid, cid, x, y;
{
XCopyPlane(display, pms[pmid], win, thingGCs[cid], 0, 0,
BOXSIZE, BOXSIZE, x, y, (unsigned long) 1);
}
/* ------------------------------------------------------------------ */
static void
clearBox(x, y)
int x, y;
{
XFillRectangle(display, blockWin, revGC, x, y, BOXSIZE, BOXSIZE);
}
/* ------------------------------------------------------------------ */
void
drawField()
{
int i, j;
for (i = 0; i < COLS; i++)
for (j = 0; j < ROWS; j++)
if (field[j][i].pm_num >= 0)
drawBox(blockWin, field[j][i].pm_num, field[j][i].cid,
i * BOXSIZE, j * BOXSIZE);
}
/* ------------------------------------------------------------------ */
void
drawThing()
{
int i, j;
for (i = 0; i < curThing.size; i++)
for (j = 0; j < curThing.size; j++)
if (curThing.map[j][i])
drawBox(blockWin, curThing.map[j][i], curThing.px,
(curThing.xpos + i) * BOXSIZE,
(curThing.ypos + j) * BOXSIZE);
}
/* ------------------------------------------------------------------ */
void
drawThingDiff(old)
thing_t *old;
{
int i, j, ox, oy;
for (i = 0; i < curThing.size; i++)
for (j = 0; j < curThing.size; j++)
if (curThing.map[j][i])
drawBox(blockWin, curThing.map[j][i], curThing.px,
(curThing.xpos + i) * BOXSIZE,
(curThing.ypos + j) * BOXSIZE);
for (i = 0; i < curThing.size; i++)
for (j = 0; j < curThing.size; j++) {
ox = old->xpos + i - curThing.xpos;
oy = old->ypos + j - curThing.ypos;
if (old->map[j][i] &&
((ox < 0) || (ox >= curThing.size) ||
(oy < 0) || (oy >= curThing.size) ||
!curThing.map[oy][ox]))
clearBox((old->xpos + i) * BOXSIZE, (old->ypos + j) * BOXSIZE);
}
}
/* ------------------------------------------------------------------ */
void
drawNext()
{
int x, y;
int i, j;
x = topMidX + (topRWidth - nextThing.size * BOXSIZE) / 2;
y = topMidY - nextThing.size * BOXSIZE / 2;
for (i = 0; i < nextThing.size; i++)
for (j = 0; j < nextThing.size; j++)
if (nextThing.map[j][i])
drawBox(mainWin, nextThing.map[j][i], nextThing.px,
x + i * BOXSIZE, y + j * BOXSIZE);
}
/* ------------------------------------------------------------------ */
void
clearNext()
{
XFillRectangle(display, mainWin, revGC,
topMidX, topMidY - BOXSIZE * 2, topRWidth, BOXSIZE * 4);
}
/* ------------------------------------------------------------------ */
void
banner(msg)
char msg[];
{
int mlen = strlen(msg);
int w = XTextWidth(bigFont, msg, mlen);
int x = (topRWidth - w)/2 + topMidX;
XFillRectangle(display, mainWin, revGC,
x - 60, topMidY - bigFont->ascent - 5,
w + 120, bigFont->ascent + bigFont->descent + 10);
XDrawString(display, mainWin, bigGC, x, topMidY, msg, mlen);
}
/* ------------------------------------------------------------------ */
void
putBox()
{
int i, j;
int x = curThing.xpos, y = curThing.ypos;
for (i = 0; i < curThing.size; i++)
for (j = 0; j < curThing.size; j++)
if (curThing.map[j][i]) {
field[y + j][x + i].pm_num = curThing.map[j][i];
field[y + j][x + i].cid = curThing.px;
}
}
/* ------------------------------------------------------------------ */
Bool
overlapping()
{
int i, j;
int x = curThing.xpos, y = curThing.ypos;
for (i = 0; i < curThing.size; i++)
for (j = 0; j < curThing.size; j++)
if (curThing.map[j][i]) {
if ((y + j >= ROWS) || (x + i < 0) || (x + i >= COLS))
return True;
if (field[y + j][x + i].pm_num >= 0)
return True;
}
return False;
}
/* ------------------------------------------------------------------ */
Bool
atBottom()
{
int i, j;
int x = curThing.xpos, y = curThing.ypos;
for (i = 0; i < curThing.size; i++)
for (j = 0; j < curThing.size; j++)
if (curThing.map[j][i]) {
if ((y + j >= ROWS - 1) || (x + i < 0) || (x + i >= COLS))
return True;
if (field[y + j + 1][x + i].pm_num >= 0)
return True;
}
return False;
}
/* ------------------------------------------------------------------ */
void
tryMove(move)
move_t move;
{
thing_t old;
old = curThing;
switch (move) {
case FALL:
curThing.ypos ++;
break;
case DROP:
do {
curThing.ypos ++;
score += level + prefilled;
} while (!overlapping());
curThing.ypos --;
break;
case ROTATE:
curThing = possible[old.px][(old.py + 3) % 4];
curThing.xpos = old.xpos;
curThing.ypos = old.ypos;
break;
case LEFT:
curThing.xpos --;
break;
case RIGHT:
curThing.xpos ++;
break;
}
if (!overlapping())
drawThingDiff(&old);
else
curThing = old;
}
/* ------------------------------------------------------------------ */
int
checkLines()
{
int lSet[ROWS], nset = 0;
int i, j, y;
for (j = 0; j < ROWS; j++) {
lSet[j] = 0;
for (i = 0; i < COLS; i++)
if (field[j][i].pm_num >= 0)
lSet[j] ++;
if (lSet[j] == COLS)
nset ++;
}
if (nset) {
for (i = 0; i < ((NUM_FLASHES / nset) % 2) * 2; i ++) {
for (j = 0; j < ROWS; j++) {
if (lSet[j] == COLS)
XFillRectangle(display, blockWin, xorGC,
0, j * BOXSIZE, frameW, BOXSIZE);
}
XFlush(display);
}
for (j = ROWS-1; j >= 0; j--) {
if (lSet[j] == COLS) {
for (y = j; y > 0; y--)
for (i = 0; i < COLS; i++)
field[y][i] = field[y-1][i];
for (i = 0; i < COLS; i++)
field[0][i].pm_num = -1;
XCopyArea(display, blockWin, blockWin, tinyGC,
0, 0, frameW, j * BOXSIZE, 0, BOXSIZE);
XFillRectangle(display, blockWin, revGC,
0, 0, frameW, BOXSIZE);
for (i = j; i > 0; i--)
lSet[i] = lSet[i-1];
lSet[0] = 0;
j++;
XFlush(display);
}
}
if (beep) XBell(display, BVOLUME);
XSync(display, False);
}
return nset;
}
/* ------------------------------------------------------------------ */
void
realTime(tv)
struct timeval *tv;
{
while (tv->tv_usec < 0) {
tv->tv_sec --;
tv->tv_usec += MILLION;
}
while (tv->tv_usec >= MILLION) {
tv->tv_sec ++;
tv->tv_usec -= MILLION;
}
}
/* ------------------------------------------------------------------ */