-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCardTypes.ts
More file actions
125 lines (101 loc) · 2.96 KB
/
CardTypes.ts
File metadata and controls
125 lines (101 loc) · 2.96 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
export enum Suit {
Hearts = 'Hearts',
Diamonds = 'Diamonds',
Spades = 'Spades',
Clubs = 'Clubs',
Invalid = 'Invalid',
}
export type CardValue = 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14;
export type Card = {
suit: Suit;
value: CardValue;
};
export const Emojis = {
[Suit.Invalid]: '',
[Suit.Hearts]: '♥️',
[Suit.Diamonds]: '♦️',
[Suit.Spades]: '♠️',
[Suit.Clubs]: '♣️',
};
export const Offsuit = {
[Suit.Invalid]: Suit.Invalid,
[Suit.Hearts]: Suit.Diamonds,
[Suit.Diamonds]: Suit.Hearts,
[Suit.Spades]: Suit.Clubs,
[Suit.Clubs]: Suit.Spades,
};
export const isTrump = (trump: Suit, card: Card | undefined) => {
return (
trump !== Suit.Invalid &&
card &&
(card.suit === trump || isJick(trump, card))
);
};
export const isJick = (trump: Suit, card: Card) =>
card.value === 11 && card.suit === Offsuit[trump];
// TODO: This got messy trying to mix the logic from sorting and checking winners
export const isWinner = (trump: Suit, a: Card, b: Card) => {
const ta = isTrump(trump, a);
const tb = isTrump(trump, b);
// Trumps wins if the other card is not one
if (ta && !tb) {
return true;
}
if (tb && !ta) {
return false;
}
const sameSuit = a.suit === b.suit;
const betterCard = a.value > b.value;
// Both are trump!
if (ta && tb) {
// Only a challenge if both are jacks, everything else use the card value
if (a.value === 11 && b.value === 11) {
return a.suit === trump;
}
return betterCard;
}
// Matching suits? check the values
if (sameSuit) {
return betterCard;
}
// If trump is set, pick the first card, when it is not set sort the cards
return trump !== Suit.Invalid || suitOrder[a.suit] > suitOrder[b.suit];
};
export const isRed = (suit: Suit) =>
suit === Suit.Hearts || suit === Suit.Diamonds;
export const Sentinel: Card = { suit: Suit.Invalid, value: 2 };
const suitOrder = {
[Suit.Invalid]: -1,
[Suit.Hearts]: 1,
[Suit.Clubs]: 2,
[Suit.Diamonds]: 3,
[Suit.Spades]: 4,
};
export const sort = (a: Card, b: Card): number =>
a.suit === b.suit ? a.value - b.value : suitOrder[a.suit] - suitOrder[b.suit];
export const reverseSort = (a: Card, b: Card): number => -1 * sort(a, b);
export function shuffle<T>(array: T[]) {
let currentIndex = array.length;
// While there remain elements to shuffle.
while (currentIndex !== 0) {
// Pick a remaining element.
const randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex],
array[currentIndex],
];
}
return array;
}
export function getPerfectDeck(): Card[] {
const suits = [Suit.Hearts, Suit.Spades, Suit.Diamonds, Suit.Clubs];
const result: Card[] = [];
for (let i = 0; i < suits.length; i++) {
for (let j = 2; j <= 14; j++) {
result.push({ suit: suits[i], value: j as CardValue });
}
}
return result;
}