Dungeon Crawler












39












$begingroup$


Input




  • A binary matrix $M$ representing the walls of a dungeon.

  • The position $(x,y)$ of the player within the dungeon.

  • The direction $d$ that the player is currently facing (0 = North, 1 = East, 2 = South, 3 = West)


Output



A pseudo-3D representation of the walls that are in the field of view of the player, as an ASCII art of $30times 10$ characters.



Below are several possible output frames, along with the corresponding map and compass to help getting the hang of it (but drawing the map and the compass is not part of the challenge).



animation



Specification



Field of view



The player has $13$ walls in his field of view, labeled from $A$ to $M$. Below are the positions of the walls relative to the player (in yellow), in all possible directions.



field of view



Drawing the walls



The walls are supposed to be drawn from $A$ to $M$ in this exact order, given that any part drawn previously may be overwritten by closer walls. You may of course implement it differently as long as the final result is the same.



The entire output is drawn with 7 distinct characters: " ", "'", ".", "|", "-", "_" and ":".



Because detailing the shapes of the walls in the body of this challenge would make it too lengthy, they are instead provided in the following TIO link:



Try it online!



The characters that are not part of a given wall are marked with a "?" in these diagrams. They must be treated as 'transparent' characters that are not drawn at all. On the other hand, all spaces within a wall are 'solid' and must overwrite any other characters that may have been previously drawn there.



Rules



About the input




  • You may take $M$, $x$, $y$ and $d$ in any reasonable format.

  • You may use either 0-indexed or 1-indexed coordinates.

  • You may use 4 distinct values of your choice for the directions.

  • The matrix is guaranteed to be at least $3times 3$.

  • You may assume that there will always be surrounding walls on the edges.

  • The player is guaranteed to be located on an empty square.

  • The input is guaranteed to be valid.


About the output




  • The walls must be drawn exactly as described.

  • However, the output format is also flexible: single string, array of strings, matrix of characters, etc.

  • Leading and trailing whitespace is acceptable as long as it's consistent.


This is code-golf.



Test cases



All test cases are using the following 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 ] ]


The following inputs are using 0-indexed coordinates, with $(0,0)$ pointing to the top-left corner.



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


Expected outputs:



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




Related challenge:



This challenge from 2013 is closely related. But it has a different winning criterion (code-challenge), a much looser specification of the output, and requires interactive I/O.










share|improve this question











$endgroup$












  • $begingroup$
    This instantly reminded me of 3D Monster Maze, although that uses block graphics of course.
    $endgroup$
    – Neil
    Dec 20 '18 at 23:37






  • 8




    $begingroup$
    Your challenges are so fun and well-written!
    $endgroup$
    – Oliver
    Dec 21 '18 at 0:32










  • $begingroup$
    Waiting for a solution in Minecraft...
    $endgroup$
    – Rogem
    Dec 22 '18 at 20:20
















39












$begingroup$


Input




  • A binary matrix $M$ representing the walls of a dungeon.

  • The position $(x,y)$ of the player within the dungeon.

  • The direction $d$ that the player is currently facing (0 = North, 1 = East, 2 = South, 3 = West)


Output



A pseudo-3D representation of the walls that are in the field of view of the player, as an ASCII art of $30times 10$ characters.



Below are several possible output frames, along with the corresponding map and compass to help getting the hang of it (but drawing the map and the compass is not part of the challenge).



animation



Specification



Field of view



The player has $13$ walls in his field of view, labeled from $A$ to $M$. Below are the positions of the walls relative to the player (in yellow), in all possible directions.



field of view



Drawing the walls



The walls are supposed to be drawn from $A$ to $M$ in this exact order, given that any part drawn previously may be overwritten by closer walls. You may of course implement it differently as long as the final result is the same.



The entire output is drawn with 7 distinct characters: " ", "'", ".", "|", "-", "_" and ":".



Because detailing the shapes of the walls in the body of this challenge would make it too lengthy, they are instead provided in the following TIO link:



Try it online!



The characters that are not part of a given wall are marked with a "?" in these diagrams. They must be treated as 'transparent' characters that are not drawn at all. On the other hand, all spaces within a wall are 'solid' and must overwrite any other characters that may have been previously drawn there.



Rules



About the input




  • You may take $M$, $x$, $y$ and $d$ in any reasonable format.

  • You may use either 0-indexed or 1-indexed coordinates.

  • You may use 4 distinct values of your choice for the directions.

  • The matrix is guaranteed to be at least $3times 3$.

  • You may assume that there will always be surrounding walls on the edges.

  • The player is guaranteed to be located on an empty square.

  • The input is guaranteed to be valid.


About the output




  • The walls must be drawn exactly as described.

  • However, the output format is also flexible: single string, array of strings, matrix of characters, etc.

  • Leading and trailing whitespace is acceptable as long as it's consistent.


This is code-golf.



Test cases



All test cases are using the following 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 ] ]


The following inputs are using 0-indexed coordinates, with $(0,0)$ pointing to the top-left corner.



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


Expected outputs:



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




Related challenge:



