home *** CD-ROM | disk | FTP | other *** search
- /*
- * PilotMines is Copyright (c) 1997-2000 by Thomas Pundt
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose, without fee, and without a written agreement is hereby granted,
- * provided that the above copyright notice and this paragraph and the
- * following two paragraphs appear in all copies.
- *
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
- * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
- * THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
- * BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
- * UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- */
-
- /*
- * Incorporates changes from Lucas Bremgartner <breml@trash.net>
- * and Laurent Thaler <lthaler@free.net>
- */
-
- #include <Common.h>
- #include <System/KeyMgr.h>
- #include <System/SysAll.h>
- #include <UI/UIAll.h>
-
- #include "minercp.h"
- #include "mine.h"
- #include "hscore.h"
-
- /*
- * bit 5 : Marked
- * bit 4 : Cover/uncovered
- * bit 3-0 : number of mines in adjoining cells
- */
- #define MINE 0x09
- #define COVERED 0x10
- #define MARKED 0x20
- #define TMPMARK 0x40
-
- static int width, height, length_bitmap, bitmap_offset;
-
- #define InArray(x,y) (((x)>=0 && (x)<width) && ((y)>=0 && (y)<height))
- #define IsVisible(x,y) ((game.minefield[x][y] & COVERED) ? 0 : 1)
-
- /*
- * Game options
- */
- #define ShowAll 1
- #define AlternateControl 2
- #define FirstNoMine 4
- #define CornerNoMine 8 // due to Laurent Thaler
-
- // every level has it's own number of mines per level.
- static int levelmines[] = {
- 10, 30, 50, 60, // 16x14-Layout
- 20, 50, 80, 100, // 20x18-Layout
- 40, 80, 140, 170 // 26x24-Layout
- };
-
- static struct { SWord x,y; } stack[WIDTH*HEIGHT];
-
- static int numuncovered, marked, nummines, StckPtr;
- static Boolean isHighlighted;
- static ULong GameStartedAt;
- static WinHandle bitmaps = 0; // Offscreen Window with tile bitmaps
-
- long score = 0;
-
- static DmOpenRef pmDB;
- Game game;
-
- /*
- * mapping function, that applies f to all neighbours of (x,y)
- */
- static int Neighbours (func f, SWord x, SWord y)
- {
- int res = 0;
- res += f(x-1,y-1); res += f(x,y-1); res += f(x+1,y-1);
- res += f(x-1,y ); res += f(x+1,y );
- res += f(x-1,y+1); res += f(x,y+1); res += f(x+1,y+1);
- return res;
- }
-
- static int IsMine(SWord x, SWord y)
- {
- return (InArray(x,y) && (game.minefield[x][y] & 0xf) == MINE);
- }
-
- static int IsMarked(SWord x, SWord y)
- {
- return (InArray(x,y) && (game.minefield[x][y] & MARKED));
- }
-
- /*
- * computes the number of mines around field (x,y)
- */
- static int countMines(int x, int y)
- {
- return Neighbours (IsMine, x, y);
- }
-
- /*
- * computes the marked fields (supposed mines) around field (x,y)
- */
- static int foundMines(int x, int y)
- {
- return Neighbours (IsMarked, x, y);
- }
-
- /*
- * pushes (x,y) on the stack, if field (x,y) isn't marked, isn't
- * visible, and isn't already on the stack.
- */
- static int push(SWord x, SWord y)
- {
- if (InArray(x,y) && !(game.minefield[x][y] & (MARKED|TMPMARK)) &&
- (game.minefield[x][y] & COVERED)) {
- game.minefield[x][y] |= TMPMARK;
- stack[StckPtr].x=x;
- stack[StckPtr].y=y;
- StckPtr++;
- }
- return StckPtr;
- }
-
- /*
- * pops the topmost element (x,y) off the stack, and stores it in
- * the parameters x and y.
- */
- static void pop(SWord *x, SWord *y)
- {
- StckPtr--;
- *x=stack[StckPtr].x;
- *y=stack[StckPtr].y;
- }
-
- /*
- * Draw the cell at coordinates (x,y); if Id==0, look at the contents
- * of field (x,y) and decide what pattern to draw; else draw pattern
- * Id.
- */
- static void DrawCell(SWord x, SWord y, int Id)
- {
- RectangleType rect;
- Byte field = game.minefield[x][y] & ~TMPMARK;
-
- if (Id==0) {
- if (field & MARKED)
- Id = ID_Flag + bitmap_offset;
- else if (field & COVERED)
- Id = ID_Covered + bitmap_offset;
- else
- Id = ID_Blank + field + bitmap_offset;
- }
-
- // Copy bitmap from offscreen window to active window
- rect.topLeft.x = (Id - ID_Flag - bitmap_offset) * length_bitmap;
- rect.topLeft.y = 0;
- rect.extent.x = rect.extent.y = length_bitmap;
- WinCopyRectangle(bitmaps,
- WinGetActiveWindow(),
- &rect,
- x*length_bitmap,
- (y+2)* length_bitmap,
- scrCopy);
- }
-
- /*
- * Draw the "mines left to mark" status information
- */
- static void DrawMarked()
- {
- char buf[3];
- buf[0] = (nummines - marked) / 100 + 48;
- buf[1] = ((nummines - marked) % 100 ) / 10 + 48;
- buf[2] = (nummines - marked) % 10 + 48;
- WinDrawInvertedChars(buf, 3, 10, 0);
- }
-
- /*
- * Draw the "passed time" status information; if a menubar is active,
- * don't draw.
- */
- static void DrawTime()
- {
- char buf[5] = "00:00";
- ULong actseconds;
- MenuBarPtr menu;
-
- if ((menu = MenuGetActiveMenu()) && menu->attr.visible)
- return;
-
- actseconds = TimGetSeconds() - GameStartedAt;
-
- // pilot switched off
- if (actseconds-game.seconds>2) {
- GameStartedAt = TimGetSeconds() - game.seconds;
- actseconds = TimGetSeconds() - GameStartedAt;
- }
-
- game.seconds = actseconds;
- if (actseconds>3599)
- actseconds = 3599;
-
- buf[4] = actseconds % 10 + 48;
- buf[3] = (actseconds / 10) % 6 + 48;
- buf[1] = (actseconds / 60) % 10 + 48;
- buf[0] = (actseconds / 600) % 10 + 48;
- WinDrawInvertedChars(buf, 5, 130, 0);
- }
-
- /*
- * Draw the field with all elements uncovered.
- */
- static void UncoverAll()
- {
- SWord x,y;
-
- if (!(game.options & ShowAll))
- return;
-
- for (y=0; y<height; y++)
- for (x=0; x<width; x++)
- if (!IsVisible(x,y)) {
- game.minefield[x][y] &= 0xf;
- DrawCell(x,y,0);
- }
- }
-
- /*
- * Draw the field; is called, if status was restored after an application
- * switch.
- */
- static void ShowFormMine()
- {
- SWord x,y;
-
- FrmDrawForm(FrmGetActiveForm());
- for (y=0; y<height; y++)
- for (x=0; x<width; x++)
- DrawCell(x,y,0);
- GameStartedAt = TimGetSeconds() - game.seconds;
- DrawMarked();
- }
-
- /*
- * show the contents of field (x,y); "recursively" (well a recursive
- * function actually would crash the application :-) uncover all
- * neighbours of a field, if it has no mine as neighbour.
- */
- static int Show(SWord x, SWord y)
- {
- push(x,y);
- while(StckPtr) {
- pop(&x,&y);
- game.minefield[x][y] &= ~COVERED;
- numuncovered++;
- DrawCell(x, y, 0);
- if (IsMine(x,y)) {
- if (game.done == IsRunning)
- game.done = IsLost;
- UncoverAll();
- } else {
- if (game.done == IsRunning && numuncovered + nummines == width*height) {
- game.done = IsWon;
- score = TimGetSeconds() - GameStartedAt;
- if (score>3599) score = 3599;
- if (score==0) score = 1;
- }
- if (game.minefield[x][y] == TMPMARK) {
- Neighbours (push, x, y);
- }
- }
- }
- return 0;
- }
-
- /*
- * highlight covered field (x,y). Is called, if you tap on an uncovered field.
- */
- static int Highlight(SWord x, SWord y)
- {
- if (InArray(x,y) && !IsMarked(x,y) && !IsVisible(x,y))
- DrawCell(x, y, ID_Gray + bitmap_offset);
- return 0;
- }
-
- /*
- * unhighlight previously highlighted field.
- */
- static int unHighlight(SWord x, SWord y)
- {
- if (InArray(x,y) && !IsMarked(x,y) && !IsVisible(x,y))
- DrawCell(x, y, 0);
- return 0;
- }
-
- static void CreateOffscreenWindow()
- {
- SWord i;
- RectangleType r;
- WinHandle tmpHandle;
- VoidHand bitmapHandle;
- BitmapPtr bitmap;
- Word err;
-
- // level also determines board layout!!
- length_bitmap = 10;
- width = 16;
- height = 14;
- bitmap_offset = 0;
-
- if (game.level > 3) {
- length_bitmap = 8;
- width = 20;
- height = 18;
- bitmap_offset = 100;
- }
- if (game.level > 7) {
- length_bitmap = 6;
- width = 26;
- height = 24;
- bitmap_offset = 200;
- }
-
- // the borders in 26x24 mode won't exactly fill the board, so we
- // erase the background.
- r.topLeft.x=0;
- r.topLeft.y=12;
- r.extent.x=160;
- r.extent.y=148;
- WinEraseRectangle(&r,0);
-
- bitmaps = WinCreateOffscreenWindow( 14*length_bitmap,
- length_bitmap,
- screenFormat,
- &err );
- tmpHandle = WinSetDrawWindow(bitmaps);
-
- for (i=0; i<13; i++) {
- bitmapHandle = DmGetResource ('Tbmp', ID_Flag + i + bitmap_offset);
- bitmap = MemHandleLock (bitmapHandle);
- WinDrawBitmap(bitmap, i*length_bitmap, 0);
- MemHandleUnlock (bitmapHandle);
- DmReleaseResource (bitmapHandle);
- }
-
- WinSetDrawWindow (tmpHandle);
- }
-
- /*
- * compute values "numuncovered" and "marked" after restoring
- * saved status from an application switch.
- */
- static void InitBoard()
- {
- SWord x, y;
-
- numuncovered = 0;
- marked = 0;
-
- // also sets "height" and "width"
- CreateOffscreenWindow();
-
- for (y=0; y<height; y++)
- for (x=0; x<width; x++) {
- if (IsMarked(x,y))
- marked++;
- if (IsVisible(x,y))
- numuncovered++;
- }
-
- }
-
- /*
- * Mines are distributed on the board; depending on choosen mode
- * the position of the first tap or corners are also taken into
- * account.
- */
- static void SetupBoard (SWord tap_x, SWord tap_y)
- {
- SWord ix,iy,pieces;
-
- SysRandom(TimGetSeconds());
- for (pieces=0; pieces<nummines; pieces++) {
- do {
- ix = SysRandom(0) % (160 / length_bitmap);
- iy = SysRandom(0) % (140 / length_bitmap);
- } while ( IsMine(ix,iy) // already has mine
- || ((game.options & FirstNoMine) && // field of first tap
- ((ix == tap_x) && (iy == tap_y)) )
- || ((game.options & CornerNoMine) && // one of the corners
- ( ((ix == 0) && (iy == 0))
- || ((ix == 0) && (iy == height-1))
- || ((ix == width-1) && (iy == 0))
- || ((ix == width-1) && (iy == height-1)) ))
- );
- game.minefield[ix][iy] = MINE+COVERED;
- }
-
- for (iy=0; iy<height; iy++)
- for (ix=0; ix<width; ix++)
- if (!IsMine(ix,iy))
- game.minefield[ix][iy] = countMines(ix,iy)+COVERED;
- }
-
- /*
- * Initialize the game and make all necessary drawings.
- * Computing an initial mine layout is delayed until after the
- * first tap.
- */
- static void InitFormMine()
- {
- SWord x,y;
-
- if (bitmaps) {
- WinDeleteWindow(bitmaps, false);
- CreateOffscreenWindow();
- }
-
- FrmDrawForm(FrmGetActiveForm());
-
- for (y=0; y<height; y++) {
- for (x=0; x<width; x++) {
- game.minefield[x][y] = COVERED;
- DrawCell(x, y, ID_Covered + bitmap_offset);
- }
- }
-
- numuncovered = marked = StckPtr = score = 0;
- game.done = IsToBeStarted;
- isHighlighted = false;
- DrawMarked();
- }
-
- /*
- * Handle any action necessary, if you tap on field (x,y);
- * "ctrl == true" means, you've also pressed the PageUp or PageDown button;
- * in that case, a covered unmarked field is marked or a covered marked
- * field is unmarked. Else, a covered field is uncovered.
- */
- static Boolean HandlePenDownEvent(SWord x, SWord y, Boolean ctrl)
- {
- if (!InArray(x,y))
- return false;
-
- if (game.done == IsToBeStarted) {
- SetupBoard(x,y); // here to take first tap into account.
- game.done = IsRunning;
- GameStartedAt = TimGetSeconds();
- game.seconds = 0;
- if (game.options & CornerNoMine) {
- Show(0,0);
- Show(width-1,height-1);
- Show(width-1,0);
- Show(0,height-1);
- }
- }
-
- switch (ctrl) {
- case false:
- if (IsVisible(x,y)) {
- if (foundMines(x,y) == (game.minefield[x][y] & 0xf)) {
- Neighbours (Show, x, y);
- } else {
- Neighbours (Highlight, x, y);
- isHighlighted = true;
- }
- } else {
- if (game.options & AlternateControl) { // "Dylan style controls"
- if (!(game.minefield[x][y] & MARKED)) {
- game.minefield[x][y] |= MARKED;
- DrawCell(x, y, 0);
- marked++;
- } else {
- game.minefield[x][y] &= ~MARKED;
- marked--;
- Show(x,y);
- }
- DrawMarked();
- } else {
- if (!(game.minefield[x][y] & MARKED)) {
- Show(x,y);
- }
- }
- }
- break;
- case true:
- if (!IsVisible(x,y)) {
- if (!(game.minefield[x][y] & MARKED)) {
- game.minefield[x][y] |= MARKED;
- DrawCell(x, y, 0);
- marked++;
- } else {
- game.minefield[x][y] &= ~MARKED;
- DrawCell(x, y, 0);
- marked--;
- }
- DrawMarked();
- }
- break;
- }
-
- return true;
- }
-
- /*
- * Dispatch any menu events we have to handle
- */
- static Boolean MyHandleMenuEvent(EventPtr e)
- {
- Boolean handled;
-
- CALLBACK_PROLOGUE
- handled = false;
-
- MenuEraseStatus (MenuGetActiveMenu());
- switch(e->data.menu.itemID) {
-
- case ID_MenuItem: /* New Game */
- InitFormMine();
- handled = true;
- break;
-
- case ID_MenuItem+10: /* About Pilot Mines */
- FrmPopupForm(ID_FrmAbout);
- handled = true;
- break;
-
- case ID_MenuItem+11: /* Preferences */
- FrmPopupForm(ID_FrmPreferences);
- handled = true;
- break;
-
- case ID_MenuItem+12: /* High Scores */
- FrmPopupForm(ID_FrmHighScores);
- handled = true;
- break;
-
- case ID_MenuItem+13: /* Reset High Scores */
- InitHighScore();
- FrmPopupForm(ID_FrmHighScores);
- handled = true;
- break;
-
- default:
- break;
- }
-
- CALLBACK_EPILOGUE
- return handled;
- }
-
- /*
- * dispatch all events we have to handle in the main form (the one
- * showing the mine field)
- */
- static Boolean MineFormHandleEvent(EventPtr e)
- {
- Boolean handled;
- static SWord saveX, saveY;
-
- CALLBACK_PROLOGUE
- handled = false;
-
- if (game.done == Restart)
- InitFormMine();
-
- if (game.done == IsRunning)
- DrawTime();
-
- if (game.done == HighScoreWon) {
- if (!FrmAlert(GameOver)) {
- InitFormMine();
- } else {
- game.done = IsFinishedWon;
- }
- }
-
- if (game.done == HighScoreLost) {
- if (!FrmAlert(GameOver+1)) {
- InitFormMine();
- } else {
- game.done = IsFinishedLost;
- }
- }
-
- switch (e->eType) {
-
- case menuEvent:
- handled = MyHandleMenuEvent(e);
- break;
-
- case frmOpenEvent:
- handled = true;
- break;
-
- case keyDownEvent:
- switch(e->data.keyDown.chr) {
- case 'n':
- InitFormMine();
- handled = true;
- break;
-
- case 'h':
- FrmPopupForm(ID_FrmHighScores);
- handled = true;
- break;
-
- #ifdef ENGLISH
- case 'p':
- #else
- case 'e':
- #endif
- FrmPopupForm(ID_FrmPreferences);
- handled = true;
- break;
- }
- break;
-
- case penDownEvent:
- saveX=e->screenX / length_bitmap;
- saveY=e->screenY / length_bitmap - 2;
- handled = HandlePenDownEvent(saveX, saveY,
- (KeyCurrentState() & (keyBitPageUp | keyBitPageDown))!=0);
-
- switch (game.done) {
- case IsWon:
- game.done = IsFinishedWon;
- if (isHighScore((int)score))
- FrmPopupForm(ID_FrmHighScores);
- else
- if (!FrmAlert(GameOver))
- InitFormMine();
- break;
- case IsLost:
- game.done = IsFinishedLost;
- if (!FrmAlert(GameOver+1))
- InitFormMine();
- break;
- }
-
- break;
-
- case penUpEvent:
- if (isHighlighted) {
- Neighbours (unHighlight, saveX, saveY);
- isHighlighted = false;
- }
- handled = true;
- break;
-
- default:
- break;
- }
-
- CALLBACK_EPILOGUE
- return handled;
- }
-
- /**
- * About Form
- */
- static Boolean AboutFormHandleEvent(EventPtr e)
- {
- Boolean handled;
-
- CALLBACK_PROLOGUE
- handled = false;
-
- switch (e->eType) {
-
- case frmOpenEvent:
- FrmDrawForm(FrmGetActiveForm());
- handled = true;
- break;
-
- case ctlSelectEvent:
- if (e->data.ctlSelect.controlID == ID_FrmAboutButton) {
- FrmReturnToForm(0);
- handled = true;
- break;
- }
- break;
-
- default:
- break;
- }
-
- CALLBACK_EPILOGUE
- return handled;
- }
-
- /**
- * Preferences Form
- */
-
- /*
- * preset the radio buttons for selecting the difficulty level and
- * the check box, that controls if all fields are uncovered, if you
- * loose a game
- */
- static void InitFormPref()
- {
- FormPtr frm = FrmGetActiveForm();
- FrmSetControlGroupSelection(frm, 1, ID_PrefButton + (game.level % 4));
- FrmSetControlGroupSelection(frm, 2, ID_PrefButton + 10 + (game.level / 4));
- FrmSetControlValue(frm, FrmGetObjectIndex(frm, ID_PrefButton + 6),
- (game.options & ShowAll));
- FrmSetControlValue(frm, FrmGetObjectIndex(frm, ID_PrefButton + 7),
- (game.options & AlternateControl));
- FrmSetControlValue(frm, FrmGetObjectIndex(frm, ID_PrefButton + 8),
- (game.options & FirstNoMine));
- FrmSetControlValue(frm, FrmGetObjectIndex(frm, ID_PrefButton + 9),
- (game.options & CornerNoMine));
- }
-
- /*
- * handle any events in the preferences form; i.e. setting game
- * difficulty level and "Uncover all" check box.
- */
- static Boolean PrefFormHandleEvent(EventPtr e)
- {
- Boolean handled;
-
- CALLBACK_PROLOGUE
- handled = false;
-
- switch (e->eType) {
-
- case frmOpenEvent:
- FrmDrawForm(FrmGetActiveForm());
- handled = true;
- break;
-
- case ctlSelectEvent:
- switch (e->data.ctlSelect.controlID) {
-
- // look at status of radio buttons and save level information accordingly
- case ID_PrefButton + 4: /* Ok */
- game.level = FrmGetObjectId(FrmGetActiveForm(),
- FrmGetControlGroupSelection(FrmGetActiveForm(), 1))
- - ID_PrefButton;
- game.level += ( FrmGetObjectId(FrmGetActiveForm(),
- FrmGetControlGroupSelection(FrmGetActiveForm(), 2))
- - ID_PrefButton - 10 ) * 4;
- nummines = levelmines[game.level];
-
- FrmReturnToForm(0);
- game.done = Restart;
- handled = true;
- break;
-
- // don't do anything, simply return to main form
- case ID_PrefButton + 5: /* Cancel */
- FrmReturnToForm(0);
- handled = true;
- break;
-
- // toggle "uncover all" status information
- case ID_PrefButton + 6: /* Show all */
- game.options ^= ShowAll;
- handled = true;
- break;
-
- // select alternate "Dylan style controls" (Dylan Ginsburg)
- case ID_PrefButton + 7:
- game.options ^= AlternateControl;
- handled = true;
- break;
-
- // select alternate "First field is never a mine" (Lucas Bremgartner)
- case ID_PrefButton + 8:
- game.options ^= FirstNoMine;
- handled = true;
- break;
-
- // select alternate "No mines in corners" (Laurent Thaler)
- case ID_PrefButton + 9:
- game.options ^= CornerNoMine;
- handled = true;
- break;
- }
-
- break;
-
- default:
- break;
- }
-
- CALLBACK_EPILOGUE
- return handled;
- }
-
-
- /**
- * dispatch all previously unhandled events, and set event handling
- * routines for the different forms
- */
- static Boolean ApplicationHandleEvent(EventPtr e)
- {
- Boolean handled;
-
- CALLBACK_PROLOGUE
- handled = false;
-
- if (e->eType == frmLoadEvent) {
- Word frmId = e->data.frmLoad.formID;
- FormPtr frm = FrmInitForm(frmId);
-
- FrmSetActiveForm(frm);
-
- switch (frmId) {
- case ID_FrmMine:
- if (game.done == Restart)
- InitFormMine();
- else
- ShowFormMine();
- FrmSetEventHandler(frm, MineFormHandleEvent);
- handled = true;
- break;
-
- case ID_FrmAbout:
- FrmSetEventHandler(frm, AboutFormHandleEvent);
- handled = true;
- break;
-
- case ID_FrmPreferences:
- InitFormPref();
- FrmSetEventHandler(frm, PrefFormHandleEvent);
- handled = true;
- break;
-
- case ID_FrmHighScores:
- FrmSetEventHandler(frm, HighscoresFormHandleEvent);
- handled = true;
- break;
- }
-
- }
-
- CALLBACK_EPILOGUE
- return handled;
- }
-
-
- /**
- * Database (here: game status information) handling routines.
- */
- static Err OpenDatabase(void)
- {
- UInt index = 0;
- VoidHand RecHandle;
- VoidPtr RecPointer;
- Err err;
-
- // Create database, if it doesn't exist, and save default game status.
- if (!(pmDB = DmOpenDatabaseByTypeCreator('Data', 'tpPM', dmModeReadWrite))) {
- if ((err = DmCreateDatabase(0, "PilotMinesDB", 'tpPM', 'Data', false)))
- return err;
- pmDB = DmOpenDatabaseByTypeCreator('Data', 'tpPM', dmModeReadWrite);
-
- RecHandle = DmNewRecord(pmDB, &index, sizeof(game));
- DmWrite(MemHandleLock(RecHandle), 0, &game, sizeof(game));
- MemHandleUnlock(RecHandle);
- DmReleaseRecord(pmDB, index, true);
- }
-
- // Load a saved game status.
- RecHandle = DmGetRecord(pmDB, 0);
- RecPointer = MemHandleLock(RecHandle);
- MemMove(&game, RecPointer, sizeof(game));
-
- // convert v1 database to v2 format
- if (game.version == 1) {
- int i, j;
- game.version = 2;
- game.done = Restart;
- for (i=0; i<4; i++) {
- for (j=0; j<5; j++) {
- MemMove(&game.hscore[i][j], RecPointer+230+(i*5+j)*18, 18);
- MemSet(&game.hscore[i+4][j], 18, 0);
- MemSet(&game.hscore[i+8][j], 18, 0);
- }
- }
- game.seconds = 0;
- }
-
- MemHandleUnlock(RecHandle);
- DmReleaseRecord(pmDB, 0, true);
-
- return 0;
- }
-
- /*
- * Save game status information.
- */
- static void SaveStatus()
- {
- VoidPtr p = MemHandleLock(DmResizeRecord(pmDB, 0, sizeof(game)));
- game.seconds = TimGetSeconds() - GameStartedAt;
- DmWrite(p, 0, &game, sizeof(game));
- MemPtrUnlock(p);
- DmReleaseRecord(pmDB, 0, true);
- }
-
- /*
- * Main program.
- */
- DWord PilotMain(Word cmd, Ptr cmdPBP, Word launchFlags)
- {
- if (cmd==sysAppLaunchCmdNormalLaunch) {
- EventType e;
- short err;
-
- // initialize game status information
- game.level = 2;
- game.version = 2;
- game.options = ShowAll | FirstNoMine | AlternateControl;
- game.done = Restart;
- game.seconds = 0;
- InitHighScore();
-
- // load a saved game
- if ((err = OpenDatabase()))
- return err;
-
- // restore game status from loaded game, if necessary
- nummines = levelmines[game.level];
- InitBoard();
-
- // is needed on PalmOS 3.3, but why...
- WinSetActiveWindow(WinGetDisplayWindow());
- FrmGotoForm(ID_FrmMine);
-
- do {
- EvtGetEvent(&e,35);
-
- // don't make noise when pressing PgUp/PgDn
- if (e.eType == keyDownEvent &&
- (e.data.keyDown.modifiers & commandKeyMask) &&
- (e.data.keyDown.chr == pageUpChr || e.data.keyDown.chr == pageDownChr))
- continue;
-
- if (SysHandleEvent(&e)) {
- continue;
- }
-
- if (MenuHandleEvent(NULL, &e, &err)) {
- continue;
- }
-
- if (ApplicationHandleEvent(&e)) {
- continue;
- }
-
- FrmDispatchEvent( &e );
-
- } while (e.eType != appStopEvent);
-
- FrmCloseAllForms();
- SaveStatus();
- DmCloseDatabase(pmDB);
- WinDeleteWindow(bitmaps, false);
- }
-
- return 0;
- }
-