/* * xplode -- enjoyable demonstration of a simple pVDI * Copyright (C) 1992 Joerg Heitkoetter. All rights reserved. */ #include #include #define BOARD_MAX 10 #define BOARD_LVL 3 #define CLEAR ' ' #define BORDER '#' #define ESCAPE '\033' #define NOBODY 9 #define EMPTY 0 #define LOW 0 #define OWNER 1 #define HIGH 2 #define NPLAYERS 2 #define NPENNIES 5 #define NDEFAULT 3 #define XOFFSET (3) #define YOFFSET (4) #define XSTATUS (2) #define YSTATUS (1) #define bell() write(1,"\007",1); typedef int boolean; #define true 1 #define false 0 char penny[NPLAYERS][NPENNIES]; char left[NPLAYERS]; char right[NPLAYERS]; char up[NPLAYERS]; char down[NPLAYERS]; char drop[NPLAYERS]; int board[BOARD_MAX][BOARD_MAX][BOARD_LVL]; /***************************************************************************/ /***** portable Virtual Device Interface ***********************************/ /***************************************************************************/ main (argc, argv) int argc; char **argv; { boolean done; int player; int moves; InitpVDI (CURSESpVDI); InitPennies (); InitKeys (); do { /* initialize */ clearpVDI (); InitBoard (); PrintFrame (); player = NPLAYERS - 1; moves = 0; do { /* next turn */ if (++player == NPLAYERS) player = 0; /* show status */ movepVDI (YSTATUS, XSTATUS); printpVDI ("Player %d to throw.", player + 1); refreshpVDI (); /* prompt player(s) */ ThrowPenny (player); Xplode (player); /* first move, no other player(s) yet */ if (++moves == 1) done = false; else done = isAlone (player); #ifdef DEBUG PrintBoard (XSTATUS + BOARD_MAX + 3, YSTATUS + 3, OWNER); #endif } while (!done); /* show statistics */ movepVDI (YSTATUS, XSTATUS); printpVDI ("Player %d wins after %d moves. Again (y/n)? ", player + 1, moves); refreshpVDI (); done = (getchpVDI () == 'n'); } while (!done); ExitpVDI (); return (0); } InitPennies () { int i, j; for (i = 0; i < NPENNIES; i++) { for (j = 0; j < NPLAYERS; j++) { penny[j][i] = '1' + i; } } } InitKeys () { int i; clearpVDI (); for (i = 0; i < NPLAYERS; i++) { printpVDI ("\n\nPlayer #%d: define your moving keys...\n", i + 1); printpVDI ("Up:\t"); refreshpVDI (); up[i] = getchpVDI (); printpVDI ("%c\n", up[i]); refreshpVDI (); printpVDI ("Down:\t"); refreshpVDI (); down[i] = getchpVDI (); printpVDI ("%c\n", down[i]); refreshpVDI (); printpVDI ("Left:\t"); refreshpVDI (); left[i] = getchpVDI (); printpVDI ("%c\n", left[i]); refreshpVDI (); printpVDI ("Right:\t"); refreshpVDI (); right[i] = getchpVDI (); printpVDI ("%c\n", right[i]); refreshpVDI (); printpVDI ("Drop:\t"); refreshpVDI (); drop[i] = getchpVDI (); printpVDI ("%c\n", drop[i]); refreshpVDI (); } } Print (x, y, c, flag) int x, y; char c; boolean flag; { movepVDI (y + YOFFSET, x + XOFFSET); if (flag) { printpVDI ("%c\b", c); } else { /* position cursor */ } refreshpVDI (); } PrintFrame () { int x; for (x = 0; x < BOARD_MAX + 1; x++) { Print (x - 1, -1, BORDER, true); Print (BOARD_MAX - x, BOARD_MAX, BORDER, true); Print (-1, BOARD_MAX - x, BORDER, true); Print (BOARD_MAX, x - 1, BORDER, true); } } InitBoard () { int i, j; for (i = 0; i < BOARD_MAX; i++) { for (j = 0; j < BOARD_MAX; j++) { board[i][j][HIGH] = EMPTY; board[i][j][OWNER] = NOBODY; board[i][j][LOW] = NDEFAULT; if (i == 0 || i == BOARD_MAX - 1) board[i][j][LOW]--; if (j == 0 || j == BOARD_MAX - 1) board[i][j][LOW]--; } } } ThrowPenny (player) int player; { int x, y; boolean done; char key; x = y = 0; done = false; do { Print (x, y, CLEAR, false); key = getchpVDI (); if (key == left[player]) { if (--x < 0) x = BOARD_MAX - 1; } else if (key == right[player]) { if (++x == BOARD_MAX) x = 0; } else if (key == up[player]) { if (--y < 0) y = BOARD_MAX - 1; } else if (key == down[player]) { if (++y == BOARD_MAX) y = 0; } else if (key == drop[player]) { if (board[x][y][OWNER] == NOBODY || board[x][y][OWNER] == player) { board[x][y][OWNER] = player; board[x][y][HIGH]++; done = true; Print (x, y, penny[player][board[x][y][HIGH]], true); } else { bell (); } } else if (key == ESCAPE) { movepVDI (YSTATUS, XSTATUS); printpVDI ("User abort...\n"); refreshpVDI (); ExitpVDI (); exit (1); } else bell (); } while (!done); } Drop (x, y, player) int x, y; int player; { if (x >= 0 && y >= 0 && x < BOARD_MAX && y < BOARD_MAX) { board[x][y][HIGH]++; board[x][y][OWNER] = player; Print (x, y, penny[player][board[x][y][HIGH]], true); } } Xplode (player) int player; { int x, y; boolean done; do { done = true; for (x = 0; x < BOARD_MAX; x++) { for (y = 0; y < BOARD_MAX; y++) { if (board[x][y][HIGH] > board[x][y][LOW]) { done = false; Drop (x - 1, y, player); Drop (x + 1, y, player); Drop (x, y - 1, player); Drop (x, y + 1, player); if (board[x][y][HIGH] == NPENNIES) Drop (x - 1, y, player); Print (x, y, CLEAR, true); board[x][y][OWNER] = NOBODY; board[x][y][HIGH] = EMPTY; } } } } while (!done); } boolean isAlone (player) int player; { int i, j; for (i = 0; i < BOARD_MAX; i++) { for (j = 0; j < BOARD_MAX; j++) { /* anybody out there ? */ if (board[i][j][OWNER] != NOBODY && board[i][j][OWNER] != player) { return (false); } } } return (true); } #ifdef DEBUG PrintBoard (x, y, level) int x, y, level; { int i, j; for (i = 0; i < BOARD_MAX; i++) { for (j = 0; j < BOARD_MAX; j++) { movepVDI (j + y, i + x); printpVDI ("%d", board[i][j][level]); } } } #endif