This challenge from 2013 is closely related. But it has a different winning criterion (code-challenge), a much looser specification of the output, and requires interactive I/O.










share|improve this question











$endgroup$












  • $begingroup$
    This instantly reminded me of 3D Monster Maze, although that uses block graphics of course.
    $endgroup$
    – Neil
    Dec 20 '18 at 23:37






  • 8




    $begingroup$
    Your challenges are so fun and well-written!
    $endgroup$
    – Oliver
    Dec 21 '18 at 0:32










  • $begingroup$
    Waiting for a solution in Minecraft...
    $endgroup$
    – Rogem
    Dec 22 '18 at 20:20














39












39








39


6



$begingroup$


Input




  • A binary matrix $M$ representing the walls of a dungeon.

  • The position $(x,y)$ of the player within the dungeon.

  • The direction $d$ that the player is currently facing (0 = North, 1 = East, 2 = South, 3 = West)


Output



A pseudo-3D representation of the walls that are in the field of view of the player, as an ASCII art of $30times 10$ characters.



Below are several possible output frames, along with the corresponding map and compass to help getting the hang of it (but drawing the map and the compass is not part of the challenge).



animation



Specification



Field of view



The player has $13$ walls in his field of view, labeled from $A$ to $M$. Below are the positions of the walls relative to the player (in yellow), in all possible directions.



field of view



Drawing the walls



The walls are supposed to be drawn from $A$ to $M$ in this exact order, given that any part drawn previously may be overwritten by closer walls. You may of course implement it differently as long as the final result is the same.



The entire output is drawn with 7 distinct characters: " ", "'", ".", "|", "-", "_" and ":".



Because detailing the shapes of the walls in the body of this challenge would make it too lengthy, they are instead provided in the following TIO link:



Try it online!



The characters that are not part of a given wall are marked with a "?" in these diagrams. They must be treated as 'transparent' characters that are not drawn at all. On the other hand, all spaces within a wall are 'solid' and must overwrite any other characters that may have been previously drawn there.



Rules



About the input




  • You may take $M$, $x$, $y$ and $d$ in any reasonable format.

  • You may use either 0-indexed or 1-indexed coordinates.

  • You may use 4 distinct values of your choice for the directions.

  • The matrix is guaranteed to be at least $3times 3$.

  • You may assume that there will always be surrounding walls on the edges.

  • The player is guaranteed to be located on an empty square.

  • The input is guaranteed to be valid.


About the output




  • The walls must be drawn exactly as described.

  • However, the output format is also flexible: single string, array of strings, matrix of characters, etc.

  • Leading and trailing whitespace is acceptable as long as it's consistent.


This is code-golf.



Test cases



All test cases are using the following 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 ] ]


The following inputs are using 0-indexed coordinates, with $(0,0)$ pointing to the top-left corner.



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


Expected outputs:



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




Related challenge:



This challenge from 2013 is closely related. But it has a different winning criterion (code-challenge), a much looser specification of the output, and requires interactive I/O.










share|improve this question











$endgroup$




Input




  • A binary matrix $M$ representing the walls of a dungeon.

  • The position $(x,y)$ of the player within the dungeon.

  • The direction $d$ that the player is currently facing (0 = North, 1 = East, 2 = South, 3 = West)


Output



A pseudo-3D representation of the walls that are in the field of view of the player, as an ASCII art of $30times 10$ characters.



Below are several possible output frames, along with the corresponding map and compass to help getting the hang of it (but drawing the map and the compass is not part of the challenge).



animation



Specification



Field of view



The player has $13$ walls in his field of view, labeled from $A$ to $M$. Below are the positions of the walls relative to the player (in yellow), in all possible directions.



field of view



Drawing the walls



The walls are supposed to be drawn from $A$ to $M$ in this exact order, given that any part drawn previously may be overwritten by closer walls. You may of course implement it differently as long as the final result is the same.



The entire output is drawn with 7 distinct characters: " ", "'", ".", "|", "-", "_" and ":".



Because detailing the shapes of the walls in the body of this challenge would make it too lengthy, they are instead provided in the following TIO link:



Try it online!



The characters that are not part of a given wall are marked with a "?" in these diagrams. They must be treated as 'transparent' characters that are not drawn at all. On the other hand, all spaces within a wall are 'solid' and must overwrite any other characters that may have been previously drawn there.



Rules



About the input




  • You may take $M$, $x$, $y$ and $d$ in any reasonable format.

  • You may use either 0-indexed or 1-indexed coordinates.

  • You may use 4 distinct values of your choice for the directions.

  • The matrix is guaranteed to be at least $3times 3$.

  • You may assume that there will always be surrounding walls on the edges.

  • The player is guaranteed to be located on an empty square.

  • The input is guaranteed to be valid.


About the output




  • The walls must be drawn exactly as described.

  • However, the output format is also flexible: single string, array of strings, matrix of characters, etc.

  • Leading and trailing whitespace is acceptable as long as it's consistent.


This is code-golf.



Test cases



All test cases are using the following 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 ] ]


The following inputs are using 0-indexed coordinates, with $(0,0)$ pointing to the top-left corner.



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


