Schiebe-Puzzle ByPuzz
ByPuzz
ByPuzz

ByPuzz ist ein 4×4-Schiebe-Puzzle. Man muss 15 Spielsteine durch Schieben über ein leeres Feld in eine bestimmte, vorgegebene Anordnung bringen. In ByPuzz sind die Spielsteine mit Zahlen gekennzeichnet, die die Zuordnung zur Zielposition erleichtern sollen. (Statt Zahlen wären auch Symbole oder Bilder denkbar, aber das ist erst für eine mögliche spätere Version angedacht.)

AuswahlDer AuswahlbildschirmMan kann aus 10 voreingestellten Puzzle-"Bildern" auswählen oder daraus vom Programm eins per Zufall bestimmen lassen (s. kleines Bild). Diese Zielstellung kann man während des Spiels jederzeit zur Erinnerung einblenden. Nach Auswahl eines Zielbildes mischt ByPuzz die Spielsteine in drei verschiedenen Schwierigkeitsstufen (leicht/normal/schwer), was sich ebenfalls vorher konfigurieren lässt.

Die Spielsteine verschiebt man mit der Tastatur, mit dem Joystick oder mit einer 1351-kompatiblen Maus. Dabei geht es immer darum, das Leerfeld zu verlagern, also mit einem der Nachbarsteine zu tauschen. Daher wirken sich die Tasten für "nach oben", "nach unten", "nach links" und "nach rechts" auf die jeweiligen Nachbarsteine des Leerfeldes aus und sind deshalb für Tastatur und Joystick eindeutig zugeordnet. Bei Mausbedienung muss man den Stein, der sich bewegen soll, anklicken. Soll im Bild oben der Stein 6 auf das Leerfeld vorrücken, drückt man also entweder die Taste für "nach oben", zieht den Joystick nach oben oder klickt auf Stein 6.

KonfigurationDer KonfigurationsbildschirmDie Konfiguration ermöglicht die Zuordnung anderer Tasten als die Cursor-Tasten (die auf dem Original-C64 etwas umständlich mit Shift zu bedienen sind) zum Bewegen der Puzzle-Steine, und zwar sowohl für Rechts- als auch für Linkshänder (s. Bild). Die jeweils aktuelle Einstellung ist durch die grüne Hervorhebung erkennbar. Mit den schwarz unterlegten Buchstaben (L, C, R, M, T, J und G) kann man diese Einstellung verändern. <Return> übernimmt dann und führt zum Auswahlbildschirm für Puzzles (s. voriges Bild).

Direkt nach dem Konfigurieren erscheint die Vorschau des Ziel-Puzzles, die während des Spiels jederzeit mit der Taste "V" erneut aufgerufen werden kann. Mit <Return> geht es weiter. Ist man zu schnell gewesen und wollte eigentlich nur das Spiel beenden, drückt man hier statt <Return> die Taste "X" und vermeidet damit den langen Mischvorgang.

Im nächsten Schritt werden die Spielsteine gemischt, was etwas dauert und daher durch eine Farbanimation begleitet wird (die Beschriftung "Mischen." im Titelkasten oben links wechselt zwischen schwarz und weiß). Je schwieriger der Spielgrad desto länger dauert dieser Vorgang. Er endet mit einem Prüflauf, in dem getestet wird, welche Spielsteine bereits an ihrer richtigen Position liegen (diese Steine blinken kurz grün und werden in einem Kasten oben rechts mitgezählt). Diese Anzeige ändert sich nicht, solange man nicht "P" für Prüfen drückt, was den Prüflauf mit der dann aktuellen Steinkonstellation wiederholt.

