Skip to content

Instantly share code, notes, and snippets.

@prabuw
Last active May 27, 2020 07:28
Show Gist options
  • Save prabuw/051656ac573ac527b7b48f53e1883d40 to your computer and use it in GitHub Desktop.
Save prabuw/051656ac573ac527b7b48f53e1883d40 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
function buildLetterMap() {
let start = 'A'.codePointAt(0);
const end = 'Z'.codePointAt(0);
const letterMap = {};
while (start <= end) {
letterMap[String.fromCodePoint(start)] = false;
start += 1;
}
return letterMap;
}
function degreesToRadians(degrees) {
return (degrees * Math.PI) / 180;
}
let words = [];
function fetchWords() {
/* Commented out so xstate viz doesn't try to actually fetch words */
// return fetch('/words.json')
// .then(response => response.json())
// .then(response => {
// words = response;
// });
return Promise
.resolve(['Arsenal', 'Midfield', 'Football'])
.then(words => words);
}
const hangmanMachine = Machine(
{
id: 'hangman',
context: {
guessesLeft: 10,
lettersGuessed: buildLetterMap(),
word: [],
streak: 0,
},
initial: 'loading',
states: {
loading: {
invoke: {
src: () => fetchWords(),
onDone: {
target: 'start',
},
onError: {
target: 'failure',
},
},
},
failure: {
on: {
RETRY: 'loading',
},
},
start: {
on: {
'': {
target: 'playing',
actions: 'initialiseGame',
},
},
},
playing: {
on: {
'': [
{
target: 'won',
cond: 'hasGuessedCorrectly',
},
{
target: 'lost',
cond: 'haveRunOutOfGuesses',
},
],
GUESS: [
{
target: 'playing',
actions: 'applyGuess',
cond: 'haveGuessesLeft',
},
],
},
},
won: {
entry: ['incrementStreak'],
on: {
RESET: {
target: 'start',
},
},
},
lost: {
entry: ['resetStreak'],
on: {
RESET: {
target: 'start',
},
},
},
},
},
{
guards: {
hasGuessedCorrectly: ctx => ctx.word.every(letter => letter.hasBeenGuessed),
haveRunOutOfGuesses: ctx => ctx.guessesLeft === 0,
haveGuessesLeft: ctx => ctx.guessesLeft > 0,
},
actions: {
initialiseGame: assign({
guessesLeft: () => 10,
lettersGuessed: () => buildLetterMap(),
word: () => {
const word = words[Math.floor(Math.random() * words.length)];
return word
.toUpperCase()
.split('')
.map(letter => ({ value: letter, hasBeenGuessed: false }));
},
}),
applyGuess: assign((ctx, event) => ({
guessesLeft: ctx.word.some(letter => letter.value === event.data.letter)
? ctx.guessesLeft
: ctx.guessesLeft - 1,
lettersGuessed: {
...ctx.lettersGuessed,
[event.data.letter]: true,
},
word: ctx.word.map(letter => {
if (letter.value !== event.data.letter) {
return letter;
}
return {
...letter,
hasBeenGuessed: true,
};
}),
})),
incrementStreak: assign(ctx => ({
streak: ctx.streak + 1,
})),
resetStreak: assign(() => ({
streak: 0,
})),
},
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment