Dungeon Crawler

40

Entrada

  • Uma matriz binária representando as paredes de uma masmorra.M
  • A posição do jogador dentro da masmorra.(x,y)
  • A direção que o jogador está enfrentando no momento (0 = Norte, 1 = Leste, 2 = Sul, 3 = Oeste)d

Saída

Uma representação pseudo-3D das paredes que estão no campo de visão do jogador, como uma arte ASCII de caracteres.30×10

Abaixo estão vários quadros de saída possíveis, juntamente com o mapa e a bússola correspondentes para ajudar a entender o problema (mas desenhar o mapa e a bússola não faz parte do desafio).

animação

Especificação

Campo de visão

O jogador tem paredes no seu campo de vista, marcada a partir de para . Abaixo estão as posições das paredes em relação ao jogador (em amarelo), em todas as direções possíveis.13AM

campo de visão

Desenhando as paredes

As paredes devem ser desenhadas de a nesta ordem exata, uma vez que qualquer peça desenhada anteriormente pode ser substituída por paredes mais próximas. Obviamente, você pode implementá-lo de maneira diferente, desde que o resultado final seja o mesmo.AM

Toda a saída é desenhada com 7 caracteres distintos: " ", "'", ".", "|", "-", "_"e ":".

Como o detalhamento das formas das paredes no corpo desse desafio o tornaria muito longo, elas são fornecidas no seguinte link TIO:

Experimente online!

Os caracteres que não fazem parte de uma parede são marcados com a "?"nesses diagramas. Eles devem ser tratados como caracteres 'transparentes' que não são desenhados. Por outro lado, todos os espaços dentro de uma parede são 'sólidos' e devem substituir quaisquer outros caracteres que possam ter sido desenhados anteriormente lá.

Regras

Sobre a entrada

  • Pode tomar , , e em qualquer formato razoável.Mxyd
  • Você pode usar coordenadas com índice 0 ou 1.
  • Você pode usar quatro valores distintos de sua escolha para as instruções.
  • A matriz é garantida como pelo menos .3×3
  • Você pode supor que sempre haverá paredes circundantes nas bordas.
  • É garantido que o jogador esteja localizado em um quadrado vazio.
  • A entrada é garantida como válida.

Sobre a saída

  • As paredes devem ser desenhadas exatamente como descrito.
  • No entanto, o formato de saída também é flexível: cadeia única, matriz de cadeias, matriz de caracteres, etc.
  • Os espaços em branco à esquerda e à direita são aceitáveis ​​desde que sejam consistentes.

Isso é .

Casos de teste

Todos os casos de teste estão usando a seguinte matriz:

[ [ 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 ] ]

As seguintes entradas estão usando coordenadas indexadas em 0, com apontando para o canto superior esquerdo.(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

Resultados esperados:

------------------------------    ------------------------------
 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:
------------------------------    ------------------------------
'.                          __    '.                            
  |'.                    .'|        |                           
  |   '.              .'   |        |----.--------------.-------
  |    | '.        .' |    |        |    |              |       
  |    |  |:      :|  |    |        |    |              |       
  |    |  |:      :|  |    |        |    |              |       
  |    | .'        '. |    |        |    |              |       
  |   .'              '.   |        |----'--------------'-------
  |.'                    '.|__      |                           
.'                                .'                            

Desafio relacionado:

Este desafio de 2013 está intimamente relacionado. Mas possui um critério de ganho diferente (desafio de código), uma especificação muito mais flexível da saída e requer E / S interativa.

Arnauld
fonte
Isso me lembrou instantaneamente o 3D Monster Maze, embora isso use gráficos em bloco, é claro.
21418 Neil
9
Seus desafios são tão divertidos e bem escritos!
Oliver
Esperando por uma solução no Minecraft ... #
Alguém mais se lembra do protetor de tela do Windows? Foi um "jogo" tão divertido quando eu tinha 5 ou 6 anos ...
Magic Octopus Urn

Respostas:

10

Limpo (com Snappy ), 800 785 670 644 bytes

460 402 bytes de código + literal da string 360 242 bytes
(escapada aqui e no TIO porque não é UTF-8 válido)

Você pode verificar o comprimento do literal aqui.

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]]])

Experimente online!

A compactação instantânea realmente se sai muito bem nesse caso, apesar de ser focada na velocidade, porque há muitas execuções de caracteres únicos na cadeia sendo compactada.