Nebenbei: Sollte man ByPuzz auf einem Emulator oder auf schneller C64-Hardware verwenden (z.B. Turbo Chameleon, Ultimate Elite, Mega 65), kann man die Prüfanzeige mit Taste "S" auf Dauerbetrieb einstellen und ist so ständig über seinen Spielfortschritt informiert. Ist die automatische Prüfung aktiviert, merkt ByPuzz auch selbständig, ob das Spielziel schon erreicht ist (sonst muss man am Ende "P" drücken oder kurz vor Ende "S").

SpielenDer SpielbildschirmUnd damit startet das Spielen. Jede Spielsteinbewegung wird als Zug oben links unter dem Titelkasten mitgezählt (im Bild: 31 Züge). Jedes Puzzle in ByPuzz ist lösbar, es kommt also nur darauf an, das Ziel mit möglichst wenigen Zügen zu erreichen. Hat man es geschafft, gibt es eine kurze Bildschirmanimation und man kann ein neues Spiel beginnen oder ByPuzz beenden.

Wenn man zwischendurch die Lust verliert, lässt sich ByPuzz aber auch jederzeit mit den Tasten "X" (für Exit) oder "Q" (für Quit) abbrechen. Auch ein Neustart, z.B. wenn man bei der Puzzle-Auswahl eigentlich ein anderes Zielbild haben wollte, ist mit der Taste "R" (für Restart) möglich. Hier - wie auch bei allen anderen entsprechenden Gelegenheiten - wird nachgefragt, ob man den angewählten Vorgang auch wirklich in Gang setzen will.

HilfeDer HilfebildschirmDamit man bei diesen vielen möglichen Tastendrücken nicht durcheinander gerät, besitzt ByPuzz auch einen Hilfebildschirm. Er wird mit der Taste "F1" aufgerufen (und mit einer beliebigen Taste wieder verlassen), was während des Spiels an jeder Stelle möglich ist.

Außerdem lassen sich die Maus oder der Joystick mit "M" bzw. "J" auch beim Spielen aktivieren. Die Tastatur hingegen ist immer aktiv, man kann aber mit der Taste "T" die anderen Eingabegeräte ausdrücklich ausschalten (was ein wenig Geschwindigkeitsgewinn bedeutet).

Download ByPuzz (als D64-Datei)


Auch bei diesem Spiel (wie bei Sokoban) ein paar Worte zur Programmierung.

Für ein Spiel mit Spielfeld sind ein paar Regeln beim Bewegen der Spielsteine erforderlich: Wie steuere ich eine Spielfigur? Wo kann/darf ich mich hinbewegen, wo nicht? Wie stelle ich fest, ob das Spiel erfolgreich verlaufen ist? Wie sorge ich für immer neue Spielsituationen? Auf diese vier Aspekte gehen wir im Folgenden ein.

Steuerung der Spielsteine

In ByPuzz spielen der Befehl ON KEY und die Variable T die wichtigste Rolle. ON KEY erlaubt es, während des Programmlaufs zu jeder Zeit auf vorher festgelegte Tastendrücke zu reagieren. Wird eine solche Taste betätigt, unterbricht ON KEY (ähnlich wie bei einem Interrupt in Maschinensprache) das laufende Basic-Programm und setzt seine Arbeit hinter dem Befehl ON KEY fort. ON KEY kann an beliebiger Stelle des Programms stehen und beliebig oft mit unterschiedlichen Kontrollstrings erfolgen (für geänderte Bedingungen), wie auch hier (Z.1515 und Z.1530).

