-
-
Save mamamia5x/1df9d0b7c49c6545e573e91cbb2f5156 to your computer and use it in GitHub Desktop.
SCRIPT-8
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// title: Cardette | |
const SUIT_HEARTS = 0 | |
const SUIT_DIAMONDS = 1 | |
const SUIT_SPADES = 2 | |
const SUIT_CLUBS = 3 | |
const SUITS = [SUIT_HEARTS, SUIT_DIAMONDS, SUIT_SPADES, SUIT_CLUBS] | |
const SHADES = [3, 3, 6, 6] | |
const VALUES = range(1, 7) | |
const SPRITES = { | |
corner_visible: 0, | |
edge_visible: 1, | |
corner_hidden: 2, | |
edge_hidden: 3, | |
[SUIT_HEARTS]: 4, | |
[SUIT_DIAMONDS]: 5, | |
[SUIT_SPADES]: 6, | |
[SUIT_CLUBS]: 7 | |
} | |
const SPRITE_CURSOR = 8 | |
const BETS = [ | |
{ suits: [SUIT_HEARTS, SUIT_DIAMONDS], multiplier: 2 }, | |
{ suits: [SUIT_SPADES, SUIT_CLUBS], multiplier: 2 }, | |
{ values: [1, 2], multiplier: 3 }, | |
{ values: [3, 4], multiplier: 3 }, | |
{ values: [5, 6], multiplier: 3 }, | |
{ suits: [SUIT_HEARTS], multiplier: 4 }, | |
{ suits: [SUIT_DIAMONDS], multiplier: 4 }, | |
{ suits: [SUIT_SPADES], multiplier: 4 }, | |
{ suits: [SUIT_CLUBS], multiplier: 4 }, | |
...VALUES.map(value => ({ values: [value], multiplier: 6 })), | |
...SUITS.flatMap(suit => | |
VALUES.map(value => ({ suits: [suit], values: [value], multiplier: 24 })) | |
) | |
] | |
const GRID_W = 16 | |
const GRID_H = 16 | |
const GRID_BETS_START = BETS.length - (SUITS.length * VALUES.length) | |
const BET_AMOUNTS = [1, 2, 3] | |
const STATE_BET_AMOUNT = 0 | |
const STATE_BET_TYPE = 1 | |
const STATE_DEAL = 2 | |
const STATE_PICK = 3 | |
const STATE_RESULT = 4 | |
const STATE_CONTINUE = 5 | |
const GAMESTATES = [ | |
STATE_BET_AMOUNT, | |
STATE_BET_TYPE, | |
STATE_DEAL, | |
STATE_PICK, | |
STATE_RESULT, | |
STATE_CONTINUE | |
] | |
const createDeck = (suits, values) => { | |
return suits | |
.flatMap(suit => values.map(value => [suit, value, Math.random()])) | |
.sort((a, b) => a[2] - b[2]) // Shuffle deck | |
.map(([suit, value]) => [suit, value]) | |
} | |
init = state => { | |
state.deck = createDeck(SUITS, VALUES) | |
state.currentBet = 0 | |
state.currentBetAmount = 0 | |
state.gameState = 0 | |
state.credits = 10 | |
state.dealt = [] | |
state.currentDealt = 0 | |
} | |
const modify = (current, list, amount = 1) => { | |
return (current + list.length + amount) % list.length | |
} | |
const updateBetSelection = (state, input) => { | |
if (input.upPressed) { | |
state.currentBet = modify(state.currentBet, BETS, -1) | |
} | |
if (input.downPressed) { | |
state.currentBet = modify(state.currentBet, BETS, 1) | |
} | |
if (input.leftPressed) { | |
if (state.currentBet <= GRID_BETS_START) { | |
// sequential movement | |
state.currentBet = modify(state.currentBet, BETS, -1) | |
} else { | |
if (state.currentBet <= GRID_BETS_START + VALUES.length - 1) { | |
// wrap to previous row | |
state.currentBet = modify( | |
state.currentBet, | |
BETS, | |
VALUES.length * (SUITS.length - 1) - 1 | |
) | |
} else { | |
// move left | |
state.currentBet = modify(state.currentBet, BETS, -VALUES.length) | |
} | |
} | |
} | |
if (input.rightPressed) { | |
if (state.currentBet >= GRID_BETS_START && state.currentBet !== 38) { | |
if ( | |
state.currentBet >= | |
GRID_BETS_START + VALUES.length * (SUITS.length - 1) | |
) { | |
// wrap to next row | |
state.currentBet = modify( | |
state.currentBet, | |
BETS, | |
1 - VALUES.length * (SUITS.length - 1) | |
) | |
} else { | |
// move right | |
state.currentBet = modify(state.currentBet, BETS, VALUES.length) | |
} | |
} else { | |
// sequential movement | |
state.currentBet = modify(state.currentBet, BETS, 1) | |
} | |
} | |
if (input.aPressed || input.startPressed) { | |
nextState(state) | |
} | |
} | |
const nextState = state => { | |
state.gameState = modify(state.gameState, GAMESTATES, 1) | |
} | |
const updateBetAmount = (state, input) => { | |
const availableBets = BET_AMOUNTS.filter(amount => amount <= state.credits) | |
if (state.currentBetAmount >= availableBets.length) state.currentBetAmount = 0 | |
if (input.upPressed || input.leftPressed) { | |
state.currentBetAmount = modify(state.currentBetAmount, availableBets, -1) | |
} | |
if (input.downPressed || input.rightPressed) { | |
state.currentBetAmount = modify(state.currentBetAmount, availableBets, 1) | |
} | |
if (input.aPressed || input.startPressed) { | |
state.credits -= BET_AMOUNTS[state.currentBetAmount] | |
nextState(state) | |
} | |
} | |
const updateDeal = (state, input) => { | |
state.dealt = [popFromDeck(state), popFromDeck(state)] | |
nextState(state) | |
} | |
const popFromDeck = state => { | |
return state.deck.pop() | |
} | |
const updatePickCard = (state, input) => { | |
if (input.upPressed || input.leftPressed) { | |
state.currentDealt = modify(state.currentDealt, state.dealt, 1) | |
} | |
if (input.downPressed || input.rightPressed) { | |
state.currentDealt = modify(state.currentDealt, state.dealt, -1) | |
} | |
if (input.aPressed || input.startPressed) { | |
nextState(state) | |
} | |
} | |
const updateResult = (state, input) => { | |
const win = checkWin(state) | |
if (win) { | |
state.win = | |
BET_AMOUNTS[state.currentBetAmount] * BETS[state.currentBet].multiplier | |
state.credits += state.win | |
} | |
nextState(state) | |
} | |
const checkWin = state => { | |
const bet = BETS[state.currentBet] | |
const card = state.dealt[state.currentDealt] | |
return betMatches(bet, ...card) | |
} | |
const waitForNextRound = (state, input) => { | |
if (input.aPressed || input.startPressed) { | |
state.win = 0 | |
if (state.deck.length < 2) { | |
state.deck = createDeck(SUITS, VALUES) | |
} | |
nextState(state) | |
} | |
} | |
update = (state, input, elapsed) => { | |
switch (state.gameState) { | |
case STATE_BET_AMOUNT: | |
updateBetAmount(state, input) | |
break | |
case STATE_BET_TYPE: | |
updateBetSelection(state, input) | |
break | |
case STATE_DEAL: | |
updateDeal(state) | |
break | |
case STATE_PICK: | |
updatePickCard(state, input) | |
break | |
case STATE_RESULT: | |
updateResult(state, input) | |
break | |
case STATE_CONTINUE: | |
log(BETS[state.currentBet]) | |
waitForNextRound(state, input) | |
break | |
default: | |
log('no such state: ' + state.gameState) | |
} | |
} | |
const drawCard = (position, hidden, value, suit) => { | |
const cornerSprite = hidden ? SPRITES.corner_hidden : SPRITES.corner_visible | |
const edgeSprite = hidden ? SPRITES.edge_hidden : SPRITES.edge_visible | |
const [x, y] = position | |
sprite(x, y, cornerSprite) | |
sprite(x + 8, y, cornerSprite, 0, true) | |
sprite(x, y + 8, edgeSprite, 0) | |
sprite(x + 8, y + 8, edgeSprite, 0, true) | |
sprite(x, y + 16, cornerSprite, 0, false, true) | |
sprite(x + 8, y + 16, cornerSprite, 0, true, true) | |
if (hidden) return | |
print(x + 3, y + 3, value, SHADES[suit]) | |
sprite(x + 4, y + 11, SPRITES[suit], 0 - SHADES[suit]) | |
} | |
const drawDeck = ([x, y], deck) => { | |
Array.from({ length: Math.ceil(deck.length / 6) }).forEach((_, i) => { | |
drawCard([x + i * 2, y + i * 2], 1, ...deck[i]) | |
}) | |
const offset = Math.ceil(deck.length / 6) * 2 | |
print(x + 16 + offset, y + 17 + offset, deck.length, 3) | |
print(x + 16 + offset, y + 10 + offset, 'left:', 3) | |
} | |
const drawBetGrid = ([x, y] = [0, 0], state) => { | |
const { currentBet, currentBetAmount } = state | |
const bet = BETS[currentBet] | |
state.gameState === STATE_BET_TYPE && print(x + 32, y + 1, `place your bet`) | |
print(x + 12, y + 8, `pays`) | |
print(x + 12, y + 14, `${bet.multiplier}x${BET_AMOUNTS[currentBetAmount]}`) | |
range(0, SUITS.length / 2).forEach(suitIndex => { | |
const tileY = y + 8 | |
const tileX = 32 + x + suitIndex * GRID_W * 2 | |
const highlight = currentBet === suitIndex | |
rectFill(tileX, tileY, GRID_W * 2 - 1, 11, highlight ? 0 : 4) | |
!highlight && rectStroke(tileX, tileY, GRID_W * 2 - 1, 11, 5) | |
sprite( | |
tileX + 3, | |
tileY + 1, | |
SPRITES[suitIndex * 2], | |
highlight ? -SHADES[suitIndex * 2] : -5 | |
) | |
print(tileX + 12, tileY + 3, 'or', highlight ? SHADES[suitIndex * 2] : 5) | |
sprite( | |
tileX + 19, | |
tileY + 1, | |
SPRITES[suitIndex * 2 + 1], | |
highlight ? -SHADES[suitIndex * 2] : -5 | |
) | |
}) | |
range(0, VALUES.length / 2).forEach(valueIndex => { | |
const tileX = x + 12 | |
const tileY = 32 + y + valueIndex * GRID_H * 2 | |
const highlight = currentBet - 2 === valueIndex | |
rectFill(tileX, tileY, 11, GRID_H * 2 - 1, highlight ? 0 : 4) | |
!highlight && rectStroke(tileX, tileY, 11, GRID_H * 2 - 1, 5) | |
print(tileX + 4, tileY + 6, 1 + valueIndex * 2, highlight ? 6 : 5) | |
print(tileX + 2, tileY + 13, 'or', highlight ? 6 : 5) | |
print(tileX + 4, tileY + 20, 1 + valueIndex * 2 + 1, highlight ? 6 : 5) | |
}) | |
VALUES.forEach((value, valueIndex) => { | |
const tileX = x + 20 | |
const tileY = 32 + valueIndex * GRID_H | |
const highlight = currentBet - 9 == valueIndex | |
rectFill(tileX + 4, tileY, 7, GRID_H - 1, highlight ? 0 : 4) | |
!highlight && rectStroke(tileX + 4, tileY, 7, GRID_H - 1, 5) | |
print(tileX + 6, tileY + 5, value, 5) | |
}) | |
SUITS.forEach((suit, suitIndex) => { | |
const tileX = 32 + x + suitIndex * GRID_W | |
const tileY = y + 20 | |
const highlight = currentBet - 5 === suitIndex | |
rectFill(tileX, tileY, GRID_W - 1, 11, highlight ? 0 : 4) | |
!highlight && rectStroke(tileX, tileY, GRID_W - 1, 11, 5) | |
sprite(tileX + 3, tileY + 1, SPRITES[suit], highlight ? -SHADES[suit] : -5) | |
VALUES.forEach((value, valueIndex) => { | |
const tileY = 32 + y + valueIndex * GRID_H | |
const active = betMatches(bet, suit, value) | |
const highlight = active && currentBet >= GRID_BETS_START | |
rectFill(tileX, tileY, GRID_W - 1, GRID_H - 1, highlight ? 0 : 2) | |
rectStroke( | |
tileX, | |
tileY, | |
GRID_W - 1, | |
GRID_H - 1, | |
active ? (highlight ? 0 : 1) : 3 | |
) | |
sprite( | |
tileX + 5, | |
tileY + 5, | |
SPRITES[suit], | |
highlight && currentBet >= GRID_BETS_START ? -SHADES[suit] : -5 | |
) | |
print(tileX + 2, tileY + 2, value, highlight ? SHADES[suit] : 5) | |
}) | |
}) | |
} | |
const betMatches = (bet, suit, value) => { | |
let match = true | |
if (Array.isArray(bet.suits)) { | |
match = bet.suits.includes(suit) | |
} | |
if (match && Array.isArray(bet.values)) { | |
match = bet.values.includes(value) | |
} | |
return match | |
} | |
const drawBetAmount = ([x, y], state) => { | |
print(x + 10, y, 'Wager:') | |
BET_AMOUNTS.forEach((amount, amountIndex) => { | |
const current = amountIndex === state.currentBetAmount | |
const yOffset = 10 + y + amountIndex * 8 | |
print( | |
x + 10, | |
yOffset, | |
amount + ' credit' + (amount !== 1 ? 's' : ''), | |
current ? 0 : 5 | |
) | |
current && drawCursor(x - 2, yOffset - 2) | |
}) | |
} | |
const drawCredits = ([x, y], credits) => { | |
print(x, y, `Credits:${credits}`) | |
} | |
const drawDealt = ([x, y], state) => { | |
print(x, y, 'Pick a card') | |
state.dealt.forEach(([suit, value], cardIndex) => { | |
const current = state.currentDealt === cardIndex | |
const offsetY = 8 + y + cardIndex * 26 | |
drawCard( | |
[x + 6, offsetY], | |
!(state.gameState >= STATE_RESULT && current), | |
value, | |
suit | |
) | |
current && drawCursor(x - 2, offsetY + 8) | |
}) | |
} | |
const drawCursor = (x, y) => { | |
sprite(x, y, SPRITE_CURSOR) | |
} | |
const drawResult = ([x, y], state) => { | |
if (state.win) { | |
print(x, y, 'You won') | |
print(x, y + 6, `+${state.win} money!`) | |
} else { | |
print(x, y, 'Better luck') | |
print(x, y + 6, 'Next time...') | |
} | |
} | |
const SPRITES_LOGO = [ | |
[16, 17, 18, 19, 20, 21, 21, 20], | |
[32, 33, 34, 35, 36, 37, 37, 36] | |
] | |
const drawLogo = ([x, y]) => { | |
SPRITES_LOGO.forEach((sprites, row) => | |
sprites.forEach((s, letter) => sprite(x + letter * 8, y + row * 8, s)) | |
) | |
} | |
const drawInfo = ([x, y]) => { | |
;[ | |
'Win credits by', | |
'guessing the card.', | |
'Better guesses give', | |
'better payouts. ', | |
'The deck is shuffled ', | |
'once it runs out.' | |
].forEach((row, rowIndex) => { | |
print(x, y + rowIndex * 7, row, 2) | |
}) | |
} | |
draw = state => { | |
clear(7) | |
log(GRID_BETS_START) | |
drawDeck([0, 97], state.deck) | |
if (state.gameState === STATE_BET_AMOUNT) { | |
drawBetAmount([55, 32], state) | |
drawLogo([64, 0]) | |
drawInfo([50, 73]) | |
} | |
if (state.gameState >= STATE_BET_TYPE) { | |
drawBetGrid([32, 0], state) | |
} | |
if (state.gameState >= STATE_DEAL) { | |
drawDealt([0, 24], state) | |
} | |
if (state.gameState >= STATE_CONTINUE) { | |
drawResult([0, 84], state) | |
} | |
drawCredits([0, 1], state.credits) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"iframeVersion": "0.1.280", | |
"lines": [ | |
434, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0 | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"0": [ | |
" 0000000", | |
"00111111", | |
"01000000", | |
"01000000", | |
"01000000", | |
"01000000", | |
"01000000", | |
"01000000" | |
], | |
"1": [ | |
"01000000", | |
"01000000", | |
"01000000", | |
"01000000", | |
"01000000", | |
"01000000", | |
"01000000", | |
"01000000" | |
], | |
"2": [ | |
" 1111111", | |
"11444444", | |
"14222222", | |
"14223232", | |
"14232323", | |
"14223232", | |
"14232323", | |
"14223232" | |
], | |
"3": [ | |
"14232323", | |
"14223232", | |
"14232323", | |
"14223232", | |
"14223232", | |
"14232323", | |
"14223232", | |
"14232323" | |
], | |
"4": [ | |
" ", | |
" 00 00 ", | |
" 0000000", | |
" 0000000", | |
" 0000000", | |
" 00000 ", | |
" 000 ", | |
" 0 " | |
], | |
"5": [ | |
" ", | |
" 0 ", | |
" 000 ", | |
" 00000 ", | |
" 0000000", | |
" 00000 ", | |
" 000 ", | |
" 0 " | |
], | |
"6": [ | |
" 0 ", | |
" 000 ", | |
" 00000 ", | |
" 0000000", | |
" 0000000", | |
" 00000 ", | |
" 0 ", | |
" 000 " | |
], | |
"7": [ | |
" ", | |
" 000 ", | |
" 000 ", | |
" 00 0 00", | |
" 0000000", | |
" 00 0 00", | |
" 0 ", | |
" 000 " | |
], | |
"8": [ | |
" ", | |
" ", | |
" 1100 ", | |
" 14330 ", | |
" 143330", | |
" 14330 ", | |
" 1100 ", | |
" " | |
], | |
"16": [ | |
" ", | |
" 000 ", | |
" 00 00 ", | |
" 00 00", | |
" 00 00", | |
" 00 ", | |
" 00 ", | |
" 00 " | |
], | |
"17": [ | |
" ", | |
" 0 ", | |
" 0 ", | |
" 000 ", | |
" 0 0 ", | |
" 00 00 ", | |
" 0 0 ", | |
" 00 00" | |
], | |
"18": [ | |
" ", | |
" 00000 ", | |
" 00 00 ", | |
" 00 00", | |
" 00 00", | |
" 00 00", | |
" 00 00", | |
" 00 00 " | |
], | |
"19": [ | |
" ", | |
" 00000 ", | |
" 00 00 ", | |
" 00 00", | |
" 00 00", | |
" 00 00", | |
" 00 00", | |
" 00 00" | |
], | |
"20": [ | |
" ", | |
" 0000000", | |
" 00 ", | |
" 00 ", | |
" 00 ", | |
" 00 ", | |
" 00 ", | |
" 00 " | |
], | |
"21": [ | |
" ", | |
" 0000000", | |
" 00 ", | |
" 00 ", | |
" 00 ", | |
" 00 ", | |
" 00 ", | |
" 00 " | |
], | |
"32": [ | |
" 00 ", | |
" 00 ", | |
" 00 ", | |
" 00 00", | |
" 00 00", | |
" 00 00 ", | |
" 000 ", | |
" " | |
], | |
"33": [ | |
" 0000000", | |
" 00 00", | |
" 00 00", | |
" 00 00", | |
" 00 00", | |
" 00 00", | |
" 00 00", | |
" " | |
], | |
"34": [ | |
" 00000 ", | |
" 00 00 ", | |
" 00 00", | |
" 00 00", | |
" 00 00", | |
" 00 00", | |
" 00 00", | |
" " | |
], | |
"35": [ | |
" 00 00", | |
" 00 00", | |
" 00 00", | |
" 00 00", | |
" 00 00", | |
" 00 00 ", | |
" 00000 ", | |
" " | |
], | |
"36": [ | |
" 00000 ", | |
" 00 ", | |
" 00 ", | |
" 00 ", | |
" 00 ", | |
" 00 ", | |
" 0000000", | |
" " | |
], | |
"37": [ | |
" 00 ", | |
" 00 ", | |
" 00 ", | |
" 00 ", | |
" 00 ", | |
" 00 ", | |
" 00 ", | |
" " | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment