|
|
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: 9581 (0x256d)
Types: TextFile
Names: »suntetris.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/Sun/Suntetris/suntetris.c«
#ifndef lint
static char sccsid[] = "@(#)suntetris.c 1.17 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"
static short icon_image[] = {
#include "suntetris.icon"
};
DEFINE_ICON_FROM_IMAGE (tetris_icon, icon_image);
Canvas canvas;
static int my_client_object;
static int *me = &my_client_object;
static int paused = 0, selht = 0, height = 0;
static int level, lines, score, make_new_fig;
static int current_color, current_fig, current_rot, current_x, current_y;
static struct itimerval timer;
void init_pw (), draw_board (), rand_blocks (), draw_figure (), draw_score ();
void close_board (), display_choices (), display_hs (), update_hs ();
void select_level (), select_height ();
void mark_board ();
int safe_move ();
static Notify_value figure_dropper ();
static void new_figure (), place_figure ();
static void game_setup (), start_game (), game_over (), drop_down ();
static void start_timer (), stop_timer ();
static void game_control_proc (), choose_level ();
static void choose_height (), wait_for_return ();
/*
4 canvas input event routines
1) choose_level ()
player chooses level to start at
2) choose_height ()
player chooses height to start at
3) game_control_proc ()
game controls (move blocks around etc.)
4) wait_for_return ()
game waits for player to hit return while displaying highscores
*/
main (argc, argv)
int argc;
char **argv;
{
Frame frame;
frame = window_create (0, FRAME,
FRAME_LABEL, argv[0],
FRAME_ICON, &tetris_icon,
0);
canvas = window_create (frame, CANVAS,
CANVAS_RETAINED, FALSE,
WIN_WIDTH, 400,
WIN_HEIGHT, 400,
WIN_CONSUME_PICK_EVENT, WIN_IN_TRANSIT_EVENTS,
WIN_CONSUME_KBD_EVENTS, WIN_ASCII_EVENTS, WIN_RIGHT_KEYS, 0,
0);
window_fit (frame);
init_pw (argc > 1); /* force b&w operation if any arguments exist */
window_set (canvas, CANVAS_RETAINED, TRUE, 0);
srandom (getpid ());
game_setup ();
window_main_loop (frame);
}
/* figure_dropper does the periodic downward moving of the figures */
static Notify_value
figure_dropper (me, which)
Notify_client me;
int which;
{
/* if next position is unoccupied, move the figure down by 1 */
if (safe_move (current_fig, current_rot, current_x, current_y+1)) {
draw_figure (current_fig, current_rot, current_x*BLOCKSIZE+BOARD_X,
current_y*BLOCKSIZE+BOARD_Y, BLACK);
current_y++;
draw_figure (current_fig, current_rot, current_x*BLOCKSIZE+BOARD_X,
current_y*BLOCKSIZE+BOARD_Y, current_color);
}
else if (current_y < 0) game_over (); /* all over when at the top */
else if (make_new_fig) {
make_new_fig = 0;
place_figure (); /* the figure comes to rest */
new_figure (); /* start a new one */
}
else {
make_new_fig = 1;
}
}
/* drop_down drops the figure down as far as it can go without hitting
other blocks along the way */
static void
drop_down ()
{
int new_y = current_y;
while (safe_move (current_fig, current_rot, current_x, new_y+1)) new_y++;
if (new_y < 0) {
game_over ();
return;
}
score += BOARDHEIGHT-(current_y+2); /* bonus for dropping */
draw_figure (current_fig, current_rot, current_x*BLOCKSIZE+BOARD_X,
current_y*BLOCKSIZE+BOARD_Y, BLACK);
current_y = new_y;
draw_figure (current_fig, current_rot, current_x*BLOCKSIZE+BOARD_X,
current_y*BLOCKSIZE+BOARD_Y, current_color);
place_figure (); /* rest the figure */
new_figure (); /* start a new one */
}
static void
game_over ()
{
stop_timer ();
window_set (canvas, WIN_EVENT_PROC, wait_for_return, 0);
close_board ();
update_hs (score, level);
display_hs ();
}
/* this select delay stuff doesn't work all that well, but it's sufficient */
static struct timeval delay_1sec = { 0, 999999 };
/* place the figure at its resting spot, update scores, do any reducing
of rows */
static void
place_figure ()
{
stop_timer ();
score += 2*level + BOARDHEIGHT-(current_y+2) + 5;
mark_board (current_fig, current_rot, current_x, current_y);
lines += reduce_rows (current_y);
if (level < MAXLEVEL && lines > 10*(level+1)) {
level++; /* should pause for a sec */
select (1, 0, 0, 0, &delay_1sec);
}
draw_score (lines, score, level);
if (!paused) start_timer ();
}
/* new_figure generates a new random figure */
static void
new_figure ()
{
current_x = 3;
current_y = -1;
current_rot = 0;
current_fig = random () % 7;
current_color = current_fig + 1;
draw_figure (current_fig, current_rot, current_x*BLOCKSIZE+BOARD_X,
current_y*BLOCKSIZE+BOARD_Y, current_color);
}
/*
* The cursor left (R10), 'j', and the left mouse button cause the block to
* move left. R11, 'k', and the middle mouse button cause the block to
* rotate counter-clockwise. The cursor right (R12), 'l', and the right
* mouse button cause the block to move right. The cursor down (R14) and
* the spacebar cause the block to drop down to the bottom.
* The Cursor keys must not be emitting escape sequences (SunView Defaults)
*/
static void
game_control_proc (canvas, event)
Canvas canvas;
Event *event;
{
int new_x = current_x;
int new_rot = current_rot;
if (event_is_button (event) && event_is_up (event)) return;
switch (event_id (event)) {
case 'q':
exit (0);
case MS_LEFT:
case 'j':
case KEY_RIGHT(10): /* LEFT */
new_x = current_x - 1;
break;
case MS_MIDDLE:
case 'k':
case KEY_RIGHT(11): /* ROTATE */
new_rot = (current_rot + 1) % 4;
break;
case MS_RIGHT:
case 'l':
case KEY_RIGHT(12): /* RIGHT */
new_x = current_x + 1;
break;
case ' ':
case KEY_RIGHT(14): /* DOWN */
drop_down ();
return;
break;
case 'u':
case KEY_RIGHT(8): /* UP LEVEL */
if (level < MAXLEVEL) {
level++;
stop_timer ();
select (1, 0, 0, 0, &delay_1sec);
draw_score (lines, score, level);
start_timer ();
}
return;
break;
case LOC_WINENTER:
case LOC_RGNENTER:
start_timer ();
paused = 0;
return;
case LOC_WINEXIT:
case LOC_RGNEXIT:
stop_timer ();
paused = 1;
return;
default:
return;
break;
}
if (safe_move (current_fig, new_rot, new_x, current_y)) {
draw_figure (current_fig, current_rot, current_x*BLOCKSIZE+BOARD_X,
current_y*BLOCKSIZE+BOARD_Y, BLACK);
current_rot = new_rot;
current_x = new_x;
draw_figure (current_fig, current_rot, current_x*BLOCKSIZE+BOARD_X,
current_y*BLOCKSIZE+BOARD_Y, current_color);
}
}
#define ITIMER_NULL ((struct itimerval *) 0)
static void
start_timer ()
{
timer.it_interval.tv_usec = (11-level)*50000;
timer.it_interval.tv_sec = 0;
timer.it_value.tv_usec = (11-level)*50000;
timer.it_value.tv_sec = 0;
(void) notify_set_itimer_func (me, figure_dropper,
ITIMER_REAL, &timer, ITIMER_NULL);
}
static void
stop_timer ()
{
/* turn off timer */
notify_set_itimer_func (me, figure_dropper, ITIMER_REAL, ITIMER_NULL,
ITIMER_NULL);
}
static void
start_game ()
{
lines = 0;
score = 0;
make_new_fig = 0;
draw_board ();
draw_score (lines, score, level);
rand_blocks (height);
window_set (canvas, WIN_EVENT_PROC, game_control_proc, 0);
new_figure ();
start_timer ();
}
static void
choose_level (canvas, event)
Canvas canvas;
Event *event;
{
switch (event_id (event)) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
select_level (level);
level = event_id (event) - '0';
select_level (level);
break;
case 'q':
exit (0);
case 'h':
case KEY_RIGHT(10): /* LEFT */
select_level (level);
level = (level + 9) % 10;
select_level (level);
break;
case 'l':
case KEY_RIGHT(12): /* RIGHT */
select_level (level);
level = (level + 1) % 10;
select_level (level);
break;
case 'k':
case KEY_RIGHT(8): /* UP */
case 'j':
case KEY_RIGHT(14): /* DOWN */
select_level (level);
level = (level + 5) % 10;
select_level (level);
break;
case '\015': /* RETURN */
selht = 0;
select_height (selht);
window_set (canvas, WIN_EVENT_PROC, choose_height, 0);
break;
}
}
static void
choose_height (canvas, event)
Canvas canvas;
Event *event;
{
switch (event_id (event)) {
case 'q':
exit (0);
case 'h':
case KEY_RIGHT(10): /* LEFT */
select_height (selht);
selht = (selht + 5) % 6;
select_height (selht);
break;
case 'l':
case KEY_RIGHT(12): /* RIGHT */
select_height (selht);
selht = (selht + 1) % 6;
select_height (selht);
break;
case 'k':
case KEY_RIGHT(8): /* UP */
case 'j':
case KEY_RIGHT(14): /* DOWN */
select_height (selht);
selht = (selht + 3) % 6;
select_height (selht);
break;
case '\015': /* RETURN */
switch (selht) {
case 0: height = 0; break;
case 1: height = 4; break;
case 2: height = 7; break;
case 3: height = 10; break;
case 4: height = 13; break;
}
start_game ();
break;
}
}
static void
wait_for_return (canvas, event)
Canvas canvas;
Event *event;
{
switch (event_id (event)) {
case 'q': exit (0);
case '\015':
game_setup ();
break;
}
}
static void
game_setup ()
{
display_choices ();
window_set (canvas, WIN_EVENT_PROC, choose_level, 0);
level = 5;
select_level (level);
}