Greenheart / swipeforfuture.com

Solving the climate crisis, one swipe at a time 🌍🔥
https://swipeforfuture.com
GNU General Public License v3.0
6 stars 1 forks source link

WIP: Feature/simplify game types #166

Closed Greenheart closed 3 years ago

Greenheart commented 3 years ago

Resolves #165

Greenheart commented 3 years ago
Outdated comment: I wrote a separate example to try another approach to card linking, using the actual card runtime instances instead of relying on custom trigger flags like the old `EventCard` implementation did. This show how to load a list of cards from a `CardData` format and then transform them into the linked `Card` data type. When in the `Card` format, they can reference their related cards directly, making it super easy to link cards together and control the flow of the game. Next step will be to implement this card linking into the actual game, which should be possible now that the basic linking algorithm is finished. --- (Optional): Run the following script with https://deno.land: `deno run .\src\game\linked-cards.ts` ```ts interface Card { id: string left?: Card right?: Card } interface CardData { id: string left?: string right?: string } function card(id: string, left?: string, right?: string): CardData { return { id, left, right, } } /** * All cards and their relationships * * * A C * B D * E * F * G H J K * I * A M L * */ const cardData: CardData[] = [ card('B'), card('F', 'G', 'H'), card('I', undefined, 'A'), card('C', 'D'), card('E'), card('G'), card('D', undefined, 'E'), card('J'), card('K'), card('A', 'B'), card('M'), card('H', undefined, 'I'), card('L'), ] const initialState: { remaining: CardData[] linked: Card[] } = { remaining: [...cardData], linked: [], } function moveCard(id: string, from: CardData[], to: Card[]) { const i = from.findIndex((c) => c.id === id) to.push(from.splice(i, 1)[0] as Card) } // Begin by finding the cards that are already linked (since they are leaf nodes and don't reference other cards) const { linked, remaining } = cardData.reduce(({ linked, remaining }, card) => { if (!card.left && !card.right) { moveCard(card.id, remaining, linked) } return { linked, remaining } }, initialState) console.log(linked, remaining) // Link all cards by iterating several times, to catch new link targets that might not be available from the start. let iterations = 0 while (remaining.length) { iterations++ for (const linkedCard of linked) { for (const card of remaining) { if (card.left === linkedCard.id) { ;(card as Card).left = linkedCard moveCard(card.id, remaining, linked) console.log('linkning ', card.id) } else if (card.right === linkedCard.id) { ;(card as Card).right = linkedCard moveCard(card.id, remaining, linked) console.log('linkning ', card.id) } } } } console.log(linked, remaining) console.log(linked.length, remaining.length, 'iterations:', iterations) // deno run --allow-write .\src\game\linked-cards.ts // Deno.writeTextFile('./cards.json', JSON.stringify(linked, null, 4)) // NOTE: Below is an interactive simulation to explore the linked cards. const state: { cards: Card[] current?: Card } = { cards: [...linked], current: undefined, } function setNextCard(card: Card) { state.current = card } function getRandomCard(): Card { const i = Math.floor(Math.random() * state.cards.length) return state.cards[i] } function userChoice(message: string, validResponses: string[]): string { let choice = '' do { choice = prompt(message) ?? '' } while (!validResponses.includes(choice.toLowerCase())) return choice } function start() { setNextCard(getRandomCard()) // setNextCard(state.cards.find(c => c.id === 'H') as Card) while (state.cards.length) { if (!state.current) throw 'Error: No current card' console.log(state.current.id) const choice = userChoice('Next side:', ['l', 'r']) if (choice === 'l' && state.current.left) { setNextCard(state.current.left) } else if (choice === 'r' && state.current.right) { setNextCard(state.current.right) } else { setNextCard(getRandomCard()) } } } start() export {} ```