Expected outputs:



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




Related challenge:



This challenge from 2013 is closely related. But it has a different winning criterion (code-challenge), a much looser specification of the output, and requires interactive I/O.







code-golf ascii-art game binary-matrix






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 21 '18 at 8:38







Arnauld

















asked Dec 20 '18 at 23:30









ArnauldArnauld

73.5k689308




73.5k689308












  • $begingroup$
    This instantly reminded me of 3D Monster Maze, although that uses block graphics of course.
    $endgroup$
    – Neil
    Dec 20 '18 at 23:37






  • 8




    $begingroup$
    Your challenges are so fun and well-written!
    $endgroup$
    – Oliver
    Dec 21 '18 at 0:32










  • $begingroup$
    Waiting for a solution in Minecraft...
    $endgroup$
    – Rogem
    Dec 22 '18 at 20:20


















  • $begingroup$
    This instantly reminded me of 3D Monster Maze, although that uses block graphics of course.
    $endgroup$
    – Neil
    Dec 20 '18 at 23:37






  • 8




    $begingroup$
    Your challenges are so fun and well-written!
    $endgroup$
    – Oliver
    Dec 21 '18 at 0:32










  • $begingroup$
    Waiting for a solution in Minecraft...
    $endgroup$
    – Rogem
    Dec 22 '18 at 20:20
















$begingroup$
This instantly reminded me of 3D Monster Maze, although that uses block graphics of course.
$endgroup$
– Neil
Dec 20 '18 at 23:37




$begingroup$
This instantly reminded me of 3D Monster Maze, although that uses block graphics of course.
$endgroup$
– Neil
Dec 20 '18 at 23:37




8




8




$begingroup$
Your challenges are so fun and well-written!
$endgroup$
– Oliver
Dec 21 '18 at 0:32




$begingroup$
Your challenges are so fun and well-written!
$endgroup$
– Oliver
Dec 21 '18 at 0:32












$begingroup$
Waiting for a solution in Minecraft...
$endgroup$
– Rogem
Dec 22 '18 at 20:20




$begingroup$
Waiting for a solution in Minecraft...
$endgroup$
– Rogem
Dec 22 '18 at 20:20










4 Answers
4






active

oldest

votes


















10












$begingroup$


Clean (with Snappy), 800 785 670 644 bytes



460 402 bytes of code + 360 242-byte string literal

(escaped here and on TIO because it isn't valid UTF-8)



You can verify the length of the literal here.



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"2116444141415556404140174725460554740414141434141411765655r12456404117617440r141747272r47r4635722513110341252435113176253113311224r1522056404040412121710404756311444017412614456472174471741340r22025242111252502536011125253376302130253331112447414143137137111542041404017447r3441157534111153361721134564741137137174564713472043176176401371321440417521176113565150116137635376351263513234720137174414347101337517441133122410564740"),q<-let l=[[c\c<-:rpad s 30'~']\s<-split"!"w]in[l,map reverse l]]])


Try it online!



Snappy compression actually does pretty well in this case, despite being speed-focused, because there are so many single-character runs in the string being compressed.



