Quand j'étais enfant, je jouais au jeu Intellivision Advanced Dungeons and Dragons: Treasure of Tarmin . Les graphismes en 3D vous mettent dans une perspective à la première personne avec un réalisme choquant:
Mais ensuite, j'ai eu un C-64. Et j'ai pu dessiner sur la grille de 40x25 caractères en survolant l'écran, en définissant la couleur avec la touche Ctrl et un chiffre, et en plaçant des symboles où je voulais (pourquoi ne me bash
laisse-t-il pas faire cela?) . Le jeu de caractères avait des composants triangulaires et des composants en blocs solides. J'ai donc pu raisonner sur la façon dont on pouvait générer un rendu de sa perspective dans une grille à travers ce support.
J'ai trouvé la spécification vieille de près de trois décennies, dans du papier pour cahier à reliure spirale, sur "Dungeon Construction Set" cette semaine:
( MISE À JOUR : Les lecteurs attentifs remarqueront que cela ne tient pas tout à fait ensemble sur les pièces inclinées. Les nombres corrigés sont fournis ci-dessous.)
Bien que Treasure of Tarmin ait été joué sur une grille, les murs n'existaient que sur les bords des carrés de la grille. Ayant appris quels étaient les octets, j'ai réalisé que si je faisais la carte à partir d'octets ... alors chaque carré sur la carte pourrait avoir quatre états possibles pour chacun de ses bords:
- Dégagée
- mur
- Porte
- Autre chose?
Je n'ai jamais réussi à l'écrire (jusqu'à hier soir). J'ai pensé que ça pourrait être amusant pour les autres d'essayer.
Votre tâche consiste donc à implémenter un rendu de labyrinthe basé sur le mode caractère qui implémente mes spécifications (corrigées !!) ... mais en utilisant les technologies de 2013.
Contribution
Étant donné que la spécification ne définit pas le rendu des portes, nous supposerons simplement que les seules options sont mur et non mur. Pour plus de simplicité, votre entrée est une carte composée de lignes de chaînes qui ressemblent à ceci:
WN.. .N.. .N.. .N.. .N.E
W... .... .... ..S. ...E
W... .N.E W... .N.. ...E
W... .... .... .... ...E
W.S. ..S. ..S. ..S. ..SE
Ce serait une carte 5x5. Le coin supérieur gauche (1,1) a son ensemble de murs W
est et N
orth. Le coin inférieur droit (5,5) a son ensemble de murs extérieur S
et E
ast.
C'est beaucoup moins amusant sans navigation sur la carte. Donc au minimum, placez votre joueur à (1,1) face au nord et offrez-lui:
[F]orward, [B]ackward, turn [L]eft, turn [R]ight or [Q]uit?
À chaque étape, affichez un affichage 16x15 de la perspective à la première personne, comme défini par la spécification papier du carnet. Pour vous éviter d'avoir à compter, la taille des murs plats aux trois distances est:
14x13 (directly in front of you; e.g. wall is in same cell)
8x7 (one step away)
6x5 (two steps away)
Les dimensions limites des murs inclinés sont les suivantes:
1x15 (your direct left or right; e.g. wall is in same cell)
3x13 (one step away)
1x7 (two steps away)
Clarifications
Les cellules adjacentes peuvent ne pas être d'accord sur les murs partagés. Ainsi, le bord sud d'un carré pourrait être un mur, tandis que le bord nord du carré au sud serait dégagé. Dans la conception originale, je considérais cela comme une caractéristique: cela permet des idées intéressantes comme des portes à sens unique ... ou des murs invisibles qui n'apparaissent qu'après les avoir franchis. Pour cette simplification, suivez la même règle: pour la navigation et le rendu, faites attention uniquement à l'état du bord sur la cellule la plus proche de vous dans la direction vers laquelle vous faites face .
La vue est bien meilleure avec "l'ombrage". Donc, pour vos blocs complets, alternez soit Unicode 2593 ▓ et 2591 ░, soit utilisez
X
et+
si votre implémentation est ASCII.Les caractères triangulaires Unicode (25E2 ◢, 25E3 ◣, 25E4 ◤, 25E5 ◥) sont un peu boiteux pour dessiner cela. En plus de ne pas avoir de variantes ombrées, elles étirent souvent uniquement la largeur du caractère et non la pleine hauteur ... même dans les polices à largeur fixe. Vous pouvez dessiner des blocs entiers ou des caractères slash ou quelque chose de votre choix dans les endroits où je voulais des diagonales. Des solutions créatives intéressantes qui incorporent la couleur et utilisent ces caractères au lieu de l'ombrage sont appréciées.
Vous pouvez supposer que les murs les plus extérieurs sont définis pour délimiter la zone de jeu, vous n'avez donc pas à vous soucier de rendre quoi que ce soit en dehors du labyrinthe. Tous les murs plus éloignés de vous que la spécification sont ignorés et ne laissent qu'un espace vide.
L'ombrage du mur que vous voyez directement devant vous si vous faites face au nord à (1,1) doit être FONCÉ. Ombrage alterné sur les murs adjacents de la carte, de sorte que si tous les murs étaient présents, un mur clair ne serait jamais en contact avec un mur sombre.
Une implémentation C-64 qui fait réellement ce que je voulais à l'origine ... avec les caractères diagonaux et tout ... l'emportera sur tout autre critère d'entrée. :-)
Exemples
Pour l'exemple de carte ci-dessus ...
Au (1,3) plein sud:
/
/+
/X+
/XX+
/XXX+
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
\XXX+
\XX+
\X+
\+
\
Au (3,2) plein sud:
/* blank line */
X /
X /+
X /++
X +++
X +++
X +++
X +++
X +++
X +++
X +++
X \++
X \+
X \
/* blank line */
À (3,2) face à l'est:
/* blank line */
/
/X
/XX
XXX
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
XXX
\XX
\X
\
/* blank line */
À (2,3) face au nord:
/
++++++++++++++X
++++++++++++++X
++++++++++++++X
++++++++++++++X
X++++++++++++++X
X++++++++++++++X
X++++++++++++++X
X++++++++++++++X
X++++++++++++++X
++++++++++++++X
++++++++++++++X
++++++++++++++X
++++++++++++++X
\
la source
X
s dans votre vue du3, 2
sud?Réponses:
Commodore 64 Basic
C'était amusant. Et dur. C64 Basic est presque non débogable, vous ne pouvez même pas utiliser le
print
débogage car l'écran est déjà utilisé pour le rendu du donjon. Vous savez que vous vous amusez lorsque vous écrivez du code comme55250 goto 55110
. Dijkstra va me tuer.Le programme utilise deux couleurs et des caractères diagonaux.
Inutile de dire que je ne l'ai pas joué au golf. Il dit défi de code maintenant, après tout. C'est 7183 octets si vous êtes intéressé.
C'est lent - à la vitesse par défaut, il faut plusieurs secondes pour rendre la scène. La taille maximale de la carte est de 10 x 10, mais elle peut être modifiée en modifiant la ligne 120.
J'ai développé et testé cela en utilisant l' émulateur VICE . Le code ci-dessous est affiché en ASCII, ce qui signifie PETSCII décalé . Cependant, lors de la saisie de la carte, vous devez utiliser PETSCII non décalé .
Capture d'écran:
Code:
Image de la bande: téléchargez-la ici .
Les exemples:
la source
Je devais juste le faire maintenant.
Bash, 12743 caractères
S'il vous plaît, gardez à l'esprit que c'est à peu près la première chose que j'ai faite avec
bash
cela, c'était plus que simplement passer quelques commandes ensemble. Il serait probablement beaucoup plus réductible si je ne codais pas en dur tous les murs, mais cela semblait plus facile. Il n'a aucune cohérence. Le format d'octet pour chaque carré est choisi d'une manière horrible. Mais ça marche.J'ai même ajouté un support pour le mouvement à travers les touches fléchées :)
Voici quelques captures d'écran de l'exemple d'entrée (notez que ma carte commence à (0 | 0)):
Mis à part le quatrième, ils ressemblent tous à ceux de l'échantillon (voir mon commentaire sur l'OP).Ces captures d'écran ont été prises sur urxvt v9.15 avec une prise en charge de 256 couleurs, cela aurait probablement l'air assez merdique sur un terminal 88 couleurs, et les terminaux sans prise en charge Unicode ne fonctionnent pas du tout. La police que j'ai utilisée était Source Code Pro d'Adobe.
la source
Voici ma version, en Python 3. C'est quelque chose comme 3k caractères et pourrait devenir un peu plus petit avec un petit effort (il y a beaucoup d'espace blanc qui pourrait être supprimé, pour commencer).
Il utilise actuellement
+X/\
comme caractères de dessin, mais il est configuré pour dessiner avec des caractères Unicode si vous avez une police à largeur fixe qui les rendra correctement. Il prend en charge l'utilisation de tuiles distinctes pour les parties angulaires des murs à coleurs différents, bien que je n'utilise pas cette fonctionnalité. Il vous permet également de fournir des dalles de plafond, de sol et "distantes", et vous pouvez en utiliser différentes lorsque le joueur est face à l'est ou à l'ouest par rapport au nord ou au sud. Hélas, cela n'a jamais semblé très bon, donc probablement tous ces éléments devraient être vides (ou quelque chose de solide, comme█
).Hélas, sur mon système Windows 7, j'ai eu un horrible temps à essayer de trouver une police à espacement fixe avec l'ensemble complet des caractères de bloc (par exemple
▜
et▟
). La plupart de celles que j'ai trouvées n'ont pas pu être disponibles dans lacmd
console pour une raison quelconque (peut-être parce qu'elles ne sont pas parfaitement espacées?). Si vous pensez que votre console est plus fonctionnelle, essayez d'utiliser le jeu de caractères alternatif que j'ai commenté près du haut du fichier, qui ne semble pas trop mal même avec seulement deux couleurs. Il a rempli les plafonds et les planchers et surtout les murs transparents.Le code:
Le jeu de caractères est spécifié près du haut du fichier. L'ordre des caractères est le suivant:
/
avec un mur en dessous)Il y a 15 murs qui pourraient devoir être rendus par le jeu, dans un modèle comme celui-ci (avec
V
indication de la position et de l'arc de vue du joueur):Les tuiles utilisées par les 15 murs sont définies dans la
shapes
liste. C'est une liste de 2 tuples. La première valeur du tuple indique la "parité" du mur, en0
indiquant qu'il doit être dessiné avec les mêmes caractères qu'un mur directement devant le personnage et en1
indiquant qu'il doit être le motif alternatif (par exemple+
vsX
). La deuxième valeur est une liste dex,y,t
tuples indiquant les coordonnées d'écran et l'indice de tuile d'un pixel (les murs rendus avec une parité impaire auront été1
ajoutés à chacun de ces index). Les formes sont ordonnées par distance, de sorte que les trois premiers représentent les murs perpendiculaires deux carreaux devant le personnage, suivis par les deux murs parallèles deux carreaux devant, et ainsi de suite.Les fonctions sont:
rr
: "rendre" l'écran (en imprimant les tuiles dans le tampon d'écran).dw
: "dessiner des murs" vers un tampon d'écran fourni. Cela utilise l'algorithme des peintres, de sorte que les murs les plus éloignés sont dessinés en premier et peuvent être recouverts par des murs plus proches.ga
: "get area" renvoie une liste de valeurs booléennes indiquant quels murs sont opaques pour une position de carte et un revêtement donnés.rd
: "read", un générateur qui lit la carte, donnant les lignes. Cela n'est nécessaire que parce que la console d'IDLE fait des trucs bizarres lorsque vous collez des entrées multi-lignes plutôt que d'entrer une ligne à la fois.rm
: "read map", analyse la carte en une liste imbriquée de booléens, indexée parm[y][x][d]
(avecd=0
étant Est etd=1
étant Sud). Il ajoute également deux lignes et deux colonnes de carrés de remplissage, pour éviter les erreurs d'index dans l'autre code.cl
: "effacer" la sortie (en écrivant suffisamment de nouvelles lignes pour faire défiler l'ancienne vue du haut de la plupart des consoles).gl
: "boucle de jeu", où l'entrée est collectée et les éléments ci-dessus sont appelés.Quelques "captures d'écran":
La position de départ:
En regardant le long du mur nord:
Quelques plans correspondant à vos exemples (notez que les premières lignes vides sont coupées par Stack Overflow, elles sont dans la sortie du programme):
Et:
Voici l'une des vues les plus étranges de la carte fournie, car le mur parallèle à notre vue est de la même couleur que le mur perpendiculaire qui sort derrière:
Voici à quoi ressemblerait la zone du dernier plan:
la source