Dungeon Crawler

40

Eingang

  • Eine binäre Matrix M die die Wände eines Dungeons darstellt.
  • Die Position (x,y) des Spielers im Dungeon.
  • Die Richtung d , in die der Spieler gerade schaut (0 = Nord, 1 = Ost, 2 = Süd, 3 = West)

Ausgabe

Eine Pseudo-3D-Darstellung der Wände, die sich im Sichtfeld des Players befinden, als ASCII-Grafik mit 30×10 Zeichen.

Nachfolgend finden Sie einige mögliche Ausgaberahmen sowie die entsprechende Karte und den Kompass, um den Überblick zu behalten (das Zeichnen der Karte und des Kompasses ist jedoch nicht Teil der Herausforderung).

Animation

Spezifikation

Sichtfeld

Der Spieler hat 13 Wände in seinem Sichtfeld, die von A bis M beschriftet sind . Unten sind die Positionen der Wände in Bezug auf den Spieler (in Gelb) in alle möglichen Richtungen angegeben.

Sichtfeld

Die Wände zeichnen

AM

Die gesamte Ausgabe wird mit 7 verschiedenen Zeichen gezogen: " ", "'", ".", "|", "-", "_"und ":".

Da eine detaillierte Darstellung der Wandformen im Körper dieser Herausforderung zu langwierig wäre, werden sie stattdessen in folgendem TIO-Link bereitgestellt:

Probieren Sie es online!

Die Zeichen, die nicht Teil einer bestimmten Wand sind, sind "?"in diesen Diagrammen mit einem gekennzeichnet . Sie müssen als "transparente" Zeichen behandelt werden, die überhaupt nicht gezeichnet werden. Auf der anderen Seite sind alle Leerzeichen innerhalb einer Wand „fest“ und müssen alle anderen Zeichen überschreiben, die zuvor dort gezeichnet wurden.

Regeln

Über die Eingabe

  • Mxyd
  • Sie können entweder 0-indexierte oder 1-indexierte Koordinaten verwenden.
  • Sie können 4 verschiedene Werte Ihrer Wahl für die Richtungen verwenden.
  • 3×3
  • Sie können davon ausgehen, dass sich immer umlaufende Wände an den Rändern befinden.
  • Der Spieler befindet sich garantiert auf einem leeren Feld.
  • Die Eingabe ist garantiert gültig.

Über die Ausgabe

  • Die Wände müssen genau wie beschrieben gezeichnet werden.
  • Das Ausgabeformat ist jedoch auch flexibel: einzelner String, Array von Strings, Matrix von Zeichen usw.
  • Führende und nachfolgende Leerzeichen sind zulässig, solange sie konsistent sind.

Das ist .

Testfälle

Alle Testfälle verwenden die folgende Matrix:

