// Calculation Solitaire / CALCSLTR for the TI-84 Plus CE // Copyright (C) 2025 euphory // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include "ops.h" #include #include #include "variables.h" #include "save.h" #include "drawing.h" unsigned char cursorStack; unsigned char cursorIndex; enum cursorMode_t cursorMode; unsigned char selectedCard; unsigned char selectedQty; unsigned char orgStack; unsigned char orgIndex; void start() { loadWins(); load(); // will call deal() as well if necessary // set initial variables cursorMode = SELECT; cursorStack = NUM_FREECELLS; maxCursorIndex(); selectedCard = CARD_EMPTY; } bool canGrabCard() { if (cursorStack < NUM_FREECELLS) return false; else if (tableau[cursorStack - NUM_FREECELLS][cursorIndex + 1] & CARD_EXISTS) return false; else return tableau[cursorStack - NUM_FREECELLS][cursorIndex] & CARD_EXISTS; } bool canDropCard() { if (cursorStack < NUM_FREECELLS) { if ((freeCells[cursorStack] & CARD_NUMBER) == CARD_KING) return false; else return (selectedCard & CARD_NUMBER) == (cursorStack + (freeCells[cursorStack] & CARD_NUMBER) + 1) % 13; } else if (orgStack != DECK_ORG) { return cursorStack == orgStack; } else if (cursorIndex == 0) { return true; } else { return !(tableau[cursorStack - NUM_FREECELLS][cursorIndex + 1] & CARD_EXISTS); } } bool canClearCard() { if (orgStack == DECK_ORG) return false; else return selectedCard & CARD_EXISTS; } void getNewCard() { while (true) { selectedCard = (rand() & CARD_SUIT) | (rand() % 13) | CARD_EXISTS; if (!removeFromDeck(selectedCard)) break; } animateDraw(); } bool removeFromDeck(card_t toRemove) { unsigned char cardIndex = ((toRemove & CARD_SUIT) >> 4) * 13 + (toRemove & CARD_NUMBER); unsigned char *deckByte = deck + (cardIndex / 8); unsigned char pokeByte = 0x01 << (cardIndex % 8); if (*deckByte & pokeByte) return true; *deckByte |= pokeByte; deckCards--; return false; } void grabCard() { orgStack = cursorStack; orgIndex = cursorIndex; selectedCard = tableau[cursorStack - NUM_FREECELLS][cursorIndex]; tableau[cursorStack - NUM_FREECELLS][cursorIndex] = CARD_EMPTY; animateGrab(); } void dropCard() { animateDrop(); unsigned char const prevProgress = progress; if (cursorStack < NUM_FREECELLS) { freeCells[cursorStack] = selectedCard; if ((selectedCard & CARD_NUMBER) == CARD_KING) progress++; } else { tableau[cursorStack - NUM_FREECELLS][cursorIndex] = selectedCard; } if (progress == PROGRESS_COMPLETE && prevProgress < PROGRESS_COMPLETE) (*numWins)++; } void clearCard() { animateClear(); tableau[orgStack - NUM_FREECELLS][orgIndex] = selectedCard; selectedCard = CARD_EMPTY; } void maxCursorIndex() { if (cursorStack < NUM_FREECELLS) return; cursorIndex = 0; while (tableau[cursorStack - NUM_FREECELLS][cursorIndex + 1] & CARD_EXISTS) cursorIndex++; }