Solitaire for the TI-84 Plus CE!
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 "ops.h"
18
19#include <stdlib.h>
20#include <fileioc.h>
21
22#include "variables.h"
23#include "save.h"
24
25unsigned char cursorStack;
26unsigned char cursorIndex;
27enum cursorMode_t cursorMode;
28unsigned char selectedCard;
29unsigned char selectedQty;
30unsigned char orgStack;
31unsigned char orgIndex;
32
33void start()
34{
35 loadWins();
36
37 // fill tableau and free cells with empty space
38 for (unsigned char i = 0; i < NUM_FREECELLS; i++)
39 freeCells[i] = 11;
40 for (unsigned char i = 0; i < NUM_TABLSLOTS; i++)
41 for (unsigned char j = 0; j < TABL_STACK_SIZE; j++)
42 tableau[i][j] = 11;
43
44 load(); // will call deal() as well if necessary
45
46 // set initial variables
47 cursorMode = SELECT;
48 cursorStack = NUM_FREECELLS;
49 maxCursorIndex();
50 selectedCard = tableau[cursorStack][cursorIndex];
51}
52
53bool canGrabCard()
54{
55 if (cursorStack < NUM_FREECELLS) return freeCells[cursorStack] < 11;
56
57 if (tableau[cursorStack - NUM_FREECELLS][0] > 11) return false;
58 for (unsigned char i = cursorIndex + 1; i < TABL_STACK_SIZE; i++)
59 {
60 const unsigned char x = tableau[cursorStack - NUM_FREECELLS][i];
61 if (x == 11) return true;
62 if (x != selectedCard) return false;
63 }
64
65 return true;
66}
67
68bool canDropCard()
69{
70 if (cursorStack < NUM_FREECELLS)
71 {
72 const unsigned char x = freeCells[cursorStack];
73 if (cursorStack < fcUnlocked)
74 {
75 if (selectedQty == 1 || selectedQty == 4) return x == 11;
76 else return x == selectedCard && selectedQty == 3;
77 }
78 else return false;
79 }
80 else if (cursorIndex == 0) return true;
81 else return tableau[cursorStack - NUM_FREECELLS][cursorIndex - 1] == selectedCard;
82}
83
84bool checkTableauCollapse(unsigned char stackToCheck)
85{
86 const unsigned char x = tableau[stackToCheck][0];
87 for (unsigned char i = 1; i < 5; i++)
88 {
89 const unsigned char y = tableau[stackToCheck][i];
90 if (i == 4 && y == 11) return true;
91 if (y != x) return false;
92 }
93
94 return false;
95}
96
97void dropCard()
98{
99 if (cursorStack == orgStack) return;
100
101 unsigned char const prevProgress = progress;
102
103 if (cursorStack < NUM_FREECELLS)
104 {
105 if (selectedQty == 1) freeCells[cursorStack] = selectedCard;
106 else
107 {
108 progress++;
109 freeCells[cursorStack] = 12 + selectedCard;
110 }
111 }
112 else
113 {
114 for (unsigned char i = cursorIndex; i < cursorIndex + selectedQty; i++)
115 tableau[cursorStack - NUM_FREECELLS][i] = selectedCard;
116 if (checkTableauCollapse(cursorStack - NUM_FREECELLS))
117 {
118 fcUnlocked++;
119 progress++;
120 tableau[cursorStack - NUM_FREECELLS][0] = selectedCard + 12;
121 for (int i = 1; i < 4; i++) tableau[cursorStack - NUM_FREECELLS][i] = 11;
122 }
123 }
124
125 if (orgStack < NUM_FREECELLS) freeCells[orgStack] = 11;
126 else for (unsigned char i = orgIndex; i < orgIndex + selectedQty; i++)
127 tableau[orgStack - NUM_FREECELLS][i] = 11;
128
129 if (progress == 10 && prevProgress < 10) numWins++;
130}
131
132void maxCursorIndex()
133{
134 if (cursorStack < NUM_FREECELLS) return;
135
136 cursorIndex = TABL_STACK_SIZE - 1;
137 while (tableau[cursorStack - NUM_FREECELLS][cursorIndex] == 11 && cursorIndex > 0) cursorIndex--;
138}
139
140bool cursorOnCollapsed()
141{
142 return cursorStack < NUM_FREECELLS ? freeCells[cursorStack] > 11
143 : tableau[cursorStack - NUM_FREECELLS][0] > 11;
144}
145
146bool cursorOnLocked()
147{
148 return cursorStack >= fcUnlocked && cursorStack < NUM_FREECELLS;
149}
150