Last active
September 19, 2024 13:29
-
-
Save semiversus/b457071ce0af6b9215531f9d817a9af9 to your computer and use it in GitHub Desktop.
Grüfello - Alles wird gut
This file contains hidden or 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
{ | |
"cells": [ | |
{ | |
"attachments": {}, | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Grüffelo - Alles wird gut\n", | |
"* See this link for the actual game: [Schmidt Spiele](https://www.schmidtspiele-shop.de/der-grueffelo-alles-wird-gut)\n", | |
"* This script calculates the chances to win - you'll win in exactly 8 of 9 games." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from dataclasses import dataclass\n", | |
"from typing import Tuple, MutableSet\n", | |
"from queue import LifoQueue\n", | |
"\n", | |
"\n", | |
"@dataclass(frozen=True)\n", | |
"class State:\n", | |
" position: int # position of the mouse\n", | |
" predators: Tuple[int] # uncovered pieces per predator" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Chance to win is 88.8889 %\n" | |
] | |
} | |
], | |
"source": [ | |
"open_states: LifoQueue[State] = LifoQueue()\n", | |
"open_states.put(State(position=0, predators=(0, 0, 0)))\n", | |
"\n", | |
"visited_states: MutableSet[State] = set()\n", | |
"\n", | |
"wins, losses = 0, 0\n", | |
"\n", | |
"while not open_states.empty():\n", | |
" state = open_states.get()\n", | |
"\n", | |
" if state in visited_states:\n", | |
" # preventing loops by storing already visited states\n", | |
" # loops in gameplay are possible (reaching same state after some dice rolls)\n", | |
" continue\n", | |
" \n", | |
" visited_states.add(state)\n", | |
"\n", | |
" for dice in range(1, 7):\n", | |
"\n", | |
" if dice <= 3:\n", | |
" # corresponds to going 1, 2 or 3 steps with the mouse\n", | |
" if state.position + dice >= 31:\n", | |
" wins += 1\n", | |
" else:\n", | |
" open_states.put(State(state.position + dice, state.predators))\n", | |
"\n", | |
" elif state.predators[dice - 4] < 4:\n", | |
" # for predator 0, 1 or 2 check if not all 4 pieces are uncovered\n", | |
" predators = list(state.predators)\n", | |
" predators[dice - 4] += 1\n", | |
"\n", | |
" if predators == [4, 4, 4]:\n", | |
" losses += 1\n", | |
" else:\n", | |
" open_states.put(State(state.position, tuple(predators)))\n", | |
"\n", | |
" elif state.position not in (0, 4, 7, 12, 14, 17, 21, 24, 27):\n", | |
" # if a predator piece is already fully uncovered, go one step back if possible\n", | |
" open_states.put(State(state.position - 1, state.predators))\n", | |
"\n", | |
"print(f'Chance to win is {wins / (wins + losses) * 100:.3f} %')" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": ".venv", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.10.6" | |
}, | |
"orig_nbformat": 4, | |
"vscode": { | |
"interpreter": { | |
"hash": "2238c7368be3ff70b0d7ef17f915d48d7b5e28b77999a6664896ef4c9d3f2923" | |
} | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment