/branches/g5/uspace/app/tetris/screen.c |
---|
0,0 → 1,313 |
/* $OpenBSD: screen.c,v 1.13 2006/04/20 03:25:36 ray Exp $ */ |
/* $NetBSD: screen.c,v 1.4 1995/04/29 01:11:36 mycroft Exp $ */ |
/*- |
* Copyright (c) 1992, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* This code is derived from software contributed to Berkeley by |
* Chris Torek and Darren F. Provine. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)screen.c 8.1 (Berkeley) 5/31/93 |
*/ |
/** @addtogroup tetris |
* @{ |
*/ |
/** @file |
*/ |
/* |
* Tetris screen control. |
*/ |
#include <err.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <unistd.h> |
#include <io/stream.h> |
#include <async.h> |
#include "screen.h" |
#include "tetris.h" |
#include "../../srv/console/console.h" |
static cell curscreen[B_SIZE]; /* 1 => standout (or otherwise marked) */ |
static int curscore; |
static int isset; /* true => terminal is in game mode */ |
/* |
* putstr() is for unpadded strings (either as in termcap(5) or |
* simply literal strings); |
*/ |
static inline void putstr(char *s) |
{ |
while (*s) |
putchar(*(s++)); |
} |
static int con_phone; |
static void set_style(int fgcolor, int bgcolor) |
{ |
async_msg_2(con_phone, CONSOLE_SET_STYLE, fgcolor, bgcolor); |
} |
static void start_standout(void) |
{ |
set_style(0xf0f0f0, 0); |
} |
static void resume_normal(void) |
{ |
set_style(0, 0xf0f0f0); |
} |
void clear_screen(void) |
{ |
async_msg_0(con_phone, CONSOLE_CLEAR); |
moveto(0, 0); |
} |
/* |
* Clear the screen, forgetting the current contents in the process. |
*/ |
void |
scr_clear(void) |
{ |
resume_normal(); |
async_msg_0(con_phone, CONSOLE_CLEAR); |
curscore = -1; |
memset((char *)curscreen, 0, sizeof(curscreen)); |
} |
/* |
* Set up screen |
*/ |
void |
scr_init(void) |
{ |
con_phone = get_cons_phone(); |
async_msg_1(con_phone, CONSOLE_CURSOR_VISIBILITY, 0); |
resume_normal(); |
scr_clear(); |
} |
void moveto(int r, int c) |
{ |
async_msg_2(con_phone, CONSOLE_GOTO, r, c); |
} |
static void fflush(void) |
{ |
async_msg_0(con_phone, CONSOLE_FLUSH); |
} |
winsize_t winsize; |
static int get_display_size(winsize_t *ws) |
{ |
return async_req_0_2(con_phone, CONSOLE_GETSIZE, &ws->ws_row, |
&ws->ws_col); |
} |
/* |
* Set up screen mode. |
*/ |
void |
scr_set(void) |
{ |
winsize_t ws; |
Rows = 0, Cols = 0; |
if (get_display_size(&ws) == 0) { |
Rows = ws.ws_row; |
Cols = ws.ws_col; |
} |
if (Rows < MINROWS || Cols < MINCOLS) { |
char smallscr[55]; |
snprintf(smallscr, sizeof(smallscr), |
"the screen is too small (must be at least %dx%d)", |
MINROWS, MINCOLS); |
stop(smallscr); |
} |
isset = 1; |
scr_clear(); |
} |
/* |
* End screen mode. |
*/ |
void |
scr_end(void) |
{ |
} |
void |
stop(char *why) |
{ |
if (isset) |
scr_end(); |
errx(1, "aborting: %s", why); |
} |
/* |
* Update the screen. |
*/ |
void |
scr_update(void) |
{ |
cell *bp, *sp; |
cell so, cur_so = 0; |
int i, ccol, j; |
static const struct shape *lastshape; |
/* always leave cursor after last displayed point */ |
curscreen[D_LAST * B_COLS - 1] = -1; |
if (score != curscore) { |
moveto(0, 0); |
printf("Score: %d", score); |
curscore = score; |
} |
/* draw preview of next pattern */ |
if (showpreview && (nextshape != lastshape)) { |
int i; |
static int r=5, c=2; |
int tr, tc, t; |
lastshape = nextshape; |
/* clean */ |
resume_normal(); |
moveto(r-1, c-1); putstr(" "); |
moveto(r, c-1); putstr(" "); |
moveto(r+1, c-1); putstr(" "); |
moveto(r+2, c-1); putstr(" "); |
moveto(r-3, c-2); |
putstr("Next shape:"); |
/* draw */ |
start_standout(); |
moveto(r, 2 * c); |
putstr(" "); |
for (i = 0; i < 3; i++) { |
t = c + r * B_COLS; |
t += nextshape->off[i]; |
tr = t / B_COLS; |
tc = t % B_COLS; |
moveto(tr, 2*tc); |
putstr(" "); |
} |
resume_normal(); |
} |
bp = &board[D_FIRST * B_COLS]; |
sp = &curscreen[D_FIRST * B_COLS]; |
for (j = D_FIRST; j < D_LAST; j++) { |
ccol = -1; |
for (i = 0; i < B_COLS; bp++, sp++, i++) { |
if (*sp == (so = *bp)) |
continue; |
*sp = so; |
if (i != ccol) { |
if (cur_so) { |
resume_normal(); |
cur_so = 0; |
} |
moveto(RTOD(j), CTOD(i)); |
} |
if (so != cur_so) { |
if (so) |
start_standout(); |
else |
resume_normal(); |
cur_so = so; |
} |
putstr(" "); |
ccol = i + 1; |
/* |
* Look ahead a bit, to avoid extra motion if |
* we will be redrawing the cell after the next. |
* Motion probably takes four or more characters, |
* so we save even if we rewrite two cells |
* `unnecessarily'. Skip it all, though, if |
* the next cell is a different color. |
*/ |
#define STOP (B_COLS - 3) |
if (i > STOP || sp[1] != bp[1] || so != bp[1]) |
continue; |
if (sp[2] != bp[2]) |
sp[1] = -1; |
else if (i < STOP && so == bp[2] && sp[3] != bp[3]) { |
sp[2] = -1; |
sp[1] = -1; |
} |
} |
} |
if (cur_so) |
resume_normal(); |
fflush(); |
} |
/* |
* Write a message (set!=0), or clear the same message (set==0). |
* (We need its length in case we have to overwrite with blanks.) |
*/ |
void |
scr_msg(char *s, int set) |
{ |
int l = strlen(s); |
moveto(Rows - 2, ((Cols - l) >> 1) - 1); |
if (set) |
putstr(s); |
else |
while (--l >= 0) |
(void) putchar(' '); |
} |
/** @} |
*/ |
/branches/g5/uspace/app/tetris/input.c |
---|
0,0 → 1,187 |
/* $OpenBSD: input.c,v 1.12 2005/04/13 02:33:08 deraadt Exp $ */ |
/* $NetBSD: input.c,v 1.3 1996/02/06 22:47:33 jtc Exp $ */ |
/*- |
* Copyright (c) 1992, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* This code is derived from software contributed to Berkeley by |
* Chris Torek and Darren F. Provine. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)input.c 8.1 (Berkeley) 5/31/93 |
*/ |
/** @addtogroup tetris |
* @{ |
*/ |
/** @file |
*/ |
/* |
* Tetris input. |
*/ |
#include <sys/types.h> |
#include <sys/time.h> |
#include <stdio.h> |
#include <errno.h> |
#include <unistd.h> |
#include <string.h> |
#include "input.h" |
#include "tetris.h" |
#include <async.h> |
#include "../../srv/console/console.h" |
/* return true iff the given timeval is positive */ |
#define TV_POS(tv) \ |
((tv)->tv_sec > 0 || ((tv)->tv_sec == 0 && (tv)->tv_usec > 0)) |
/* subtract timeval `sub' from `res' */ |
#define TV_SUB(res, sub) \ |
(res)->tv_sec -= (sub)->tv_sec; \ |
(res)->tv_usec -= (sub)->tv_usec; \ |
if ((res)->tv_usec < 0) { \ |
(res)->tv_usec += 1000000; \ |
(res)->tv_sec--; \ |
} |
/* We will use a hack here - if lastchar is non-zero, it is |
* the last character read. We will somehow simulate the select |
* semantics. |
*/ |
static aid_t getchar_inprog = 0; |
static char lastchar = '\0'; |
/* |
* Do a `read wait': select for reading from stdin, with timeout *tvp. |
* On return, modify *tvp to reflect the amount of time spent waiting. |
* It will be positive only if input appeared before the time ran out; |
* otherwise it will be zero or perhaps negative. |
* |
* If tvp is nil, wait forever, but return if select is interrupted. |
* |
* Return 0 => no input, 1 => can read() from stdin |
* |
*/ |
int |
rwait(struct timeval *tvp) |
{ |
struct timeval starttv, endtv, *s; |
static ipc_call_t charcall; |
ipcarg_t rc; |
/* |
* Someday, select() will do this for us. |
* Just in case that day is now, and no one has |
* changed this, we use a temporary. |
*/ |
if (tvp) { |
(void) gettimeofday(&starttv, NULL); |
endtv = *tvp; |
s = &endtv; |
} else |
s = NULL; |
if (!lastchar) { |
if (!getchar_inprog) |
getchar_inprog = async_send_2(1,CONSOLE_GETCHAR,0,0,&charcall); |
if (!s) |
async_wait_for(getchar_inprog, &rc); |
else if (async_wait_timeout(getchar_inprog, &rc, s->tv_usec) == ETIMEOUT) { |
tvp->tv_sec = 0; |
tvp->tv_usec = 0; |
return (0); |
} |
getchar_inprog = 0; |
if (rc) { |
stop("end of file, help"); |
} |
lastchar = IPC_GET_ARG1(charcall); |
} |
if (tvp) { |
/* since there is input, we may not have timed out */ |
(void) gettimeofday(&endtv, NULL); |
TV_SUB(&endtv, &starttv); |
TV_SUB(tvp, &endtv); /* adjust *tvp by elapsed time */ |
} |
return (1); |
} |
/* |
* `sleep' for the current turn time (using select). |
* Eat any input that might be available. |
*/ |
void |
tsleep(void) |
{ |
struct timeval tv; |
tv.tv_sec = 0; |
tv.tv_usec = fallrate; |
while (TV_POS(&tv)) |
if (rwait(&tv)) { |
lastchar = '\0'; |
} else |
break; |
} |
/* |
* getchar with timeout. |
*/ |
int |
tgetchar(void) |
{ |
static struct timeval timeleft; |
char c; |
/* |
* Reset timeleft to fallrate whenever it is not positive. |
* In any case, wait to see if there is any input. If so, |
* take it, and update timeleft so that the next call to |
* tgetchar() will not wait as long. If there is no input, |
* make timeleft zero or negative, and return -1. |
* |
* Most of the hard work is done by rwait(). |
*/ |
if (!TV_POS(&timeleft)) { |
faster(); /* go faster */ |
timeleft.tv_sec = 0; |
timeleft.tv_usec = fallrate; |
} |
if (!rwait(&timeleft)) |
return (-1); |
c = lastchar; |
lastchar = '\0'; |
return ((int)(unsigned char)c); |
} |
/** @} |
*/ |
/branches/g5/uspace/app/tetris/Makefile |
---|
0,0 → 1,35 |
LIBC_PREFIX = ../../lib/libc |
SOFTINT_PREFIX = ../../lib/softint |
include $(LIBC_PREFIX)/Makefile.toolchain |
LIBS = $(LIBC_PREFIX)/libc.a |
OUTPUT = tetris |
SOURCES = shapes.c scores.c input.c tetris.c screen.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
.PHONY: all clean depend disasm |
all: $(OUTPUT) disasm |
-include Makefile.depend |
depend: |
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend |
$(OUTPUT): $(OBJECTS) $(LIBS) |
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map |
clean: |
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend *.o |
disasm: |
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm |
%.o: %.S |
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@ |
%.o: %.s |
$(AS) $(AFLAGS) $< -o $@ |
%.o: %.c |
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@ |
/branches/g5/uspace/app/tetris/tetris.c |
---|
0,0 → 1,469 |
/* $OpenBSD: tetris.c,v 1.21 2006/04/20 03:24:12 ray Exp $ */ |
/* $NetBSD: tetris.c,v 1.2 1995/04/22 07:42:47 cgd Exp $ */ |
/*- |
* Copyright (c) 1992, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* This code is derived from software contributed to Berkeley by |
* Chris Torek and Darren F. Provine. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)tetris.c 8.1 (Berkeley) 5/31/93 |
*/ |
/** @addtogroup tetris Tetris |
* @brief Tetris ported from OpenBSD |
* @{ |
*/ |
/** @file |
*/ |
#ifndef lint |
static const char copyright[] = |
"@(#) Copyright (c) 1992, 1993\n\ |
The Regents of the University of California. All rights reserved.\n"; |
#endif /* not lint */ |
/* |
* Tetris (or however it is spelled). |
*/ |
#include <sys/time.h> |
#include <sys/types.h> |
#include <err.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <unistd.h> |
#include "input.h" |
#include "scores.h" |
#include "screen.h" |
#include "tetris.h" |
cell board[B_SIZE]; |
int Rows, Cols; |
const struct shape *curshape; |
const struct shape *nextshape; |
long fallrate; |
int score; |
//gid_t gid, egid; |
char key_msg[100]; |
int showpreview, classic; |
static void elide(void); |
static void setup_board(void); |
const struct shape *randshape(void); |
void onintr(int); |
void usage(void); |
/* |
* Set up the initial board. The bottom display row is completely set, |
* along with another (hidden) row underneath that. Also, the left and |
* right edges are set. |
*/ |
static void |
setup_board(void) |
{ |
int i; |
cell *p; |
p = board; |
for (i = B_SIZE; i; i--) |
*p++ = i <= (2 * B_COLS) || (i % B_COLS) < 2; |
} |
/* |
* Elide any full active rows. |
*/ |
static void |
elide(void) |
{ |
int rows = 0; |
int i, j, base; |
cell *p; |
for (i = A_FIRST; i < A_LAST; i++) { |
base = i * B_COLS + 1; |
p = &board[base]; |
for (j = B_COLS - 2; *p++ != 0;) { |
if (--j <= 0) { |
/* this row is to be elided */ |
rows++; |
memset(&board[base], 0, B_COLS - 2); |
scr_update(); |
tsleep(); |
while (--base != 0) |
board[base + B_COLS] = board[base]; |
scr_update(); |
tsleep(); |
break; |
} |
} |
} |
switch (rows) { |
case 1: |
score += 10; |
break; |
case 2: |
score += 30; |
break; |
case 3: |
score += 70; |
break; |
case 4: |
score += 150; |
break; |
default: |
break; |
} |
} |
const struct shape * |
randshape(void) |
{ |
const struct shape *tmp; |
int i, j; |
tmp = &shapes[random() % 7]; |
j = random() % 4; |
for (i = 0; i < j; i++) |
tmp = &shapes[classic? tmp->rotc : tmp->rot]; |
return (tmp); |
} |
static void srandomdev(void) |
{ |
struct timeval tv; |
gettimeofday(&tv, NULL); |
srandom(tv.tv_sec + tv.tv_usec / 100000); |
} |
static void tetris_menu_draw(int level) |
{ |
clear_screen(); |
moveto(5,10); |
puts("Tetris\n\n"); |
moveto(8,10); |
printf("Level = %d (press keys 1 - 9 to change)",level); |
moveto(9,10); |
printf("Preview is %s (press 'p' to change)", (showpreview?"on ":"off")); |
moveto(12,10); |
printf("Press 'h' to show hiscore table."); |
moveto(13,10); |
printf("Press 's' to start game."); |
moveto(14,10); |
printf("Press 'q' to quit game."); |
moveto(20,10); |
printf("In game controls:"); |
moveto(21,0); |
puts(key_msg); |
} |
static int tetris_menu(int *level) |
{ |
static int firstgame = 1; |
int i; |
/* if (showpreview == 0) |
(void)printf("Your score: %d point%s x level %d = %d\n", |
score, score == 1 ? "" : "s", level, score * level); |
else { |
(void)printf("Your score: %d point%s x level %d x preview penalty %0.3f = %d\n", |
score, score == 1 ? "" : "s", level, (double)PRE_PENALTY, |
(int)(score * level * PRE_PENALTY)); |
score = score * PRE_PENALTY; |
} |
savescore(level); |
showscores(level); |
printf("\nHit 's' to new game, 'q' to quit.\n"); |
*/ |
tetris_menu_draw(*level); |
while (1) { |
i = getchar(); |
switch(i) { |
case 'p': |
showpreview = !showpreview; |
moveto(9,21); |
if (showpreview) |
printf("on "); |
else |
printf("off"); |
break; |
case 'h': |
showscores(firstgame); |
tetris_menu_draw(*level); |
break; |
case 's': |
firstgame = 0; |
return 1; |
case 'q': |
return 0; |
case '1': |
case '2': |
case '3': |
case '4': |
case '5': |
case '6': |
case '7': |
case '8': |
case '9': |
*level = i - '0'; |
moveto(8,18); |
printf("%d", *level); |
break; |
} |
} |
} |
int |
main(int argc, char *argv[]) |
{ |
int pos, c; |
char *keys; |
int level = 2; |
char key_write[6][10]; |
int i, j; |
keys = "jkl pq"; |
// gid = getgid(); |
// egid = getegid(); |
// setegid(gid); |
classic = 0; |
showpreview = 1; |
/* while ((ch = getopt(argc, argv, "ck:l:ps")) != -1) */ |
/* switch(ch) { */ |
/* case 'c': */ |
/* /\* */ |
/* * this means: */ |
/* * - rotate the other way; */ |
/* * - no reverse video. */ |
/* *\/ */ |
/* classic = 1; */ |
/* break; */ |
/* case 'k': */ |
/* if (strlen(keys = optarg) != 6) */ |
/* usage(); */ |
/* break; */ |
/* case 'l': */ |
/* level = (int)strtonum(optarg, MINLEVEL, MAXLEVEL, */ |
/* &errstr); */ |
/* if (errstr) */ |
/* errx(1, "level must be from %d to %d", */ |
/* MINLEVEL, MAXLEVEL); */ |
/* break; */ |
/* case 'p': */ |
/* showpreview = 1; */ |
/* break; */ |
/* case 's': */ |
/* showscores(0); */ |
/* exit(0); */ |
/* default: */ |
/* usage(); */ |
/* } */ |
/* argc -= optind; */ |
/* argv += optind; */ |
/* if (argc) */ |
/* usage(); */ |
for (i = 0; i <= 5; i++) { |
for (j = i+1; j <= 5; j++) { |
if (keys[i] == keys[j]) |
errx(1, "duplicate command keys specified."); |
} |
if (keys[i] == ' ') |
strncpy(key_write[i], "<space>", sizeof key_write[i]); |
else { |
key_write[i][0] = keys[i]; |
key_write[i][1] = '\0'; |
} |
} |
snprintf(key_msg, sizeof key_msg, |
"%s - left %s - rotate %s - right %s - drop %s - pause %s - quit", |
key_write[0], key_write[1], key_write[2], key_write[3], |
key_write[4], key_write[5]); |
scr_init(); |
initscores(); |
while (tetris_menu(&level)) { |
fallrate = 1000000 / level; |
scr_clear(); |
setup_board(); |
srandomdev(); |
scr_set(); |
pos = A_FIRST*B_COLS + (B_COLS/2)-1; |
nextshape = randshape(); |
curshape = randshape(); |
scr_msg(key_msg, 1); |
for (;;) { |
place(curshape, pos, 1); |
scr_update(); |
place(curshape, pos, 0); |
c = tgetchar(); |
if (c < 0) { |
/* |
* Timeout. Move down if possible. |
*/ |
if (fits_in(curshape, pos + B_COLS)) { |
pos += B_COLS; |
continue; |
} |
/* |
* Put up the current shape `permanently', |
* bump score, and elide any full rows. |
*/ |
place(curshape, pos, 1); |
score++; |
elide(); |
/* |
* Choose a new shape. If it does not fit, |
* the game is over. |
*/ |
curshape = nextshape; |
nextshape = randshape(); |
pos = A_FIRST*B_COLS + (B_COLS/2)-1; |
if (!fits_in(curshape, pos)) |
break; |
continue; |
} |
/* |
* Handle command keys. |
*/ |
if (c == keys[5]) { |
/* quit */ |
break; |
} |
if (c == keys[4]) { |
static char msg[] = |
"paused - press RETURN to continue"; |
place(curshape, pos, 1); |
do { |
scr_update(); |
scr_msg(key_msg, 0); |
scr_msg(msg, 1); |
// (void) fflush(stdout); |
} while (rwait((struct timeval *)NULL) == -1); |
scr_msg(msg, 0); |
scr_msg(key_msg, 1); |
place(curshape, pos, 0); |
continue; |
} |
if (c == keys[0]) { |
/* move left */ |
if (fits_in(curshape, pos - 1)) |
pos--; |
continue; |
} |
if (c == keys[1]) { |
/* turn */ |
const struct shape *new = &shapes[ |
classic? curshape->rotc : curshape->rot]; |
if (fits_in(new, pos)) |
curshape = new; |
continue; |
} |
if (c == keys[2]) { |
/* move right */ |
if (fits_in(curshape, pos + 1)) |
pos++; |
continue; |
} |
if (c == keys[3]) { |
/* move to bottom */ |
while (fits_in(curshape, pos + B_COLS)) { |
pos += B_COLS; |
score++; |
} |
continue; |
} |
if (c == '\f') { |
scr_clear(); |
scr_msg(key_msg, 1); |
} |
} |
scr_clear(); |
insertscore(score, level); |
score=0; |
} |
scr_clear(); |
printf("\n\n\n\t\tGame over.\n"); |
/* |
while ((i = getchar()) != '\n') |
if (i == EOF) |
break |
*/ |
scr_end(); |
return 0; |
} |
/* void */ |
/* onintr(int signo) */ |
/* { */ |
/* scr_clear(); /\* XXX signal race *\/ */ |
/* scr_end(); /\* XXX signal race *\/ */ |
/* _exit(0); */ |
/* } */ |
void |
usage(void) |
{ |
(void)fprintf(stderr, "usage: tetris [-ps] [-k keys] [-l level]\n"); |
exit(1); |
} |
/** @} |
*/ |
/branches/g5/uspace/app/tetris/scores.c |
---|
0,0 → 1,543 |
/* $OpenBSD: scores.c,v 1.11 2006/04/20 03:25:36 ray Exp $ */ |
/* $NetBSD: scores.c,v 1.2 1995/04/22 07:42:38 cgd Exp $ */ |
/*- |
* Copyright (c) 1992, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* This code is derived from software contributed to Berkeley by |
* Chris Torek and Darren F. Provine. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)scores.c 8.1 (Berkeley) 5/31/93 |
*/ |
/** @addtogroup tetris |
* @{ |
*/ |
/** @file |
*/ |
/* |
* Score code for Tetris, by Darren Provine (kilroy@gboro.glassboro.edu) |
* modified 22 January 1992, to limit the number of entries any one |
* person has. |
* |
* Major whacks since then. |
*/ |
#include <errno.h> |
/* #include <err.h> */ |
/* #include <fcntl.h> */ |
/* #include <pwd.h> */ |
#include <stdio.h> |
/* #include <stdlib.h> */ |
#include <string.h> |
/* #include <time.h> */ |
/* #include <term.h> */ |
/* #include <unistd.h> */ |
/* #include <sys/param.h> */ |
/* #include <sys/stat.h> */ |
/* #include <sys/types.h> */ |
#include "pathnames.h" |
#include "screen.h" |
#include "tetris.h" |
#include "scores.h" |
/* |
* Within this code, we can hang onto one extra "high score", leaving |
* room for our current score (whether or not it is high). |
* |
* We also sometimes keep tabs on the "highest" score on each level. |
* As long as the scores are kept sorted, this is simply the first one at |
* that level. |
*/ |
#define NUMSPOTS (MAXHISCORES + 1) |
#define NLEVELS (MAXLEVEL + 1) |
/* static time_t now; */ |
/* static int nscores; */ |
/* static int gotscores; */ |
/* static struct highscore scores[NUMSPOTS]; */ |
static struct highscore scores[NUMSPOTS]; |
/* static int checkscores(struct highscore *, int); */ |
/* static int cmpscores(const void *, const void *); */ |
/* static void getscores(FILE **); */ |
/* static void printem(int, int, struct highscore *, int, const char *); */ |
/* static char *thisuser(void); */ |
void showscores(int firstgame) |
{ |
int i; |
clear_screen(); |
moveto(10, 0); |
printf("\tRank \tLevel \tName\t points\n"); |
printf("\t========================================================\n"); |
for (i = 0; i < NUMSPOTS - 1; i++) { |
printf("\t%6d %6d %-16s %20d\n", i+1, scores[i].hs_level, scores[i].hs_name, scores[i].hs_score); |
} |
if (!firstgame) { |
printf("\t========================================================\n"); |
printf("\t Last %6d %-16s %20d\n", scores[NUMSPOTS - 1].hs_level, scores[NUMSPOTS - 1].hs_name, scores[NUMSPOTS - 1].hs_score); |
} |
printf("\n\n\n\n\tPress any key to return to main menu."); |
getchar(); |
} |
/** Copy from hiscore table score with index src to dest |
* |
*/ |
static void copyhiscore(int dest, int src) |
{ |
strcpy(scores[dest].hs_name, scores[src].hs_name); |
scores[dest].hs_score = scores[src].hs_score; |
scores[dest].hs_level = scores[src].hs_level; |
} |
void insertscore(int score, int level) |
{ |
int i,j; |
int key; |
clear_screen(); |
moveto(10 , 10); |
puts("Insert your name: "); |
strncpy(scores[NUMSPOTS - 1].hs_name, "Player", MAXLOGNAME); |
i = 6; |
moveto(10 , 28); |
printf("%s%.*s",scores[NUMSPOTS - 1].hs_name,MAXLOGNAME-i,"........................................"); |
key = getchar(); |
while(key != '\n') { |
if (key == '\b') { |
if (i > 0) |
scores[NUMSPOTS - 1].hs_name[--i] = '\0'; |
} else { |
if (i < (MAXLOGNAME - 1)) |
scores[NUMSPOTS - 1].hs_name[i++] = key; |
scores[NUMSPOTS - 1].hs_name[i] = '\0'; |
} |
moveto(10 , 28); |
printf("%s%.*s",scores[NUMSPOTS - 1].hs_name,MAXLOGNAME-i,"........................................"); |
key = getchar(); |
} |
scores[NUMSPOTS - 1].hs_score = score; |
scores[NUMSPOTS - 1].hs_level = level; |
i = NUMSPOTS-1; |
while ((i > 0) && (scores[i - 1].hs_score < score)) |
i--; |
for (j = NUMSPOTS - 2; j > i; j--) { |
copyhiscore(j,j-1); |
} |
copyhiscore(i, NUMSPOTS - 1); |
} |
void initscores(void) |
{ |
int i; |
for(i = 0; i < NUMSPOTS; i++) { |
strncpy(scores[i].hs_name, "HelenOS Team", MAXLOGNAME); |
scores[i].hs_score = (NUMSPOTS - i) * 200; |
scores[i].hs_level = (i + 1 > MAXLEVEL?MAXLEVEL:i + 1); |
} |
} |
/* |
* Read the score file. Can be called from savescore (before showscores) |
* or showscores (if savescore will not be called). If the given pointer |
* is not NULL, sets *fpp to an open file pointer that corresponds to a |
* read/write score file that is locked with LOCK_EX. Otherwise, the |
* file is locked with LOCK_SH for the read and closed before return. |
* |
* Note, we assume closing the stdio file releases the lock. |
*/ |
/* static void */ |
/* getscores(FILE **fpp) */ |
/* { */ |
/* int sd, mint, lck, mask, i; */ |
/* char *mstr, *human; */ |
/* FILE *sf; */ |
/* if (fpp != NULL) { */ |
/* mint = O_RDWR | O_CREAT; */ |
/* mstr = "r+"; */ |
/* human = "read/write"; */ |
/* lck = LOCK_EX; */ |
/* } else { */ |
/* mint = O_RDONLY; */ |
/* mstr = "r"; */ |
/* human = "reading"; */ |
/* lck = LOCK_SH; */ |
/* } */ |
/* setegid(egid); */ |
/* mask = umask(S_IWOTH); */ |
/* sd = open(_PATH_SCOREFILE, mint, 0666); */ |
/* (void)umask(mask); */ |
/* setegid(gid); */ |
/* if (sd < 0) { */ |
/* if (fpp == NULL) { */ |
/* nscores = 0; */ |
/* return; */ |
/* } */ |
/* err(1, "cannot open %s for %s", _PATH_SCOREFILE, human); */ |
/* } */ |
/* setegid(egid); */ |
/* if ((sf = fdopen(sd, mstr)) == NULL) */ |
/* err(1, "cannot fdopen %s for %s", _PATH_SCOREFILE, human); */ |
/* setegid(gid); */ |
/* /\* */ |
/* * Grab a lock. */ |
/* *\/ */ |
/* if (flock(sd, lck)) */ |
/* warn("warning: score file %s cannot be locked", */ |
/* _PATH_SCOREFILE); */ |
/* nscores = fread(scores, sizeof(scores[0]), MAXHISCORES, sf); */ |
/* if (ferror(sf)) */ |
/* err(1, "error reading %s", _PATH_SCOREFILE); */ |
/* for (i = 0; i < nscores; i++) */ |
/* if (scores[i].hs_level < MINLEVEL || */ |
/* scores[i].hs_level > MAXLEVEL) */ |
/* errx(1, "scorefile %s corrupt", _PATH_SCOREFILE); */ |
/* if (fpp) */ |
/* *fpp = sf; */ |
/* else */ |
/* (void)fclose(sf); */ |
/* } */ |
void |
savescore(int level) |
{ |
return; |
} |
/* struct highscore *sp; */ |
/* int i; */ |
/* int change; */ |
/* FILE *sf; */ |
/* const char *me; */ |
/* getscores(&sf); */ |
/* gotscores = 1; */ |
/* (void)time(&now); */ |
/* /\* */ |
/* * Allow at most one score per person per level -- see if we */ |
/* * can replace an existing score, or (easiest) do nothing. */ |
/* * Otherwise add new score at end (there is always room). */ |
/* *\/ */ |
/* change = 0; */ |
/* me = thisuser(); */ |
/* for (i = 0, sp = &scores[0]; i < nscores; i++, sp++) { */ |
/* if (sp->hs_level != level || strcmp(sp->hs_name, me) != 0) */ |
/* continue; */ |
/* if (score > sp->hs_score) { */ |
/* (void)printf("%s bettered %s %d score of %d!\n", */ |
/* "\nYou", "your old level", level, */ |
/* sp->hs_score * sp->hs_level); */ |
/* sp->hs_score = score; /\* new score *\/ */ |
/* sp->hs_time = now; /\* and time *\/ */ |
/* change = 1; */ |
/* } else if (score == sp->hs_score) { */ |
/* (void)printf("%s tied %s %d high score.\n", */ |
/* "\nYou", "your old level", level); */ |
/* sp->hs_time = now; /\* renew it *\/ */ |
/* change = 1; /\* gotta rewrite, sigh *\/ */ |
/* } /\* else new score < old score: do nothing *\/ */ |
/* break; */ |
/* } */ |
/* if (i >= nscores) { */ |
/* strlcpy(sp->hs_name, me, sizeof sp->hs_name); */ |
/* sp->hs_level = level; */ |
/* sp->hs_score = score; */ |
/* sp->hs_time = now; */ |
/* nscores++; */ |
/* change = 1; */ |
/* } */ |
/* if (change) { */ |
/* /\* */ |
/* * Sort & clean the scores, then rewrite. */ |
/* *\/ */ |
/* nscores = checkscores(scores, nscores); */ |
/* rewind(sf); */ |
/* if (fwrite(scores, sizeof(*sp), nscores, sf) != nscores || */ |
/* fflush(sf) == EOF) */ |
/* warnx("error writing %s: %s\n\t-- %s", */ |
/* _PATH_SCOREFILE, strerror(errno), */ |
/* "high scores may be damaged"); */ |
/* } */ |
/* (void)fclose(sf); /\* releases lock *\/ */ |
/* } */ |
/* |
* Get login name, or if that fails, get something suitable. |
* The result is always trimmed to fit in a score. |
*/ |
/* static char * */ |
/* thisuser(void) */ |
/* { */ |
/* const char *p; */ |
/* struct passwd *pw; */ |
/* static char u[sizeof(scores[0].hs_name)]; */ |
/* if (u[0]) */ |
/* return (u); */ |
/* p = getlogin(); */ |
/* if (p == NULL || *p == '\0') { */ |
/* pw = getpwuid(getuid()); */ |
/* if (pw != NULL) */ |
/* p = pw->pw_name; */ |
/* else */ |
/* p = " ???"; */ |
/* } */ |
/* strlcpy(u, p, sizeof(u)); */ |
/* return (u); */ |
/* } */ |
/* |
* Score comparison function for qsort. |
* |
* If two scores are equal, the person who had the score first is |
* listed first in the highscore file. |
*/ |
/* static int */ |
/* cmpscores(const void *x, const void *y) */ |
/* { */ |
/* const struct highscore *a, *b; */ |
/* long l; */ |
/* a = x; */ |
/* b = y; */ |
/* l = (long)b->hs_level * b->hs_score - (long)a->hs_level * a->hs_score; */ |
/* if (l < 0) */ |
/* return (-1); */ |
/* if (l > 0) */ |
/* return (1); */ |
/* if (a->hs_time < b->hs_time) */ |
/* return (-1); */ |
/* if (a->hs_time > b->hs_time) */ |
/* return (1); */ |
/* return (0); */ |
/* } */ |
/* |
* If we've added a score to the file, we need to check the file and ensure |
* that this player has only a few entries. The number of entries is |
* controlled by MAXSCORES, and is to ensure that the highscore file is not |
* monopolised by just a few people. People who no longer have accounts are |
* only allowed the highest score. Scores older than EXPIRATION seconds are |
* removed, unless they are someone's personal best. |
* Caveat: the highest score on each level is always kept. |
*/ |
/* static int */ |
/* checkscores(struct highscore *hs, int num) */ |
/* { */ |
/* struct highscore *sp; */ |
/* int i, j, k, numnames; */ |
/* int levelfound[NLEVELS]; */ |
/* struct peruser { */ |
/* char *name; */ |
/* int times; */ |
/* } count[NUMSPOTS]; */ |
/* struct peruser *pu; */ |
/* /\* */ |
/* * Sort so that highest totals come first. */ |
/* * */ |
/* * levelfound[i] becomes set when the first high score for that */ |
/* * level is encountered. By definition this is the highest score. */ |
/* *\/ */ |
/* qsort((void *)hs, nscores, sizeof(*hs), cmpscores); */ |
/* for (i = MINLEVEL; i < NLEVELS; i++) */ |
/* levelfound[i] = 0; */ |
/* numnames = 0; */ |
/* for (i = 0, sp = hs; i < num;) { */ |
/* /\* */ |
/* * This is O(n^2), but do you think we care? */ |
/* *\/ */ |
/* for (j = 0, pu = count; j < numnames; j++, pu++) */ |
/* if (strcmp(sp->hs_name, pu->name) == 0) */ |
/* break; */ |
/* if (j == numnames) { */ |
/* /\* */ |
/* * Add new user, set per-user count to 1. */ |
/* *\/ */ |
/* pu->name = sp->hs_name; */ |
/* pu->times = 1; */ |
/* numnames++; */ |
/* } else { */ |
/* /\* */ |
/* * Two ways to keep this score: */ |
/* * - Not too many (per user), still has acct, & */ |
/* * score not dated; or */ |
/* * - High score on this level. */ |
/* *\/ */ |
/* if ((pu->times < MAXSCORES && */ |
/* getpwnam(sp->hs_name) != NULL && */ |
/* sp->hs_time + EXPIRATION >= now) || */ |
/* levelfound[sp->hs_level] == 0) */ |
/* pu->times++; */ |
/* else { */ |
/* /\* */ |
/* * Delete this score, do not count it, */ |
/* * do not pass go, do not collect $200. */ |
/* *\/ */ |
/* num--; */ |
/* for (k = i; k < num; k++) */ |
/* hs[k] = hs[k + 1]; */ |
/* continue; */ |
/* } */ |
/* } */ |
/* levelfound[sp->hs_level] = 1; */ |
/* i++, sp++; */ |
/* } */ |
/* return (num > MAXHISCORES ? MAXHISCORES : num); */ |
/* } */ |
/* |
* Show current scores. This must be called after savescore, if |
* savescore is called at all, for two reasons: |
* - Showscores munches the time field. |
* - Even if that were not the case, a new score must be recorded |
* before it can be shown anyway. |
*/ |
/* |
void |
showscores(int level) |
{ |
return; |
} |
*/ |
/* struct highscore *sp; */ |
/* int i, n, c; */ |
/* const char *me; */ |
/* int levelfound[NLEVELS]; */ |
/* if (!gotscores) */ |
/* getscores((FILE **)NULL); */ |
/* (void)printf("\n\t\t Tetris High Scores\n"); */ |
/* /\* */ |
/* * If level == 0, the person has not played a game but just asked for */ |
/* * the high scores; we do not need to check for printing in highlight */ |
/* * mode. If SOstr is null, we can't do highlighting anyway. */ |
/* *\/ */ |
/* me = level && SOstr ? thisuser() : NULL; */ |
/* /\* */ |
/* * Set times to 0 except for high score on each level. */ |
/* *\/ */ |
/* for (i = MINLEVEL; i < NLEVELS; i++) */ |
/* levelfound[i] = 0; */ |
/* for (i = 0, sp = scores; i < nscores; i++, sp++) { */ |
/* if (levelfound[sp->hs_level]) */ |
/* sp->hs_time = 0; */ |
/* else { */ |
/* sp->hs_time = 1; */ |
/* levelfound[sp->hs_level] = 1; */ |
/* } */ |
/* } */ |
/* /\* */ |
/* * Page each screenful of scores. */ |
/* *\/ */ |
/* for (i = 0, sp = scores; i < nscores; sp += n) { */ |
/* n = 20; */ |
/* if (i + n > nscores) */ |
/* n = nscores - i; */ |
/* printem(level, i + 1, sp, n, me); */ |
/* if ((i += n) < nscores) { */ |
/* (void)printf("\nHit RETURN to continue."); */ |
/* (void)fflush(stdout); */ |
/* while ((c = getchar()) != '\n') */ |
/* if (c == EOF) */ |
/* break; */ |
/* (void)printf("\n"); */ |
/* } */ |
/* } */ |
/* if (nscores == 0) */ |
/* printf("\t\t\t - none to date.\n"); */ |
/* } */ |
/* static void */ |
/* printem(int level, int offset, struct highscore *hs, int n, const char *me) */ |
/* { */ |
/* struct highscore *sp; */ |
/* int row, highlight, i; */ |
/* char buf[100]; */ |
/* #define TITLE "Rank Score Name (points/level)" */ |
/* #define TITL2 "==========================================================" */ |
/* printf("%s\n%s\n", TITLE, TITL2); */ |
/* highlight = 0; */ |
/* for (row = 0; row < n; row++) { */ |
/* sp = &hs[row]; */ |
/* (void)snprintf(buf, sizeof(buf), */ |
/* "%3d%c %6d %-31s (%6d on %d)\n", */ |
/* row + offset, sp->hs_time ? '*' : ' ', */ |
/* sp->hs_score * sp->hs_level, */ |
/* sp->hs_name, sp->hs_score, sp->hs_level); */ |
/* /\* Print leaders every three lines *\/ */ |
/* if ((row + 1) % 3 == 0) { */ |
/* for (i = 0; i < sizeof(buf); i++) */ |
/* if (buf[i] == ' ') */ |
/* buf[i] = '_'; */ |
/* } */ |
/* /\* */ |
/* * Highlight if appropriate. This works because */ |
/* * we only get one score per level. */ |
/* *\/ */ |
/* if (me != NULL && */ |
/* sp->hs_level == level && */ |
/* sp->hs_score == score && */ |
/* strcmp(sp->hs_name, me) == 0) { */ |
/* putpad(SOstr); */ |
/* highlight = 1; */ |
/* } */ |
/* (void)printf("%s", buf); */ |
/* if (highlight) { */ |
/* putpad(SEstr); */ |
/* highlight = 0; */ |
/* } */ |
/* } */ |
/* } */ |
/** @} |
*/ |
/branches/g5/uspace/app/tetris/tetris.h |
---|
0,0 → 1,188 |
/* $OpenBSD: tetris.h,v 1.9 2003/06/03 03:01:41 millert Exp $ */ |
/* $NetBSD: tetris.h,v 1.2 1995/04/22 07:42:48 cgd Exp $ */ |
/*- |
* Copyright (c) 1992, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* This code is derived from software contributed to Berkeley by |
* Chris Torek and Darren F. Provine. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)tetris.h 8.1 (Berkeley) 5/31/93 |
*/ |
/** @addtogroup tetris |
* @{ |
*/ |
/** @file |
*/ |
/* |
* Definitions for Tetris. |
*/ |
/* |
* The display (`board') is composed of 23 rows of 12 columns of characters |
* (numbered 0..22 and 0..11), stored in a single array for convenience. |
* Columns 1 to 10 of rows 1 to 20 are the actual playing area, where |
* shapes appear. Columns 0 and 11 are always occupied, as are all |
* columns of rows 21 and 22. Rows 0 and 22 exist as boundary areas |
* so that regions `outside' the visible area can be examined without |
* worrying about addressing problems. |
*/ |
/* the board */ |
#define B_COLS 12 |
#define B_ROWS 23 |
#define B_SIZE (B_ROWS * B_COLS) |
typedef unsigned char cell; |
extern cell board[B_SIZE]; /* 1 => occupied, 0 => empty */ |
/* the displayed area (rows) */ |
#define D_FIRST 1 |
#define D_LAST 22 |
/* the active area (rows) */ |
#define A_FIRST 1 |
#define A_LAST 21 |
/* |
* Minimum display size. |
*/ |
#define MINROWS 23 |
#define MINCOLS 40 |
extern int Rows, Cols; /* current screen size */ |
/* |
* Translations from board coordinates to display coordinates. |
* As with board coordinates, display coordiates are zero origin. |
*/ |
#define RTOD(x) ((x) - 1) |
#define CTOD(x) ((x) * 2 + (((Cols - 2 * B_COLS) >> 1) - 1)) |
/* |
* A `shape' is the fundamental thing that makes up the game. There |
* are 7 basic shapes, each consisting of four `blots': |
* |
* X.X X.X X.X |
* X.X X.X X.X.X X.X X.X.X X.X.X X.X.X.X |
* X X X |
* |
* 0 1 2 3 4 5 6 |
* |
* Except for 3 and 6, the center of each shape is one of the blots. |
* This blot is designated (0,0). The other three blots can then be |
* described as offsets from the center. Shape 3 is the same under |
* rotation, so its center is effectively irrelevant; it has been chosen |
* so that it `sticks out' upward and leftward. Except for shape 6, |
* all the blots are contained in a box going from (-1,-1) to (+1,+1); |
* shape 6's center `wobbles' as it rotates, so that while it `sticks out' |
* rightward, its rotation---a vertical line---`sticks out' downward. |
* The containment box has to include the offset (2,0), making the overall |
* containment box range from offset (-1,-1) to (+2,+1). (This is why |
* there is only one row above, but two rows below, the display area.) |
* |
* The game works by choosing one of these shapes at random and putting |
* its center at the middle of the first display row (row 1, column 5). |
* The shape is moved steadily downward until it collides with something: |
* either another shape, or the bottom of the board. When the shape can |
* no longer be moved downwards, it is merged into the current board. |
* At this time, any completely filled rows are elided, and blots above |
* these rows move down to make more room. A new random shape is again |
* introduced at the top of the board, and the whole process repeats. |
* The game ends when the new shape will not fit at (1,5). |
* |
* While the shapes are falling, the user can rotate them counterclockwise |
* 90 degrees (in addition to moving them left or right), provided that the |
* rotation puts the blots in empty spaces. The table of shapes is set up |
* so that each shape contains the index of the new shape obtained by |
* rotating the current shape. Due to symmetry, each shape has exactly |
* 1, 2, or 4 rotations total; the first 7 entries in the table represent |
* the primary shapes, and the remaining 12 represent their various |
* rotated forms. |
*/ |
struct shape { |
int rot; /* index of rotated version of this shape */ |
int rotc; /* -- " -- in classic version */ |
int off[3]; /* offsets to other blots if center is at (0,0) */ |
}; |
extern const struct shape shapes[]; |
extern const struct shape *curshape; |
extern const struct shape *nextshape; |
/* |
* Shapes fall at a rate faster than once per second. |
* |
* The initial rate is determined by dividing 1 million microseconds |
* by the game `level'. (This is at most 1 million, or one second.) |
* Each time the fall-rate is used, it is decreased a little bit, |
* depending on its current value, via the `faster' macro below. |
* The value eventually reaches a limit, and things stop going faster, |
* but by then the game is utterly impossible. |
*/ |
extern long fallrate; /* less than 1 million; smaller => faster */ |
#define faster() (fallrate -= fallrate / 3000) |
/* |
* Game level must be between 1 and 9. This controls the initial fall rate |
* and affects scoring. |
*/ |
#define MINLEVEL 1 |
#define MAXLEVEL 9 |
/* |
* Scoring is as follows: |
* |
* When the shape comes to rest, and is integrated into the board, |
* we score one point. If the shape is high up (at a low-numbered row), |
* and the user hits the space bar, the shape plummets all the way down, |
* and we score a point for each row it falls (plus one more as soon as |
* we find that it is at rest and integrate it---until then, it can |
* still be moved or rotated). |
* |
* If previewing has been turned on, the score is multiplied by PRE_PENALTY. |
*/ |
#define PRE_PENALTY 0.75 |
extern int score; /* the obvious thing */ |
//extern gid_t gid, egid; |
extern char key_msg[100]; |
extern int showpreview; |
extern int classic; |
int fits_in(const struct shape *, int); |
void place(const struct shape *, int, int); |
void stop(char *); |
/** @} |
*/ |
/branches/g5/uspace/app/tetris/scores.h |
---|
0,0 → 1,67 |
/* $OpenBSD: scores.h,v 1.5 2003/06/03 03:01:41 millert Exp $ */ |
/* $NetBSD: scores.h,v 1.2 1995/04/22 07:42:40 cgd Exp $ */ |
/*- |
* Copyright (c) 1992, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* This code is derived from software contributed to Berkeley by |
* Chris Torek and Darren F. Provine. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)scores.h 8.1 (Berkeley) 5/31/93 |
*/ |
/** @addtogroup tetris |
* @{ |
*/ |
/** @file |
*/ |
/* |
* Tetris scores. |
*/ |
#include <sys/time.h> |
#define MAXLOGNAME 16 |
struct highscore { |
char hs_name[MAXLOGNAME + 1]; /* login name */ |
int hs_score; /* raw score */ |
int hs_level; /* play level */ |
// time_t hs_time; /* time at game end */ |
}; |
#define MAXHISCORES 10 |
//#define MAXSCORES 9 /* maximum high score entries per person */ |
//#define EXPIRATION (5L * 365 * 24 * 60 * 60) |
void savescore(int); |
void showscores(int); |
void insertscore(int score, int level); |
void initscores(void); |
/** @} |
*/ |
/branches/g5/uspace/app/tetris/shapes.c |
---|
0,0 → 1,116 |
/* $OpenBSD: shapes.c,v 1.8 2004/07/10 07:26:24 deraadt Exp $ */ |
/* $NetBSD: shapes.c,v 1.2 1995/04/22 07:42:44 cgd Exp $ */ |
/*- |
* Copyright (c) 1992, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* This code is derived from software contributed to Berkeley by |
* Chris Torek and Darren F. Provine. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)shapes.c 8.1 (Berkeley) 5/31/93 |
*/ |
/** @addtogroup tetris |
* @{ |
*/ |
/** @file |
*/ |
/* |
* Tetris shapes and related routines. |
* |
* Note that the first 7 are `well known'. |
*/ |
#include <unistd.h> |
#include "tetris.h" |
#define TL -B_COLS-1 /* top left */ |
#define TC -B_COLS /* top center */ |
#define TR -B_COLS+1 /* top right */ |
#define ML -1 /* middle left */ |
#define MR 1 /* middle right */ |
#define BL B_COLS-1 /* bottom left */ |
#define BC B_COLS /* bottom center */ |
#define BR B_COLS+1 /* bottom right */ |
const struct shape shapes[] = { |
/* 0*/ { 7, 7, { TL, TC, MR } }, |
/* 1*/ { 8, 8, { TC, TR, ML } }, |
/* 2*/ { 9, 11, { ML, MR, BC } }, |
/* 3*/ { 3, 3, { TL, TC, ML } }, |
/* 4*/ { 12, 14, { ML, BL, MR } }, |
/* 5*/ { 15, 17, { ML, BR, MR } }, |
/* 6*/ { 18, 18, { ML, MR, 2 } }, /* sticks out */ |
/* 7*/ { 0, 0, { TC, ML, BL } }, |
/* 8*/ { 1, 1, { TC, MR, BR } }, |
/* 9*/ { 10, 2, { TC, MR, BC } }, |
/*10*/ { 11, 9, { TC, ML, MR } }, |
/*11*/ { 2, 10, { TC, ML, BC } }, |
/*12*/ { 13, 4, { TC, BC, BR } }, |
/*13*/ { 14, 12, { TR, ML, MR } }, |
/*14*/ { 4, 13, { TL, TC, BC } }, |
/*15*/ { 16, 5, { TR, TC, BC } }, |
/*16*/ { 17, 15, { TL, MR, ML } }, |
/*17*/ { 5, 16, { TC, BC, BL } }, |
/*18*/ { 6, 6, { TC, BC, 2*B_COLS } }/* sticks out */ |
}; |
/* |
* Return true iff the given shape fits in the given position, |
* taking the current board into account. |
*/ |
int |
fits_in(const struct shape *shape, int pos) |
{ |
int *o = shape->off; |
if (board[pos] || board[pos + *o++] || board[pos + *o++] || |
board[pos + *o]) |
return 0; |
return 1; |
} |
/* |
* Write the given shape into the current board, turning it on |
* if `onoff' is 1, and off if `onoff' is 0. |
*/ |
void |
place(const struct shape *shape, int pos, int onoff) |
{ |
int *o = shape->off; |
board[pos] = onoff; |
board[pos + *o++] = onoff; |
board[pos + *o++] = onoff; |
board[pos + *o] = onoff; |
} |
/** @} |
*/ |
/branches/g5/uspace/app/tetris/input.h |
---|
0,0 → 1,50 |
/* $OpenBSD: input.h,v 1.5 2003/06/03 03:01:41 millert Exp $ */ |
/* $NetBSD: input.h,v 1.2 1995/04/22 07:42:36 cgd Exp $ */ |
/*- |
* Copyright (c) 1992, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* This code is derived from software contributed to Berkeley by |
* Chris Torek and Darren F. Provine. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)input.h 8.1 (Berkeley) 5/31/93 |
*/ |
/** @addtogroup tetris |
* @{ |
*/ |
/** @file |
*/ |
int rwait(struct timeval *); |
int tgetchar(void); |
void tsleep(void); |
/** @} |
*/ |
/branches/g5/uspace/app/tetris/screen.h |
---|
0,0 → 1,71 |
/* $OpenBSD: screen.h,v 1.5 2003/06/03 03:01:41 millert Exp $ */ |
/* $NetBSD: screen.h,v 1.2 1995/04/22 07:42:42 cgd Exp $ */ |
/*- |
* Copyright (c) 1992, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* This code is derived from software contributed to Berkeley by |
* Chris Torek and Darren F. Provine. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)screen.h 8.1 (Berkeley) 5/31/93 |
*/ |
/** @addtogroup tetris |
* @{ |
*/ |
/** @file |
*/ |
/* |
* putpad() is for padded strings with count=1. |
*/ |
#define putpad(s) tputs(s, 1, put) |
#include <async.h> |
typedef struct { |
ipcarg_t ws_row; |
ipcarg_t ws_col; |
} winsize_t; |
extern winsize_t winsize; |
void moveto(int r, int c); |
void clear_screen(void); |
int put(int); /* just calls putchar; for tputs */ |
void scr_clear(void); |
void scr_end(void); |
void scr_init(void); |
void scr_msg(char *, int); |
void scr_set(void); |
void scr_update(void); |
/** @} |
*/ |
/branches/g5/uspace/app/tetris/pathnames.h |
---|
0,0 → 1,49 |
/* $OpenBSD: pathnames.h,v 1.3 2003/06/03 03:01:41 millert Exp $ */ |
/* $NetBSD: pathnames.h,v 1.2 1995/04/22 07:42:37 cgd Exp $ */ |
/*- |
* Copyright (c) 1992, 1993 |
* The Regents of the University of California. All rights reserved. |
* |
* This code is derived from software contributed to Berkeley by |
* Chris Torek and Darren F. Provine. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)pathnames.h 8.1 (Berkeley) 5/31/93 |
*/ |
/** @addtogroup tetris |
* @{ |
*/ |
/** @file |
*/ |
#define _PATH_SCOREFILE "/var/games/tetris.scores" |
/** @} |
*/ |