-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathstock.c
More file actions
executable file
·164 lines (139 loc) · 4.39 KB
/
stock.c
File metadata and controls
executable file
·164 lines (139 loc) · 4.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/* stock.c */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <raylib.h>
#include "baize.h"
#include "pile.h"
#include "array.h"
#include "stock.h"
#include "trace.h"
#include "ui.h"
static struct PileVtable stockVtable = {
&StockCanMoveTail,
&StockCanAcceptCard,
&StockCanAcceptTail,
&InertTailTapped,
&PileInertCollect,
&StockComplete,
&PileGenericUnsortedPairs,
&StockReset,
&PileUpdate,
&StockDraw,
&PileFree,
};
static void CreateCardLibrary(struct Baize *const baize, size_t packs, size_t suits, _Bool cardFilter[14])
{
// first time this is called, baize->cardLibrary will be NULL because we used calloc()
if (baize->cardLibrary) {
free(baize->cardLibrary);
}
size_t numberOfCardsInSuit = 0;
for ( int i=1; i<14; i++ ) {
if (cardFilter[i]) {
numberOfCardsInSuit += 1;
}
}
size_t cardsRequired = packs * suits * numberOfCardsInSuit;
baize->cardLibrary = calloc(cardsRequired, sizeof(struct Card));
baize->numberOfCardsInLibrary = cardsRequired;
size_t i = 0;
for ( size_t pack = 0; pack < packs; pack++ ) {
for ( enum CardOrdinal o = ACE; o <= KING; o++ ) {
for ( enum CardSuit s = 0; s < suits; s++ ) {
if (cardFilter[o]) {
// run the suits loop backwards, so spades are used first
// (folks expect Spider One Suit to use spades)
baize->cardLibrary[i++] = CardNew(pack, o, SPADE - s);
} else {
// fprintf(stderr, "Skipping %u\n", o);
}
}
}
}
baize->numberOfCardsInLibrary = i; // in case any were taken out by cardFilter
CSOL_INFO("%lu packs, %lu suits, %lu cards created", packs, suits, baize->numberOfCardsInLibrary);
}
static void FillStockFromLibrary(struct Baize *const baize, struct Pile *const stock)
{
for ( size_t i = 0; i < baize->numberOfCardsInLibrary; i++ ) {
// don't use PilePushCard because baize->stock is not set up,
// and we aren't fanning
// PilePushCard(stock, &baize->cardLibrary[i]);
struct Card *c = &baize->cardLibrary[i];
// cards are created face down, but may be face up when recalled with StockReset
c->prone = 1;
c->owner = stock;
c->pos = stock->pos;
stock->cards = ArrayPush(stock->cards, c);
}
}
static void ShuffleStock(struct Pile *const stock)
{
extern int flag_noshuf;
if (flag_noshuf) return;
srand(time(NULL));
// Knuth-Fisher–Yates shuffle
size_t len = ArrayLen(stock->cards);
// tests have shown we do this six times to get a good shuffle
for ( int n = 0; n < 6; n++ ) {
for ( int i = len-1; i > 0; i-- ) {
int j = rand() % (i+1);
ArraySwap(stock->cards, i, j);
}
}
}
struct Stock* StockNew(struct Baize *const baize, Vector2 slot, enum FanType fan, size_t packs, size_t suits, _Bool cardFilter[14])
{
struct Stock* self = calloc(1, sizeof(struct Stock));
if ( self ) {
PileCtor(baize, (struct Pile*)self, "Stock", slot, fan);
self->super.vtable = &stockVtable;
CreateCardLibrary(baize, packs, suits, cardFilter);
FillStockFromLibrary(baize, (struct Pile *const)self);
ShuffleStock((struct Pile *const)self);
self->recycles = 32767; // infinite by default
}
return self;
}
void StockReset(struct Pile *const self)
{
struct Baize *baize = PileOwner(self);
ArrayReset(self->cards);
FillStockFromLibrary(baize, self);
ShuffleStock(self);
}
_Bool StockCanMoveTail(struct Array *const tail)
{
(void)tail;
return 1;
}
_Bool StockCanAcceptCard(struct Baize *const baize, struct Pile *const self, struct Card *const c)
{
BaizeSetError(baize, "(CSOL) Cannot move cards to the Stock");
(void)baize;
(void)self;
(void)c;
return 0;
}
_Bool StockCanAcceptTail(struct Baize *const baize, struct Pile *const self, struct Array *const tail)
{
BaizeSetError(baize, "(CSOL) Cannot move cards to the Stock");
(void)baize;
(void)self;
(void)tail;
return 0;
}
_Bool StockComplete(struct Pile *const self)
{
return PileEmpty(self);
}
void StockDraw(struct Pile *const self)
{
struct Stock* s = (struct Stock*)self;
if (s->recycles) {
PileDrawCenteredGlyph(self, 0x267b);
}
PileDraw(self);
}