[ [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
  [ 1, 0, 1, 1, 1, 0, 0, 0, 0, 1 ],
  [ 1, 0, 1, 0, 1, 0, 0, 1, 0, 1 ],
  [ 1, 0, 0, 0, 0, 0, 1, 1, 0, 1 ],
  [ 1, 0, 0, 1, 0, 0, 0, 1, 0, 1 ],
  [ 1, 0, 0, 1, 1, 0, 1, 1, 0, 1 ],
  [ 1, 1, 1, 1, 0, 0, 0, 0, 0, 1 ],
  [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 ],
  [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ] ]

(0,0)

x=3, y=3, d=0
x=6, y=4, d=3
x=4, y=4, d=1
x=1, y=5, d=2
x=7, y=7, d=3
x=6, y=6, d=1
x=8, y=1, d=2
x=7, y=6, d=1

Erwartete Ergebnisse:

------------------------------    ------------------------------
 x=3, y=3, d=0:                    x=6, y=4, d=3:
------------------------------    ------------------------------
__                          __    '.                          .'
  |'.                    .'|        |                        |  
  |   '.--------------.'   |        |----.                   |  
  |    |              |    |        |    | '.--------.       |  
  |    |              |    |        |    |  |        |       |  
  |    |              |    |        |    |  |        |       |  
  |    |              |    |        |    | .'--------'       |  
  |   .'--------------'.   |        |----'                   |  
__|.'                    '.|__      |                        |  
                                  .'                          '.
------------------------------    ------------------------------
 x=4, y=4, d=1:                    x=1, y=5, d=2:
------------------------------    ------------------------------
                            .'    __ ________________________ .'
                           |        |                        |  
-------.              .----|        |                        |  
       | '.--------.' |    |        |                        |  
       |  |        |  |    |        |                        |  
       |  |        |  |    |        |                        |  
       | .'--------'. |    |        |                        |  
-------'              '----|        |                        |  
                           |      __|________________________|  
                            '.                                '.
------------------------------    ------------------------------
 x=7, y=7, d=3:                    x=6, y=6, d=1:
------------------------------    ------------------------------
'.                                '.                            
  |'.                               |'.                         
  |   '.                            |   '.                      
  |    | '.                 .-      |    |--.--------.--------.-
  |    |  |:               :|       |    |  |        |        | 
  |    |  |:               :|       |    |  |        |        | 
  |    | .'                 '-      |    |--'--------'--------'-
  |   .'                            |   .'                      
  |.'                               |.'                         
.'                                .'                            
------------------------------    ------------------------------
 x=8, y=1, d=2:                    x=7, y=6, d=1:
------------------------------    ------------------------------
'.                          __    '.                            
  |'.                    .'|        |                           
  |   '.              .'   |        |----.--------------.-------
  |    | '.        .' |    |        |    |              |       
  |    |  |:      :|  |    |        |    |              |       
  |    |  |:      :|  |    |        |    |              |       
  |    | .'        '. |    |        |    |              |       
  |   .'              '.   |        |----'--------------'-------
  |.'                    '.|__      |                           
.'                                .'                            

Verwandte Herausforderung:

Diese Herausforderung von 2013 ist eng miteinander verbunden. Es hat jedoch ein anderes Gewinnkriterium (Code-Challenge), eine viel lockerere Spezifikation der Ausgabe und erfordert interaktive E / A.

Arnauld
quelle
Das erinnerte mich sofort an 3D Monster Maze, obwohl das natürlich Blockgrafiken verwendet.
Neil
9
Ihre Herausforderungen sind so lustig und gut geschrieben!
Oliver
Warten auf eine Lösung in Minecraft ...
Erinnert sich noch jemand an den Windows-Bildschirmschoner? War so ein lustiges "Spiel", als ich 5 oder 6 war ...
Magic Octopus Urn

Antworten:

10

Sauber (mit Snappy ), 800 785 670 644 Bytes

460 402 Byte Code + 360 Zeichenfolgenliteral mit 242 Byte
(hier und in TIO mit Escapezeichen versehen, da UTF-8 nicht gültig)

Hier können Sie die Länge des Literal überprüfen .

import StdEnv,Data.List,Data.Maybe,Codec.Compression.Snappy,Text
@a b|b<'~'=b=a
$m x y d=map(@' ')(foldl(\a b=[@u v\\u<-a&v<-b])['~~'..][join['
']k\\Just(Just 1)<-[mapMaybe(\e=e!?(x+[u,v,~u,~v]!!d))(m!?(y+[~v,u,v,~u]!!d))\\u<-[-2,2,-1,1,0,-1,1,0,-1,1,0,-1,1]&v<-[3,3,3,3,3,2,2,2,1,1,1,0,0]]&k<-nub[q\\w<-split"#"(snappy_uncompress"\211\6\44\41\41\41\55\56\40\41\40\174\72\5\4\60\55\47\40\41\41\41\43\41\41\41\176\56\55\r\1\24\56\40\41\176\174\40\r\1\4\174\72\72\r\0\0\47\r\46\35\72\25\1\31\103\0\41\25\24\35\113\176\25\0\31\133\11\224\r\152\20\56\40\40\40\41\21\217\10\40\47\56\31\14\4\40\174\126\14\0\4\56\47\21\74\0\47\1\74\1\340\r\220\25\242\11\1\25\250\25\360\11\1\25\253\376\30\0\21\30\25\333\11\1\24\47\41\41\43\137\137\11\154\20\41\40\40\174\47\r\344\1\157\5\341\1\11\5\336\172\11\0\34\56\47\41\137\137\174\56\47\1\347\20\43\176\176\40\137\132\1\0\4\40\41\75\211\76\1\0\1\356\5\150\116\1\0\376\35\0\376\35\0\126\35\0\132\347\0\20\137\174\41\43\47\101\337\51\74\41\133\122\4\0\10\56\47\40"),q<-let l=[[c\\c<-:rpad s 30'~']\\s<-split"!"w]in[l,map reverse l]]])

Probieren Sie es online!

Schnelle Komprimierung funktioniert in diesem Fall eigentlich recht gut, obwohl sie auf die Geschwindigkeit ausgerichtet ist, da die zu komprimierende Zeichenfolge so viele einzelne Zeichen enthält.

Die unkomprimierte Saite (mit #ersetzt mit \nder Klarheit halber) ist:

!!!-. ! |:! |:!-' !!!
!!!~.--------. !~|        |:!~|        |:!~'--------' !!!
!!!~~~~~~~~~~.--------.!~~~~~~~~~~|        |!~~~~~~~~~~|        |!~~~~~~~~~~'--------'!!!
!!-------.   !       | '.!       |  |!       |  |!       | .'!-------'   !!
!!~~~~~~~.--------------.!~~~~~~~|              |!~~~~~~~|              |!~~~~~~~|              |!~~~~~~~|              |!~~~~~~~'--------------'!!
__      !  |'.   !  |   '.!  |    |!  |    |!  |    |!  |    |!  |   .'!__|.'   !
~~ ________________________ !~~|                        |!~~|                        |!~~|                        |!~~|                        |!~~|                        |!~~|                        |!~~|                        |!~~|________________________|!
'. !  |!  |!  |!  |!  |!  |!  |!  |!.' 

Diese Codiert den linksseitigen Versionen der verschiedenen Bildschirmkomponenten mit !anstelle von Zeilenumbrüchen, und ~statt ?, die dann mit rechts aufgefüllt , ~bevor sie sich zu 30 Zeichen und ihr Line-Umkehrungen zu einer Lookup - Liste haben.

Der Rest des Codes behandelt einfach die Koordinatensuche, wobei Fälle außerhalb des gültigen Bereichs ignoriert werden.

Οurous
quelle
5

Python 2 , 864 854 848 826 810 Bytes

L=[zip(*[iter(w)]*30)for w in zip(*[iter("eJzdllESgyAMRL+5Rf7yRQ7AZbhIDl9BwTqzSVtHrbKffR0Mm13HEM5SFHIoadpNI3snDyaS6NCknhU+JfZOvq8kLoIBU1oEI+RTbiePGzBa3QM0rf78TGl17+CZr5ZrUXBN+ECfY1GvGKEqtDsSI4s6xTn5jgqyqNcTTnUjTQO2FAEqTC0ngCrtpywenX5le6or1SsGi9ZLBKt0HuXtVEeUNGdzG6EsRNmo2EzLxuBbqFH8njmfwnqGcl+VY+s5+5ezSYXVel4dxaRK/6F15SatK1frvm//y4aoT4Ckj6XWfY2cbvz2fLSCPiiVvR+3ZuerzDwPSqeSvgAP9woa".decode('base64').decode('zip'))]*300)]
E=enumerate
def f(m,x,y,d):
 D=eval(`[[' ']*30]*10`);w,h=len(m[0]),len(m);a=[m,zip(*m)[::-1]][d%2];x,y=[x,y,w+~x,h+~y,y,w+~x,h+~y,x][d::4];X=sum([[0]*(x<2)+list(l)[x-2+(x<2):x+3]for l in[l*2for l in[a,[l[::-1]for l in a[::-1]]][d/2]*2][y:y+4]],[])
 for d,w in zip(L,'sropqmklhfgca'):
  for j,l in E(d):
   for i,q in E(l):
    if q*X[ord(w)%32]>=' ':D[j][i]=q
 for l in D:print''.join(l)

Probieren Sie es online!

TFeld
quelle
4

Kohle , 500 332 Bytes

F⁴≔⮌E§θ⁰⁺00⭆θ§μλθ≔E✂θ⊖ζ⁺⁶ζ¹✂ι⊖η⁺⁶η¹θFε≔⮌E§θ⁰⭆θ§μλθB³⁰χ F²«‖FΦ⪪⟦“ |0⟧P+N?⟧‹G”³¦⁰”{➙d⊟EX⍘k↧D({Vt⍘gRd◨ⅉ^δ#T;”³¦¹“ ¶↖+9G₂pF^c1e⌈¬;”³χω⁰χ”{➙∧⊟∧◨ηü∧↖z↨⁸\G'λI∧¡∕⪫θJoΣ³⊖I⊟ζ⊙”²¦⁰”{➙∧⊟∧◨ηü∨§·◧﹪d‹⟲ OzºκFⅉRï⎇”²¦⁷ω⁰χ”{➙∧⊟≔⊘⬤|↔3Zθ✂≔÷t⍘ε✂↨≔⧴×ld≕≡⌕m⟧6ψ=Z”⁰¦⁰”}∧80KυgCAêJm⟦↘/§‖Ck⮌C₂¡μ↗W”⁰¦²ω⁰χ”{⊟∨·◧¤∨¶⧴⬤2GL▷⁸ê5Gψ”⁰¦⁰⟧³I§⭆θ⭆³§μ⎇ι⊕ξ⁻⁵ξλ«J⁻⊟κײ⁹¬ι⊟κ⊟κ

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Ich fürchte, ein etwas langweiliger Ansatz; viel Druck von komprimierten String-Literalen. Erläuterung:

F⁴≔⮌E§θ⁰⁺00⭆θ§μλθ

Pad das Array mit zwei zusätzlichen 0s auf jeder Seite.

≔E✂θ⊖ζ⁺⁶ζ¹✂ι⊖η⁺⁶η¹θ

Schneiden Sie einen 7x7Unterabschnitt des Arrays zentriert auf die angegebenen Koordinaten.

Fε≔⮌E§θ⁰⭆θ§μλθ

Drehen Sie das Array entsprechend der angegebenen Richtung.

B³⁰χ 

(Leerzeichen beachten) Zeichnen Sie ein leeres 30×10Feld, damit die Ausgabe immer eine einheitliche Größe hat.

F²«‖

Zeichne jede Hälfte einzeln und reflektiere dazwischen.

FΦ⪪⟦...⟧³I§⭆θ⭆³§μ⎇ι⁻⁵ξ⊕ξλ«

Nehmen Sie ein Array von Wanddeskriptoren, aufgeteilt in Teile von (Zeichenfolge, y-Koordinate, x-Koordinate), filtern Sie nach den Teilen, die eine Wand an der relevanten Position in der relevanten Hälfte des Arrays aufweisen, und ziehen Sie eine Schleife über die Wände. Die Position wird berechnet, indem 12 Wände aus dem Array extrahiert und mit dem Chunk-Index indiziert werden, da dies besser ist, als die Wand direkt mit dem Chunk-Index zu lokalisieren.

J⁻⊟κײ⁹¬ι⊟κ⊟κ

Springe zu den Koordinaten der Wand und drucke sie aus. Beachten Sie, dass durch Spiegeln die X-Koordinaten von [0, 30)bis negiert werden , (-30, 0]sodass die Zeichenfläche bei einem Durchgang effektiv um 29 Zeichen nach links verschoben wird.

Neil
quelle
1
@Arnauld In der Tat nutze ich die Symmetrie überhaupt nicht aus. Ich sollte in der Lage sein, ein Drittel abzuschneiden, indem ich jede Hälfte einzeln zeichne.
Neil
1
+1 für einen 168-Byte-Golfschlag. Ich denke, das ist der größte Einzelgolfplatz, den ich hier gesehen habe.
ElPedro
2

Ruby , 412 391 385 383 Bytes

->a,x,y,d{b=Array.new(97){[" "]*10}
e=[-1,0,1,0]
14.times{|i|m=-i%3-1
w=[31,25,15,9][n=i>2?4-i/3:(m*=2;3)]
(a*3)[y+n*e[d]+m*c=e[d-3]][x+n*c-m*e[d]]&&[p=w*(m*2-1)/2,r=[12,7,4,3][n]*m*m.abs+m/3].min.upto([q=w*(m*2+1)/2,r].max){|j|t=" .'"*9
b[j+15]=(p<j&&j<q ?%w{-%2s- -%4s- _%7s_}[-n]%"":t[k=(j^j>>9)%(36/-~n)]+"   :|  |    |"[k%13]*(k/3*2)+t[-k]).center(10).chars}}
b[0,30].transpose}

Probieren Sie es online!

Nimmt Eingaben als Array von Wahrheits- / Falsch-Werten (Anmerkung 0ist in Ruby wahr, aber nilfalsch.)

Gibt ein Array von Zeichen aus.

Erläuterung

Die Blöcke werden von vorne nach hinten gezeichnet, wobei der Abstand nabnimmt und die Position von Seite zu Seite mdurch -1,1,0links, rechts und in der Mitte wechselt. Der mittlere Block E in der am weitesten entfernten Reihe wird tatsächlich zweimal gezeichnet, da sowohl die Blöcke A / B als auch die Blöcke C / D überprüft werden müssen. n,mund dverwendet , um die zu modifizieren xund yWerte - Array zu suchen a. Wenn xaußerhalb des Bereichs nilfür eine Zelle außerhalb des Bereichs zurückgegeben wird und kein Fehler ausgegeben ywird, nilwird für die Zeile jedoch ein Wert außerhalb des Bereichs zurückgegeben, und Ruby gibt einen Typfehler aus, wenn nach der Zelle gesucht wird. Um dies zu vermeiden, wird das Array vor dem Suchen in vertikaler Richtung verdreifacht. Wenn ein wahrer Wert gefunden wird, wird ein Block gezeichnet.

Die Ausgabe besteht aus einem Array bvon 10-Element-Arrays, die die Spalten der Ausgabe darstellen, und wird am Ende der Funktion in 10 Zeilen transponiert. Die gesamte Vorderseite aller Blöcke wird gezeichnet (unabhängig davon, ob sie im Ansichtsfenster angezeigt werden oder nicht), sodass zusätzlicher Platz im Array erforderlich ist, um Fehler außerhalb des Bereichs zu vermeiden. Der Wertebereich jim Ansichtsfenster reicht von -15bis +14, dies wird beim Speichern im Array um 15 versetzt, um einen Bereich von 0bis anzugeben 29. Für jeden gezogenen Block werden drei Werte berechnet: pund qfür die linke und rechte Ecke der Vorderwand bzw. rfür die Rückseite der Seitenwand. jwird vom Minimum zum Maximum dieser drei Werte iteriert, wobei die Spalten der Reihe nach gezeichnet werden.

Es gibt drei Arten von Linien: horizontal -oder _vertikal |oder :diagonal mit sich wiederholendem " .'"Muster. Wobei p < j < qSpalten, die Leerzeichen enthalten, mit -oder _gezeichnet werden, um die Vorderseite zu bilden. Befindet jsich eine Spalte außerhalb dieses Bereichs, enthält sie Leerzeichen |oder :ist mit Symbolen von begrenzt t=" .'", um die Kanten und / oder die Seitenfläche zu bilden. Dies wird durch die Variable verwaltet , k=jwo jpositiv ist oder k=-j-1wo jist negativ. Die Anzahl der Zeichen zwischen der oberen und der unteren Groß- / Kleinschreibung beträgt k/3*2. Um die Außenkanten der am weitesten entfernten Blöcke richtig handhaben zu können n=3, kmuss modulo 9 gewählt werden, dies darf jedoch nicht für kleinere Werte von erfolgenn. kwird daher modulo genommen 36/-~n, wo sich -~nauswertet n+1.

Ungolfed Code

->a,x,y,d{
  b=Array.new(97){[" "]*10}                                        #Set up array for output, allow space for plotting outside viewport
  e=[-1,0,1,0]                                                     #Direction offsets from player position
  14.times{|i|                                                     #Iterate through all blocks including block E twice 
    m=-i%3-1                                                       #Cycle -1,1,0 = left, right, centre
    n=i>2?4-i/3:(m*=2;3)                                           #Distance n=4-i/3. But if i/3==0 n=3 and double m for blocks A,B 
    w=[31,25,15,9][n]                                              #Width of front face of block
    r=[12,7,4,3][n]*m*m.abs+m/3                                    #Value of j for back edge of block. m/3 offsets by -1 when m negative 
    (a*3)[y+n*e[d]+m*c=e[d-3]][x+n*c-m*e[d]]&&(                    #If a block is present at the location then
      [p=w*(m*2-1)/2,r].min.upto([q=w*(m*2+1)/2,r].max){|j|        #Calculate left and right edges of front of block p,q and iterate
        t=" .'"*9                                                  #t=character constant for diagonal lines 
        k=(j^j>>9)%(36/-~n)                                        #k=j for positive j=distance from centre. For negative j, k=-1-j by XOR with j>>9=-1. If n=3 take modulo 9 for correct output of outer side of block. 
        b[j+15]=(p<j&&j<q ?%w{-%2s- -%4s- _%7s_}[-n]%"":           #If j between p&q, draw horizontal lines separated by 2,4 or 7 spaces depending on value of n
        t[k]+"   :|  |    |"[k%13]*(k/3*2)+t[-k]).center(10).chars #else draw space or vertical line capped by diagonal markers
      }
    )
  }
b[0,30].transpose}                                                 #Truncate values outside viewport, transpose, and return value.
Level River St
quelle
Gute Antwort! Mir gefällt die Art und Weise, wie alle Linien programmgesteuert generiert werden, auch diagonale.
Arnauld