// Kabufuda Solitaire / KBFDSLTR for the TI-84 Plus CE // Copyright (C) 2024 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" 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(); // fill tableau and free cells with empty space for (unsigned char i = 0; i < NUM_FREECELLS; i++) freeCells[i] = 11; for (unsigned char i = 0; i < NUM_TABLSLOTS; i++) for (unsigned char j = 0; j < TABL_STACK_SIZE; j++) tableau[i][j] = 11; load(); // will call deal() as well if necessary // set initial variables cursorMode = SELECT; cursorStack = NUM_FREECELLS; maxCursorIndex(); selectedCard = tableau[cursorStack][cursorIndex]; } bool canGrabCard() { if (cursorStack < NUM_FREECELLS) return freeCells[cursorStack] < 11; if (tableau[cursorStack - NUM_FREECELLS][0] > 11) return false; for (unsigned char i = cursorIndex + 1; i < TABL_STACK_SIZE; i++) { const unsigned char x = tableau[cursorStack - NUM_FREECELLS][i]; if (x == 11) return true; if (x != selectedCard) return false; } return true; } bool canDropCard() { if (cursorStack < NUM_FREECELLS) { const unsigned char x = freeCells[cursorStack]; if (cursorStack < fcUnlocked) { if (selectedQty == 1 || selectedQty == 4) return x == 11; else return x == selectedCard && selectedQty == 3; } else return false; } else if (cursorIndex == 0) return true; else return tableau[cursorStack - NUM_FREECELLS][cursorIndex - 1] == selectedCard; } bool checkTableauCollapse(unsigned char stackToCheck) { const unsigned char x = tableau[stackToCheck][0]; for (unsigned char i = 1; i < 5; i++) { const unsigned char y = tableau[stackToCheck][i]; if (i == 4 && y == 11) return true; if (y != x) return false; } return false; } void dropCard() { if (cursorStack == orgStack) return; unsigned char const prevProgress = progress; if (cursorStack < NUM_FREECELLS) { if (selectedQty == 1) freeCells[cursorStack] = selectedCard; else { progress++; freeCells[cursorStack] = 12 + selectedCard; } } else { for (unsigned char i = cursorIndex; i < cursorIndex + selectedQty; i++) tableau[cursorStack - NUM_FREECELLS][i] = selectedCard; if (checkTableauCollapse(cursorStack - NUM_FREECELLS)) { fcUnlocked++; progress++; tableau[cursorStack - NUM_FREECELLS][0] = selectedCard + 12; for (int i = 1; i < 4; i++) tableau[cursorStack - NUM_FREECELLS][i] = 11; } } if (orgStack < NUM_FREECELLS) freeCells[orgStack] = 11; else for (unsigned char i = orgIndex; i < orgIndex + selectedQty; i++) tableau[orgStack - NUM_FREECELLS][i] = 11; if (progress == 10 && prevProgress < 10) numWins++; } void maxCursorIndex() { if (cursorStack < NUM_FREECELLS) return; cursorIndex = TABL_STACK_SIZE - 1; while (tableau[cursorStack - NUM_FREECELLS][cursorIndex] == 11 && cursorIndex > 0) cursorIndex--; } bool cursorOnCollapsed() { return cursorStack < NUM_FREECELLS ? freeCells[cursorStack] > 11 : tableau[cursorStack - NUM_FREECELLS][0] > 11; } bool cursorOnLocked() { return cursorStack >= fcUnlocked && cursorStack < NUM_FREECELLS; }