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.
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.
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.
Het vakje waarnaar de arbeider verzet wordt, mag niet bezet zijn door een andere arbeider of een koepel.
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.
Een speler die als eerste één van zijn arbeiders op het derde niveau van een toren kan zetten, wint het spel.
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 array $$[r, k]$$ (Array), waarbij $$r \in \mathbb{N}$$ (Number) het rijnummer en $$k \in \mathbb{N}$$ (Number) het kolomnummer aanduidt.
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 (String) 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 array (Array) 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 array 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 array $$\left[[3, 0], [4, 1], [1, 1], [2, 2]\right]$$:
Elk spel (Santorini) moet een eigenschap arbeiders hebben: een object (Object) dat de hoofdletter (String) van elke arbeider afbeeldt op de positie van die arbeider op het spelbord.
Op een spel $$s$$ (Santorini) moeten minstens de volgende methoden kunnen aangeroepen worden:
Een methode niveau waaraan de hoofdletter (String) van een arbeider moet doorgegeven worden. De methode moet het niveau (Number) van de toren teruggeven waarop de arbeider staat: 0 als de arbeider op de grond staat, 1 als de arbeider op een toren van één blokje staat, 2 als de arbeider op een toren van twee blokjes staat en 3 als de arbeider op een toren van drie blokjes staat (de arbeiders kan nooit bovenop een afgewerkte toren staan).
Een methode toString waaraan geen argumenten moeten doorgegeven worden. De methode moet een stringvoorstelling (String) van spel $$s$$ teruggeven. 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).
Een methode verzetArbeider waaraan de hoofdletter (String) van een arbeider en een richting (String) moeten doorgegeven worden. De methode moet de arbeider naar het aangrenzende vakje in de gegeven richting verzetten en een verwijzing teruggeven naar spel $$s$$. De arbeider kan zich enkel verplaatsen naar een aangrenzend vakje
dat binnen het spelbord valt
waar geen andere arbeider staat
waar geen afgewerkte toren staat
waar hij niet meer dan één niveau moet stijgen
Als minstens één van deze voorwaarden niet voldaan is, dan moet de arbeider blijven staan en moet de methode een AssertionError opwerpen met de boodschap ongeldige zet.
Een methode bouwToren waaraan de hoofdletter (String) van een arbeider en een richting (String) moeten doorgegeven worden. De methode moet de arbeider een blokje of een koepel laten bouwen op het aangrenzende vakje in de gegeven richting en een verwijzing teruggeven naar spel $$s$$. De arbeider kan enkel bouwen op een aangrenzend vakje
dat binnen het spelbord valt
waar geen andere arbeider staat
waar geen afgewerkte toren staat
Als minstens één van deze voorwaarden niet voldaan is, dan moet er niets gebouwd worden en moet de methode een AssertionError opwerpen met de boodschap ongeldige zet.
> const spelbord = new Santorini([[3, 0], [4, 1], [1, 1], [2, 2]]);
> console.log(spelbord.toString())
00000
0C000
00D00
A0000
0B000
> spelbord.arbeiders
{"A": [3, 0], "B": [4, 1], "C": [1, 1], "D": [2, 2]}
> spelbord.winnendeArbeider()
undefined
> spelbord.niveau("B")
0
> console.log(spelbord.verzetArbeider("B", "O").toString())
00000
0C000
00D00
A0000
00B00
> console.log(spelbord.bouwToren("B", "W").toString())
00000
0C000
00D00
A0000
01B00
> spelbord.niveau("B")
0
> spelbord.niveau("C")
0
> console.log(spelbord.verzetArbeider("C", "ZW").bouwToren("C", "O").toString())
00000
00000
C1D00
A0000
01B00
> spelbord.niveau("C")
0
> spelbord.verzetArbeider("A", "W")
AssertionError: ongeldige zet