|
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); }