A sequência não compactada ( #substituída por \npara maior clareza) é:

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

Isso codifica as versões do lado esquerdo dos diferentes componentes da tela com, em !vez de novas linhas, e em ~vez de ?, que são preenchidas com ~30 caracteres antes de serem adicionadas a eles e suas inversões de linha em uma lista de pesquisa.

O restante do código simplesmente lida com a pesquisa de coordenadas com casos fora dos limites ignorados.

Furioso
fonte
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)

Experimente online!

TFeld
fonte
4

Carvão , 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⁻⊟κײ⁹¬ι⊟κ⊟κ

Experimente online! Link é a versão detalhada do código. Uma abordagem um pouco chata, receio; muita impressão de literais de string compactada. Explicação:

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

Encha a matriz com dois 0s extras de cada lado.

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

Fatie uma 7x7subseção da matriz centralizada nas coordenadas fornecidas.

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

Gire a matriz conforme apropriado para a direção especificada.

B³⁰χ 

(observe o espaço à direita) Desenhe uma 30×10caixa vazia para que a saída tenha sempre um tamanho consistente.

F²«‖

Desenhe cada metade separadamente, refletindo no meio.

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

Pegue uma matriz de descritores de parede, divida em pedaços de (string, coordenada y, coordenada x), filtre os pedaços que possuem uma parede na posição relevante na metade relevante da matriz e faça um loop sobre as paredes. A posição é calculada extraindo 12 paredes da matriz e indexando-as usando o índice de chunk, pois é mais golfista do que localizar a parede diretamente usando o índice de chunk.

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

Pule para as coordenadas da parede e imprima-a. Observe que refletir nega as coordenadas X de [0, 30)para (-30, 0]para que, em uma passagem, a tela efetivamente desloque 29 caracteres para a esquerda.

Neil
fonte
11
@ Arnauld De fato, não estou aproveitando a simetria, devo cortar um terço desenhando cada metade separadamente.
Neil
11
+1 para um golpe de golfe de 168 bytes. Eu acho que é o maior golfe individual que eu já vi aqui.
ElPedro
2

Rubi , 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}

Experimente online!

Recebe entrada como uma matriz de valores verdadeiros / falsos (a nota 0é verdadeira em Ruby, mas nilé falsa).

Produz uma matriz de caracteres.

Explicação

Os blocos são desenhados de frente para trás com a distância ndiminuindo e a posição de um lado para o outro mpassando pela -1,1,0esquerda, direita e meio. O bloco do meio E na fila mais distante é realmente desenhado duas vezes porque precisamos verificar os blocos A / B e C / D. n,me dsão usados ​​para modificar os valores xe ypara pesquisar a matriz a. Se xestiver fora do intervalo, nilé retornado para uma célula fora do intervalo e nenhum erro é gerado, mas se yestiver fora do intervalo nil, será retornado para a linha e Ruby lançará um erro de tipo ao tentar procurar a célula. Para evitar isso, o array é triplicado na direção vertical antes da pesquisa. Se um valor verdadeiro é encontrado, um bloco é desenhado.

A saída é criada em uma matriz bde matrizes de 10 elementos representando as colunas da saída e é transposta para 10 linhas no final da função. A face frontal completa de todos os blocos é desenhada (aparecendo ou não na janela de exibição), portanto, é necessário espaço adicional na matriz para evitar erros fora do intervalo. O intervalo de jvalores na viewport é de -15até +14, isso é compensado em 15 ao salvar na matriz para fornecer um intervalo de 0até 29. Para cada bloco desenhado, três valores são calculados: pe qpara os cantos esquerdo e direito da parede frontal, respectivamente, e rpara o fundo da parede lateral. jé iterado do mínimo para o máximo desses três valores, desenhando as colunas por sua vez.

Existem 3 tipos de linhas: horizontal -ou _vertical |ou :diagonal com um " .'"padrão repetitivo . Onde p < j < qcolunas contendo espaços limitados com -ou _são desenhadas para formar a face frontal. Onde jestá fora desse intervalo, as colunas que contêm espaço |ou :são desenhadas com símbolos de tampas t=" .'"para formar as bordas e / ou a face lateral. Isso é gerenciado pela variável k=jonde jé positivo ou k=-j-1onde jé negativo. O número de caracteres entre as letras maiúsculas e minúsculas é k/3*2. A fim de processar correctamente as bordas exteriores dos blocos mais distantes onde n=3, kdevem ser tomadas módulo 9, mas isto não deve ser feito para os valores mais pequenos den. ké, portanto, tomado módulo 36/-~n, onde -~navalia para n+1.

Código ungolfed

->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
fonte
Boa resposta! Gosto da maneira como todas as linhas são geradas programaticamente, incluindo as diagonais.
Arnauld