1500 proc spielen                                              ; Erläuterung:
1505 insert k6$,1,1,10,3,0                                     ; Titelkasten ausgeben
1510 loop: exit if t=255                                       ; Anfang der Spielschleife (beendet bei t=255)
1512 print at(2,2)"Spielen."at(3,23)"ByPuzz": t=0              ; Titelkasten beschriften
1515 on key k$(0): disable: auswertung: resume                 ; -> Tastaturkontrolle (mit CRSR-Tasten)
1520 repeat: if jy then t=joy(2) and $7f                       ; Warten auf Tastendruck/Joystick
1525 until t                                                   ; Wenn t: Tastendruck/Joyst. erfolgt
1530 on key k$(1): disable: auswertung: resume                 ; -> Tastaturkontrolle (ohne CRSR-Tasten)
1535 x1=e%(4)                                                  ; X1:   e%(4) (ist das Leerfeld)
1537 if t=128 then mauscheck                                   ; Mausklick erfolgt (umwandeln in t)
1540 if t=1 then if e%(0) then p=e%(0): active: schieben       ; t=1 / e%(0): nach oben
1550 if t=3 then if e%(1) then p=e%(1): active: schieben       ; t=3 / e%(1): nach rechts
1555 if t=5 then if e%(2) then p=e%(2): active: schieben       ; t=5 / e%(2): nach unten
1560 if t=7 then if e%(3) then p=e%(3): active: schieben       ; t=7 / e%(3): nach links
1565 if t=255 then finish                                      ; t=255: X, Q gedrückt oder Puzzle gelöst
1570 if t=10 then vorschau: pr=0: eintragen                    ; t=10:  V
1575 if t=11 then neustart: if (t=255)or(ee=15) then run       ; t=11:  R
1585 end loop                                                  ; Ende der Spielschleife
1590 end proc

In der von einem ON-KEY-Ereignis aufgerufenen Prozedur "auswertung" (Z.1515, die zugehörige Routine liegt an Z.3500 bis 3660) wird den laut K$(0) erfolgten Tastendrücken eine Bedeutung zugewiesen und in der Variablen T wie in einem Basic-Token weitertransportiert. Die Werte 1, 3, 5 und 7 stehen dabei für die Bewegungsrichtung der Spielsteine (diese Werte entsprechen den von JOY zurückgelieferten Werten, sie werden hier einfach auch den entsprechenden Richtungstasten zugeordnet).

Damit nun nicht während der Bearbeitung der Bewegung ein weiterer Tastendruck dazwischenfunken und den ersten Wert verändern kann, wird in Zeile 1530 ON KEY mit einem anderen Kontrollstring (K$(1)) aufgerufen, der diese Tasten nicht enthält. So ist ein reibungsloser Ablauf einer Bewegung sichergestellt.

Zulässige Felder

In der Liste E%(..) befinden sich die zulässigen Bewegungsziele für den jeweiligen Tastendruck. So darf etwa Spielfeld 2 (Z.4002) nur von Spielfeld 6, 1 und 3 aus angewählt werden.

rem" Zulässige Felder: up, right, down, left:
rem" 0 = unzulässig
rem" Lesart: Feld n erreicht man von Feld x

rem"    e%(0; 1; 2; 3;       4)
4000 rem"  u  r  d  l        n:        x:

4001 data  5, 0, 0, 2  ; feld 1       0 0 0 0
4002 data  6, 1, 0, 3  ; feld 2     0 1 2 3 4 0
4003 data  7, 2, 0, 4    ...  3     0 5 6 7 8 0
4004 data  8, 3, 0, 0         4     0 9 a b c 0
4005 data  9, 0, 1, 6         5     0 d e f . 0
4006 data 10, 5, 2, 7         6       0 0 0 0
4007 data 11, 6, 3, 8         7
4008 data 12, 7, 4, 0         8
4009 data 13, 0, 5,10         9
4010 data 14, 9, 6,11         a
4011 data 15,10, 7,12         b
4012 data 16,11, 8, 0         c
4013 data  0, 0, 9,14         d
4014 data  0,13,10,15         e
4015 data  0,14,11,16         f
4016 data  0,15,12, 0         .

Das heißt: Wenn z.B. das Feld 2 das Leerfeld ist und die Nach-oben-Taste gedrückt wurde (T=1, Z.1540), prüft ByPuzz in E%(0), ob diese Bewegung zulässig ist (also das Feld unter der jetzigen Position nach oben geholt werden darf). Ergebnis: ja, Feld 6 ist in E%(0) aufgeführt, die Bewegung darf erfolgen.

