Als ich ein Junge war, gingen die Kinder in Computerläden und spielten Hunt the Wumpus, bis die Angestellten uns rausschmissen. Es war ein einfaches Spiel, das auf den Heimcomputern der Mitte der 1970er Jahre programmiert werden konnte. Die Maschinen waren so rudimentär, dass ich glaube, dass einige von ihnen anstelle von Mikroprozessoren in Chicklet-Größe echte Chicklets enthielten.
Erinnern wir uns an diese vergangene Ära, indem wir das Spiel auf moderner Hardware reproduzieren.
Der Spieler startet in einem zufälligen Raum auf einer Ikosaeder-Karte (es gibt also insgesamt 20 Räume, die wie die Gesichter eines Ikosaeders miteinander verbunden sind und jeder Raum hat genau drei Ausgänge).
Der Wumpus startet in einem zufällig ausgewählten anderen Raum. Der Wumpus stinkt und sein Geruch kann in jedem der drei Räume neben seinem Standort festgestellt werden, obwohl der Spieler die Richtung des Geruchs nicht bestimmen kann. Das Spiel meldet nur "Sie riechen einen Wumpus."
Der Spieler trägt einen Bogen und unendlich viele Pfeile, die er jederzeit in den Raum vor sich schießen kann. Befindet sich der Wumpus in diesem Raum, stirbt er und der Spieler gewinnt. Wenn sich der Wumpus nicht in diesem Raum befand, wird er erschrocken und bewegt sich zufällig in einen der drei Räume, die mit seiner aktuellen Position verbunden sind.
Ein zufällig ausgewählter Raum (der garantiert nicht der Raum ist, in dem der Spieler beginnt) enthält eine bodenlose Grube. Befindet sich der Spieler in einem Raum neben der Grube, spürt er eine Brise, bekommt aber keine Ahnung, von welcher Tür die Brise kam. Wenn er mit der Grube in den Raum geht, stirbt er und Wumpus gewinnt. Der Wumpus bleibt von der Grube unberührt.
Betritt der Spieler den Raum des Wumpus oder betritt der Wumpus den Raum des Spielers, gewinnt der Wumpus.
Der Spieler gibt die Richtung an, in die er schaut, mit einer Zahl (1 = rechts, 2 = links, 3 = zurück) und einer Aktion (4 = Pfeil abschießen, 5 = in die angegebene Richtung gehen).
Aus Gründen der Punktzahl kann jede Spielfolge ("Sie spüren eine Brise", "Sie riechen einen Wumpus", "Ihr Pfeil hat nichts getroffen" usw.) als ein Byte angesehen werden. Kein Missbrauch, um den Spielcode im Text zu verstecken. Dies ist nur für die Interaktion mit dem Spieler.
Ziehe 10% deiner Byteanzahl ab, um Megabats zu implementieren, die in einem zufälligen Raum beginnen, der sich vom Spieler unterscheidet (obwohl sie einen Raum mit dem Wumpus und / oder der Grube teilen können). Wenn der Spieler den Raum mit den Fledermäusen betritt, tragen die Fledermäuse den Spieler in einen anderen zufällig ausgewählten Raum (der garantiert nicht der Raum mit der Grube oder dem Wumpus ist), bevor sie zu ihrem eigenen neuen zufälligen Ort fliegen. In den drei Räumen neben den Fledermäusen ist ein Quietschen zu hören, dem Spieler wird jedoch nicht mitgeteilt, aus welchem Raum der Ton kommt.
Ziehen Sie 35% Ihrer Byteanzahl ab, um eine grafische Oberfläche zu implementieren, die die Ikosaeder-Karte und eine Art Anzeige der Informationen enthält, die der Spieler bisher über die Position der Grube, des Wumpus und der Fledermäuse (falls zutreffend) im Verhältnis zu hat der Spieler. Wenn sich der Wumpus bewegt oder der Spieler von den Fledermäusen bewegt wird, muss die Karte natürlich entsprechend zurückgesetzt werden.
Die niedrigste angepasste Byteanzahl gewinnt.
BASIC-Quellcode für eine Version des Spiels (die nicht unbedingt den oben genannten Regeln entspricht und auf jeden Fall völlig ungolfed ist) finden Sie auf dieser Website und wahrscheinlich auch auf anderen.
quelle
Antworten:
GolfScript, 163
Die Bewertung wird erhalten, indem die Byteanzahl (290) genommen wird, die Anzahl der für die Interaktion mit dem Benutzer (6) verwendeten Zeichenfolgen addiert wird und die kombinierte Länge dieser Zeichenfolgen subtrahiert wird (133). Die Zeilenvorschübe sind Teil der Zeichenfolgen und tragen zur Bytezahl bei.
Meilensteine
Portierte professorfish's Antwort von Bash nach GolfScript. Ergebnis: 269
Hat auf die Vorschläge von Peter Taylor in den Kommentaren reagiert. Ergebnis: 250
Peter Taylor überarbeitete meinen gesamten Code und half mir, die Nachschlagetabelle zu komprimieren. Prüfungsergebnis: 202
Die Nachschlagetabelle benachbarter Räume wurde durch einen mathematischen Ansatz ersetzt. Prüfungsergebnis: 182
Refactored Input, Output und die Funktion, die den mathematischen Ansatz unterstützt. Prüfungsergebnis: 163
Ein großes Dankeschön geht an Peter Taylor für all seine Hilfe.
Wie es funktioniert
Die 20 Räume werden als Eckpunkte eines Dodekaeders dargestellt, denen auf folgende Weise Nummern von 0 bis 19 zugewiesen wurden:
Um die an Raum N angrenzenden Räume zu finden und im Uhrzeigersinn zu ordnen, müssen wir vier Fälle betrachten:
Wenn N ≤ 0 mod 4 (blaue Eckpunkte) ist, sind der angrenzende Raum 19 - N , N + 2 mod 20 und N - 2 mod 20 .
Wenn N ≤ 1 mod 4 (grüne Eckpunkte) ist, sind der angrenzende Raum 19 - N , N - 4 mod 20 und N + 4 mod 20 .
Wenn N ≤ 2 mod 4 (gelbe Eckpunkte) ist, sind der angrenzende Raum 19 - N , N - 2 mod 20 und N + 2 mod 20 .
Wenn N ≤ 3 mod 4 (rote Eckpunkte), ist der angrenzende Raum, 19 - N , N + 4 mod 20 und N - 4 mod 20 .
quelle
Q
mit speichern19rand 97+
; 2 in@
mit97%3*&>
..., eine weitere 1 durch InliningQ
als{19rand 97+}2*:,\:H
, ein paar durch Ersetzen|
durch*
, was oft der beste Weg ist, um eineif
.B
hat keinen Zweck, und ich denke, ein paar weitere Variablen könnten durch die Verwendung des Stacks beseitigt werden.256base 20base
(und möglicherweise auch einige +/- 97 Zeichen entfernen ). Der einzige Nachteil ist, dass nicht druckbare Zeichen erforderlich sind.You were killed by the wumpus
ohne dass der Pfeil fehlt. Deshalb habe ich in der nicht-hübschen Version angehängt.2*2+
=>)2*
REV0 C ++ (Visual Studio unter Windows) 405Im Folgenden sehen Sie einen Durchgang, der zeigt, dass Sie bei korrektem Spiel immer gewinnen können (vorausgesetzt, Sie beginnen nicht direkt neben einer Gefahr). Der Spieler fühlt eine Brise, dreht sich um und macht eine vollständige Schleife gegen den Uhrzeigersinn. Da er genau 5 Züge braucht, um wieder eine Brise zu spüren, kennt er das Loch zu seiner Rechten und kommt so weit wie möglich weg. Wenn er den Wumpus riecht und nicht weiß, ob er rechts oder links ist, dreht er sich um und macht eine Schleife im Uhrzeigersinn. Er braucht 5 Züge, um den Wumpus wieder zu riechen, also weiß er, dass er links ist und schießt mit Sicherheit.
Wenn er sich anders herum geschleift hätte, hätte er den Wumpus früher gefunden und gewusst, dass er sich in die gleiche Richtung drehte.
REV1 C (GCC auf Cygwin), 431-35% Bonus = 280,15Zeilenumbrüche zur Verdeutlichung hinzugefügt. Die Änderungen von Rev 0 sind wie folgt:
Ein großes Dankeschön an @Dennis für die Empfehlung des GCC-Compilers für den Cygwin Linux-Emulator für Windows. Für diesen Compiler ist das
include
s im Rev. 0-Programm nicht erforderlich , und der Standardtypint
für Variablenmain.
ist zulässig. Dies ist ein lebensverändernder Golftipp!Wenn Sie zusätzlich unter Linux arbeiten
\f
, bewegt sich der Cursor nach unten, ohne dass ein Wagenrücklauf ausgeführt wird (im Gegensatz zu Windows, in dem nur ein druckbares Symbol erstellt wird). Dadurch konnte die printf-Anweisung, mit der die Karte gedruckt wird, erheblich verkürzt werdenEinige zusätzliche Tipps von Dennis in den Kommentaren und einen von mir: Zustandsänderung beim Prüfen, ob der Pfeil auf den Wumpus trifft:
if(q==w)
>if(q-w)
(..else .. ist umgekehrt)Zusätzliches Grafikdisplay mit den Informationen, die der Spieler darüber kennt, wo ein Wumpus riecht / eine Brise spürt, dass er den 35% -Bonus beansprucht. (Ich habe die alte Debug-Version gelöscht, in der die genaue Position von Wumpus und Loch angegeben ist. Sie ist im Bearbeitungsverlauf zu sehen.)
REV2 C (GCC auf Cygwin), 389-35% Bonus = 252,85
Nochmals vielen Dank an Dennis für die Überarbeitung meines Codes:
Zeichenkonstante
m[]
durch Literale ersetzt (Ich wusste nicht, dass Sie ein Literal indizieren können.)Seeding von Zufallszahlen mit Stapelvariablen (systemabhängig, einige Systeme setzen die Speicherzuordnung als Sicherheitsmaßnahme zufällig fest.)
Makro mit
puts
ersetzt durch ein Makro mitprintf
und zusätzlichem Code, der ausgeführt werden muss, wenn die angezeigte Nachricht inprintf
Argumenten platziert wird (Vorteil, dass printf die letzten Argumente nicht druckt, wenn nicht genügend Formatspezifizierer in der Formatzeichenfolge vorhanden sind.)if
ersetzt durch||
Berechnung der neuen Position des Spielers / Wumpus innerhalb des neuen Makros.
Nachrichten außerhalb der
while
Schleife gewinnen / verlieren .if
ersetzt durch bedingten Operator.Verwendung des bedingten Operators in der Linie zum Schießen des Pfeils. Wenn der Spieler ausfällt, müssen Sie sowohl eine Nachricht drucken als auch die Wumpusposition anpassen. Dennis bot ein paar Möglichkeiten an,
printf
die Wumpus-Position in einem Ausdruck zu kombinieren und zu berechnen, aber ich habe mich für einen eigenen entschieden.printf
gibt die Anzahl der gedruckten Zeichen, dieYour arrow didn't hit anything\n
also 31 (11111 binär.)31&Q(w)==Q(w)
.Mein anderer Beitrag zu dieser Bearbeitung war die Beseitigung einiger unnötiger Klammern.
Ausgabe
Hier hat der Spieler bereits gefunden, wo sich der Wumpus befindet, entscheidet sich jedoch für eine gründliche Untersuchung, um herauszufinden, wo sich auch die Grube befindet. Im Gegensatz zu meiner alten Debug-Version, in der angezeigt wurde, wo sich Wumpus und Pit während des Spiels befanden, werden hier nur die Räume angezeigt, in denen der Spieler den Wumpus (2) oder beides (3) besucht und eine Brise gespürt hat (1). (Wenn der Spieler einen Pfeil schießt und verfehlt, wird die Variable
a
mit den Wumpuspositionsinformationen zurückgesetzt.)ICOSAHEDRON-VERTRETUNG
Hinweis: Dieser Abschnitt basiert auf Version 1
Mein Star-Feature! Mein Code enthält kein Diagramm. Informationen zur Funktionsweise finden Sie auf der folgenden Weltkarte. Jeder Punkt auf dem Ikosaeder kann durch einen Breitengrad 0-3 und einen Längengrad 0-4 (oder eine einzelne Zahl) dargestellt werden
long*4+lat
. Die auf der Karte markierte Längengradlinie verläuft nur durch die Flächen mit dem Längengrad Null, und die Breitengradlinie verläuft durch die Mitte der Gesichter mit dem Breitengrad Null.Der Spieler kann sich an drei möglichen Achsen orientieren, die durch die folgenden Symbole dargestellt werden: Nord-Süd-
-
Nordost-Südwest\
- Nordost -Südost/
. In jedem Raum steht ihm auf jeder dieser Achsen genau ein Ausgang zur Verfügung. In der angezeigten Anzeige macht der Player eine vollständige Schleife im Uhrzeigersinn. Es ist im Allgemeinen einfach, anhand der Spielermarkierung zu erkennen, woher er kam und wohin er gehen darf.Der eine Fall, der für das nicht eingeweihte Auge etwas schwierig ist, ist der vierte. Wenn Sie eine Neigung in einer dieser Polarreihen sehen, ist der Spieler von der Polarzelle gekommen, die dem äußeren Ende der Neigung am nächsten liegt, und zeigt im Allgemeinen zum Äquator. Der Spieler ist also nach Südosten ausgerichtet und hat folgende Optionen: 15 (SÜD, die Zelle rechts) 25 (Nordosten, die Zelle oben) oder 35 (Nordwesten, die Zelle unten).
Im Grunde genommen ordne ich das Ikosaeder einem 5x4-Raster zu, wobei die Zellen in der Reihenfolge, in der sie gedruckt werden, von 19 bis 0 nummeriert sind. Der Zug erfolgt durch Addieren oder Subtrahieren der aktuellen Position, abhängig vom Breitengrad und der Richtung des Spielers, gemäß der folgenden Tabelle.
Wenn der Spieler vom Boden (Westen) des Bretts absteigt, kehrt er auf die Oberseite (Osten) zurück und umgekehrt, sodass seine Position modulo 20 eingenommen wird. Im Allgemeinen werden die Züge durch Hinzufügen von ASCII 80 in m [] codiert.
P
) zu dem Rohwert hinzu, der die unten gezeigten Zeichen angibt, aber grundsätzlich kann ein beliebiges Vielfaches von 20 hinzugefügt werden, ohne die Operation zu beeinflussen.Die Eingabe des Spielers (geteilt durch 10, um die zweite Ziffer zu entfernen) wird zu seiner aktuellen Richtung addiert und modulo 3 genommen, um seine neue Richtung zu erhalten. Dies funktioniert in den meisten Fällen einwandfrei. Es gibt jedoch ein Problem, wenn er sich in einem Polarraum befindet und sich auf die Stange zubewegt. Wenn Sie die Karte darunter falten, wird klar, dass er, wenn er den Raum nach "Nordosten" verlässt, das neue Quadrat nach "Südosten" betritt, sodass eine Korrektur vorgenommen werden muss. Dies geschieht in der Zeile
e=(d+i/10)*m[p%4]%3;
durch Multiplikation mitm[p%4]
. Die ersten vier Werte von m [] werden so gewählt, dass sie zusätzlich zu ihrer obigen Funktion auch die Charakteristikm[1]%3==m[2]%3==1
und habenm[0]%3==m[3]%3==2
. Dies lässt die Richtung für die Äquatorialräume allein und wendet die notwendige Korrektur für Polarräume an.Die logische Zeit für die Korrektur wäre nach dem Umzug. Das Speichern von Zeichen erfolgt jedoch vor dem Verschieben. Daher müssen bestimmte Werte in m [] transponiert werden. So sind die letzten 2 Zeichen
LT
anstelle derTL
obigen Tabelle zum Beispiel.UNGOLFED CODE
Dies ist Rev. 1 Code, der weniger verschleiert ist als Rev. 2.
Dies wird unter GCC / Linux ausgeführt. Ich habe in den Kommentaren den zusätzlichen Code angegeben, der für die Ausführung unter Visual Studio / Windows erforderlich ist. Das ist ein großer Unterschied!
FRAGEN UND NEUGIERIGKEITEN
Ich habe den von @professorfish erwähnten Punkt ausgenutzt. Wenn der Wumpus und die Grube an zufälligen Orten beginnen, muss der Spieler nicht an zufälligen Orten beginnen. Der Spieler startet immer in Raum 19 nach Norden.
Ich verstehe, dass, da der Wumpus "von der Grube nicht betroffen" ist, der Wumpus beginnen oder den Raum betreten kann, in dem sich die Grube befindet. Im Allgemeinen vereinfacht dies die Dinge bis auf einen Punkt. Ich habe keine spezifische Variable, die anzeigt, dass das Spiel beendet ist. es ist vorbei, wenn der Spieler mit dem Wumpus oder der Grube zusammenfällt. Wenn der Spieler gewinnt, zeige ich die Gewinnnachricht an, aber bewege die Grube zum Spieler, um aus der Schleife herauszukommen! Ich kann den Spieler nicht in die Box setzen, da der Wumpus dort sein könnte und ich eine Nachricht über den Wumpus erhalten würde, die ich nicht möchte.
Das rev0-Programm funktionierte perfekt in Visual Studio, aber die IDE meldete beim Beenden "Stapel um Variable i beschädigt". Dies ist darauf zurückzuführen, dass scanf versucht,
int
ein vonchar.
Dennis gemeldetes falsches Verhalten auf seinem Linux-Computer zu erzeugen . Auf jeden Fall wird es durch Verwendung des richtigen Typs in Rev. 1 behoben.Die Zeile für die Anzeige des Boards in Rev. 0 ist unbeholfen und sieht auf anderen Plattformen etwas anders aus. In
printf(" %c%c%c")
der Mitte% c wird das druckbare Zeichen angezeigt. Das letzte% c ist entweder ASCII 0 oder ASCII 10 (\ n, Zeilenumbruch mit Wagenrücklauf in Windows.) In Windows scheint es kein Zeichen zu geben, das in der Konsole funktioniert und das eine Zeile ohne Wagenrücklauf abfährt. Wenn es das gäbe, bräuchte ich nicht das erste c% (ASCII 0- oder ASCII 9-Tab vor dem 1. Breitengrad-Zeichen. Tabs sind in ihrem Verhalten notorisch undefiniert.) Das führende Leerzeichen verbessert die Formatierung (bringt die 3. und 2. Breite näher an das 1. Breitengrad-Zeichen .) Rev 1 enthält eine Überarbeitung dieser Zeile, die ein \ f-Formatvorschubzeichen verwendet und daher am Anfang des Ausdrucks kein Formatzeichen benötigt. Das macht es kürzer, aber das \ f funktioniert nicht in Windows.quelle
scanf_s
mitscanf
und schließen Sie es ein,stdio.h
wenn ich als C ++ Rater als C kompiliere), aber es funktioniert nicht ganz für mich. Zum Beispiel, wenn ich nach links gehe, dann wieder rechts am Anfang (15 35
), bin ich in einem anderen Raum als dem, in dem ich angefangen habe.i
ist in der Tat das Problem. Die Manpage sagt: " d Entspricht einer optional vorzeichenbehafteten Dezimalzahl; der nächste Zeiger muss ein Zeiger auf int sein ." Durch Ändern des Typs funktioniert es einwandfrei.NULL
mit0
undscanf_s
mitscanf
, die Sie nicht brauchen ,int
bevormain
und Sie können sich bewegeni
undd
der Haupt außen (sie standardmäßig aufint
und werden initialisiert0
). Sie können auch definierenp=19,h=rand()%p,w=rand()%p
, ersetzenm[]
durch*m
und es sollte möglich sein, ein Makro für alle Instanzen von zu definierenif(...==...)puts(...);
.GolfScript, 269 Zeichen
Beachten Sie, dass 163 von der Zeichenanzahl für die hartcodierten Zeichenfolgen abgezogen wurde. Wenn Sie eine Debug-Ausgabe unter Angabe der Raumnummern wünschen, fügen Sie die folgende Zeile direkt nach dem ersten Auftreten von hinzu
^
:Eine Beispielsitzung (mit zusätzlicher Debug-Ausgabe):
quelle
{puts}:|;
, 5 Zeichen durch Ersetzen vonR
undW
mit-
und>
(umliegende Leerzeichen können entfernt werden) und 9 Zeichen durch Löschen'> 'print
(scheint in der Frage nicht erforderlich zu sein).JavaScript (ECMAScript 6) -
21971759 -45% = 967,45 ZeichenFast fertig mit Golfen ...
Enthält eine grafische Benutzeroberfläche mit einer Ikosaeder-Karte und Mega-Fledermäusen für die vollen Boni.
X
(die Grube);B
(der Mega-Bat);W
(der Wumpus); undP
(Sie).W
undP
können nur in den Räumen neben Ihrem aktuellen Standort angeklickt werden.Code:
quelle
Bash, 365 (erste Arbeitsversion 726!)
FANGEN SIE MIT GOLFSCRIPT?
@Dennis hat im Grunde das ganze Golfen für mich erledigt. Vielen Dank!
Das Programm geht von einer gültigen Eingabe aus. Die gültige Eingabe ist die von Ihnen gewählte Richtung (1 für rechts, 2 für links, 3 für hinten), gefolgt von Ihrer Aktion (4 zum Schießen, 5 zum Gehen).
Einige Erklärungen
Normalerweise erkläre ich ausführlich, aber das ist wahrscheinlich ein bisschen zu kompliziert, als dass ich mich darum kümmern könnte.
Jeder Scheitelpunkt im Dodekaedergraphen wird als Buchstabe kodiert (a = 1, b = 2, ... t = 20).
Die Startposition des Spielers ist immer 20 (und sie stehen mit dem Rücken zu 18), da dies an sich keine Rolle spielt, sondern nur die relativen Positionen des Spielers, der Grube und des Wumpus.
Die Variable
$p
speichert den Standort des Players.$r
Speichert den vorherigen Standort des Players.$w
ist der Wumpus und$h
(H für Loch) ist die Grube.Code
Versionsgeschichte
grep -oE
eine Variable. 5 Zeichen gespeichert.[a-z]{3}
eine Variable. 3 Zeichen gespeichert.echo
eine Variable. 5 Zeichen gespeichert.$m
.grep
und etwas mehr Sinn rasiert .C
als reguläre Suchfunktion, die in if-Anweisungen verwendet werden soll, undE
als Funktion, die "Sie haben den Wumpus getötet" ausgibt und beendet.d
unnötige Klammern entfernt wurden.Probelauf
"In:" wird eingegeben, "Out: wird ausgegeben".
Der Spieler läuft ein bisschen umher, riecht den Wumpus und schießt. Sie vermissen, und der Wumpus kommt in ihr Zimmer und isst sie.
quelle
exit
ist nur ein Byte länger alsg=1
und erübrigt das Testen auf Nicht-Nullg
und einigeelif
Anweisungen. 2. Sie können((i==35))
anstelle von[ $i = 35 ]
und...&&...
anstelle von verwendenif ... then ... fi
. 3.q(){ L=({a..s});$j ${L[RANDOM%19]};}
undn=`$k $w$m<<<$d`;w=${n:RANDOM%2+1:1}
beide sparen ein paar Bytes.while :;do
...done
durchfor((;;);{
...,}
um 3 Zeichen zu sparend(){ x=npoemfgnshtoksblbtckpdpljqniorelgfhkbqraicadjaghimsmjtqecrdf;s=${x:3*30#$1-30:3};}
können Sie die Definitionen vons
undn
durchd $p
und ersetzend $w
. Wenn Sie außerdemu=${s#*$r}$s
die Definitionen vonl
undf
entsprechend definieren (und anpassen ), brauchen Sie$k
und$m
nicht mehr. Spart 83 Bytes, denke ich. Auch der Platz inq ()
ist nicht erforderlich.c(){ [[ $1 =~ $2 ]];}
indem Sie zB die vorletzte Zeile mit definieren und ersetzenc $r $b||{ $j You missed;d $w;w=${s:RANDOM%2+1:1};}
.b=$p
mitd $p;u=u${s#*$r}$s
, die Zeilen nachread i
mity=${u:i/10:1};C $i 5&&{ p=$y;r=$b;}||{ d $w;C $y $w&&$j You killed the wumpus&&exit;$j You missed;w=${s:RANDOM%2:1};}
und loswerden ersetzenE()
.GolfScript (
206198)Endlich mit Dennis 'Lookup-Table-Version, von der es sich einiges leiht, mithalten können. Das Interessante an dieser Version ist, dass es keine Nachschlagetabelle für die Raumaufteilung gibt.
Die 60 Rotationssymmetrien eines Ikosaeders sind isomorph zu der alternierenden Gruppe von 5 Buchstaben A_5. Nachdem ich alle Arten von Ansätzen zur kompakten Darstellung der Gruppe ausprobiert habe, bin ich auf die einfachste zurückgekehrt: Jedes Element ist eine Permutation mit gerader Parität. Die Gruppe kann auf mehrere Arten aus zwei Generatoren generiert werden: Der von mir verfolgte Ansatz verwendet die Generatoren
3
und3 1
. Diese ermöglichen es uns zu erzeugen1 = 3 3 1
,2 = 3 3 1 3 1
und3 = 3
.Beachten Sie, dass die Richtung
3
einem Element der Ordnung 2 entspricht, denn nachdem Sie durch die Tür hinter sich gegangen sind, befindet sich diese Tür wieder hinter Ihnen. Die Richtung1
entspricht einem Element der Ordnung 5, das um einen Scheitelpunkt des Ikosaeders läuft. (Ähnliches Element2
). Und die Kombination3 1
ist in der Größenordnung 3, da sie die Räume umrundet, die an den Raum angrenzen, der hinter Ihnen beginnt.Wir suchen also nach einer Permutation der Ordnung 2, um die Richtung darzustellen,
3
und einer Permutation der Ordnung 5, um die Richtung darzustellen1
,3 1
die der Ordnung 3 entspricht.Es gibt 15 Permutationen der Ordnung 2 in A_5, und für jede gibt es 8 mögliche Permutationen für
1
(und damit für3 1
). Es gibt eine offensichtliche Anziehungskraft[4 3 2 1 0]
für3
: Das Umkehren eines Arrays ist gerecht-1%
. Von seinen möglichen Companion-Permutationen3 1
habe ich gewählt[0 1 3 4 2]
, was eine recht kurze Implementierung als zulässt[~@]
.Ungolfed
quelle
10/@3%=
versucht, auf das vierte Element eines Arrays der Länge 3 zuzugreifen, wenn die Eingabe lautet35
.9/3%@3%=
.9/
anstatt10/
noch funktioniert, also danke.Wumpus , 384 - 129 (Zeichenfolgen) = 255 Byte
Probieren Sie es online! (Natürlich macht TIO nicht viel Sinn, da Sie das Programm dort nicht interaktiv verwenden können und wenn die Anweisungen für STDIN nicht mehr ausreichen, wird es lesen
0 0
, was äquivalent ist3 4
, sodass Sie am Ende enden werden schieße Pfeile, bis der Wumpus sich dorthin bewegt oder dich tötet.)Wenn Sie dies lokal ausführen, stellen Sie sicher, dass der Zeilenvorschub nach der zweiten Nummer jeder Eingabe gelöscht wird (da Wumpus ihn benötigt, um festzustellen, dass die Nummer überschritten ist). In Powershell muss ich nach dem Zeilenvorschub noch ein Zeichen eingeben, damit es funktioniert (egal welches Zeichen, aber ich habe nur doppelte Zeilenvorschübe zum Testen verwendet).
Es gibt viel Platz zum Golfspielen, aber das Ausprobieren völlig neuer Layouts dauert eine Weile. Die endgültige Bewertung hängt auch stark von den tatsächlichen Zeichenfolgen ab, die ich verwende. In einer 2D-Sprache kostet eine Zeichenfolge mit N Bytes in der Regel mehr als N Bytes Quellcode, da dies das Codelayout erheblich einschränkt, und zwar häufig Es muss in mehrere Abschnitte unterteilt werden (zusätzliche doppelte Anführungszeichen). Am äußersten Ende würde ich wahrscheinlich eine Tonne Bytes sparen, wenn ich jede Zeichenfolge auf einen einzelnen Buchstaben (und die -129 bis -12) reduzieren würde.
Erläuterung
Zunächst wird ein Haftungsausschluss: Trotz des Namens der Sprache, wurde es nicht zu machen Umsetzung entworfen Hunt Wumpus besonders einfach. Stattdessen entwarf ich zuerst die Sprache rund um das Thema Dreiecke, endete mit einer ikosaedrischen Datenstruktur und beschloss, sie deswegen Wumpus zu nennen.
Also ja, während Wumpus hauptsächlich stapelbasiert ist, hat es auch 20 Register, die um die Flächen eines Ikosaeders angeordnet sind. Das heißt, wir bekommen eine Datenstruktur, um die Karte kostenlos darzustellen. Das Einzige, was wir nicht so einfach machen können, ist, bestimmte Gesichter auf dem Ikosaeder zu finden. Um nach ihnen zu suchen, müssen wir den "d20" rollen, bis wir auf dem Gesicht landen, das wir suchen. (Es ist möglich, dies deterministisch zu tun, aber das würde viel mehr Bytes in Anspruch nehmen.) Die Suche nach Gesichtern wie diesem endet fast sicher (dh mit Wahrscheinlichkeit 1), sodass die Suche, die für immer läuft, in der Praxis kein Problem darstellt.
Der obige Code ist eine Golf-Version dieser ersten Implementierung mit einem klareren Layout:
Da das Golfen hauptsächlich das Komprimieren des Layouts beinhaltete, erkläre ich diese Version erst einmal (bis ich irgendwelche Golftricks hinzufüge, die über die Umstrukturierung des Codes hinausgehen).
Beginnen wir mit dem Setup-Code:
Anfangs sind alle Gesichter auf 0 gesetzt . Wir codieren den Wumpus, indem wir das 1-Bit der entsprechenden Fläche und den Pit, indem wir das 2-Bit setzen. Auf diese Weise können sich beide im selben Raum befinden. Die Position des Spielers wird überhaupt nicht im Ikosaeder aufgezeichnet, sondern ist immer aktiv (es ist immer nur eines der 20 Register aktiv).
Jetzt müssen wir ein zufälliges leeres Gesicht finden, um den Spieler hinein zu setzen.
Dieser nächste Abschnitt prüft die Umgebung des Players und druckt die entsprechenden Warnungen aus:
Dies ist eine Schleife, die wir dreimal durchlaufen. Jedes Mal, wenn wir auf den rechten Nachbarn schauen, drucken wir die entsprechende (n) Zeichenfolge (n), wenn eine Gefahr besteht, und drehen dann das Ikosaeder um 120 °.
Der nächste Abschnitt liest zwei Zahlen vom Spieler und bewegt dann entweder den Spieler oder schießt einen Pfeil. Ersteres ist trivial, letzteres weniger. Das Hauptproblem beim Schießen des Pfeils ist der Fall, in dem er verfehlt. In diesem Fall müssen wir a) nach dem Wumpus suchen, um ihn zu bewegen, und dann b) in den Raum des Spielers zurückkehren und die richtige Ausrichtung des Ikosaeders feststellen (so dass "zurück" "zurück" bleibt). Dies ist der teuerste Teil des gesamten Programms.
Der Einstiegspunkt zu diesem Abschnitt befindet sich
I
auf der linken Seite.Puh, das war der schwierige Teil. Jetzt müssen wir nur noch prüfen, ob der Spieler stirbt und ansonsten über die Hauptschleife starten:
Die Struktur dieses Abschnitts ist im Wesentlichen identisch mit der Struktur, die wir beim Überprüfen der Umgebung des Spielers verwendet haben: Wir überprüfen das 1-Bit des aktuellen Gesichts (des Raums des Spielers), und wenn es gesetzt ist, drucken wir
The wumpus ate you.
das Programm und beenden es. Andernfalls überprüfen wir das 2-Bit und setzen es, wir druckenYou fell into the pit.
und beenden das Programm. Ansonsten erreichen wir die,2.
die an den Anfang der Hauptschleife zurückspringt (bei Koordinaten(0, 2)
).quelle
awk - groß
Dies fiel nicht so kurz aus, wie ich es mir erhofft hatte, aber ich ging etwas anders mit dem Graphen um, also poste ich die ungolfed Version trotzdem.
Ich habe die Tatsache ausgenutzt, dass ein Ikosaeder (20-seitiges Polyeder) unter Wahrung der Orientierung bei Rotationen isomorph zu der alternierenden Gruppe des Grades 5 ist (5 Elementpermutationen mit einer geraden Anzahl von Zyklen mit gerader Länge). Ich wähle dann zwei Permutationen mit der Zykluslänge 5 als "left" und "right" und ich wähle eine Permutation mit der Zykluslänge 2 als "back". Mit diesen baue ich den Graphen aus einem Raum auf, indem ich den Hamilton-Pfad gehe (2xRRRLLLRLRL, mit 3xRB in jedem Raum, um die 3 möglichen Richtungen zu erfassen).
quelle