Solitaire for the TI-84 Plus CE!
at main 150 lines 3.7 kB view raw
1// Kabufuda Solitaire / KBFDSLTR for the TI-84 Plus CE 2// Copyright (C) 2024 euphory 3// 4// This program is free software: you can redistribute it and/or modify 5// it under the terms of the GNU General Public License as published by 6// the Free Software Foundation, either version 3 of the License, or 7// (at your option) any later version. 8// 9// This program is distributed in the hope that it will be useful, 10// but WITHOUT ANY WARRANTY; without even the implied warranty of 11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12// GNU General Public License for more details. 13// 14// You should have received a copy of the GNU General Public License 15// along with this program. If not, see <https://www.gnu.org/licenses/>. 16 17#include "input.h" 18 19#include <stdlib.h> 20#include <keypadc.h> 21#include "variables.h" 22#include "ops.h" 23#include "save.h" 24 25unsigned char down, left, right, up; 26 27bool doInput() 28{ 29 const bool prevSecond = kb_IsDown(kb_Key2nd); 30 const bool prevEnter = kb_IsDown(kb_KeyEnter); 31 const bool prevAlpha = kb_IsDown(kb_KeyAlpha); 32 const bool prevClear = kb_IsDown(kb_KeyClear); 33 34 kb_Scan(); 35 36 up = kb_IsDown(kb_KeyUp) ? up + 1 : 0; 37 down = kb_IsDown(kb_KeyDown) ? down + 1 : 0; 38 left = kb_IsDown(kb_KeyLeft) ? left + 1 : 0; 39 right = kb_IsDown(kb_KeyRight) ? right + 1 : 0; 40 41 const bool select = (kb_IsDown(kb_Key2nd) && !prevSecond) || (kb_IsDown(kb_KeyEnter) && !prevEnter); 42 const bool clear = (kb_IsDown(kb_KeyClear) && !prevClear) || (kb_IsDown(kb_KeyAlpha) && !prevAlpha); 43 44 if (select) 45 { 46 if (cursorMode == SELECT && canGrabCard()) 47 { 48 orgStack = cursorStack; 49 orgIndex = cursorIndex; 50 cursorMode = DROP; 51 } 52 else if (canDropCard()) 53 { 54 dropCard(); 55 cursorMode = SELECT; 56 } 57 else if (cursorStack == orgStack) 58 { 59 cursorMode = SELECT; 60 } 61 } 62 else if (clear) cursorMode = SELECT; 63 64 unsigned char prevCursorStack = cursorStack; 65 66 if (down == 1 || down > HOLD_TIME) 67 { 68 cursorIndex++; 69 } 70 else if (left == 1 || left > HOLD_TIME) 71 { 72 do 73 { 74 if (cursorStack == 0) cursorStack = NUM_FREECELLS + NUM_TABLSLOTS - 1; // wrap 75 else cursorStack--; 76 } 77 while (cursorOnCollapsed() || cursorOnLocked()); // skip useless stacks 78 } 79 else if (right == 1 || right > HOLD_TIME) 80 { 81 do 82 { 83 if (cursorStack > NUM_FREECELLS + NUM_TABLSLOTS - 2) cursorStack = 0; // wrap 84 else cursorStack++; 85 } 86 while (cursorOnCollapsed() || cursorOnLocked()); // skip useless stacks 87 } 88 else if (up == 1 || up > HOLD_TIME) 89 { 90 if (cursorIndex > 0) cursorIndex--; 91 } 92 93 if (cursorStack < NUM_FREECELLS) 94 { 95 cursorIndex = 0; 96 } 97 else if (cursorMode == DROP) 98 { 99 // if dropping cards, the cursor should always be at the top of the stack it's on 100 // except maxCursorIndex() doesn't work so well on empty tableau stacks 101 if (cursorStack != orgStack) 102 { 103 if (tableau[cursorStack - NUM_FREECELLS][0] == 11) 104 { 105 cursorIndex = 0; 106 } 107 else 108 { 109 maxCursorIndex(); 110 cursorIndex++; 111 } 112 } 113 else cursorIndex = orgIndex; // also this makes it more clear if we are trying to drop 114 // back on the original cards 115 } 116 else if (cursorStack != prevCursorStack) 117 { 118 maxCursorIndex(); 119 } 120 else 121 { 122 while (tableau[cursorStack - NUM_FREECELLS][cursorIndex] == 11 && cursorIndex > 0) cursorIndex--; 123 } 124 125 if (cursorMode == SELECT) 126 { 127 selectedQty = 1; 128 if (cursorStack < NUM_FREECELLS) selectedCard = freeCells[cursorStack]; 129 else 130 { 131 selectedCard = tableau[cursorStack - NUM_FREECELLS][cursorIndex]; 132 for (int i = cursorIndex + 1; tableau[cursorStack - NUM_FREECELLS][i] == selectedCard; i++) 133 selectedQty++; 134 } 135 136 if (selectedCard > 11) 137 { 138 selectedCard -= 12; 139 selectedQty = 4; 140 } 141 } 142 143 if (kb_IsDown(kb_KeyDel)) 144 { 145 deleteSave(); 146 start(); 147 } 148 149 return !kb_On && progress < 10; 150}