home *** CD-ROM | disk | FTP | other *** search
- /* This program appeared in an article written by Alex Lane in the April
- * 1990 issue of Dr. Dobb's Journal (pg 72). It is used here with
- * permission of the publisher, M&T Publishing Inc.
- */
-
- /****************************************************************************
- File: Kaboooom.c
- Purpose: Allows the user to 'walk' through a minefield; a detector shows
- how many mines are immediately adjacent to you. As you visit a cell, it
- leaves a marker telling you how many were next to you, and you have the
- ability to mark cells with a character (assumably to mark mines).
- Changes:
- 11/10/89 (tdeii) If you call the program with "/s" or "/S", it gives
- you a "safer" game, where it does not let you walk on spaces that you
- have marked (whether there is a mine there or not!)
- 11/11/89 (tdeii) Allows you to press "?" and get some help starting at your
- current position; will mark mines that it knows (by deducing their position),
- and "visit" places that it knows are safe. This propagates until it cannot
- deduce anything else (see EvaluatePosition).
- 10/90 (pharlap) Added switchs to allow number of mines (/n) and random seed
- to (/r) be set on command line.
- ****************************************************************************/
- #include "stdio.h"
- #include "stdarg.h"
- #include "stdlib.h"
- #include "dos.h"
- #include "conio.h"
- #include "string.h"
- #include "kaboom1.h"
-
- #define SCREEN_X 80
- #define SCREEN_Y 25
- #define GRID_X 15
- #define GRID_Y 9
- #define TRUE 1
- #define FALSE 0
-
- #define bEMPTY 0
- #define bVISITED 1
- #define bBOMB 2
- #define bCURRENT 3
- #define bFINISH 4
- #define bEXPLODED 5
-
- #define MAKECOLOR(fore,back) ((back)*16+(fore))
-
- typedef int BOOL;
- typedef struct tagADJACENCYGROUP {
- int BombCount; /* Number of bombs located in this adj. group */
- int CellCount; /* Number of cells filled */
- int Cell[8][2]; /* x,y coordinates of up to 8 cells */
- } ADJACENCYGROUP;
-
- int Board[GRID_X][GRID_Y]; /* Board; see codes above (bXXX) */
- int UserMark[GRID_X][GRID_Y]; /* User marks; 0 = none, 'M' = mine */
- int nNumMines; /* Number of mines on board */
- int initmines=0; /* nMines passed with /n switch */
- int initrand=0; /* init rand seed from command line */
- int UserX, UserY; /* Current user X and Y position */
- BOOL bShowBombs; /* TRUE if program shows bombs (it */
- /* does this after you win or lose) */
- BOOL bSafeGame; /* TRUE if program does not let you */
- /* walk on mines you have marked */
- ADJACENCYGROUP AdjacencyGroup[GRID_X][GRID_Y]; /* AG for each board pos */
- char szClear[79] = " ";
- int CountMines(int x, int y)
- {
- int i, j;
- int nCount;
- nCount = 0;
- for (i=-1; i<=1; i++) {
- for (j=-1; j<=1; j++) {
- if ((x+i >= 0) && (x+i < GRID_X) &&
- (y+j >= 0) && (y+j < GRID_Y)) {
- if ((Board[x+i][y+j] == bBOMB) ||
- (Board[x+i][y+j] == bEXPLODED)) {
- nCount++;
- }
- }
- }
- }
- return (nCount);
- }
- void DisplayCell(int x, int y)
- {
- int Char;
- Char = UserMark[x][y];
- if (Char == 0) {
- Char = 32;
- }
- DisplayChar(x*4+1, y*2+1, Char, MAKECOLOR(14,1));
- DisplayChar(x*4+3, y*2+1, Char, MAKECOLOR(14,1));
- switch (Board[x][y]) {
- case bEMPTY: /** Empty cell **/
- Char = ' ';
- break;
- case bVISITED: /** Visited cell **/
- Char = '0' + CountMines(x, y);
- break;
- case bBOMB: /** Bomb cell! **/
- if (bShowBombs) {
- Char = 15;
- } else {
- Char =' ';
- }
- break;
- case bCURRENT: /** Current pos **/
- Char = 2;
- break;
- case bFINISH: /** Finish cell **/
- Char = 19;
- break;
- case bEXPLODED: /** Exploded! **/
- Char = 15;
- break;
- }
- if (Char != 0) {
- DisplayChar(x*4+2, y*2+1, Char, MAKECOLOR(14,1));
- }
- }
-
- void PaintBoard(void)
- {
- int x, y, i;
- for (x=0; x<SCREEN_X; x++) {
- for (y=0; y<SCREEN_Y; y++) {
- DisplayChar(x, y, ' ', MAKECOLOR(14, 1));
- }
- }
- /** Draw left and right sides **/
- DisplayChar(0, 0, 218, MAKECOLOR(14,1)); /*upper left corner */
- DisplayChar(GRID_X*4, 0, 191, MAKECOLOR(14,1)); /*upper right corner */
- for (y=1; y<=GRID_Y; y++) {
- DisplayChar(0, y*2, 195, MAKECOLOR(14,1)); /* left edge */
- DisplayChar(GRID_X*4, y*2, 180, MAKECOLOR(14,1)); /* right edge */
- }
- DisplayChar(0, GRID_Y*2, 192, MAKECOLOR(14,1)); /* lower left corner */
- DisplayChar(GRID_X*4, GRID_Y*2, 217, MAKECOLOR(14,1)); /*lower right */
- /** Draw inside corners **/
- for (x=1; x<GRID_X; x++) {
- DisplayChar(x*4, 0, 194, MAKECOLOR(14,1)); /* top edge */
- for (y=1; y<GRID_Y; y++) {
- DisplayChar(x*4, y*2, 197, MAKECOLOR(14,1)); /* intersections */
- }
- DisplayChar(x*4, GRID_Y*2, 193, MAKECOLOR(14,1)); /* bottom edge */
- }
- /** Draw connecting lines **/
- for (x=0; x<=GRID_X; x++) {
- for (y=0; y<=GRID_Y; y++) {
- if (y != GRID_Y) {
- DisplayChar(x*4, y*2+1, 179, MAKECOLOR(14,1)); /* verticals */
- }
- if (x != GRID_X) {
- for (i=1; i<4; i++) {
- DisplayChar(x*4+i, y*2, 196 , MAKECOLOR(14,1)); /* horizontals */
- }
- }
- }
- }
- GotoXY_(0, SCREEN_Y - 2);
- for (x=0; x<GRID_X; x++) {
- for (y=0; y<GRID_Y; y++) {
- DisplayCell(x, y);
- }
- }
- }
- void SetUpBoard(void)
- {
- int i, j;
- int nMines;
- BOOL bDone;
- char cBuffer[80];
- bShowBombs = FALSE;
- /** First, get number of bombs **/
- if(!initmines) {
- nNumMines = 0;
- while ((nNumMines < 10) || (nNumMines > 40)) {
- GotoXY_(0, 24);
- _cprintf("How many bombs do you want? (10-40)?? ");
- fgets(cBuffer, sizeof(cBuffer), stdin);
- sscanf(cBuffer, "%d", &nNumMines);
- }
- } else
- nNumMines = initmines;
-
- /** next, clear out board & user scratchpad **/
- for (i=0; i<GRID_X; i++) {
- for (j=0; j<GRID_Y; j++) {
- Board[i][j] = 0;
- UserMark[i][j] = 0;
- }
- }
- for (nMines=0; nMines<nNumMines; nMines++) {
- bDone = FALSE;
- while (!bDone) {
- i = nRandom(GRID_X); /* First you roll it, */
- j = nRandom(GRID_Y); /* Then you pat it, */
- if ((Board[i][j] == bEMPTY) &&
- (!((i <= 1) && (j <= 1))) &&
- (!((i >= GRID_X - 2) && (j >= GRID_Y - 2)))
- ) {
- bDone = TRUE;
- }
- }
- Board[i][j] = bBOMB; /* Then you mark it with a 'B' */
- }
- /* Set user at position 0, 0 */
- UserX = 0;
- UserY = 0;
- Board[0][0] = bCURRENT;
- /* Set finish (hq) at position GRID_X, GRID_Y */
- Board[GRID_X - 1][GRID_Y - 1] = bFINISH;
- /* Display board on screen */
- PaintBoard();
- }
- BOOL Travel(int dx, int dy)
- {
- int NewX, NewY; /* New X and Y coordinates of user */
- BOOL bInvalid; /* TRUE if trying to walk off board */
- BOOL bAbort; /* TRUE if user won or lost (abort game) */
- BOOL bBombWalk; /* TRUE if user tried to walk on a bomb */
-
- bAbort = FALSE;
- NewX = UserX + dx;
- NewY = UserY + dy;
- bInvalid = FALSE;
- bBombWalk = FALSE;
- if ((NewX < 0) || (NewX >= GRID_X)) {
- bInvalid = TRUE;
- }
- if ((NewY < 0) || (NewY >= GRID_Y)) {
- bInvalid = TRUE;
- }
- if ((!bInvalid) && (bSafeGame) && (UserMark[NewX][NewY] == 'M')) {
- bInvalid = TRUE;
- bBombWalk = TRUE;
- }
- if (bInvalid) {
- GotoXY_(0, SCREEN_Y - 2);
- _cprintf("** INVALID MOVE ** ... press any key...");
- if (bBombWalk) {
- _cprintf("(You must un-mark it.)");
- }
- Pause();
- GotoXY_(0, SCREEN_Y - 2);
- _cprintf(szClear);
- } else {
- if (Board[NewX][NewY] == bBOMB) {
- bAbort = TRUE;
- Board[UserX][UserY] = bVISITED;
- DisplayCell(UserX, UserY);
- Board[NewX][NewY] = bEXPLODED;
- DisplayCell(NewX, NewY);
- GotoXY_(0, 22);
- _cprintf("******** YOU HAVE STEPPED ON A BOMB!! ********");
- Pause();
- GotoXY_(0, 22);
- _cprintf(szClear);
- GotoXY_(0, 22);
- } else {
- if ((NewX == GRID_X-1) && (NewY == GRID_Y-1)) {
- bAbort = TRUE;
- Board[UserX][UserY] = bVISITED;
- DisplayCell(UserX, UserY);
- Board[NewX][NewY] = bCURRENT;
- DisplayCell(NewX, NewY);
- GotoXY_(0, 22);
- _cprintf("************* YOU HAVE WON!! *************");
- Pause();
- GotoXY_(0, 22);
- _cprintf(szClear);
- GotoXY_(0, 22);
- } else {
- Board[UserX][UserY] = bVISITED;
- DisplayCell(UserX, UserY);
- UserX = NewX;
- UserY = NewY;
- Board[UserX][UserY] = bCURRENT;
- DisplayCell(UserX, UserY);
- }
- }
- }
- GotoXY_(0, GRID_Y*2+2);
- _cprintf("Number of mines around you: %d", CountMines(UserX, UserY));
- GotoXY_(0, SCREEN_Y - 2);
- return (bAbort);
- }
- void PlaceUserMark(void)
- {
- BOOL bDone, bAbort;
- int Ch;
- int NewX, NewY;
- int dx, dy;
-
- bAbort = FALSE;
- GotoXY_(0, 24);
- _cprintf("Mark in which direction? (ESC=abort)");
- bDone = FALSE;
- while (!bDone) {
- bDone = TRUE;
- Ch = _getch();
- switch (Ch) {
- case 0:
- Ch = _getch();
- switch (Ch) {
- case 71: /* home */
- dx = -1;
- dy = -1;
- break;
- case 72: /* up arrow */
- dx = 0;
- dy = -1;
- break;
- case 73: /* page up */
- dx = 1;
- dy = -1;
- break;
- case 75: /* left arrow */
- dx = -1;
- dy = 0;
- break;
- case 77: /* right arrow */
- dx = 1;
- dy = 0;
- break;
- case 79: /* end */
- dx = -1;
- dy = 1;
- break;
- case 80: /* down arrow */
- dx = 0;
- dy = 1;
- break;
- case 81: /* page down */
- dx = 1;
- dy = 1;
- break;
- default:
- bDone = FALSE;
- break;
- }
- break;
- case '7': /* home */
- dx = -1;
- dy = -1;
- break;
- case '8': /* up arrow */
- dx = 0;
- dy = -1;
- break;
- case '9': /* page up */
- dx = 1;
- dy = -1;
- break;
- case '4': /* left arrow */
- dx = -1;
- dy = 0;
- break;
- case '6': /* right arrow */
- dx = 1;
- dy = 0;
- break;
- case '1': /* end */
- dx = -1;
- dy = 1;
- break;
- case '2': /* down arrow */
- dx = 0;
- dy = 1;
- break;
- case '3': /* page down */
- dx = 1;
- dy = 1;
- break;
- case 27:
- case 13:
- case 10:
- case 8:
- bAbort = TRUE;
- break;
- default:
- bDone = FALSE;
- break;
- }
- }
- GotoXY_(0, 24);
- _cprintf(szClear);
- if (!bAbort) {
- NewX = UserX + dx;
- NewY = UserY + dy;
- if ((NewX < 0) || (NewX >= GRID_X) || (NewY < 0) || (NewY >= GRID_Y)) {
- GotoXY_(0, 24);
- _cprintf("ERROR: Out of bounds!!");
- Pause();
- GotoXY_(0, 24);
- _cprintf(szClear);
- } else {
- GotoXY_(0, 24);
- if (UserMark[NewX][NewY] != 0) {
- Ch = 0;
- } else {
- Ch = 'M';
- }
- UserMark[NewX][NewY] = Ch;
- DisplayCell(NewX, NewY);
- }
- }
- GotoXY_(0, 24);
- }
- void ComputeAdjacency(int x, int y)
- {
- int dX, dY;
- int BombCount;
- int Cell;
- if ((x >= 0) && (x < GRID_X) && (y >= 0) && (y < GRID_Y)) {
- if ((Board[x][y] == bVISITED) || (Board[x][y] == bCURRENT)) {
- BombCount = CountMines(x, y);
- Cell = 0;
- for (dX=-1; dX<=1; dX++) {
- for (dY=-1; dY<=1; dY++) {
- if (!((dX == 0) && (dY == 0))) {
- if ((x+dX >= 0) && (x+dX < GRID_X) &&
- (y+dY >= 0) && (y+dY < GRID_Y)) {
- if ((Board[x+dX][y+dY] != bVISITED) &&
- (Board[x+dX][y+dY] != bCURRENT)) {
- if (UserMark[x+dX][y+dY] != 0) {
- /* code folded from here */
- BombCount--;
- /* unfolding */
- } else {
- /* code folded from here */
- AdjacencyGroup[x][y].Cell[Cell][0] = x+dX;
- AdjacencyGroup[x][y].Cell[Cell][1] = y+dY;
- Cell++;
- /* unfolding */
- }
- }
- }
- }
- }
- }
- AdjacencyGroup[x][y].BombCount = BombCount;
- AdjacencyGroup[x][y].CellCount = Cell;
- } else {
- AdjacencyGroup[x][y].CellCount = 0;
- AdjacencyGroup[x][y].BombCount = -1; /** Don't look flag */
- }
- }
- }
- int AddToPositionList(int PositionList[GRID_X * GRID_Y][2],
- int PositionListHead, int x, int y)
- {
- int nIndex;
- BOOL bFound;
- ComputeAdjacency(x, y);
- bFound = FALSE;
- for (nIndex=0; (nIndex<PositionListHead) && (!bFound); nIndex++) {
- if ((PositionList[nIndex][0] == x) && (PositionList[nIndex][1] == y)) {
- bFound = TRUE;
- }
- }
- if (!bFound) {
- PositionList[PositionListHead][0] = x;
- PositionList[PositionListHead][1] = y;
- PositionListHead++;
- }
- if (PositionListHead > GRID_X * GRID_Y) {
- GotoXY_(0, 22);
- _cprintf("ERROR! PositionListHead > max (%d)", PositionListHead);
- Pause();
- GotoXY_(0, 22);
- _cprintf(szClear);
- GotoXY_(0, 22);
- }
- return (PositionListHead);
- }
- int AddSurroundingToPositionList(int PositionList[GRID_X * GRID_Y][2],
- int PositionListHead, int x, int y)
- {
- int dX, dY;
-
- for (dX=-1; dX<=1; dX++) {
- for (dY=-1; dY<=1; dY++) {
- if ((x+dX >= 0) && (x+dX < GRID_X) && (y+dY >= 0) && (y+dY < GRID_Y)) {
- if ((Board[x+dX][y+dY] == bVISITED) ||
- (Board[x+dX][y+dY] == bCURRENT)) {
- PositionListHead = AddToPositionList(PositionList, PositionListHead,
- x+dX, y+dY);
- }
- }
- }
- }
- return (PositionListHead);
- }
- BOOL FindPositionInAG(ADJACENCYGROUP *pAG, int x, int y)
- {
- int nIndex;
- BOOL bFound;
- bFound = FALSE;
- for (nIndex=0; nIndex<pAG->CellCount; nIndex++) {
- if ((pAG->Cell[nIndex][0] == x) && (pAG->Cell[nIndex][1] == y)) {
- bFound = TRUE;
- }
- }
- return (bFound);
- }
- void MarkBombCell(int x, int y)
- {
- UserMark[x][y] = 'M';
- DisplayCell(x, y);
- if (Board[x][y] != bBOMB) {
- GotoXY_(0, 22);
- _cprintf("LOGIC ERROR: I tagged a phantom bomb @ (%d,%d).", x, y);
- Pause();
- GotoXY_(0, 22);
- _cprintf(szClear);
- GotoXY_(0, 24);
- }
- }
- void VisitCell(int x, int y)
- {
- if (Board[x][y] != bCURRENT) {
- if (Board[x][y] == bBOMB) {
- GotoXY_(0, 22);
- _cprintf("LOGIC ERROR: I walked on a bomb @ (%d,%d).", x, y);
- Pause();
- GotoXY_(0, 22);
- _cprintf(szClear);
- GotoXY_(0, 24);
- }
- Board[x][y] = bVISITED;
- DisplayCell(x, y);
- }
- }
- int CountCommonCells(ADJACENCYGROUP *pGroup1, ADJACENCYGROUP *pGroup2)
- {
- int Cell, nCount;
- nCount = 0;
- for (Cell=0; Cell<pGroup1->CellCount; Cell++) {
- if (FindPositionInAG(pGroup2,
- pGroup1->Cell[Cell][0], pGroup1->Cell[Cell][1])) {
- nCount++;
- }
- }
- return (nCount);
- }
- BOOL ProcessRule3(ADJACENCYGROUP *pCurrentAG, ADJACENCYGROUP *pTempAG,
- int PositionList[GRID_X * GRID_Y][2],
- int *pPositionListHead)
- {
- int x;
- int BombCount, CellCount;
- int PositionListHead;
- int CellHolder[9][2];
- int CellHolderHead;
- BOOL bRetVal;
- PositionListHead = *pPositionListHead;
- bRetVal = FALSE;
- BombCount = pCurrentAG->BombCount;
- CellCount = pCurrentAG->CellCount;
- if (pTempAG->CellCount == CountCommonCells(pTempAG, pCurrentAG)) {
- BombCount -= pTempAG->BombCount;
- CellCount -= pTempAG->CellCount;
- if ((CellCount > 0) && ((BombCount == CellCount) || (BombCount == 0))) {
- bRetVal = TRUE;
- CellHolderHead = 0;
- CellCount = pCurrentAG->CellCount;
- for (x=0; x<CellCount; x++) {
- if (!FindPositionInAG(pTempAG, pCurrentAG->Cell[x][0],
- pCurrentAG->Cell[x][1])) {
- if (BombCount == 0) {
- VisitCell(pCurrentAG->Cell[x][0], pCurrentAG->Cell[x][1]);
- } else {
- MarkBombCell(pCurrentAG->Cell[x][0], pCurrentAG->Cell[x][1]);
- }
- /* Queue up cells to put in position list for later */
- CellHolder[CellHolderHead][0] = pCurrentAG->Cell[x][0];
- CellHolder[CellHolderHead][1] = pCurrentAG->Cell[x][1];
- CellHolderHead++;
- }
- }
- for (x=0; x<CellHolderHead; x++) {
- PositionListHead = AddSurroundingToPositionList(
- PositionList,
- PositionListHead,
- CellHolder[x][0],
- CellHolder[x][1]);
- }
- }
- }
- *pPositionListHead = PositionListHead;
- return (bRetVal);
- }
- void EvaluatePosition(void)
- {
- int CurrentX, CurrentY;
- int x, y;
- int Cell;
- int dX, dY;
- int BombCount, CellCount;
- int PositionList[GRID_X * GRID_Y][2], PositionListHead;
- ADJACENCYGROUP *pTempAG;
- BOOL bDone;
- BOOL bModifiedAny;
- bModifiedAny = TRUE;
- for (x=0; x<GRID_X; x++) {
- for (y=0; y<GRID_Y; y++) {
- ComputeAdjacency(x, y);
- }
- }
- PositionList[0][0] = UserX;
- PositionList[0][1] = UserY;
- PositionListHead = 1;
- while (bModifiedAny) {
- bModifiedAny = FALSE;
- while (PositionListHead > 0) {
- CurrentX = PositionList[0][0];
- CurrentY = PositionList[0][1];
- for (x=0; x<PositionListHead-1; x++) {
- PositionList[x][0] = PositionList[x+1][0];
- PositionList[x][1] = PositionList[x+1][1];
- }
- PositionListHead--;
- ComputeAdjacency(CurrentX, CurrentY);
- BombCount = AdjacencyGroup[CurrentX][CurrentY].BombCount;
- CellCount = AdjacencyGroup[CurrentX][CurrentY].CellCount;
- if ((CellCount > 0) && (BombCount > -1)) {
- /*
- Rule 1: if number of bombs = number of cells, all are bombs!
- */
- if (CellCount == BombCount) {
- for (Cell=0; Cell<CellCount; Cell++) {
- x = AdjacencyGroup[CurrentX][CurrentY].Cell[Cell][0];
- y = AdjacencyGroup[CurrentX][CurrentY].Cell[Cell][1];
- MarkBombCell(x, y);
- PositionListHead = AddSurroundingToPositionList(PositionList,
- PositionListHead,
- x, y);
- bModifiedAny = TRUE;
- }
- } else {
- /*
- Rule 2: if number of bombs = 0, all cells are ok!
- */
- if ((BombCount == 0) && (CellCount > 0)) {
- for (Cell=0; Cell<CellCount; Cell++) {
- x = AdjacencyGroup[CurrentX][CurrentY].Cell[Cell][0];
- y = AdjacencyGroup[CurrentX][CurrentY].Cell[Cell][1];
- VisitCell(x, y);
- PositionListHead = AddToPositionList(PositionList,
- PositionListHead,
- x, y);
- PositionListHead = AddSurroundingToPositionList(PositionList,
- PositionListHead,
- x, y);
- bModifiedAny = TRUE;
- }
- } else {
- /*
- Rule 3: if AG completely overlaps another AG, subtract 2nd
- # of bombs from 1st; check rules 1 & 2. If rule 1 or
- 2 is true in this case, stop looking in rule 3.
- */
- bDone = FALSE;
- for (Cell=0; (Cell<CellCount) && (!bDone); Cell++) {
- x = AdjacencyGroup[CurrentX][CurrentY].Cell[Cell][0];
- y = AdjacencyGroup[CurrentX][CurrentY].Cell[Cell][1];
- for (dX=-1; (dX<=1) && (!bDone); dX++) {
- for (dY=-1; (dY<=1) && (!bDone); dY++) {
- /* code folded from here */
- if ((x+dX >= 0) && (x+dX < GRID_X) &&
- (y+dY >= 0) && (y+dY < GRID_Y)) {
- pTempAG = &AdjacencyGroup[x+dX][y+dY];
- if (pTempAG->BombCount > 0) { /* if == 0, no help! */
- bDone = ProcessRule3(&AdjacencyGroup[CurrentX][CurrentY],
- pTempAG,
- PositionList,
- &PositionListHead);
- if (bDone) {
- bModifiedAny = TRUE;
- }
- }
- }
- /* unfolding */
- }
- }
- }
- }
- }
- }
- }
- if (bModifiedAny) {
- for (x=0; x<GRID_X; x++) {
- for (y=0; y<GRID_Y; y++) {
- if ((Board[x][y] == bVISITED) || (Board[x][y] == bCURRENT)) {
- PositionListHead = AddToPositionList(PositionList,
- PositionListHead,
- x, y);
- }
- }
- }
- }
- }
- }
- BOOL LetUserMove(void)
- {
- BOOL bDone;
- BOOL bQuit;
- int Ch;
- bDone = FALSE;
- while (!bDone) {
- Ch = _getch();
- switch (Ch) {
- case 0:
- Ch = _getch();
- switch (Ch) {
- case 71: /* home */
- bDone = Travel(-1, -1);
- break;
- case 72: /* up arrow */
- bDone = Travel(0, -1);
- break;
- case 73: /* page up */
- bDone = Travel(1, -1);
- break;
- case 75: /* left arrow */
- bDone = Travel(-1, 0);
- break;
- case 77: /* right arrow */
- bDone = Travel(1, 0);
- break;
- case 79: /* end */
- bDone = Travel(-1, 1);
- break;
- case 80: /* down arrow */
- bDone = Travel(0, 1);
- break;
- case 81: /* page down */
- bDone = Travel(1, 1);
- break;
- }
- break;
- case '7': /* home */
- bDone = Travel(-1, -1);
- break;
- case '8': /* up arrow */
- bDone = Travel(0, -1);
- break;
- case '9': /* page up */
- bDone = Travel(1, -1);
- break;
- case '4': /* left arrow */
- bDone = Travel(-1, 0);
- break;
- case '6': /* right arrow */
- bDone = Travel(1, 0);
- break;
- case '1': /* end */
- bDone = Travel(-1, 1);
- break;
- case '2': /* down arrow */
- bDone = Travel(0, 1);
- break;
- case '3': /* page down */
- bDone = Travel(1, 1);
- break;
- case 'Q':
- case 'q':
- case 27:
- bDone = TRUE;
- break;
- case 'M':
- case 'm':
- PlaceUserMark();
- break;
- case '?':
- EvaluatePosition();
- break;
- }
- }
- bShowBombs = TRUE;
- PaintBoard();
- GotoXY_(0, SCREEN_Y - 2);
- _cprintf("Again (Y/n)? ");
- bDone = FALSE;
- while (!bDone) {
- Ch = _getch();
- if ((Ch == 'Y') || (Ch == 'y') || (Ch == 13) || (Ch == 10)) {
- bDone = TRUE;
- bQuit = FALSE;
- _cprintf("Y\n");
- }
- if ((Ch == 'N') || (Ch == 'n')) {
- bDone = TRUE;
- bQuit = TRUE;
- _cprintf("N\n");
- }
- if (Ch == (int)NULL) {
- _getch();
- }
- }
- return (bQuit);
- }
- int main(int argc, char *argv[])
- {
- BOOL bDone;
- bSafeGame = FALSE;
- for(--argc, ++argv; argc--; ++argv) {
- if((argv[0][0] == '/')
- &&((argv[0][1] == 's') || (argv[0][1] == 'S'))) {
- bSafeGame = TRUE;
- _cprintf("SAFE GAME in effect.\n");
- }
- else if(argv[0][0] == '/' && argv[0][1] == 'n')
- initmines = atoi(&argv[0][2]);
- else if(argv[0][0] == '/' && argv[0][1] == 'r')
- initrand = atoi(&argv[0][2]);
- }
- bDone = FALSE;
- Initialize();
- while (!bDone) {
- SetUpBoard();
- bDone = LetUserMove();
- }
- return (0);
- }
-
- #if defined(__WATCOMC__)
- /* Special 32-bit random number generator; the one in Watcom's library
- * is only 16-bit (0-0x7FFF), and we need 32-bits (0-0x7FFFFFFF) for
- * one of the bugs in KABOOBUG.EXE
- */
- long kb_rand()
- {
- long retval = 0L;
-
- retval = (rand() << 16) | rand();
- return retval;
- }
- #endif
-