2016-07-21 00:53:52 +00:00
|
|
|
//
|
|
|
|
// ui.c
|
|
|
|
// a2bejwld
|
|
|
|
//
|
|
|
|
// Created by Jeremy Rand on 2016-07-20.
|
|
|
|
// Copyright © 2016 Jeremy Rand. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
#include <conio.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2016-08-20 04:08:29 +00:00
|
|
|
#include <string.h>
|
2016-07-21 00:53:52 +00:00
|
|
|
|
|
|
|
#include "ui.h"
|
2016-07-22 15:43:18 +00:00
|
|
|
#include "anim.h"
|
2016-07-21 00:53:52 +00:00
|
|
|
#include "dbllores.h"
|
|
|
|
#include "game.h"
|
2016-07-24 22:22:37 +00:00
|
|
|
#include "joystick.h"
|
2016-08-24 00:23:26 +00:00
|
|
|
#include "machine.h"
|
2016-08-19 04:08:38 +00:00
|
|
|
#include "mouseWrapper.h"
|
2016-12-20 05:05:41 +00:00
|
|
|
#include "sound.h"
|
2016-08-19 04:08:38 +00:00
|
|
|
|
|
|
|
|
2016-08-20 04:08:29 +00:00
|
|
|
// Defines
|
|
|
|
|
2016-08-23 03:47:29 +00:00
|
|
|
#define SAVE_OPTIONS_FILE "a2bejwld.opts"
|
2016-12-20 05:05:41 +00:00
|
|
|
#define VERSION "v2.0"
|
2016-08-20 04:08:29 +00:00
|
|
|
|
|
|
|
|
2016-08-19 04:08:38 +00:00
|
|
|
// Typedefs
|
|
|
|
|
|
|
|
typedef struct tGameOptions {
|
2016-08-20 04:08:29 +00:00
|
|
|
bool optionsSaved;
|
2016-08-19 04:08:38 +00:00
|
|
|
bool enableJoystick;
|
|
|
|
bool enableMouse;
|
|
|
|
bool enableSound;
|
2016-12-24 03:51:45 +00:00
|
|
|
tSlot mockingBoardSlot;
|
|
|
|
bool enableSpeechChip;
|
2016-08-19 04:08:38 +00:00
|
|
|
} tGameOptions;
|
2016-07-21 04:39:06 +00:00
|
|
|
|
|
|
|
|
2016-07-22 17:04:47 +00:00
|
|
|
// Forward delcarations
|
|
|
|
|
2016-07-22 04:45:07 +00:00
|
|
|
static void refreshSquare(tSquare square);
|
|
|
|
static void refreshScore(tScore score);
|
|
|
|
static void refreshLevel(tLevel level);
|
|
|
|
|
2016-07-24 22:22:37 +00:00
|
|
|
static bool joystickChangedCallback(tJoyState *oldState, tJoyState *newState);
|
|
|
|
static bool joystickNoChangeCallback(tJoyState *oldState);
|
|
|
|
|
2016-08-19 04:08:38 +00:00
|
|
|
static bool mouseSelectSquare(tSquare square);
|
2016-08-23 03:47:29 +00:00
|
|
|
static bool swapDir(tDirection dir);
|
2016-08-19 04:08:38 +00:00
|
|
|
|
2016-07-22 04:45:07 +00:00
|
|
|
|
2016-07-22 17:04:47 +00:00
|
|
|
// Globals
|
|
|
|
|
2016-07-21 00:53:52 +00:00
|
|
|
static tSquare gSelectedSquare = 0;
|
2016-07-21 19:33:31 +00:00
|
|
|
static uint8_t gScoreBar = 0;
|
2016-07-21 00:53:52 +00:00
|
|
|
|
2016-07-22 04:45:07 +00:00
|
|
|
static tGameCallbacks gCallbacks = {
|
|
|
|
refreshSquare,
|
|
|
|
refreshScore,
|
2016-07-22 17:04:47 +00:00
|
|
|
refreshLevel,
|
2016-08-17 04:07:00 +00:00
|
|
|
|
2016-07-22 17:04:47 +00:00
|
|
|
beginClearGemAnim,
|
|
|
|
addClearAtSquare,
|
|
|
|
undoClearAtSquare,
|
2016-08-17 04:07:00 +00:00
|
|
|
playSoundForExplodingGem,
|
|
|
|
playSoundForStarringGem,
|
|
|
|
playSoundForSpecialGem,
|
2016-07-22 17:04:47 +00:00
|
|
|
endClearGemAnim,
|
2016-08-17 04:07:00 +00:00
|
|
|
|
2016-07-22 19:48:49 +00:00
|
|
|
swapSquares,
|
2016-08-17 04:07:00 +00:00
|
|
|
|
2016-07-22 21:45:15 +00:00
|
|
|
beginDropAnim,
|
|
|
|
dropSquareFromTo,
|
|
|
|
dropSquareFromOffscreen,
|
|
|
|
endDropAnim
|
2016-07-22 04:45:07 +00:00
|
|
|
};
|
|
|
|
|
2016-07-21 00:53:52 +00:00
|
|
|
|
2016-07-24 22:22:37 +00:00
|
|
|
static tJoyCallbacks gJoyCallbacks = {
|
|
|
|
joystickChangedCallback,
|
|
|
|
joystickNoChangeCallback,
|
|
|
|
25, // Read poll time
|
|
|
|
40, // Initial no change poll time
|
|
|
|
10 // Subsequent no change poll time
|
|
|
|
};
|
|
|
|
|
2016-08-19 04:08:38 +00:00
|
|
|
static tMouseCallbacks gMouseCallbacks = {
|
|
|
|
mouseSelectSquare,
|
2016-08-23 03:47:29 +00:00
|
|
|
swapDir,
|
2016-08-19 04:08:38 +00:00
|
|
|
};
|
|
|
|
|
2016-07-24 22:22:37 +00:00
|
|
|
static bool gShouldSave = false;
|
|
|
|
|
2016-08-19 04:08:38 +00:00
|
|
|
static tGameOptions gGameOptions = {
|
2016-12-24 03:51:45 +00:00
|
|
|
false, // optionsSaved
|
|
|
|
false, // enableJoystick
|
|
|
|
true, // enableMouse
|
|
|
|
true, // enableSound
|
|
|
|
0, // mockingBoardSlot
|
|
|
|
false // enableSpeechChip
|
2016-08-19 04:08:38 +00:00
|
|
|
};
|
|
|
|
|
2016-07-24 22:22:37 +00:00
|
|
|
|
2016-07-22 17:04:47 +00:00
|
|
|
// Implementation
|
|
|
|
|
2016-08-19 04:08:38 +00:00
|
|
|
|
2016-12-24 03:51:45 +00:00
|
|
|
static void badThingHappened(void)
|
2016-12-20 05:05:41 +00:00
|
|
|
{
|
|
|
|
if (gGameOptions.enableSound)
|
|
|
|
printf("\007");
|
2016-08-19 04:08:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-22 05:11:36 +00:00
|
|
|
static void showAndClearDblLoRes(void)
|
2016-07-21 00:53:52 +00:00
|
|
|
{
|
|
|
|
showDblLoRes();
|
|
|
|
clearDblLoRes();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-12-24 03:51:45 +00:00
|
|
|
static void saveOptions(void)
|
2016-08-20 04:08:29 +00:00
|
|
|
{
|
|
|
|
FILE *optionsFile = fopen(SAVE_OPTIONS_FILE, "wb");
|
2016-08-23 03:47:29 +00:00
|
|
|
|
2016-08-20 04:08:29 +00:00
|
|
|
if (optionsFile != NULL) {
|
|
|
|
gGameOptions.optionsSaved = true;
|
|
|
|
fwrite(&gGameOptions, sizeof(gGameOptions), 1, optionsFile);
|
|
|
|
fclose(optionsFile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-12-24 03:51:45 +00:00
|
|
|
static bool loadOptions(void)
|
2016-08-20 04:08:29 +00:00
|
|
|
{
|
|
|
|
FILE *optionsFile = fopen(SAVE_OPTIONS_FILE, "rb");
|
|
|
|
|
|
|
|
if (optionsFile == NULL) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fread(&gGameOptions, sizeof(gGameOptions), 1, optionsFile) != 1) {
|
|
|
|
fclose(optionsFile);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(optionsFile);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-12-24 03:51:45 +00:00
|
|
|
static void applyNewOptions(tGameOptions *newOptions)
|
2016-08-20 04:08:29 +00:00
|
|
|
{
|
|
|
|
bool oldEnableMouse = gGameOptions.enableMouse;
|
|
|
|
|
|
|
|
// If there is no change in game options, then nothing to do.
|
|
|
|
if (memcmp(newOptions, &gGameOptions, sizeof(gGameOptions)) == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-12-24 03:51:45 +00:00
|
|
|
if ((gGameOptions.enableSound != newOptions->enableSound) ||
|
|
|
|
(gGameOptions.mockingBoardSlot != newOptions->mockingBoardSlot) ||
|
|
|
|
(gGameOptions.enableSpeechChip != gGameOptions.enableSpeechChip)) {
|
|
|
|
// If the sound parameters have changed, then re-init or shutdown sounds
|
|
|
|
if (newOptions->enableSound) {
|
|
|
|
soundInit(newOptions->mockingBoardSlot, newOptions->enableSpeechChip);
|
|
|
|
} else {
|
|
|
|
soundShutdown();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-20 04:08:29 +00:00
|
|
|
memcpy(&gGameOptions, newOptions, sizeof(gGameOptions));
|
|
|
|
gGameOptions.optionsSaved = false;
|
|
|
|
if (oldEnableMouse != gGameOptions.enableMouse) {
|
|
|
|
if (gGameOptions.enableMouse) {
|
|
|
|
gGameOptions.enableMouse = initMouse(&gMouseCallbacks);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
saveOptions();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-12-24 03:51:45 +00:00
|
|
|
static void showCursor(void)
|
|
|
|
{
|
|
|
|
revers(true);
|
|
|
|
cputc(' ');
|
|
|
|
revers(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void replaceCursor(char ch)
|
|
|
|
{
|
|
|
|
gotox(wherex() - 1);
|
|
|
|
cputc(ch);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void getSoundOptions(tGameOptions *newOptions)
|
|
|
|
{
|
|
|
|
char ch;
|
|
|
|
|
|
|
|
cputs("\n\nEnable sounds? (Y/N) ");
|
|
|
|
showCursor();
|
|
|
|
while (true) {
|
|
|
|
ch = cgetc();
|
|
|
|
if ((ch == 'N') ||
|
|
|
|
(ch == 'n')) {
|
|
|
|
newOptions->enableSound = false;
|
|
|
|
newOptions->mockingBoardSlot = 0;
|
|
|
|
newOptions->enableSpeechChip = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ((ch == 'Y') ||
|
|
|
|
(ch == 'y')) {
|
|
|
|
replaceCursor(ch);
|
|
|
|
newOptions->enableSound = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
badThingHappened();
|
|
|
|
}
|
|
|
|
|
|
|
|
cputs("\n\rMockingBoard slot number (0 for none) ");
|
|
|
|
showCursor();
|
|
|
|
while (true) {
|
|
|
|
ch = cgetc();
|
|
|
|
if (ch == '0') {
|
|
|
|
newOptions->mockingBoardSlot = 0;
|
|
|
|
newOptions->enableSpeechChip = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ((ch >= '1') &&
|
|
|
|
(ch <= '7')) {
|
|
|
|
replaceCursor(ch);
|
|
|
|
newOptions->mockingBoardSlot = (ch - '0');
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
badThingHappened();
|
|
|
|
}
|
|
|
|
|
|
|
|
cputs("\n\rMockingBoard has a speech chip? (Y/N) ");
|
|
|
|
showCursor();
|
|
|
|
while (true) {
|
|
|
|
ch = cgetc();
|
|
|
|
if ((ch == 'N') ||
|
|
|
|
(ch == 'n')) {
|
|
|
|
newOptions->enableSpeechChip = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ((ch == 'Y') ||
|
|
|
|
(ch == 'y')) {
|
|
|
|
newOptions->enableSpeechChip = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
badThingHappened();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void selectOptions(void)
|
2016-08-20 04:08:29 +00:00
|
|
|
{
|
|
|
|
tGameOptions newOptions;
|
|
|
|
|
|
|
|
unshowDblLoRes();
|
|
|
|
videomode(VIDEOMODE_80x24);
|
|
|
|
clrscr();
|
|
|
|
|
|
|
|
memcpy(&newOptions, &gGameOptions, sizeof(newOptions));
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
clrscr();
|
|
|
|
printf(
|
|
|
|
// 0000000001111111111222222222233333333334444444444555555555566666666667
|
|
|
|
// 1234567890123456789012345678901234567890123456789012345678901234567890
|
2016-08-23 05:06:14 +00:00
|
|
|
" Apple // Bejeweled\n"
|
2016-08-20 04:08:29 +00:00
|
|
|
" Options\n"
|
|
|
|
"\n"
|
|
|
|
" J - Joystick control - %s\n"
|
|
|
|
" M - Mouse control - %s\n"
|
2016-12-24 03:51:45 +00:00
|
|
|
" S - Sound - %s\n",
|
2016-08-20 04:08:29 +00:00
|
|
|
(newOptions.enableJoystick ? "Enable" : "Disabled"),
|
|
|
|
(newOptions.enableMouse ? "Enable" : "Disabled"),
|
|
|
|
(newOptions.enableSound ? "Enable" : "Disabled"));
|
|
|
|
|
2016-12-24 03:51:45 +00:00
|
|
|
if (newOptions.enableSound) {
|
|
|
|
if (newOptions.mockingBoardSlot > 0) {
|
|
|
|
printf(
|
|
|
|
// 0000000001111111111222222222233333333334444444444555555555566666666667
|
|
|
|
// 1234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
|
" MockingBoard - Slot %u\n"
|
|
|
|
" Speech Chip - %s\n",
|
|
|
|
newOptions.mockingBoardSlot,
|
|
|
|
(newOptions.enableSpeechChip ? "Enable" : "Disable"));
|
|
|
|
} else {
|
|
|
|
printf(
|
|
|
|
// 0000000001111111111222222222233333333334444444444555555555566666666667
|
|
|
|
// 1234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
|
" MockingBoard - Disabled\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printf(
|
|
|
|
// 0000000001111111111222222222233333333334444444444555555555566666666667
|
|
|
|
// 1234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
|
"\n"
|
|
|
|
" Type a letter to change a setting or any other key to save settings\n"
|
|
|
|
" and continue");
|
|
|
|
|
2016-08-20 04:08:29 +00:00
|
|
|
switch (cgetc()) {
|
|
|
|
case 'j':
|
|
|
|
case 'J':
|
|
|
|
newOptions.enableJoystick = !newOptions.enableJoystick;
|
|
|
|
if (newOptions.enableJoystick) {
|
|
|
|
newOptions.enableMouse = false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'm':
|
|
|
|
case 'M':
|
|
|
|
newOptions.enableMouse = !newOptions.enableMouse;
|
|
|
|
if (newOptions.enableMouse) {
|
|
|
|
newOptions.enableJoystick = false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 's':
|
|
|
|
case 'S':
|
2016-12-24 03:51:45 +00:00
|
|
|
getSoundOptions(&newOptions);
|
2016-08-20 04:08:29 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
applyNewOptions(&newOptions);
|
|
|
|
clrscr();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-21 00:53:52 +00:00
|
|
|
void printInstructions(void)
|
|
|
|
{
|
|
|
|
int seed = 0;
|
|
|
|
|
|
|
|
unshowDblLoRes();
|
|
|
|
videomode(VIDEOMODE_80x24);
|
|
|
|
clrscr();
|
|
|
|
printf(
|
2016-07-21 19:33:31 +00:00
|
|
|
// 0000000001111111111222222222233333333334444444444555555555566666666667
|
|
|
|
// 1234567890123456789012345678901234567890123456789012345678901234567890
|
2016-08-23 05:06:14 +00:00
|
|
|
" Apple // Bejeweled (" VERSION ")\n"
|
2016-07-21 19:33:31 +00:00
|
|
|
" by Jeremy Rand\n"
|
2016-07-21 00:53:52 +00:00
|
|
|
"\n"
|
2016-08-19 04:08:38 +00:00
|
|
|
" Use I-J-K-M, the arrow keys, joystick or mouse to move your selection.\n"
|
|
|
|
" Hold either apple key, joystick or mouse button and move your selection\n"
|
|
|
|
" to swap two jewels and match 3 or more jewels. When you match three\n"
|
2016-07-26 05:26:24 +00:00
|
|
|
" jewels, they disappear and new jewels will drop from the top.\n"
|
2016-07-21 00:53:52 +00:00
|
|
|
"\n"
|
2016-07-21 19:33:31 +00:00
|
|
|
" If you match four jewels or three jewels in two directions, then the\n"
|
|
|
|
" jewel does not disappear. Match it again and it explodes taking more\n"
|
2016-07-22 04:45:07 +00:00
|
|
|
" jewels with it. Match five jewels and a special jewel will appear.\n"
|
|
|
|
" Swap it with any other jewel and all jewels of that colour will\n"
|
|
|
|
" disappear.\n"
|
2016-07-21 19:33:31 +00:00
|
|
|
"\n"
|
|
|
|
" When the score bar on the right fills, the board reloads and you level\n"
|
|
|
|
" up. Play ends when no more matches can be made.\n"
|
|
|
|
"\n"
|
|
|
|
" Press Q or escape to quit at any time.\n"
|
2016-07-21 00:53:52 +00:00
|
|
|
" Press R to start a new game.\n"
|
2016-08-19 04:08:38 +00:00
|
|
|
" Press O to select options.\n"
|
2016-07-22 04:45:07 +00:00
|
|
|
" Press H to get a hint.\n"
|
|
|
|
" Press ? to see this info again.\n"
|
2016-07-21 00:53:52 +00:00
|
|
|
"\n"
|
|
|
|
" Press any key to start");
|
|
|
|
|
|
|
|
// The amount of time the user waits to read the in
|
|
|
|
while (!kbhit())
|
|
|
|
seed++;
|
|
|
|
|
|
|
|
srand(seed);
|
|
|
|
|
2016-08-20 04:08:29 +00:00
|
|
|
switch (cgetc()) {
|
|
|
|
case 'o':
|
|
|
|
case 'O':
|
|
|
|
selectOptions();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2016-08-19 04:08:38 +00:00
|
|
|
|
|
|
|
clrscr();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-21 04:39:06 +00:00
|
|
|
static void refreshSquare(tSquare square)
|
|
|
|
{
|
|
|
|
drawBgSquare(square);
|
|
|
|
drawGemAtSquare(square);
|
2016-07-21 04:55:29 +00:00
|
|
|
|
|
|
|
if (gemIsStarredAtSquare(square))
|
|
|
|
starGem(square);
|
2016-07-21 04:39:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-21 00:53:52 +00:00
|
|
|
static void drawBoard(void)
|
|
|
|
{
|
|
|
|
tSquare square;
|
|
|
|
|
|
|
|
for (square = MIN_SQUARE; square <= MAX_SQUARE; square++) {
|
2016-07-21 04:39:06 +00:00
|
|
|
refreshSquare(square);
|
2016-07-21 00:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
selectSquare(gSelectedSquare);
|
2016-08-24 05:18:19 +00:00
|
|
|
moveMouseToSquare(gSelectedSquare);
|
2016-07-21 19:33:31 +00:00
|
|
|
drawScore(gScoreBar);
|
2016-07-21 00:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void quitGame(void)
|
|
|
|
{
|
|
|
|
unshowDblLoRes();
|
|
|
|
videomode(VIDEOMODE_40x24);
|
|
|
|
clrscr();
|
2016-08-19 04:08:38 +00:00
|
|
|
shutdownMouse();
|
2016-12-24 03:51:45 +00:00
|
|
|
soundShutdown();
|
2016-08-24 00:23:26 +00:00
|
|
|
|
|
|
|
uninitMachine();
|
|
|
|
|
2016-07-21 00:53:52 +00:00
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-08-20 04:08:29 +00:00
|
|
|
static void moveDir(tDirection dir)
|
2016-07-24 22:22:37 +00:00
|
|
|
{
|
|
|
|
tSquare oldSquare = gSelectedSquare;
|
|
|
|
tPos x = SQUARE_TO_X(gSelectedSquare);
|
|
|
|
tPos y = SQUARE_TO_Y(gSelectedSquare);
|
|
|
|
|
2016-08-20 04:08:29 +00:00
|
|
|
switch (dir) {
|
|
|
|
case DIR_UP:
|
|
|
|
if (y == 0)
|
|
|
|
y = BOARD_SIZE - 1;
|
|
|
|
else
|
|
|
|
y--;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DIR_DOWN:
|
|
|
|
if (y == BOARD_SIZE - 1)
|
|
|
|
y = 0;
|
|
|
|
else
|
|
|
|
y++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DIR_LEFT:
|
|
|
|
if (x == 0)
|
|
|
|
x = BOARD_SIZE - 1;
|
|
|
|
else
|
|
|
|
x--;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DIR_RIGHT:
|
|
|
|
if (x == BOARD_SIZE - 1)
|
|
|
|
x = 0;
|
|
|
|
else
|
|
|
|
x++;
|
|
|
|
break;
|
|
|
|
}
|
2016-07-21 00:53:52 +00:00
|
|
|
|
|
|
|
gSelectedSquare = XY_TO_SQUARE(x, y);
|
|
|
|
|
2016-07-21 04:39:06 +00:00
|
|
|
refreshSquare(oldSquare);
|
2016-07-21 00:53:52 +00:00
|
|
|
selectSquare(gSelectedSquare);
|
2016-08-24 05:18:19 +00:00
|
|
|
moveMouseToSquare(gSelectedSquare);
|
2016-07-21 00:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-08-20 04:08:29 +00:00
|
|
|
static void moveTwoDirs(tDirection dir1, tDirection dir2)
|
2016-07-21 00:53:52 +00:00
|
|
|
{
|
|
|
|
tSquare oldSquare = gSelectedSquare;
|
|
|
|
tPos x = SQUARE_TO_X(gSelectedSquare);
|
|
|
|
tPos y = SQUARE_TO_Y(gSelectedSquare);
|
|
|
|
|
2016-08-20 04:08:29 +00:00
|
|
|
switch (dir1) {
|
|
|
|
case DIR_UP:
|
|
|
|
if (y == 0)
|
|
|
|
y = BOARD_SIZE - 1;
|
|
|
|
else
|
|
|
|
y--;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DIR_DOWN:
|
|
|
|
if (y == BOARD_SIZE - 1)
|
|
|
|
y = 0;
|
|
|
|
else
|
|
|
|
y++;
|
|
|
|
break;
|
2016-07-21 04:39:06 +00:00
|
|
|
}
|
|
|
|
|
2016-08-20 04:08:29 +00:00
|
|
|
switch (dir2) {
|
|
|
|
case DIR_LEFT:
|
|
|
|
if (x == 0)
|
|
|
|
x = BOARD_SIZE - 1;
|
|
|
|
else
|
|
|
|
x--;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DIR_RIGHT:
|
|
|
|
if (x == BOARD_SIZE - 1)
|
|
|
|
x = 0;
|
|
|
|
else
|
|
|
|
x++;
|
|
|
|
break;
|
2016-07-21 04:39:06 +00:00
|
|
|
}
|
|
|
|
|
2016-08-20 04:08:29 +00:00
|
|
|
gSelectedSquare = XY_TO_SQUARE(x, y);
|
2016-07-21 04:39:06 +00:00
|
|
|
|
2016-08-20 04:08:29 +00:00
|
|
|
refreshSquare(oldSquare);
|
2016-07-21 04:39:06 +00:00
|
|
|
selectSquare(gSelectedSquare);
|
2016-08-24 05:18:19 +00:00
|
|
|
moveMouseToSquare(gSelectedSquare);
|
2016-07-21 04:39:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-08-20 04:08:29 +00:00
|
|
|
static bool swapDir(tDirection dir)
|
2016-07-21 04:39:06 +00:00
|
|
|
{
|
2016-07-22 15:02:25 +00:00
|
|
|
bool result = false;
|
2016-07-21 04:39:06 +00:00
|
|
|
tPos x = SQUARE_TO_X(gSelectedSquare);
|
2016-08-20 04:08:29 +00:00
|
|
|
tPos y = SQUARE_TO_Y(gSelectedSquare);
|
2016-07-21 04:39:06 +00:00
|
|
|
|
2016-08-20 04:08:29 +00:00
|
|
|
switch (dir) {
|
|
|
|
case DIR_UP:
|
|
|
|
if (y == 0) {
|
|
|
|
badThingHappened();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DIR_DOWN:
|
|
|
|
if (y == BOARD_SIZE - 1) {
|
|
|
|
badThingHappened();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DIR_LEFT:
|
|
|
|
if (x == 0) {
|
|
|
|
badThingHappened();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DIR_RIGHT:
|
|
|
|
if (x == BOARD_SIZE - 1) {
|
|
|
|
badThingHappened();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
break;
|
2016-07-21 04:39:06 +00:00
|
|
|
}
|
|
|
|
|
2016-07-24 22:22:37 +00:00
|
|
|
resetStarAnim();
|
2016-08-20 04:08:29 +00:00
|
|
|
result = moveSquareInDir(gSelectedSquare, dir);
|
2016-07-21 04:39:06 +00:00
|
|
|
selectSquare(gSelectedSquare);
|
2016-07-22 15:02:25 +00:00
|
|
|
|
2016-07-24 22:22:37 +00:00
|
|
|
if (result)
|
|
|
|
gShouldSave = true;
|
|
|
|
|
2016-07-22 15:02:25 +00:00
|
|
|
return result;
|
2016-07-21 04:39:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool isAppleButtonPressed(void)
|
|
|
|
{
|
2016-07-24 22:22:37 +00:00
|
|
|
return (isButtonPressed(JOY_BUTTON_0) || isButtonPressed(JOY_BUTTON_1));
|
2016-07-21 04:39:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void endGame(void)
|
|
|
|
{
|
|
|
|
videomode(VIDEOMODE_80x24);
|
2016-08-24 05:18:19 +00:00
|
|
|
mixedTextMode();
|
2016-08-24 00:23:26 +00:00
|
|
|
|
2016-12-24 03:51:45 +00:00
|
|
|
speakNoMoreMoves();
|
|
|
|
|
2016-08-24 05:18:19 +00:00
|
|
|
cputsxy(0, 0, " No more moves - GAME OVER!!");
|
|
|
|
gotoxy(0,1);
|
|
|
|
cprintf( " You made it to level %u", getLevel());
|
|
|
|
cputsxy(0, 3, " Play again (Y/N)?");
|
2016-07-21 04:39:06 +00:00
|
|
|
|
2016-07-22 04:45:07 +00:00
|
|
|
while (true) {
|
|
|
|
switch (cgetc()) {
|
|
|
|
case 'y':
|
|
|
|
case 'Y':
|
|
|
|
return;
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
case 'N':
|
|
|
|
case CH_ESC:
|
|
|
|
case 'q':
|
|
|
|
case 'Q':
|
|
|
|
quitGame();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
badThingHappened();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-07-21 04:39:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-22 04:45:07 +00:00
|
|
|
static void refreshScore(tScore score)
|
2016-07-21 19:33:31 +00:00
|
|
|
{
|
|
|
|
if (score == gScoreBar)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gScoreBar = score;
|
|
|
|
drawScore(score);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-22 04:45:07 +00:00
|
|
|
static void refreshLevel(tLevel level)
|
|
|
|
{
|
|
|
|
bool waiting = true;
|
|
|
|
|
|
|
|
videomode(VIDEOMODE_80x24);
|
2016-08-24 05:18:19 +00:00
|
|
|
mixedTextMode();
|
2016-12-24 03:51:45 +00:00
|
|
|
speakLevelComplete();
|
2016-08-24 00:23:26 +00:00
|
|
|
|
2016-08-24 05:18:19 +00:00
|
|
|
gotoxy(0, 0);
|
|
|
|
cprintf( " Completed level %u!!", level);
|
|
|
|
cputsxy(0, 2, " Press space to continue to the next level...");
|
2016-07-22 04:45:07 +00:00
|
|
|
|
|
|
|
while (waiting) {
|
|
|
|
switch (cgetc()) {
|
|
|
|
case ' ':
|
|
|
|
waiting = false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
badThingHappened();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-22 05:11:36 +00:00
|
|
|
showAndClearDblLoRes();
|
2016-12-24 03:51:45 +00:00
|
|
|
speakGetReady();
|
2016-07-22 04:45:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void getHint(void)
|
|
|
|
{
|
|
|
|
refreshSquare(gSelectedSquare);
|
|
|
|
|
|
|
|
gSelectedSquare = getHintSquare();
|
|
|
|
selectSquare(gSelectedSquare);
|
2016-08-24 05:18:19 +00:00
|
|
|
moveMouseToSquare(gSelectedSquare);
|
2016-07-22 04:45:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-22 05:11:36 +00:00
|
|
|
void initUI(void)
|
|
|
|
{
|
2016-08-20 04:08:29 +00:00
|
|
|
bool optionsLoaded;
|
2016-09-07 02:55:05 +00:00
|
|
|
bool mouseInitialized;
|
2016-08-20 04:08:29 +00:00
|
|
|
|
2016-08-24 00:23:26 +00:00
|
|
|
initMachine();
|
|
|
|
|
2016-08-20 04:08:29 +00:00
|
|
|
optionsLoaded = loadOptions();
|
|
|
|
|
2016-07-22 05:11:36 +00:00
|
|
|
initGameEngine(&gCallbacks);
|
2016-09-07 02:55:05 +00:00
|
|
|
mouseInitialized = initMouse(&gMouseCallbacks);
|
2016-08-20 04:08:29 +00:00
|
|
|
|
2016-09-07 02:55:05 +00:00
|
|
|
// If we couldn't initialize a mouse and it was enabled on the options, then disable it.
|
|
|
|
if ((!mouseInitialized) &&
|
2016-08-20 04:08:29 +00:00
|
|
|
(gGameOptions.enableMouse)) {
|
2016-09-07 02:55:05 +00:00
|
|
|
gGameOptions.enableMouse = false;
|
|
|
|
gGameOptions.optionsSaved = false;
|
|
|
|
|
|
|
|
// If there were no options loaded, then let's turn on the joystick instead.
|
|
|
|
if (!optionsLoaded) {
|
|
|
|
gGameOptions.enableJoystick = true;
|
2016-08-20 04:08:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-24 22:22:37 +00:00
|
|
|
initJoystick(&gJoyCallbacks);
|
2016-08-20 04:08:29 +00:00
|
|
|
|
2016-12-24 03:51:45 +00:00
|
|
|
if (gGameOptions.enableSound) {
|
|
|
|
soundInit(gGameOptions.mockingBoardSlot, gGameOptions.enableSpeechChip);
|
|
|
|
}
|
|
|
|
|
2016-08-20 04:08:29 +00:00
|
|
|
if (!gGameOptions.optionsSaved) {
|
|
|
|
saveOptions();
|
|
|
|
}
|
2016-08-19 04:08:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool mouseSelectSquare(tSquare square)
|
|
|
|
{
|
|
|
|
refreshSquare(gSelectedSquare);
|
|
|
|
gSelectedSquare = square;
|
|
|
|
selectSquare(gSelectedSquare);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-24 22:22:37 +00:00
|
|
|
static void joystickMove(tJoyPos position)
|
|
|
|
{
|
|
|
|
switch (position) {
|
|
|
|
case JOY_POS_DOWN:
|
2016-08-20 04:08:29 +00:00
|
|
|
moveDir(DIR_DOWN);
|
2016-07-24 22:22:37 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case JOY_POS_DOWN_LEFT:
|
2016-08-20 04:08:29 +00:00
|
|
|
moveTwoDirs(DIR_DOWN, DIR_LEFT);
|
2016-07-24 22:22:37 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case JOY_POS_LEFT:
|
2016-08-20 04:08:29 +00:00
|
|
|
moveDir(DIR_LEFT);
|
2016-07-24 22:22:37 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case JOY_POS_UP_LEFT:
|
2016-08-20 04:08:29 +00:00
|
|
|
moveTwoDirs(DIR_UP, DIR_LEFT);
|
2016-07-24 22:22:37 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case JOY_POS_UP:
|
2016-08-20 04:08:29 +00:00
|
|
|
moveDir(DIR_UP);
|
2016-07-24 22:22:37 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case JOY_POS_UP_RIGHT:
|
2016-08-20 04:08:29 +00:00
|
|
|
moveTwoDirs(DIR_UP, DIR_RIGHT);
|
2016-07-24 22:22:37 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case JOY_POS_RIGHT:
|
2016-08-20 04:08:29 +00:00
|
|
|
moveDir(DIR_RIGHT);
|
2016-07-24 22:22:37 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case JOY_POS_DOWN_RIGHT:
|
2016-08-20 04:08:29 +00:00
|
|
|
moveTwoDirs(DIR_DOWN, DIR_RIGHT);
|
2016-07-24 22:22:37 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
case JOY_POS_CENTER:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool joystickChangedCallback(tJoyState *oldState, tJoyState *newState)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (oldState->position != JOY_POS_CENTER)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if ((newState->button0) ||
|
|
|
|
(newState->button1)) {
|
|
|
|
switch (newState->position) {
|
|
|
|
case JOY_POS_UP:
|
2016-08-20 04:08:29 +00:00
|
|
|
return swapDir(DIR_UP);
|
2016-07-24 22:22:37 +00:00
|
|
|
|
|
|
|
case JOY_POS_DOWN:
|
2016-08-20 04:08:29 +00:00
|
|
|
return swapDir(DIR_DOWN);
|
2016-07-24 22:22:37 +00:00
|
|
|
|
|
|
|
case JOY_POS_LEFT:
|
2016-08-20 04:08:29 +00:00
|
|
|
return swapDir(DIR_LEFT);
|
2016-07-24 22:22:37 +00:00
|
|
|
|
|
|
|
case JOY_POS_RIGHT:
|
2016-08-20 04:08:29 +00:00
|
|
|
return swapDir(DIR_RIGHT);
|
2016-07-24 22:22:37 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
joystickMove(newState->position);
|
|
|
|
|
|
|
|
return false;
|
2016-07-22 05:11:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-24 22:22:37 +00:00
|
|
|
static bool joystickNoChangeCallback(tJoyState *oldState)
|
|
|
|
{
|
|
|
|
if (oldState->button0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (oldState->button1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
joystickMove(oldState->position);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool pollKeyboard(void)
|
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
uint8_t ch;
|
|
|
|
|
|
|
|
if (!kbhit())
|
|
|
|
return result;
|
|
|
|
|
|
|
|
ch = cgetc();
|
|
|
|
switch (ch) {
|
|
|
|
case 'i':
|
|
|
|
case 'I':
|
|
|
|
case CH_CURS_UP:
|
2016-07-26 05:26:24 +00:00
|
|
|
if (!isAppleButtonPressed()) {
|
2016-08-20 04:08:29 +00:00
|
|
|
moveDir(DIR_UP);
|
2016-07-26 05:26:24 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Fallthrough...
|
|
|
|
case 139:
|
2016-08-20 04:08:29 +00:00
|
|
|
result = swapDir(DIR_UP);
|
2016-07-24 22:22:37 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'j':
|
|
|
|
case 'J':
|
|
|
|
case CH_CURS_LEFT:
|
2016-07-26 05:26:24 +00:00
|
|
|
if (!isAppleButtonPressed()) {
|
2016-08-20 04:08:29 +00:00
|
|
|
moveDir(DIR_LEFT);
|
2016-07-26 05:26:24 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Fallthrough...
|
|
|
|
case 136:
|
2016-08-20 04:08:29 +00:00
|
|
|
result = swapDir(DIR_LEFT);
|
2016-07-24 22:22:37 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'k':
|
|
|
|
case 'K':
|
|
|
|
case CH_CURS_RIGHT:
|
2016-07-26 05:26:24 +00:00
|
|
|
if (!isAppleButtonPressed()) {
|
2016-08-20 04:08:29 +00:00
|
|
|
moveDir(DIR_RIGHT);
|
2016-07-26 05:26:24 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Fallthrough...
|
|
|
|
case 149:
|
2016-08-20 04:08:29 +00:00
|
|
|
result = swapDir(DIR_RIGHT);
|
2016-07-24 22:22:37 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'm':
|
|
|
|
case 'M':
|
|
|
|
case CH_CURS_DOWN:
|
2016-07-26 05:26:24 +00:00
|
|
|
if (!isAppleButtonPressed()) {
|
2016-08-20 04:08:29 +00:00
|
|
|
moveDir(DIR_DOWN);
|
2016-07-26 05:26:24 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Fallthrough...
|
|
|
|
case 138:
|
2016-08-20 04:08:29 +00:00
|
|
|
result = swapDir(DIR_DOWN);
|
2016-07-24 22:22:37 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CH_ESC:
|
|
|
|
case 'q':
|
|
|
|
case 'Q':
|
|
|
|
if (gShouldSave) {
|
|
|
|
videomode(VIDEOMODE_80x24);
|
2016-08-24 05:18:19 +00:00
|
|
|
mixedTextMode();
|
|
|
|
gotoxy(0, 0);
|
|
|
|
cprintf("Saving your game so you can continue\r\n later...");
|
2016-07-24 22:22:37 +00:00
|
|
|
saveGame();
|
|
|
|
}
|
|
|
|
quitGame();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'r':
|
|
|
|
case 'R':
|
|
|
|
refreshScore(0);
|
|
|
|
startNewGame();
|
|
|
|
gShouldSave = false;
|
|
|
|
return true;
|
|
|
|
|
2016-08-19 04:08:38 +00:00
|
|
|
case 'o':
|
|
|
|
case 'O':
|
|
|
|
selectOptions();
|
|
|
|
showAndClearDblLoRes();
|
|
|
|
drawBoard();
|
2016-07-24 22:22:37 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'h':
|
|
|
|
case 'H':
|
|
|
|
getHint();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '?':
|
|
|
|
printInstructions();
|
|
|
|
showAndClearDblLoRes();
|
|
|
|
drawBoard();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
badThingHappened();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-07-21 00:53:52 +00:00
|
|
|
void playGame(void)
|
|
|
|
{
|
2016-07-22 05:11:36 +00:00
|
|
|
bool gameLoaded = false;
|
|
|
|
uint8_t ch;
|
|
|
|
|
2016-07-21 19:33:31 +00:00
|
|
|
gScoreBar = 0;
|
2016-07-24 22:22:37 +00:00
|
|
|
gShouldSave = false;
|
|
|
|
|
|
|
|
printf("\n\nChecking for a saved game...");
|
2016-07-21 19:33:31 +00:00
|
|
|
|
2016-07-24 22:22:37 +00:00
|
|
|
if (loadGame()) {
|
|
|
|
bool gotAnswer = false;
|
2016-07-22 05:11:36 +00:00
|
|
|
|
2016-07-24 22:22:37 +00:00
|
|
|
printf("\n\nYou have a saved game!\n Would you like to continue it (Y/N)");
|
|
|
|
|
|
|
|
while (!gotAnswer) {
|
|
|
|
ch = cgetc();
|
|
|
|
switch (ch) {
|
|
|
|
case 'y':
|
|
|
|
case 'Y':
|
|
|
|
printf("\n\nLoading your saved puzzle");
|
|
|
|
gotAnswer = true;
|
|
|
|
gShouldSave = true;
|
|
|
|
gameLoaded = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
case 'N':
|
|
|
|
gotAnswer = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
badThingHappened();
|
|
|
|
break;
|
2016-07-22 05:11:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-07-21 00:53:52 +00:00
|
|
|
|
2016-07-22 05:11:36 +00:00
|
|
|
showAndClearDblLoRes();
|
|
|
|
if (!gameLoaded) {
|
|
|
|
startNewGame();
|
|
|
|
}
|
2016-07-21 00:53:52 +00:00
|
|
|
drawBoard();
|
2016-12-24 03:51:45 +00:00
|
|
|
speakGo();
|
2016-07-21 00:53:52 +00:00
|
|
|
while (true) {
|
2016-07-24 22:22:37 +00:00
|
|
|
resetStarAnim();
|
2016-07-21 00:53:52 +00:00
|
|
|
|
2016-07-24 22:22:37 +00:00
|
|
|
while (true) {
|
2016-07-22 15:43:18 +00:00
|
|
|
doStarAnim();
|
2016-07-24 22:22:37 +00:00
|
|
|
|
|
|
|
if (pollKeyboard()) {
|
2016-07-21 00:53:52 +00:00
|
|
|
break;
|
2016-07-24 22:22:37 +00:00
|
|
|
}
|
|
|
|
|
2016-08-19 04:08:38 +00:00
|
|
|
if ((gGameOptions.enableJoystick) &&
|
|
|
|
(pollJoystick())) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((gGameOptions.enableMouse) &&
|
|
|
|
(pollMouse())) {
|
2016-07-21 04:39:06 +00:00
|
|
|
break;
|
2016-07-24 22:22:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gameIsOver()) {
|
|
|
|
endGame();
|
|
|
|
showAndClearDblLoRes();
|
|
|
|
refreshScore(0);
|
|
|
|
startNewGame();
|
|
|
|
gShouldSave = false;
|
2016-07-21 00:53:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|