mirror of
https://github.com/jeremysrand/a2sudoku.git
synced 2024-06-12 20:06:50 +00:00
766 lines
20 KiB
C
766 lines
20 KiB
C
//
|
|
// ui.c
|
|
// a2sudoku
|
|
//
|
|
// Created by Jeremy Rand on 2015-07-15.
|
|
// Copyright (c) 2015 Jeremy Rand. All rights reserved.
|
|
//
|
|
|
|
|
|
#include <conio.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <tgi.h>
|
|
#include <tgi/tgi-mode.h>
|
|
|
|
#include "game.h"
|
|
#include "ui.h"
|
|
|
|
|
|
// Extern symbols for graphics drivers
|
|
extern char a2e_hi;
|
|
|
|
|
|
// Macros and defines
|
|
#define SQUARE_WIDTH 29
|
|
#define SQUARE_HEIGHT 19
|
|
|
|
#define THICK_LINE_WIDTH 2
|
|
#define THIN_LINE_WIDTH 1
|
|
#define THICK_LINE_HEIGHT 2
|
|
#define THIN_LINE_HEIGHT 1
|
|
|
|
#define TEXT_OFFSET_X 12
|
|
#define TEXT_OFFSET_Y 6
|
|
|
|
#define TEXT_UNDERLINE_OFFSET_X -2
|
|
#define TEXT_UNDERLINE_OFFSET_Y 9
|
|
#define TEXT_UNDERLINE_WIDTH 8
|
|
|
|
#define TOTAL_WIDTH ((BOARD_SIZE * SQUARE_WIDTH) + \
|
|
((BOARD_SIZE + 1) * THIN_LINE_WIDTH) + \
|
|
(((BOARD_SIZE / SUBSQUARE_SIZE) + 1) * (THICK_LINE_WIDTH - THIN_LINE_WIDTH)))
|
|
|
|
#define TOTAL_HEIGHT ((BOARD_SIZE * SQUARE_HEIGHT) + \
|
|
((BOARD_SIZE + 1) * THIN_LINE_HEIGHT) + \
|
|
(((BOARD_SIZE / SUBSQUARE_SIZE) + 1) * (THICK_LINE_HEIGHT - THIN_LINE_HEIGHT)))
|
|
|
|
#define WON_WIDTH 100
|
|
#define WON_HEIGHT 55
|
|
|
|
#define SCRATCH_WIDTH 9
|
|
#define SCRATCH_HEIGHT 6
|
|
|
|
|
|
// Typedefs
|
|
|
|
typedef struct tOptions {
|
|
tDifficulty difficulty;
|
|
bool showInvalid;
|
|
bool showWrong;
|
|
} tOptions;
|
|
|
|
|
|
// Globals;
|
|
|
|
tPos cursorX, cursorY;
|
|
int screenSquaresX[BOARD_SIZE];
|
|
int screenSquaresY[BOARD_SIZE];
|
|
|
|
tOptions gameOptions = {
|
|
DIFFICULTY_EASY,
|
|
true,
|
|
true
|
|
};
|
|
|
|
|
|
// Implementation
|
|
|
|
|
|
char *difficultyString(tDifficulty difficulty)
|
|
{
|
|
if (difficulty == DIFFICULTY_EASY)
|
|
return "Easy";
|
|
else if (difficulty == DIFFICULTY_MEDIUM)
|
|
return "Medium";
|
|
|
|
return "Hard";
|
|
}
|
|
|
|
|
|
void drawGrid(void)
|
|
{
|
|
tPos pos;
|
|
int xPos = 0;
|
|
int yPos = 0;
|
|
|
|
tgi_clear();
|
|
|
|
tgi_setcolor(COLOR_WHITE);
|
|
for (pos = 0; pos <= BOARD_SIZE; pos++) {
|
|
if ((pos % SUBSQUARE_SIZE) == 0) {
|
|
tgi_bar(xPos, 0, xPos + THICK_LINE_WIDTH - 1, TOTAL_HEIGHT - 1);
|
|
xPos += THICK_LINE_WIDTH;
|
|
|
|
tgi_bar(0, yPos, TOTAL_WIDTH - 1, yPos + THICK_LINE_HEIGHT - 1);
|
|
yPos += THICK_LINE_HEIGHT;
|
|
} else {
|
|
tgi_bar(xPos, 0, xPos + THIN_LINE_WIDTH - 1, TOTAL_HEIGHT - 1);
|
|
xPos += THIN_LINE_WIDTH;
|
|
|
|
tgi_bar(0, yPos, TOTAL_WIDTH - 1, yPos + THIN_LINE_HEIGHT - 1);
|
|
yPos += THIN_LINE_HEIGHT;
|
|
}
|
|
|
|
if (pos < BOARD_SIZE) {
|
|
screenSquaresX[pos] = xPos;
|
|
screenSquaresY[pos] = yPos;
|
|
}
|
|
|
|
xPos += SQUARE_WIDTH;
|
|
yPos += SQUARE_HEIGHT;
|
|
}
|
|
}
|
|
|
|
|
|
void initUI(void)
|
|
{
|
|
static bool tgi_inited = false;
|
|
|
|
if (tgi_inited)
|
|
return;
|
|
|
|
// Install drivers
|
|
tgi_install(&a2e_hi);
|
|
|
|
tgi_init();
|
|
|
|
tgi_inited = true;
|
|
}
|
|
|
|
|
|
void loadOptions(void)
|
|
{
|
|
static bool optionsLoaded = false;
|
|
FILE *optionsFile;
|
|
|
|
if (optionsLoaded)
|
|
return;
|
|
|
|
optionsFile = fopen("a2sudoku.opts", "rb");
|
|
if (optionsFile != NULL) {
|
|
fread(&gameOptions, sizeof(gameOptions), 1, optionsFile);
|
|
fclose(optionsFile);
|
|
}
|
|
optionsLoaded = true;
|
|
}
|
|
|
|
|
|
void saveOptions(void)
|
|
{
|
|
FILE *optionsFile;
|
|
optionsFile = fopen("a2sudoku.opts", "wb");
|
|
if (optionsFile != NULL) {
|
|
fwrite(&gameOptions, sizeof(gameOptions), 1, optionsFile);
|
|
fclose(optionsFile);
|
|
}
|
|
}
|
|
|
|
|
|
void shutdownUI(void)
|
|
{
|
|
// Uninstall drivers
|
|
tgi_uninstall();
|
|
}
|
|
|
|
|
|
void textMode(void)
|
|
{
|
|
clrscr();
|
|
asm ("STA %w", 0xc051);
|
|
}
|
|
|
|
|
|
void graphicsMode(void)
|
|
{
|
|
asm ("STA %w", 0xc050);
|
|
}
|
|
|
|
|
|
bool setOptions(void)
|
|
{
|
|
bool shouldUpdate = false;
|
|
bool keepLooping = true;
|
|
bool shouldSave = false;
|
|
|
|
while (keepLooping) {
|
|
clrscr();
|
|
|
|
// 1111111111222222222233333333334
|
|
// 1234567890123456789012345678901234567890
|
|
printf(
|
|
" Apple // Sudoku\n"
|
|
" By Jeremy Rand\n"
|
|
"\n"
|
|
"Options:\n"
|
|
" Difficulty : %s\n"
|
|
" Show invalid values : %s\n"
|
|
" Show wrong values : %s\n"
|
|
"\n"
|
|
"Press D to change difficulty.\n"
|
|
"Press I to %sshow invalid values.\n"
|
|
"Press W to %sshow wrong values.\n"
|
|
"\n"
|
|
"Press any other key to return.\n",
|
|
difficultyString(gameOptions.difficulty),
|
|
(gameOptions.showInvalid ? "On" : "Off"),
|
|
(gameOptions.showWrong ? "On" : "Off"),
|
|
(gameOptions.showInvalid ? "not " : ""),
|
|
(gameOptions.showWrong ? "not " : ""));
|
|
|
|
switch (cgetc()) {
|
|
case 'd':
|
|
case 'D':
|
|
if (gameOptions.difficulty == DIFFICULTY_HARD)
|
|
gameOptions.difficulty = DIFFICULTY_EASY;
|
|
else
|
|
gameOptions.difficulty++;
|
|
shouldSave = true;
|
|
break;
|
|
|
|
case 'i':
|
|
case 'I':
|
|
gameOptions.showInvalid = !gameOptions.showInvalid;
|
|
shouldSave = true;
|
|
shouldUpdate = true;
|
|
break;
|
|
|
|
case 'w':
|
|
case 'W':
|
|
gameOptions.showWrong = !gameOptions.showWrong;
|
|
shouldSave = true;
|
|
shouldUpdate = true;
|
|
break;
|
|
|
|
default:
|
|
keepLooping = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (shouldSave) {
|
|
printf("\n\nSaving options...");
|
|
saveOptions();
|
|
}
|
|
|
|
return shouldUpdate;
|
|
}
|
|
|
|
|
|
void displayInstructions(void)
|
|
{
|
|
int seed = 0;
|
|
char ch;
|
|
|
|
loadOptions();
|
|
|
|
clrscr();
|
|
|
|
// 1111111111222222222233333333334
|
|
// 1234567890123456789012345678901234567890
|
|
printf(
|
|
" Apple // Sudoku\n"
|
|
" By Jeremy Rand\n"
|
|
"\n"
|
|
"The goal is to get the numbers from 1 to"
|
|
"9 uniquely in each column, row and 3x3\n"
|
|
"subsquare. Move the cursor with I-J-K-L"
|
|
"or the arrow keys. Press a number key\n"
|
|
"to enter a value. Press a number key\n"
|
|
"while holding shift or open apple to\n"
|
|
"toggle a scratch value. Press 0 to\n"
|
|
"clear a square. Play ends when the\n"
|
|
"puzzle is solved.\n"
|
|
" Difficulty : %s\n"
|
|
" Show invalid values : %s\n"
|
|
" Show wrong values : %s\n"
|
|
"\n"
|
|
"Press escape or Q to quit at any time.\n"
|
|
"Press O to change options.\n"
|
|
"Press R to restart the current game.\n"
|
|
"Press N to start a new game.\n"
|
|
"Press H to see this info again.\n"
|
|
"Press U to undo your last move.\n"
|
|
" Press O to change options now or any\n"
|
|
" other key to start",
|
|
difficultyString(gameOptions.difficulty),
|
|
(gameOptions.showInvalid ? "On" : "Off"),
|
|
(gameOptions.showWrong ? "On" : "Off"));
|
|
|
|
// The amount of time the user waits to read the in
|
|
while (!kbhit())
|
|
seed++;
|
|
|
|
ch = cgetc();
|
|
srand(seed);
|
|
|
|
if ((ch == 'o') ||
|
|
(ch == 'O'))
|
|
setOptions();
|
|
|
|
clrscr();
|
|
}
|
|
|
|
|
|
void drawOne(int screenX, int screenY)
|
|
{
|
|
tgi_line(screenX + 2, screenY, screenX + 2, screenY + 3);
|
|
tgi_line(screenX + 1, screenY + 4, screenX + 3, screenY + 4);
|
|
tgi_setpixel(screenX + 1, screenY + 1);
|
|
}
|
|
|
|
|
|
void drawTwo(int screenX, int screenY)
|
|
{
|
|
tgi_setpixel(screenX, screenY + 1);
|
|
tgi_line(screenX + 1, screenY, screenX + 3, screenY);
|
|
tgi_line(screenX + 4, screenY + 1, screenX, screenY + 4);
|
|
tgi_lineto(screenX + 4, screenY + 4);
|
|
}
|
|
|
|
|
|
void drawThree(int screenX, int screenY)
|
|
{
|
|
tgi_line(screenX + 1, screenY, screenX + 3, screenY);
|
|
tgi_line(screenX + 1, screenY + 2, screenX + 3, screenY + 2);
|
|
tgi_line(screenX + 1, screenY + 4, screenX + 3, screenY + 4);
|
|
tgi_setpixel(screenX + 4, screenY + 1);
|
|
tgi_setpixel(screenX + 4, screenY + 3);
|
|
}
|
|
|
|
|
|
void drawFour(int screenX, int screenY)
|
|
{
|
|
tgi_line(screenX, screenY + 1, screenX, screenY + 2);
|
|
tgi_lineto(screenX + 4, screenY + 2);
|
|
tgi_line(screenX + 3, screenY, screenX + 3, screenY + 4);
|
|
}
|
|
|
|
|
|
void drawFive(int screenX, int screenY)
|
|
{
|
|
tgi_line(screenX + 4, screenY, screenX, screenY);
|
|
tgi_lineto(screenX, screenY + 2);
|
|
tgi_lineto(screenX + 3, screenY + 2);
|
|
tgi_line(screenX, screenY + 4, screenX + 3, screenY + 4);
|
|
tgi_setpixel(screenX + 4, screenY + 3);
|
|
}
|
|
|
|
|
|
void drawSix(int screenX, int screenY)
|
|
{
|
|
tgi_line(screenX + 3, screenY, screenX, screenY + 3);
|
|
tgi_line(screenX + 1, screenY + 4, screenX + 3, screenY + 4);
|
|
tgi_line(screenX + 1, screenY + 2, screenX + 3, screenY + 2);
|
|
tgi_setpixel(screenX + 4, screenY + 3);
|
|
}
|
|
|
|
|
|
void drawSeven(int screenX, int screenY)
|
|
{
|
|
tgi_line(screenX, screenY, screenX + 4, screenY);
|
|
tgi_line(screenX + 4, screenY + 1, screenX + 1, screenY + 4);
|
|
}
|
|
|
|
|
|
void drawEight(int screenX, int screenY)
|
|
{
|
|
tgi_line(screenX + 1, screenY, screenX + 3, screenY);
|
|
tgi_line(screenX + 1, screenY + 2, screenX + 3, screenY + 2);
|
|
tgi_line(screenX + 1, screenY + 4, screenX + 3, screenY + 4);
|
|
tgi_setpixel(screenX, screenY + 1);
|
|
tgi_setpixel(screenX, screenY + 3);
|
|
tgi_setpixel(screenX + 4, screenY + 1);
|
|
tgi_setpixel(screenX + 4, screenY + 3);
|
|
}
|
|
|
|
|
|
void drawNine(int screenX, int screenY)
|
|
{
|
|
tgi_line(screenX + 1, screenY, screenX + 3, screenY);
|
|
tgi_line(screenX + 1, screenY + 2, screenX + 3, screenY + 2);
|
|
tgi_line(screenX + 4, screenY + 1, screenX + 4, screenY + 4);
|
|
tgi_setpixel(screenX, screenY + 1);
|
|
}
|
|
|
|
|
|
void drawScratch(tPos x, tPos y, tScratchValues scratch)
|
|
{
|
|
int screenX = screenSquaresX[x] + 1;
|
|
int screenY = screenSquaresY[y] + 1;
|
|
|
|
if (SCRATCH_TEST(scratch, 1)) {
|
|
drawOne(screenX, screenY);
|
|
}
|
|
|
|
screenX += SCRATCH_WIDTH;
|
|
if (SCRATCH_TEST(scratch, 2)) {
|
|
drawTwo(screenX, screenY);
|
|
}
|
|
|
|
screenX += SCRATCH_WIDTH;
|
|
if (SCRATCH_TEST(scratch, 3)) {
|
|
drawThree(screenX, screenY);
|
|
}
|
|
|
|
screenX = screenSquaresX[x] + 1;
|
|
screenY += SCRATCH_HEIGHT;
|
|
if (SCRATCH_TEST(scratch, 4)) {
|
|
drawFour(screenX, screenY);
|
|
}
|
|
|
|
screenX += SCRATCH_WIDTH;
|
|
if (SCRATCH_TEST(scratch, 5)) {
|
|
drawFive(screenX, screenY);
|
|
}
|
|
|
|
screenX += SCRATCH_WIDTH;
|
|
if (SCRATCH_TEST(scratch, 6)) {
|
|
drawSix(screenX, screenY);
|
|
}
|
|
|
|
screenX = screenSquaresX[x] + 1;
|
|
screenY += SCRATCH_HEIGHT;
|
|
if (SCRATCH_TEST(scratch, 7)) {
|
|
drawSeven(screenX, screenY);
|
|
}
|
|
|
|
screenX += SCRATCH_WIDTH;
|
|
if (SCRATCH_TEST(scratch, 8)) {
|
|
drawEight(screenX, screenY);
|
|
}
|
|
|
|
screenX += SCRATCH_WIDTH;
|
|
if (SCRATCH_TEST(scratch, 9)) {
|
|
drawNine(screenX, screenY);
|
|
}
|
|
|
|
tgi_setcolor(COLOR_WHITE);
|
|
}
|
|
|
|
|
|
void updatePos(tPos x, tPos y, tSquareVal val, tScratchValues scratch, bool correct, bool invalid, bool knownAtStart)
|
|
{
|
|
int screenX = screenSquaresX[x];
|
|
int screenY = screenSquaresY[y];
|
|
int edgeX = screenX + SQUARE_WIDTH - 1;
|
|
int edgeY = screenY + SQUARE_HEIGHT - 1;
|
|
char buffer[2];
|
|
|
|
tgi_setcolor(COLOR_BLACK);
|
|
tgi_bar(screenX, screenY, edgeX, edgeY);
|
|
|
|
tgi_setcolor(COLOR_WHITE);
|
|
if (val != EMPTY_SQUARE) {
|
|
buffer[0] = '0' + val;
|
|
buffer[1] = '\0';
|
|
|
|
tgi_outtextxy(screenX + TEXT_OFFSET_X, screenY + TEXT_OFFSET_Y, buffer);
|
|
|
|
if (knownAtStart) {
|
|
tgi_line(screenX + TEXT_OFFSET_X + TEXT_UNDERLINE_OFFSET_X,
|
|
screenY + TEXT_OFFSET_Y + TEXT_UNDERLINE_OFFSET_Y,
|
|
screenX + TEXT_OFFSET_X + TEXT_UNDERLINE_OFFSET_X + TEXT_UNDERLINE_WIDTH,
|
|
screenY + TEXT_OFFSET_Y + TEXT_UNDERLINE_OFFSET_Y);
|
|
}
|
|
|
|
if ((gameOptions.showWrong) &&
|
|
(!correct))
|
|
tgi_line(screenX, edgeY, edgeX, screenY);
|
|
|
|
if ((gameOptions.showInvalid) &&
|
|
(invalid))
|
|
tgi_line(screenX, edgeY, edgeX, screenY);
|
|
} else if (scratch != 0) {
|
|
drawScratch(x, y, scratch);
|
|
}
|
|
|
|
if ((cursorX == x) &&
|
|
(cursorY == y)) {
|
|
tgi_line(screenX, screenY, edgeX, screenY);
|
|
tgi_lineto(edgeX, edgeY);
|
|
tgi_lineto(screenX, edgeY);
|
|
tgi_lineto(screenX, screenY);
|
|
}
|
|
}
|
|
|
|
|
|
void youWon(void)
|
|
{
|
|
int wonX = (TOTAL_WIDTH - WON_WIDTH) / 2;
|
|
int wonY = (TOTAL_HEIGHT - WON_HEIGHT) / 2;
|
|
char *line1 = "You solved it!";
|
|
char *line2 = "Press any key";
|
|
int textHeight = tgi_textheight(line1);
|
|
|
|
tgi_setcolor(COLOR_BLACK);
|
|
tgi_bar(wonX, wonY, wonX + WON_WIDTH, wonY + WON_HEIGHT);
|
|
|
|
tgi_setcolor(COLOR_WHITE);
|
|
tgi_outtextxy(wonX + 10, wonY + (textHeight * 2), line1);
|
|
tgi_outtextxy(wonX + 7, wonY + (textHeight * 4), line2);
|
|
|
|
cgetc();
|
|
}
|
|
|
|
|
|
bool playGame(void)
|
|
{
|
|
static bool firstGame = true;
|
|
bool shouldSave = false;
|
|
bool gameLoaded = false;
|
|
char ch;
|
|
uint8_t *button0 = (uint8_t *)0xc061; // Address of button #0 or open apple
|
|
|
|
initUI();
|
|
|
|
textMode();
|
|
if (firstGame) {
|
|
firstGame = false;
|
|
printf("\n\nChecking for a saved puzzle...");
|
|
|
|
if (loadGame(updatePos)) {
|
|
bool gotAnswer = false;
|
|
|
|
printf("\n\nYou have a saved puzzle!\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");
|
|
gameLoaded = true;
|
|
gotAnswer = true;
|
|
shouldSave = true;
|
|
break;
|
|
|
|
case 'n':
|
|
case 'N':
|
|
gotAnswer = true;
|
|
break;
|
|
|
|
default:
|
|
printf("\007");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
cursorX = 0;
|
|
cursorY = 0;
|
|
|
|
if (!gameLoaded) {
|
|
clrscr();
|
|
|
|
printf("\n\nLoading a new puzzle for you\n Please be patient...");
|
|
startGame(gameOptions.difficulty, updatePos);
|
|
}
|
|
|
|
drawGrid();
|
|
refreshAllPos();
|
|
|
|
graphicsMode();
|
|
|
|
while (true) {
|
|
bool shouldNotBeep = true;
|
|
|
|
if (isPuzzleSolved()) {
|
|
youWon();
|
|
return true;
|
|
}
|
|
|
|
ch = cgetc();
|
|
|
|
switch (ch) {
|
|
case 'h':
|
|
case 'H':
|
|
textMode();
|
|
displayInstructions();
|
|
graphicsMode();
|
|
break;
|
|
|
|
case 'o':
|
|
case 'O':
|
|
textMode();
|
|
if (setOptions())
|
|
refreshAllPos();
|
|
graphicsMode();
|
|
break;
|
|
|
|
case 'r':
|
|
case 'R':
|
|
shouldSave = false;
|
|
restartGame();
|
|
break;
|
|
|
|
case 'n':
|
|
case 'N':
|
|
return true;
|
|
|
|
case 'q':
|
|
case 'Q':
|
|
case CH_ESC:
|
|
shutdownUI();
|
|
if (shouldSave) {
|
|
clrscr();
|
|
printf("\n\nSaving your puzzle so you can continue\n later...");
|
|
saveGame();
|
|
}
|
|
return false;
|
|
|
|
case 'i':
|
|
case 'I':
|
|
case 0x0B: // Only defined with apple2enh targts, CH_CURS_UP:
|
|
if (cursorY != 0) {
|
|
cursorY--;
|
|
refreshPos(cursorX, cursorY);
|
|
refreshPos(cursorX, cursorY + 1);
|
|
} else {
|
|
cursorY = BOARD_SIZE - 1;
|
|
refreshPos(cursorX, cursorY);
|
|
refreshPos(cursorX, 0);
|
|
}
|
|
break;
|
|
|
|
case 'j':
|
|
case 'J':
|
|
case CH_CURS_LEFT:
|
|
if (cursorX != 0) {
|
|
cursorX--;
|
|
refreshPos(cursorX, cursorY);
|
|
refreshPos(cursorX + 1, cursorY);
|
|
} else {
|
|
cursorX = BOARD_SIZE - 1;
|
|
refreshPos(cursorX, cursorY);
|
|
refreshPos(0, cursorY);
|
|
}
|
|
break;
|
|
|
|
case 'k':
|
|
case 'K':
|
|
case CH_CURS_RIGHT:
|
|
if (cursorX < BOARD_SIZE - 1) {
|
|
cursorX++;
|
|
refreshPos(cursorX, cursorY);
|
|
refreshPos(cursorX - 1, cursorY);
|
|
} else {
|
|
cursorX = 0;
|
|
refreshPos(cursorX, cursorY);
|
|
refreshPos(BOARD_SIZE - 1, cursorY);
|
|
}
|
|
break;
|
|
|
|
case 'm':
|
|
case 'M':
|
|
case 0x0A: // Only defined with apple2enh targts, CH_CURS_DOWN:
|
|
if (cursorY < BOARD_SIZE - 1) {
|
|
cursorY++;
|
|
refreshPos(cursorX, cursorY);
|
|
refreshPos(cursorX, cursorY - 1);
|
|
} else {
|
|
cursorY = 0;
|
|
refreshPos(cursorX, cursorY);
|
|
refreshPos(cursorX, BOARD_SIZE - 1);
|
|
}
|
|
break;
|
|
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
if (*button0 > 127)
|
|
shouldNotBeep = toggleScratchValueAtPos(cursorX, cursorY, ch - '0');
|
|
else
|
|
shouldNotBeep = setValueAtPos(cursorX, cursorY, ch - '0');
|
|
if (shouldNotBeep)
|
|
shouldSave = true;
|
|
break;
|
|
|
|
case '!':
|
|
shouldNotBeep = toggleScratchValueAtPos(cursorX, cursorY, 1);
|
|
if (shouldNotBeep)
|
|
shouldSave = true;
|
|
break;
|
|
|
|
case '@':
|
|
shouldNotBeep = toggleScratchValueAtPos(cursorX, cursorY, 2);
|
|
if (shouldNotBeep)
|
|
shouldSave = true;
|
|
break;
|
|
|
|
case '#':
|
|
shouldNotBeep = toggleScratchValueAtPos(cursorX, cursorY, 3);
|
|
if (shouldNotBeep)
|
|
shouldSave = true;
|
|
break;
|
|
|
|
case '$':
|
|
shouldNotBeep = toggleScratchValueAtPos(cursorX, cursorY, 4);
|
|
if (shouldNotBeep)
|
|
shouldSave = true;
|
|
break;
|
|
|
|
case '%':
|
|
shouldNotBeep = toggleScratchValueAtPos(cursorX, cursorY, 5);
|
|
if (shouldNotBeep)
|
|
shouldSave = true;
|
|
break;
|
|
|
|
case '^':
|
|
shouldNotBeep = toggleScratchValueAtPos(cursorX, cursorY, 6);
|
|
if (shouldNotBeep)
|
|
shouldSave = true;
|
|
break;
|
|
|
|
case '&':
|
|
shouldNotBeep = toggleScratchValueAtPos(cursorX, cursorY, 7);
|
|
if (shouldNotBeep)
|
|
shouldSave = true;
|
|
break;
|
|
|
|
case '*':
|
|
shouldNotBeep = toggleScratchValueAtPos(cursorX, cursorY, 8);
|
|
if (shouldNotBeep)
|
|
shouldSave = true;
|
|
break;
|
|
|
|
case '(':
|
|
shouldNotBeep = toggleScratchValueAtPos(cursorX, cursorY, 9);
|
|
if (shouldNotBeep)
|
|
shouldSave = true;
|
|
break;
|
|
|
|
case 'u':
|
|
case 'U':
|
|
shouldNotBeep = undoLastMove();
|
|
break;
|
|
|
|
default:
|
|
shouldNotBeep = false;
|
|
break;
|
|
}
|
|
if (!shouldNotBeep) {
|
|
printf("\007");
|
|
}
|
|
}
|
|
|
|
return false;
|
|
} |