/* Copyright (c) 2000 Jean-Marc Zucconi * All rights reserved. * * 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 * in this position and unchanged. * 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. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ #include #include #include #include #include #include #include "qix.h" #define reset_tty() tcsetattr(0, TCSADRAIN, &tty_oldmode) struct termios tty_mode, tty_oldmode; int help_shown = 0; void VT_init () { if (tcgetattr(0, &tty_mode) < 0) { perror ("tty"); sleep (5); exit (1); } tty_oldmode = tty_mode; tty_mode.c_iflag |= (IGNBRK | IGNPAR); tty_mode.c_iflag &= ~(IXON | IXOFF | ISTRIP | BRKINT); tty_mode.c_lflag &= ~(ICANON | ISIG | ECHO); tty_mode.c_cflag |= CREAD | CS8; tty_mode.c_cc[VMIN] = 1; tty_mode.c_cc[VTIME] = 0; if (tcsetattr(0, TCSADRAIN, &tty_mode) < 0) { perror ("/dev/tty"); sleep (5); exit (1); } fcntl (0, F_SETFL, O_NONBLOCK); } char VT_getchar () { char c; if (read (0, &c, 1) == 0) return K_NONE; switch (c) { case '8': case 'i': case 'I': return K_UP; case '4': case 'j': case 'J': return K_LEFT; case '6': case 'l': case 'L': return K_RIGHT; case '2': case 'k': case 'K': return K_DOWN; case 'p': case 'P': return K_PAUSE; case ' ': return K_WALL; case 'e': case 'E': return K_EXIT; case 'y': case 'Y': return K_YES; case 'n': case 'N': return K_NO; case '\n': return K_CR; default: return K_NONE; } } void outchar (unsigned char c) { write (1, &c, 1); } void outstr (char *s) { while (*s) outchar (*s++); } void VT_inverse () { outstr ("\x1b[7m"); } void VT_normal () { outstr ("\x1b[0m"); } void VT_bold () { outstr ("\x1b[1m"); } void VT_home () { outstr ("\x1b[1;1H"); } void VT_clear () { VT_home (); outstr ("\x1b[J"); } void VT_move (int x, int y) { char s[20]; sprintf(s, "\x1b[%d;%dH", x, y); outstr (s); } void Pos (int x, int y, char c) { VT_move (x, y); outchar (c); } void Help_Screen () { int X, Y; int w = WIDTH, h = HEIGHT; if (help_shown) return; help_shown = 1; VT_clear (); Pos (1, 1, F_13); for (Y = 2; Y < h-2; Y++) Pos (1, Y, F_18); usleep (1); Pos (1, h-2, F_12); for (X = 2; X < w-2; X++) Pos (X, h-2, F_1F); usleep (1); Pos (w-2, h-2, F_11); for (Y = h-3; Y > 1; Y--) Pos (w-2, Y, F_18); usleep (1); Pos (w-2, 1, F_14); for (X = w-3; X > 1; X--) Pos (X, 1, F_1F); usleep (1); X = (w-24)/2; /* title */ /* width is 18 chars. start at (h-18)/2 */ Y = (h-18)/2; Pos (X+3, Y++, F_13); Pos (X+3, Y++, F_18); Pos (X+3, Y++, F_18); Pos (X+3, Y++, F_12); Pos (X+3, Y++, Blank); Pos (X+3, Y++, Blank); Pos (X+3, Y++, F_18); Pos (X+3, Y++, F_1E); Pos (X+3, Y++, F_18); Pos (X+3, Y++, Blank); Pos (X+3, Y++, Blank); Pos (X+3, Y++, F_18); Pos (X+3, Y++, F_12); Pos (X+3, Y++, Blank); Pos (X+3, Y++, F_13); Pos (X+3, Y++, F_18); Y = (h-18)/2 - 1; Pos (X+4, Y++, F_13); Pos (X+4, Y++, F_11); Pos (X+4, Y++, Blank); Pos (X+4, Y++, Blank); Pos (X+4, Y++, F_1F); Pos (X+4, Y++, Blank); Pos (X+4, Y++, Blank); Pos (X+4, Y++, Blank); Pos (X+4, Y++, F_1F); Pos (X+4, Y++, Blank); Pos (X+4, Y++, Blank); Pos (X+4, Y++, Blank); Pos (X+4, Y++, Blank); Pos (X+4, Y++, F_14); Pos (X+4, Y++, F_1E); Pos (X+4, Y++, F_11); Y = (h-18)/2 - 1; Pos (X+5, Y++, F_1F); Pos (X+5, Y++, Blank); Pos (X+4, Y++, Blank); Pos (X+5, Y++, F_12); Pos (X+5, Y++, F_1F); Pos (X+5, Y++, Blank); Pos (X+5, Y++, Blank); Pos (X+5, Y++, Blank); Pos (X+5, Y++, F_1F); Pos (X+5, Y++, Blank); Pos (X+5, Y++, Blank); Pos (X+5, Y++, Blank); Pos (X+5, Y++, Blank); Pos (X+5, Y++, F_13); Pos (X+5, Y++, F_1D); Pos (X+5, Y++, F_12); Y = (h-18)/2 - 1; Pos (X+6, Y++, F_14); Pos (X+6, Y++, F_18); Pos (X+6, Y++, F_18); Pos (X+6, Y++, F_1D); Pos (X+6, Y++, F_1D); Pos (X+6, Y++, F_12); Pos (X+6, Y++, Blank); Pos (X+6, Y++, F_18); Pos (X+6, Y++, F_1D); Pos (X+6, Y++, F_18); Pos (X+6, Y++, Blank); Pos (X+6, Y++, Blank); Pos (X+6, Y++, F_18); Pos (X+6, Y++, F_11); Pos (X+6, Y++, Blank); Pos (X+6, Y++, F_14); Pos (X+6, Y++, F_18); Y = (h-18)/2 + 4; Pos (X+7, Y++, F_14); /* qix */ Y = (h+18)/2 + 12; Pos (X+3, Y++, Qix_Head); Pos (X+3, Y++, F_18); Pos (X+3, Y++, F_18); Pos (X+3, Y++, F_18); Pos (X+3, Y++, F_18); Pos (X+3, Y++, F_18); Pos (X+3, Y++, F_18); Pos (X+3, Y++, F_12); Pos (X+3, Y++, Blank); Pos (X+3, Y++, F_13); Pos (X+3, Y++, F_18); Pos (X+3, Y++, F_18); Pos (X+3, Y++, F_18); Pos (X+3, Y++, F_18); Pos (X+3, Y++, F_18); Y = (h+18)/2 + 16; Pos (X+4, Y++, F_13); Pos (X+4, Y++, F_18); Pos (X+4, Y++, F_18); Pos (X+4, Y++, F_11); Pos (X+4, Y++, Blank); Pos (X+4, Y++, F_1F); Y = (h+18)/2 + 16; Pos (X+5, Y++, F_14); Pos (X+5, Y++, F_18); Pos (X+5, Y++, F_18); Pos (X+5, Y++, F_18); Pos (X+5, Y++, F_18); Pos (X+5, Y++, F_11); /* texts */ Y = (h-18)/2 - 24; VT_move (X+3, Y); outstr ("You - O"); VT_move (X+5, Y); outstr ("Fuse - *"); VT_move (X+8, Y); outstr ("Fence Off The Screen Trying To Avoid The Hazzards."); VT_move (X+10, Y); outstr ("Hazzards : Qix - Kills If Touches The Line You Are Drawing"); VT_move (X+11, Y); outstr (" Fuse - Traverses The Outside Killing On Contact"); VT_move (X+14, Y); outstr ("Movement : 8,i - Up"); VT_move (X+16, Y); outstr (" 4,j - Left 6,l - Right"); VT_move (X+18, Y); outstr (" 2,k - Down"); VT_move (X+20, Y); outstr ("Draw Fence : < Space Bar >"); Y = (h+18)/2 + 6; VT_move (X+3, Y); outstr ("Qix -"); VT_move (X+14, Y-10); outstr ("New Screen : Once 75% Fenced Off"); VT_move (X+16, Y-10); outstr ("Higher Scoring For Areas"); VT_move (X+18, Y-10); outstr ("Greater Than 75%."); VT_move (X+20, Y-10); outstr ("E : Exit P : Pause"); Y = h - 24; X = w - 1; VT_move (X, Y); VT_inverse (); outstr ("Hit < Return > To Play"); VT_normal (); fcntl (0, F_SETFL, 0); while (VT_getchar () != K_CR) ; fcntl (0, F_SETFL, O_NONBLOCK); } void VT_print_covered () { VT_move (WIDTH-1, 1); VT_bold (); outstr ("Covered"); VT_normal (); } void VT_covered (double f) { char s[20]; VT_move (WIDTH-1, 9); VT_bold (); sprintf(s, "%5.2f", f); outstr(s); VT_normal (); } void VT_print_score () { VT_move (WIDTH-1, 16); VT_bold (); outstr ("Score"); VT_normal (); } void VT_score (int a) { char s[20]; VT_move (WIDTH-1, 22); VT_bold (); sprintf (s, "%5d", a); outstr (s); VT_normal (); } void VT_print_lives () { VT_move (WIDTH-1, 29); VT_bold (); outstr ("Lives"); VT_normal (); } void VT_lives (int l) { VT_move (WIDTH-1, 35); VT_bold (); while (l--) outstr (" O"); VT_normal (); outstr (" "); /* clear previous */ } void VT_print_level () { VT_move (WIDTH-1, 45); VT_bold (); outstr ("Level"); VT_normal (); } void VT_level (int l) { char s[4]; sprintf (s, "%2d", l); VT_move (WIDTH-1, 51); VT_bold (); outstr (s); VT_normal (); } void VT_fill_start () { VT_inverse (); VT_home (); } void VT_fill_end () { VT_normal (); VT_home (); } void VT_beep () { outchar ('\007'); } void top_header (char *msg, int num) { char s[100]; int l = strlen (msg); int w = (WIDTH-24)/2; VT_clear (); VT_move (w+1, (HEIGHT-l)/2); outstr (msg); sprintf (s, "QIX Super League %d Game%s", num, num > 1 ? "s" : ""); l = strlen (s); VT_move (w+5, (HEIGHT-l)/2); outstr (s); VT_move (w+6, (HEIGHT-l)/2); outstr ("================"); } void top_entry (int e, int score, int level, char *name, char *date, int you) { char s[100]; int w = (WIDTH-24)/2; if (e == 0) { VT_move (w+8, HEIGHT/2 -25); outstr ("Player Score Level Date"); } VT_move (w+10+e, HEIGHT/2-25); if (you) VT_bold (); sprintf (s, "%-16s %6d %5d %s", name, score, level, date); outstr (s); if (you) VT_normal (); } void top_score (int score) { char s[100]; int l; int w = (WIDTH-24)/2; sprintf (s, "Your Score %d", score); l = strlen (s); VT_move (w+22, HEIGHT/2-7); outstr (s); } void wait_message () { VT_clear (); VT_beep (); outstr ("Please Wait ..."); sleep (5); } void VT_pause () { VT_move (WIDTH-1, HEIGHT-10); VT_inverse (); outstr ("Paused"); VT_normal (); fcntl (0, F_SETFL, 0); while (VT_getchar () != K_PAUSE) ; fcntl (0, F_SETFL, O_NONBLOCK); VT_move (WIDTH-1, HEIGHT-10); outstr (" "); } int terminate (char *s) { char c; if (s) { VT_clear (); perror (s); } VT_move (WIDTH-1, HEIGHT-24); VT_inverse (); if (s) outstr ("Hit < Return >"); else outstr ("Another game ? (Y/N)"); VT_normal (); if (s) { while (VT_getchar () != K_CR) ; reset_tty (); exit (1); } else { do c = VT_getchar (); while (c != K_YES && c != K_NO); } if (c == K_YES) return 0; reset_tty (); return 1; } int WIDTH, HEIGHT; main (int argc, char **argv) { int i, level = 0; WIDTH = 25; HEIGHT = 82; #if 1 while ((i = getopt (argc, argv, "h:w:l:")) != -1) { switch (i) { case 'w': HEIGHT = atoi (optarg); break; case 'h': WIDTH = atoi (optarg); break; case 'l': level = atoi (optarg); break; } } #endif qix (level); }