Santorini is een bordspel voor 2–4 spelers. Het wordt gespeeld op een spelbord in de vorm van een $$5 \times 5$$ rooster, waarvan het uitzicht geïnspireerd is op de architectuur van de dorpjes langs de kliffen van het Griekse eiland Santorini1.

spelbord
Het uitzicht van het Santorini-spelbord is geïnspireerd op de architectuur van de dorpjes langs de kliffen van het Griekse eiland Santorini.

Elke speler heeft twee pionnen die arbeiders voorstellen. Bij aanvang is het spelbord leeg en zetten de spelers beurtelings hun twee arbeiders op lege vakjes van het spelbord. Daarna komen de spelers beurtelings aan zet, te beginnen bij de speler die als eerste zijn arbeiders op het spelbord gezet heeft. Een speler die aan zet is, kiest één van zijn arbeiders die hij eerst verzet en daarna laat bouwen.

Verzetten

Een arbeider kan naar één van de (maximaal) acht aangrenzende vakjes verzet worden.

verzet arbeider
Een arbeider kan naar één van de (maximaal) acht aangrenzende vakjes verzet worden.

Een arbeider kan maximaal één niveau omhoog gaan, een willekeurig aantal niveaus omlaag gaan of op hetzelfde niveau blijven.

verzet arbeider
Een arbeider kan maximaal één niveau omhoog gaan, een willekeurig aantal niveaus omlaag gaan of op hetzelfde niveau blijven. Het vakje waarnaar de arbeider verzet wordt mag niet bezet zijn door een andere arbeider of een koepel.

Het vakje waarnaar de arbeider verzet wordt, mag niet bezet zijn door een andere arbeider of een koepel.

Bouwen

Een arbeider kan een deel van een toren (een blok of een koepel) bouwen op één van de (maximaal) acht aangrenzende vakjes rondom hem dat niet door een andere arbeider of een koepel bezet wordt.

bouw blok
Een arbeider kan een deel van een toren (een blok of een koepel) bouwen op één van de (maximaal) acht aangrenzende vakjes rondom hem dat niet door een andere arbeider of een koepel bezet wordt.

De arbeider kan op elk niveau een blok of een koepel bouwen. Als hij bijvoorbeeld op de grond staat, dan kan hij nog altijd een blok bouwen op het tweede of derde niveau, of zelfs een koepel. Hij moet wel altijd de juiste vorm van een blok of een koepel kiezen voor het niveau dat gebouwd wordt (zie onderstaande afbeelding). Een toren met drie blokken en een koepel is volledig afgewerkt.

bouw blok
De arbeider kan op elk niveau een blok of een koepel bouwen, maar moet de juiste vorm van blok of koepel kiezen voor het niveau dat gebouwd wordt. Een toren met drie blokken en een koepel is volledig afgewerkt.

Einde van het spel

Een speler die als eerste één van zijn arbeiders op het derde niveau van een toren kan zetten, wint het spel.

winnen
Een speler die als eerste één van zijn arbeiders op het derde niveau van een toren kan zetten, wint het spel.

Opgave

Om naar de vakjes op het Santorini spelbord te kunnen verwijzen, worden de rijen van boven naar onder genummerd en de kolommen van links naar rechts, telkens vanaf nul. Daardoor kunnen we de positie van een vakje op het spelbord voorstellen door een tuple $$(r, k)$$, waarbij $$r \in \mathbb{N}$$ (int) het rijnummer en $$k \in \mathbb{N}$$ (int) het kolomnummer aanduidt.

richtingen
De acht mogelijke richtingen waarin een arbeider naar een aangrenzend vakje kan verzet worden of waarin een arbeider een blok kan bouwen, worden aangeduid door één of twee hoofdletters.

De acht mogelijke richtingen waarin een arbeider naar een aangrenzend vakje kan verzet worden of waarin een arbeider aan een toren kan bouwen, worden aangeduid door één of twee hoofdletters (str) zoals aangegeven in bovenstaande figuur.

Definieer een klasse Santorini waarmee het spelverloop van een spelletje Santorini kan gesimuleerd worden. Bij het aanmaken van een nieuw spel (Santorini) moet een reeks (list of tuple) doorgegeven worden met de posities waarop de spelers hun arbeiders hebben neergezet bij aanvang van het spel (4, 6 of 8 arbeiders bij 2, 3 of 4 spelers). De arbeiders worden aangeduid met opeenvolgende hoofdletters van het alfabet, in de volgorde waarin ze in de reeks opgelijst worden: op de eerste positie staat arbeider A, op de tweede positie staat arbeider B, enzoverder. Dit is bijvoorbeeld de beginopstelling die correspondeert met de reeks $$\left[(3, 0), (4, 1), (1, 1), (2, 2)\right]$$:

spelbord
Beginopstelling van Santorini nadat twee spelers hun arbeiders op het spelbord gezet hebben.

Elk spel (Santorini) moet een eigenschap arbeiders hebben: een dictionary (dict) die de hoofdletter (str) van elke arbeider afbeeldt op de positie van die arbeider op het spelbord.

Als er een spel (Santorini) wordt doorgegeven aan de ingebouwde functie str, dan moet een stringvoorstelling (str) van het spelbord teruggegeven worden. Daarin vormt elke rij een afzonderlijke regel (opgelijst van boven naar onder) die bestaat uit karakters die de opeenvolgende vakjes beschrijven (opgelijst van links naar rechts). Een vakje waarop geen arbeider staat, wordt voorgesteld door een cijfer dat het niveau van de toren op dat vakje aangeeft: 0 als er nog geen blokjes staan, 1 voor een toren van één blokje, 2 voor een toren van twee blokjes, 3 voor een toren van drie blokjes en 4 voor een toren van drie blokjes en een koepel. Een vakje waarop een arbeider staat, wordt voorgesteld door de hoofdletter van die arbeider (ongeacht het niveau van de toren waarop de arbeider staat).

Daarnaast moet een spel (Santorini) minstens ook de volgende methoden ondersteunen:

Voorbeeld

>>> spelbord = Santorini([(3, 0), (4, 1), (1, 1), (2, 2)])
>>> print(spelbord)
00000
0C000
00D00
A0000
0B000
>>> spelbord.arbeiders
{'A': (3, 0), 'B': (4, 1), 'C': (1, 1), 'D': (2, 2)}
>>> spelbord.winnende_arbeider()
>>> spelbord.niveau('B')
0
>>> print(spelbord.verzet_arbeider('B', 'O'))
00000
0C000
00D00
A0000
00B00
>>> print(spelbord.bouw_toren('B', 'W'))
00000
0C000
00D00
A0000
01B00
>>> spelbord.niveau('B')
0
>>> spelbord.niveau('C')
0
>>> print(spelbord.verzet_arbeider('C', 'ZW').bouw_toren('C', 'O'))
00000
00000
C1D00
A0000
01B00
>>> spelbord.niveau('C')
0
>>> spelbord.verzet_arbeider('A', 'W')
Traceback (most recent call last):
AssertionError: ongeldige zet