Danach wird die Liste E%(..) in Prozedur "active" (Routine von Z.1850 bis 1890) mit dem Ergebniswert von E%(0) - Variable P hält diesen Wert fest - umgestellt auf das neue Leerfeld (Nummer 6, das ja jetzt freigeworden ist) und für die nächste Puzzlestein-Bewegung vorbereitet.

Da die Bewegung noch gar nicht sichtbar durchgeführt wurde, muss dies nun von Prozedur "schieben" (Routine von Z.1650 bis 1695) erledigt werden. "Schieben" berechnet die Positionen der beiden betroffenen Felder in der Spielfeldtabelle P%(x,y) und tauscht sie gegeneinander aus, d.h. das Feld 6 rückt nach oben und das Leerfeld an Position 2 nach unten. Diese Veränderung wird auch auf dem Bildschirm widergespiegelt (in der Unter-Prozedur "eintragen" - Routine von Z.1200 bis 1245 -, auf dem Bildschirm erscheint dann im Titelkasten der Hinweis "Aufbauen"). Ist der Dauerprüfmodus an, erfolgt im Anschluss in einer weiteren Unterroutine (Prozedur "quick" - Routine von Z.2600 bis 2645), auch die Erkennung der bereits richtig platzierten Spielsteine als Lösungsstatus.

Spiel-Ende

Wurde die Lösung des Puzzles gefunden (t=255, d.h. die Tabellen P%(x,y) und G%(x,y), die das Zielpuzzle enthält, sind identisch), ruft ByPuzz die Prozedur "finish" auf (Z.1565 - Routine von Z.2200 bis 2280). Wenn nicht, kehrt das Programm zurück an den Anfang der Schleife in Z.1510 und wartet auf die nächsten Tastenereignisse.

Anpassung der Puzzles

Wer mal neue Ziel-Puzzles ausprobieren möchte, kann die vorgegebenen auch nach eigenen Vorstellungen im Basic-Code ändern. Die Daten dafür liegen ab Zeile 6000:

6000 data 10
6001 data 6010,6020,6030,6040,6050
6002 data 6060,6070,6080,6090,6100
6003 :
6010 data  1, 2, 3, 4
6011 data  5, 6, 7, 8
6012 data  9,10,11,12
6013 data 13,14,15, 0
6014 :
6020 data  1, 5, 9,13
6021 data  2, 6,10,14
6022 data  3, 7,11,15
6023 data  4, 8,12, 0
6024 :
...

Sie entsprechen schlicht dem Zielbild eines Puzzles, wobei das Leerfeld durch eine Null gekennzeichnet ist. In den Zeilen 6010 bis 6013 erkennt man natürlich gleich das Standard-Puzzle, in 6020 bis 6023 ist es um 90 Grad nach links gedreht und gespiegelt, usw. Die Zeilen 6000 bis 6003 sagen aus, wie viele Puzzles vorliegen und in welchen Basic-Zeilen sie jeweils beginnen (für den RESET-Befehl).

Wenn man hier etwas ändert, muss man allerdings auch die Auswahlansicht mitändern (in Prozedur "pauswahl" - Z.6235 bis 6275), denn aus Performance-Gründen werden die Mini-Puzzle-Ansichten hier als String-Konstanten angegeben.

Ab Version 1.9 befinden sich auf der ByPuzz-Disk unter dem Namen "ByMore #x" bereits fertige Sätze neuer Puzzles, die - analog zum Spiel Sokoban - einfach in das Programm hineingeladen werden können. Dazu beendet man ByPuzz, löscht mit D! 6000-  den aktuellen Puzzle-Satz und lädt den neuen Satz (z.B. Satz #1) mit MERGE "ByMore #1" . Danach kann es mit RUN  gleich losgehen.

Viel Spaß mit ByPuzz!