The uncompressed string (with # replaced with n for clarity) is:



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


This encodes the left-side versions of the different screen components with ! instead of newlines, and ~ instead of ?, which are then right-padded with ~ to 30 characters before having themselves and their line-reversals added to a lookup list.



The rest of the code simply handles coordinate lookup with out-of-bounds cases ignored.






share|improve this answer











$endgroup$





















    5












    $begingroup$


    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)


    Try it online!






    share|improve this answer











    $endgroup$





















      4












      $begingroup$


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


      Try it online! Link is to verbose version of code. Somewhat boring approach, I'm afraid; lots of printing of compressed string literals. Explanation:



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


      Pad the array with two extra 0s on each side.



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


      Slice a 7x7 subsection of the array centred on the given coordinates.



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


      Rotate the array as appropriate for the given direction.



      B³⁰χ 


      (note trailing space) Draw an empty 30×10 box so that the output is always a consistent size.



      F²«‖


      Draw each half separately, reflecting in between.



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


      Take an array of wall descriptors, split into chunks of (string, y-coordinate, x-coordinate), filter on those chunks that have a wall at the relevant position in the relevant half of the array, and loop over the walls. The position is calculated by extracting 12 walls from the array and indexing them using the chunk index as this is golfier than locating the wall directly using the chunk index.



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


      Jump to the coordinates of the wall and print it. Note that reflecting negates the X-coordinates from [0, 30) to (-30, 0] so that on one pass the canvas is effectively shifted 29 characters to the left.






      share|improve this answer











      $endgroup$









      • 1




        $begingroup$
        @Arnauld Indeed, I'm not taking any advantage of symmetry at all, I should be able to cut a third off by drawing each half separately.
        $endgroup$
        – Neil
        Dec 22 '18 at 11:40






      • 1




        $begingroup$
        +1 for a 168 byte golf stroke. I think that's the biggest single golf I have seen on here.
        $endgroup$
        – ElPedro
        Dec 23 '18 at 20:46



















      2












      $begingroup$


      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}


      Try it online!



      Takes input as an array of truthy/falsy values (note 0 is truthy in Ruby, but nil is falsy.)



      Outputs an array of characters.



      Explanation



      Blocks are drawn front to back with distance n decreasing and side to side position m cycling through -1,1,0 left,right,middle. The middle block E in the furthest row is actually drawn twice because we need to check both blocks A/B and blocks C/D. n,m and d are used to modify the x and y values to search array a. If x is out of range nil is returned for an out of range cell and no error is thrown, but if y is out of range nil will be returned for the row and Ruby will throw a type error when it tries to search for the cell. To avoid this the array is triplicated in the vertical direction prior to searching. If a truthy value is found a block is drawn.



      The output is built in an array b of 10-element arrays representing the columns of the output, and is transposed into 10 rows at the end of the function. The full front face of all blocks is drawn (whether it appears in the viewport or not) so additional space is needed in the array to avoid out of range errors. The range of j values in the viewport is from -15 to +14, this is offset by 15 when saving to the array to give a range of 0 to 29. For each block drawn three values are calculated: p and q for the left and right corners of the front wall respectively, and r for the back of the side wall. j is iterated from the minimum to the maximum of these three values drawing the columns in turn.



      There are 3 types of lines: horizontal - or _, vertical | or :, and diagonal with a repeating " .'" pattern. Where p < j < q columns containing spaces capped with - or _ are drawn to form the front face. Where j is outside this range, columns containing space, | or : are drawn capped with symbols from t=" .'" to form the edges and/or side face. This is managed by variable k=j where j is positive or k=-j-1 where j is negative. The number of characters between the top and bottom caps is k/3*2. In order to correctly handle the outer edges of the furthest blocks where n=3, k must be taken modulo 9, but this must not be done for smaller values of n. k is therefore taken modulo 36/-~n, where -~n evaluates to 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.





      share|improve this answer











      $endgroup$













      • $begingroup$
        Nice answer! I like the way all lines are generated programmatically, including diagonal ones.
        $endgroup$
        – Arnauld
        Jan 1 at 13:16











      Your Answer





      StackExchange.ifUsing("editor", function () {
      return StackExchange.using("mathjaxEditing", function () {
      StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
      StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
      });
      });
      }, "mathjax-editing");

      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "200"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodegolf.stackexchange.com%2fquestions%2f177893%2fdungeon-crawler%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      10












      $begingroup$


      Clean (with Snappy), 800 785 670 644 bytes



      460 402 bytes of code + 360 242-byte string literal

      (escaped here and on TIO because it isn't valid UTF-8)



      You can verify the length of the literal here.



      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"2116444141415556404140174725460554740414141434141411765655r12456404117617440r141747272r47r4635722513110341252435113176253113311224r1522056404040412121710404756311444017412614456472174471741340r22025242111252502536011125253376302130253331112447414143137137111542041404017447r3441157534111153361721134564741137137174564713472043176176401371321440417521176113565150116137635376351263513234720137174414347101337517441133122410564740"),q<-let l=[[c\c<-:rpad s 30'~']\s<-split"!"w]in[l,map reverse l]]])


      Try it online!



      Snappy compression actually does pretty well in this case, despite being speed-focused, because there are so many single-character runs in the string being compressed.



      The uncompressed string (with # replaced with n for clarity) is:



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


      This encodes the left-side versions of the different screen components with ! instead of newlines, and ~ instead of ?, which are then right-padded with ~ to 30 characters before having themselves and their line-reversals added to a lookup list.



      The rest of the code simply handles coordinate lookup with out-of-bounds cases ignored.






      share|improve this answer











      $endgroup$


















        10












        $begingroup$


        Clean (with Snappy), 800 785 670 644 bytes



        460 402 bytes of code + 360 242-byte string literal

        (escaped here and on TIO because it isn't valid UTF-8)



        You can verify the length of the literal here.



        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"2116444141415556404140174725460554740414141434141411765655r12456404117617440r141747272r47r4635722513110341252435113176253113311224r1522056404040412121710404756311444017412614456472174471741340r22025242111252502536011125253376302130253331112447414143137137111542041404017447r3441157534111153361721134564741137137174564713472043176176401371321440417521176113565150116137635376351263513234720137174414347101337517441133122410564740"),q<-let l=[[c\c<-:rpad s 30'~']\s<-split"!"w]in[l,map reverse l]]])


        Try it online!



        Snappy compression actually does pretty well in this case, despite being speed-focused, because there are so many single-character runs in the string being compressed.



        The uncompressed string (with # replaced with n for clarity) is:



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


        This encodes the left-side versions of the different screen components with ! instead of newlines, and ~ instead of ?, which are then right-padded with ~ to 30 characters before having themselves and their line-reversals added to a lookup list.



        The rest of the code simply handles coordinate lookup with out-of-bounds cases ignored.






        share|improve this answer











        $endgroup$
















          10












          10








          10





          $begingroup$


          Clean (with Snappy), 800 785 670 644 bytes



          460 402 bytes of code + 360 242-byte string literal

          (escaped here and on TIO because it isn't valid UTF-8)



          You can verify the length of the literal here.



          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"2116444141415556404140174725460554740414141434141411765655r12456404117617440r141747272r47r4635722513110341252435113176253113311224r1522056404040412121710404756311444017412614456472174471741340r22025242111252502536011125253376302130253331112447414143137137111542041404017447r3441157534111153361721134564741137137174564713472043176176401371321440417521176113565150116137635376351263513234720137174414347101337517441133122410564740"),q<-let l=[[c\c<-:rpad s 30'~']\s<-split"!"w]in[l,map reverse l]]])


          Try it online!



          Snappy compression actually does pretty well in this case, despite being speed-focused, because there are so many single-character runs in the string being compressed.



          The uncompressed string (with # replaced with n for clarity) is:



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


          This encodes the left-side versions of the different screen components with ! instead of newlines, and ~ instead of ?, which are then right-padded with ~ to 30 characters before having themselves and their line-reversals added to a lookup list.



          The rest of the code simply handles coordinate lookup with out-of-bounds cases ignored.






          share|improve this answer











          $endgroup$




          Clean (with Snappy), 800 785 670 644 bytes



          460 402 bytes of code + 360 242-byte string literal

          (escaped here and on TIO because it isn't valid UTF-8)



          You can verify the length of the literal here.



          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"2116444141415556404140174725460554740414141434141411765655r12456404117617440r141747272r47r4635722513110341252435113176253113311224r1522056404040412121710404756311444017412614456472174471741340r22025242111252502536011125253376302130253331112447414143137137111542041404017447r3441157534111153361721134564741137137174564713472043176176401371321440417521176113565150116137635376351263513234720137174414347101337517441133122410564740"),q<-let l=[[c\c<-:rpad s 30'~']\s<-split"!"w]in[l,map reverse l]]])


          Try it online!



          Snappy compression actually does pretty well in this case, despite being speed-focused, because there are so many single-character runs in the string being compressed.



          The uncompressed string (with # replaced with n for clarity) is:



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


          This encodes the left-side versions of the different screen components with ! instead of newlines, and ~ instead of ?, which are then right-padded with ~ to 30 characters before having themselves and their line-reversals added to a lookup list.



          The rest of the code simply handles coordinate lookup with out-of-bounds cases ignored.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Dec 21 '18 at 8:24

























          answered Dec 21 '18 at 2:00









          ΟurousΟurous

          6,55211033




          6,55211033























              5












              $begingroup$


              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)


              Try it online!






              share|improve this answer











              $endgroup$


















                5












                $begingroup$


                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)


                Try it online!






                share|improve this answer











                $endgroup$
















                  5












                  5








                  5





                  $begingroup$


                  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)


                  Try it online!






                  share|improve this answer











                  $endgroup$




                  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)


                  Try it online!







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Dec 21 '18 at 12:30

























                  answered Dec 21 '18 at 12:13









                  TFeldTFeld

                  14.5k21241




                  14.5k21241























                      4












                      $begingroup$


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


                      Try it online! Link is to verbose version of code. Somewhat boring approach, I'm afraid; lots of printing of compressed string literals. Explanation:



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


                      Pad the array with two extra 0s on each side.



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


                      Slice a 7x7 subsection of the array centred on the given coordinates.



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


                      Rotate the array as appropriate for the given direction.



                      B³⁰χ 


                      (note trailing space) Draw an empty 30×10 box so that the output is always a consistent size.



                      F²«‖


                      Draw each half separately, reflecting in between.



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


                      Take an array of wall descriptors, split into chunks of (string, y-coordinate, x-coordinate), filter on those chunks that have a wall at the relevant position in the relevant half of the array, and loop over the walls. The position is calculated by extracting 12 walls from the array and indexing them using the chunk index as this is golfier than locating the wall directly using the chunk index.



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


                      Jump to the coordinates of the wall and print it. Note that reflecting negates the X-coordinates from [0, 30) to (-30, 0] so that on one pass the canvas is effectively shifted 29 characters to the left.






                      share|improve this answer











                      $endgroup$









                      • 1




                        $begingroup$
                        @Arnauld Indeed, I'm not taking any advantage of symmetry at all, I should be able to cut a third off by drawing each half separately.
                        $endgroup$
                        – Neil
                        Dec 22 '18 at 11:40






                      • 1




                        $begingroup$
                        +1 for a 168 byte golf stroke. I think that's the biggest single golf I have seen on here.
                        $endgroup$
                        – ElPedro
                        Dec 23 '18 at 20:46
















                      4












                      $begingroup$


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


                      Try it online! Link is to verbose version of code. Somewhat boring approach, I'm afraid; lots of printing of compressed string literals. Explanation:



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


                      Pad the array with two extra 0s on each side.



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


                      Slice a 7x7 subsection of the array centred on the given coordinates.



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


                      Rotate the array as appropriate for the given direction.



                      B³⁰χ 


                      (note trailing space) Draw an empty 30×10 box so that the output is always a consistent size.



                      F²«‖


                      Draw each half separately, reflecting in between.



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


                      Take an array of wall descriptors, split into chunks of (string, y-coordinate, x-coordinate), filter on those chunks that have a wall at the relevant position in the relevant half of the array, and loop over the walls. The position is calculated by extracting 12 walls from the array and indexing them using the chunk index as this is golfier than locating the wall directly using the chunk index.



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


                      Jump to the coordinates of the wall and print it. Note that reflecting negates the X-coordinates from [0, 30) to (-30, 0] so that on one pass the canvas is effectively shifted 29 characters to the left.






                      share|improve this answer











                      $endgroup$









                      • 1




                        $begingroup$
                        @Arnauld Indeed, I'm not taking any advantage of symmetry at all, I should be able to cut a third off by drawing each half separately.
                        $endgroup$
                        – Neil
                        Dec 22 '18 at 11:40






                      • 1




                        $begingroup$
                        +1 for a 168 byte golf stroke. I think that's the biggest single golf I have seen on here.
                        $endgroup$
                        – ElPedro
                        Dec 23 '18 at 20:46














                      4












                      4








                      4





                      $begingroup$


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


                      Try it online! Link is to verbose version of code. Somewhat boring approach, I'm afraid; lots of printing of compressed string literals. Explanation:



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


                      Pad the array with two extra 0s on each side.



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


                      Slice a 7x7 subsection of the array centred on the given coordinates.



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


                      Rotate the array as appropriate for the given direction.



                      B³⁰χ 


                      (note trailing space) Draw an empty 30×10 box so that the output is always a consistent size.



                      F²«‖


                      Draw each half separately, reflecting in between.



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


                      Take an array of wall descriptors, split into chunks of (string, y-coordinate, x-coordinate), filter on those chunks that have a wall at the relevant position in the relevant half of the array, and loop over the walls. The position is calculated by extracting 12 walls from the array and indexing them using the chunk index as this is golfier than locating the wall directly using the chunk index.



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


                      Jump to the coordinates of the wall and print it. Note that reflecting negates the X-coordinates from [0, 30) to (-30, 0] so that on one pass the canvas is effectively shifted 29 characters to the left.






                      share|improve this answer











                      $endgroup$




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


                      Try it online! Link is to verbose version of code. Somewhat boring approach, I'm afraid; lots of printing of compressed string literals. Explanation:



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


                      Pad the array with two extra 0s on each side.



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


                      Slice a 7x7 subsection of the array centred on the given coordinates.



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


                      Rotate the array as appropriate for the given direction.



                      B³⁰χ 


                      (note trailing space) Draw an empty 30×10 box so that the output is always a consistent size.



                      F²«‖


                      Draw each half separately, reflecting in between.



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


                      Take an array of wall descriptors, split into chunks of (string, y-coordinate, x-coordinate), filter on those chunks that have a wall at the relevant position in the relevant half of the array, and loop over the walls. The position is calculated by extracting 12 walls from the array and indexing them using the chunk index as this is golfier than locating the wall directly using the chunk index.



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


                      Jump to the coordinates of the wall and print it. Note that reflecting negates the X-coordinates from [0, 30) to (-30, 0] so that on one pass the canvas is effectively shifted 29 characters to the left.







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Dec 22 '18 at 12:17

























                      answered Dec 22 '18 at 0:39









                      NeilNeil

                      79.9k744177




                      79.9k744177








                      • 1




                        $begingroup$
                        @Arnauld Indeed, I'm not taking any advantage of symmetry at all, I should be able to cut a third off by drawing each half separately.
                        $endgroup$
                        – Neil
                        Dec 22 '18 at 11:40






                      • 1




                        $begingroup$
                        +1 for a 168 byte golf stroke. I think that's the biggest single golf I have seen on here.
                        $endgroup$
                        – ElPedro
                        Dec 23 '18 at 20:46














                      • 1




                        $begingroup$
                        @Arnauld Indeed, I'm not taking any advantage of symmetry at all, I should be able to cut a third off by drawing each half separately.
                        $endgroup$
                        – Neil
                        Dec 22 '18 at 11:40






                      • 1




                        $begingroup$
                        +1 for a 168 byte golf stroke. I think that's the biggest single golf I have seen on here.
                        $endgroup$
                        – ElPedro
                        Dec 23 '18 at 20:46








                      1




                      1




                      $begingroup$
                      @Arnauld Indeed, I'm not taking any advantage of symmetry at all, I should be able to cut a third off by drawing each half separately.
                      $endgroup$
                      – Neil
                      Dec 22 '18 at 11:40




                      $begingroup$
                      @Arnauld Indeed, I'm not taking any advantage of symmetry at all, I should be able to cut a third off by drawing each half separately.
                      $endgroup$
                      – Neil
                      Dec 22 '18 at 11:40




                      1




                      1




                      $begingroup$
                      +1 for a 168 byte golf stroke. I think that's the biggest single golf I have seen on here.
                      $endgroup$
                      – ElPedro
                      Dec 23 '18 at 20:46




                      $begingroup$
                      +1 for a 168 byte golf stroke. I think that's the biggest single golf I have seen on here.
                      $endgroup$
                      – ElPedro
                      Dec 23 '18 at 20:46











                      2












                      $begingroup$


                      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}


                      Try it online!



                      Takes input as an array of truthy/falsy values (note 0 is truthy in Ruby, but nil is falsy.)



                      Outputs an array of characters.



                      Explanation



                      Blocks are drawn front to back with distance n decreasing and side to side position m cycling through -1,1,0 left,right,middle. The middle block E in the furthest row is actually drawn twice because we need to check both blocks A/B and blocks C/D. n,m and d are used to modify the x and y values to search array a. If x is out of range nil is returned for an out of range cell and no error is thrown, but if y is out of range nil will be returned for the row and Ruby will throw a type error when it tries to search for the cell. To avoid this the array is triplicated in the vertical direction prior to searching. If a truthy value is found a block is drawn.



                      The output is built in an array b of 10-element arrays representing the columns of the output, and is transposed into 10 rows at the end of the function. The full front face of all blocks is drawn (whether it appears in the viewport or not) so additional space is needed in the array to avoid out of range errors. The range of j values in the viewport is from -15 to +14, this is offset by 15 when saving to the array to give a range of 0 to 29. For each block drawn three values are calculated: p and q for the left and right corners of the front wall respectively, and r for the back of the side wall. j is iterated from the minimum to the maximum of these three values drawing the columns in turn.



                      There are 3 types of lines: horizontal - or _, vertical | or :, and diagonal with a repeating " .'" pattern. Where p < j < q columns containing spaces capped with - or _ are drawn to form the front face. Where j is outside this range, columns containing space, | or : are drawn capped with symbols from t=" .'" to form the edges and/or side face. This is managed by variable k=j where j is positive or k=-j-1 where j is negative. The number of characters between the top and bottom caps is k/3*2. In order to correctly handle the outer edges of the furthest blocks where n=3, k must be taken modulo 9, but this must not be done for smaller values of n. k is therefore taken modulo 36/-~n, where -~n evaluates to 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.





                      share|improve this answer











                      $endgroup$













                      • $begingroup$
                        Nice answer! I like the way all lines are generated programmatically, including diagonal ones.
                        $endgroup$
                        – Arnauld
                        Jan 1 at 13:16
















                      2












                      $begingroup$


                      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}


                      Try it online!



                      Takes input as an array of truthy/falsy values (note 0 is truthy in Ruby, but nil is falsy.)



                      Outputs an array of characters.



                      Explanation



                      Blocks are drawn front to back with distance n decreasing and side to side position m cycling through -1,1,0 left,right,middle. The middle block E in the furthest row is actually drawn twice because we need to check both blocks A/B and blocks C/D. n,m and d are used to modify the x and y values to search array a. If x is out of range nil is returned for an out of range cell and no error is thrown, but if y is out of range nil will be returned for the row and Ruby will throw a type error when it tries to search for the cell. To avoid this the array is triplicated in the vertical direction prior to searching. If a truthy value is found a block is drawn.



                      The output is built in an array b of 10-element arrays representing the columns of the output, and is transposed into 10 rows at the end of the function. The full front face of all blocks is drawn (whether it appears in the viewport or not) so additional space is needed in the array to avoid out of range errors. The range of j values in the viewport is from -15 to +14, this is offset by 15 when saving to the array to give a range of 0 to 29. For each block drawn three values are calculated: p and q for the left and right corners of the front wall respectively, and r for the back of the side wall. j is iterated from the minimum to the maximum of these three values drawing the columns in turn.



                      There are 3 types of lines: horizontal - or _, vertical | or :, and diagonal with a repeating " .'" pattern. Where p < j < q columns containing spaces capped with - or _ are drawn to form the front face. Where j is outside this range, columns containing space, | or : are drawn capped with symbols from t=" .'" to form the edges and/or side face. This is managed by variable k=j where j is positive or k=-j-1 where j is negative. The number of characters between the top and bottom caps is k/3*2. In order to correctly handle the outer edges of the furthest blocks where n=3, k must be taken modulo 9, but this must not be done for smaller values of n. k is therefore taken modulo 36/-~n, where -~n evaluates to 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.





                      share|improve this answer











                      $endgroup$













                      • $begingroup$
                        Nice answer! I like the way all lines are generated programmatically, including diagonal ones.
                        $endgroup$
                        – Arnauld
                        Jan 1 at 13:16














                      2












                      2








                      2





                      $begingroup$


                      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}


                      Try it online!



                      Takes input as an array of truthy/falsy values (note 0 is truthy in Ruby, but nil is falsy.)



                      Outputs an array of characters.



                      Explanation



                      Blocks are drawn front to back with distance n decreasing and side to side position m cycling through -1,1,0 left,right,middle. The middle block E in the furthest row is actually drawn twice because we need to check both blocks A/B and blocks C/D. n,m and d are used to modify the x and y values to search array a. If x is out of range nil is returned for an out of range cell and no error is thrown, but if y is out of range nil will be returned for the row and Ruby will throw a type error when it tries to search for the cell. To avoid this the array is triplicated in the vertical direction prior to searching. If a truthy value is found a block is drawn.



                      The output is built in an array b of 10-element arrays representing the columns of the output, and is transposed into 10 rows at the end of the function. The full front face of all blocks is drawn (whether it appears in the viewport or not) so additional space is needed in the array to avoid out of range errors. The range of j values in the viewport is from -15 to +14, this is offset by 15 when saving to the array to give a range of 0 to 29. For each block drawn three values are calculated: p and q for the left and right corners of the front wall respectively, and r for the back of the side wall. j is iterated from the minimum to the maximum of these three values drawing the columns in turn.



                      There are 3 types of lines: horizontal - or _, vertical | or :, and diagonal with a repeating " .'" pattern. Where p < j < q columns containing spaces capped with - or _ are drawn to form the front face. Where j is outside this range, columns containing space, | or : are drawn capped with symbols from t=" .'" to form the edges and/or side face. This is managed by variable k=j where j is positive or k=-j-1 where j is negative. The number of characters between the top and bottom caps is k/3*2. In order to correctly handle the outer edges of the furthest blocks where n=3, k must be taken modulo 9, but this must not be done for smaller values of n. k is therefore taken modulo 36/-~n, where -~n evaluates to 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.





                      share|improve this answer











                      $endgroup$




                      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}


                      Try it online!



                      Takes input as an array of truthy/falsy values (note 0 is truthy in Ruby, but nil is falsy.)



                      Outputs an array of characters.



                      Explanation



                      Blocks are drawn front to back with distance n decreasing and side to side position m cycling through -1,1,0 left,right,middle. The middle block E in the furthest row is actually drawn twice because we need to check both blocks A/B and blocks C/D. n,m and d are used to modify the x and y values to search array a. If x is out of range nil is returned for an out of range cell and no error is thrown, but if y is out of range nil will be returned for the row and Ruby will throw a type error when it tries to search for the cell. To avoid this the array is triplicated in the vertical direction prior to searching. If a truthy value is found a block is drawn.



                      The output is built in an array b of 10-element arrays representing the columns of the output, and is transposed into 10 rows at the end of the function. The full front face of all blocks is drawn (whether it appears in the viewport or not) so additional space is needed in the array to avoid out of range errors. The range of j values in the viewport is from -15 to +14, this is offset by 15 when saving to the array to give a range of 0 to 29. For each block drawn three values are calculated: p and q for the left and right corners of the front wall respectively, and r for the back of the side wall. j is iterated from the minimum to the maximum of these three values drawing the columns in turn.



                      There are 3 types of lines: horizontal - or _, vertical | or :, and diagonal with a repeating " .'" pattern. Where p < j < q columns containing spaces capped with - or _ are drawn to form the front face. Where j is outside this range, columns containing space, | or : are drawn capped with symbols from t=" .'" to form the edges and/or side face. This is managed by variable k=j where j is positive or k=-j-1 where j is negative. The number of characters between the top and bottom caps is k/3*2. In order to correctly handle the outer edges of the furthest blocks where n=3, k must be taken modulo 9, but this must not be done for smaller values of n. k is therefore taken modulo 36/-~n, where -~n evaluates to 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.






                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Dec 31 '18 at 0:55

























                      answered Dec 30 '18 at 4:41









                      Level River StLevel River St

                      20.2k32579




                      20.2k32579












                      • $begingroup$
                        Nice answer! I like the way all lines are generated programmatically, including diagonal ones.
                        $endgroup$
                        – Arnauld
                        Jan 1 at 13:16


















                      • $begingroup$
                        Nice answer! I like the way all lines are generated programmatically, including diagonal ones.
                        $endgroup$
                        – Arnauld
                        Jan 1 at 13:16
















                      $begingroup$
                      Nice answer! I like the way all lines are generated programmatically, including diagonal ones.
                      $endgroup$
                      – Arnauld
                      Jan 1 at 13:16




                      $begingroup$
                      Nice answer! I like the way all lines are generated programmatically, including diagonal ones.
                      $endgroup$
                      – Arnauld
                      Jan 1 at 13:16


















                      draft saved

                      draft discarded




















































                      If this is an answer to a challenge…




                      • …Be sure to follow the challenge specification. However, please refrain from exploiting obvious loopholes. Answers abusing any of the standard loopholes are considered invalid. If you think a specification is unclear or underspecified, comment on the question instead.


                      • …Try to optimize your score. For instance, answers to code-golf challenges should attempt to be as short as possible. You can always include a readable version of the code in addition to the competitive one.
                        Explanations of your answer make it more interesting to read and are very much encouraged.


                      • …Include a short header which indicates the language(s) of your code and its score, as defined by the challenge.



                      More generally…




                      • …Please make sure to answer the question and provide sufficient detail.


                      • …Avoid asking for help, clarification or responding to other answers (use comments instead).





                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodegolf.stackexchange.com%2fquestions%2f177893%2fdungeon-crawler%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Plaza Victoria

                      Puebla de Zaragoza

                      Musa