NetHack est un jeu peu scrupuleux dans lequel un joueur doit récupérer l'Amulette de Yendor au niveau le plus bas du donjon. Communément joué via telnet, l'ensemble du jeu est représenté avec des graphiques ASCII. Le jeu est extrêmement difficile et nécessite la connaissance de nombreux mécanismes de jeu pour réussir.
Pour les besoins de ce défi, supposons que tout le donjon soit un seul niveau et ne comporte que 5 × 16 caractères. De plus, supposons qu'il s'agit d'un donjon "sûr" ou que vous ne réalisiez qu'un prototype - il n'y aura aucun monstre, aucune inquiétude face à la faim, etc. En fait, vous devez simplement suivre l'emplacement du personnage, de l'amulette et du jeu. se terminera effectivement lorsque le joueur arrivera au même endroit que l’amulette.
Exigences du défi
- Il y aura un donjon 5 × 16 (niveau unique).
- Donnez au joueur un emplacement de départ (éventuellement aléatoire) et à l'amulette un emplacement de départ distinct (différent chaque fois que le programme est exécuté) à l'intérieur du donjon. C'est-à-dire que l'amulette n'est pas autorisée à commencer sur la même case que le joueur.
- Acceptez quatre touches de saisie qui déplacent le joueur d’une case à la fois (quatre directions cardinales). La lecture / le traitement d'autres entrées est autorisé (une fonction readline () qui nécessite d'appuyer sur 'entrée', etc.).
- Voyager en dehors des limites du donjon n'est pas autorisé. Par exemple, si le joueur est sur le bord droit du donjon, appuyer à droite ne devrait rien faire.
- Après la génération initiale et après chaque mouvement, imprimez l'état du jeu. Comme il s'agit d'un code golf et que l'impression est plutôt sans intérêt, ignorez le nombre de caractères pour la fonction d'impression et l'appel de fonction en supposant qu'aucun état ne change . Les cellules vides doivent apparaître en tant que point (
.
), amulet en tant que double guillemet ("
) et caractère en tant que symbole (@
). - La partie est terminée lorsque le joueur "découvre" l'amulette (arrive sur la même case)
Gagnant
Il s’agit d’un code de golf challenege, le code le plus court répondant aux exigences d’une semaine à partir d’aujourd’hui sera déclaré vainqueur.
Exemple
Voici un exemple de solution en C # (non golfé) pour montrer les exigences de base et les exemples de sortie.
using System;
namespace nh
{
class Program
{
static Random random = new Random();
// player x/y, amulet x/y
static int px, py, ax, ay;
static void Main(string[] args)
{
px = random.Next(0, 16);
py = random.Next(0, 5);
// amulet starts on a position different from the player
do { ax = random.Next(0, 16); } while (px == ax);
do { ay = random.Next(0, 5); } while (py == ay);
print();
do
{
// reads a single keypress (no need to press enter)
// result is cast to int to compare with character literals
var m = (int)Console.ReadKey(true).Key;
// Move the player. Here standard WASD keys are used.
// Boundary checks for edge of dungeon as well.
if (m == 'W')
py = (py > 0) ? py - 1 : py;
if (m == 'S')
py = (py < 5) ? py + 1 : py;
if (m == 'A')
px = (px > 0) ? px - 1 : px;
if (m == 'D')
px = (px < 16) ? px + 1 : px;
// print state after each keypress. If the player doesn't
// move this is redundant but oh well.
print();
// game ends when player is on same square as amulet
} while (px != ax || py != ay);
}
static void print()
{
Console.Write('\n');
for (int y=0; y<5; y++)
{
for (int x = 0; x < 16; x++)
{
if (x == px && y == py)
Console.Write('@');
else if (x == ax && y == ay)
Console.Write('"');
else
Console.Write('.');
}
Console.Write('\n');
}
}
}
}
Le nombre total de caractères est 1474, mais en ignorant les appels à la fonction d'impression et à sa définition, le nombre de caractères final est 896
.
Sortie lorsque le programme est exécuté:
................
...."...........
..........@.....
................
................
Sortie (y compris ci-dessus) après avoir appuyé deux fois sur la touche "a":
................
...."...........
..........@.....
................
................
................
...."...........
.........@......
................
................
................
...."...........
........@.......
................
................
Réponses:
TI-BASIC,
4241383635 octetsPour votre calculatrice graphique des séries TI-83 ou 84+.
Dans quelle direction le joueur ira-t-il en fonction du code de la touche enfoncée, mais quatre touches qui fonctionnent vraiment sont celles-ci dans la rangée supérieure:
L'amulette commence sur l'une des cinq cases de la première colonne et le joueur commence en bas à droite. Par exemple, un arrangement possible est:
Explication
La position du joueur est stockée sous la forme d'un nombre complexe allant de
0+0i
à15+4i
, où la partie réelle passe à droite et la partie imaginaire s'abaisse. Cela facilite la vérification des limites en haut et à gauche: nous décalons simplement légèrement le nombre et arrondissons vers zéro. Par exemple, si le décalage est0.5
et que notre position est-1+3i
(à gauche de l'écran), la position sera corrigée commeiPart(-0.5+3.5i)=0+3i
il se doit. Vérifier les limites inférieure et droite est légèrement plus compliqué. nous devons soustraire le nombre d’une constanteC
qui est environ15.635 + 4.093i
(c’est la plus courte que j’ai pu trouver entre15+4i
et16+5i
), arrondir, soustraire deC
nouveau pour renverser le nombre, et arrondir à nouveau.Lorsqu'une touche est enfoncée, la position du joueur non ajustée se déplace d'une unité dans une direction, mais la partie entière ne change que lorsque certaines touches sont enfoncées. Heureusement, les clés qui fonctionnent se trouvent toutes dans la rangée supérieure. Vous trouverez ci-dessous un graphique des décalages dans les cas où les touches 11, 12, 13 et 15 sont enfoncées, et lorsqu'aucune touche n'est enfoncée les décalages ont des parties entières différentes).
C
est la croix rouge au centre du cercle.Ancien code (42 octets):
Limites
Il n'y a aucun moyen d'échapper à un
"
caractère, donc les chaînes avec un"
ne peuvent pas être générées dans un programme. Par conséquent, cela utilise la marque de tréma¨
au lieu d'un guillemet (s'il y avait une chaîne déjà existante avec un guillemet, je pourrais l'afficher). Pour obtenir¨
et@
dans un programme, un outil extérieur est nécessaire; Cependant, il est valide TI-BASIC.la source
CHIP-8 , 48 octets
Cela peut ne pas être considéré comme légal, mais pourquoi diable pas. J'ai écrit mon programme dans CHIP-8, un langage de programmation basé sur des codes octets pour une console de jeu virtuelle. Vous pouvez essayer le programme complet (99 octets) dans votre navigateur en utilisant un émulateur / débogueur que j'ai écrit appelé Octo:
http://johnearnest.github.io/Octo/index.html?gist=1318903acdc1dd266469
Un vidage hexadécimal de ce programme complet est le suivant:
Vous pouvez déplacer le lecteur à l’aide des touches ASWD ou 7589 du clavier CHIP-8 d’origine. Si je supprime tout le code et toutes les données pour dessiner l'arrière-plan et le lecteur, j'obtiens plutôt ce dump de 48 octets:
La forme complète et non-golfée du programme a été écrite dans un langage d'assemblage de haut niveau, comme suit:
Notez que les octets compilés eux - mêmes sont le langage de programmation CHIP-8; l'assembleur est simplement un moyen plus pratique de composer de tels programmes.
la source
Python 3, 86 octets
Compter seulement les deux dernières lignes et les laisser tomber
d();
.la source
a=id(9)%79
para=id(9)%p
.raw_input
simplement l' appelinput
.C,
122121115104102101 octetsPremière publication ici! J'espère que tu aimes :)
o
est l'impression, euh, fonction. Notre courageux héros peut être déplacé avec 2, 4, 6 et 8, mais méfiez-vous de ne pas envoyer d'autre entrée (pas de nouvelles lignes!).Mise à jour 1: paramètres introduits
a
eti
dansmain
.Mise à jour 2: OP ayant confirmé qu'une seule chaîne d'entrée est correcte, je me suis débarrassé de
scanf
(ce qui me permettait de sauter la nouvelle ligne).Mise à jour 3: Utilisation d'un littéral de tableau composé et modification de la présentation en entrée. Le programme va maintenant se détraquer si vous entrez une direction invalide;)
Mise à jour 4: remarque que l'appel de la fonction d'impression ne compte pas. A pris note de lire les règles plus attentivement.
Mise à jour 5: un octet enregistré grâce à Mikkel Alan Stokkebye Christia.
la source
!!(p%16)
êtrep%16>0
? Je ne me souviens pas de mon ordre des opérations.-
ne peut s'empêcher de s'en tenir àp
ça, des parenthèses sont donc nécessaires de toute façon. Le double coup n'est qu'un obscurcissement :)CJam,
464544403937 octetsLa première ligne (définit une fonction imprimant l'état actuel du jeu) et les P de la deuxième ligne (appelez cette fonction) ne contribuent pas au nombre d'octets.
La position de départ et la position de l'amulette sont sélectionnées de manière pseudo-aléatoire. La distribution est aussi uniforme et le PRNG sous-jacent le permet.
L' entrée est E, 6, 9et Bpour Up , Bas , Gauche et Droite avec, Caps Lockactivé, suivi Enter.
Version alternative
Au prix de quatre octets supplémentaires, le format d'entrée est considérablement amélioré:
Essai
Comme les E / S sont interactives, vous devriez essayer ce code avec l' interpréteur Java .
Téléchargez la dernière version et lancez le programme comme ceci:
Pour éviter d'appuyer Enteraprès chaque touche et pour les mises à jour sur place de la sortie, vous pouvez utiliser ce wrapper:
Invoquer comme ceci:
Version principale
Version alternative
Fonction p
la source
Java, 231 octets (196 si fonction)
Voici le code complet du programme en 342:
Sans la fonction d'impression, 231:
Si juste une fonction est correcte (je ne suis pas claire à la spécification), alors je peux la réduire un peu plus loin à 196:
Et avec quelques sauts de ligne pour plus de clarté ...
Notez que je ne compte pas la fonction d'impression
p(p,y)
lui - même, mais je suis compter l'appel, puisque j'ai des choses changer dans l'instruction d'appel.Cela fonctionne avec des lettres majuscules
ASDW
. En raison de la manière dont ils sont vérifiés, certaines autres lettres peuvent également fonctionner, mais la spécification ne dit pas vraiment ce qui devrait se passer si j'appuie sur des touches différentes.la source
void m()
devient()->
p+=
?Java, 574 octets
Fondamentalement identique à la version C #, excepté obscurci et minimisé.
la source
Julia, 161 octets
Utilisations w, a, set dpour avancer, à gauche, vers le bas, et à droite, respectivement.
Code complet, y compris l'impression (330 octets):
Code scoré, exclut l'impression (161 octets):
La différence ici est que nous ne sauvegardons pas l'état du jeu en tant que matrice; toutes les informations pertinentes sont contenues dans les tableaux
c
eta
. Et bien sûr, rien n’est imprimé. L'utilisateur ne sera plus invité à entrer une fois que le joueur aura atteint l'amulette.Ungolfed + explication (code complet):
la source
a=[rand(1:5),1] c=a+1
Lot, 329 octets
la source
Microsoft Windows [Version 6.1.7601]
Microsoft Windows [Version 6.2.9200]
)Perl,
228222 caractères (sans compter les sauts de ligne qui ne font pas partie intégrante du fonctionnement du code) - 207 si les éléments de l'instructionprint
etprint if
utilisés pour l'impression ne sont pas pris en compte, mais ils ne s'ajoutent pas à la logique du jeu; 144 si le code de génération de représentation de champ est également considéré comme faisant partie de l’impression, comme suggéré par Yakk dans les commentaires)Ce code utilise wasd minuscule pour le contrôle; l'entrée doit être confirmée avec Entrée. Testé avec Perl 5.14.2.
Notez que pour ce code, il est impossible de séparer le calcul et l'impression, car les opérations sont effectuées directement sur la représentation imprimée à l'aide d'expressions régulières.
Explication:
Cette ligne détermine la position du joueur et de l'amulette. La position du joueur est déterminée par
$==rand(80)
et est en fait facile à comprendre: sur un tableau 5 × 16, il y a 80 positions distinctes où le joueur peut se trouver. La position est stockée dans la$=
variable qui force la valeur stockée en entier; cela économise quelques octets pour ne pas avoir besoin de convertir explicitement le résultat en entier (rand
fournit une valeur à virgule flottante).Etant donné qu'une des positions est déjà occupée par le joueur, il ne reste que 79 positions pour l'amulette, donc pour la position de l'amulette
$a=$==rand(79)
. Encore une fois, l'affectation$=
force la conversion en entier, mais je l'assigne ensuite$a
afin de pouvoir être réutilisée$=
pour la position du joueur.Maintenant, pour éviter que l'amulette n'occupe la même position que le joueur, elle est avancée d'une position si sa position est au moins aussi grande que celle du joueur, ce qui donne une répartition uniforme sur les places non occupées par le joueur. Ceci est réalisé par
$a = ($a >= $=)
où$=
tient ici la position du joueur. Maintenant, la première ligne est générée en insérant les deux assignations initiales au lieu du premier$a$ and the only
$ = `dans cette expression.Cela génère le champ initial et imprime ensuite.
("."x80)
génère juste une chaîne de 80 points.=~s/(.{$=})./\1@/r
remplace ensuite le$=
thème par@
, et=~s/(.{$=})./\1@/r
le$a
thème par"
. En raison dur
modificateur, ils n'essayent pas de modifier à la place, mais renvoient la chaîne modifiée, c'est pourquoi ils peuvent être appliqués aux expressions précédentes. Enfin,=~s/(.{16})/\1\n/gr
insère une nouvelle ligne tous les 16 caractères. Notez que le champ est stocké dans la variable spéciale$_
qui peut être utilisée implicitement dans les instructions ultérieures.Cela crée un hachage contenant les règles de remplacement pour les différents déplacements. Une version plus lisible de ceci est
Les clés sont les caractères pour les déplacements et les valeurs sont des chaînes contenant la règle de remplacement correspondante.
C'est la boucle principale.
while(/"/)
vérifie s'il y a encore un"
caractère dans$_
(c'est-à-dire dans le champ). Si nous passons à l'amulette, son personnage est remplacé par le personnage du joueur et disparaît du champ.eval $r{getc STDIN}
lit un caractère à partir de l'entrée standard, recherche la règle de remplacement correspondante dans la règle a%r
et l'applique, c'est-à$_
-dire le champ. Cela est considéré comme vrai si un remplacement a été réellement effectué (c'est-à-dire que la clé a été trouvée dans le hachage et que le déplacement était possible; un déplacement impossible ne correspondra pas à la règle de remplacement). Dans ce cas,print
est exécuté. Comme il est appelé sans argument, il affiche$_
le champ modifié.la source
("."x80)=~s/(.{$=})./\1@/r=~s/(.{$a})./\1"/r=~s/(.{16})/\1\n/gr
est assez proche au premier abord, mais mon perl-fu est rouillé depuis quelques années. J'aurais pu manquer un changement d'état là-bas.C #,
256 248 234 227 226225 octetsUtilise les flèches NumPad avec NumLock activé pour se déplacer.
Mis en retrait et commenté pour plus de clarté:
la source
Main
n'est pas nécessaire d'appeler laMain
méthode, vous pouvez donc supprimer trois autres caractères.Html + JavaScript (ES6), score peut-être 217
Trop looong, mais jouable en ligne dans les extraits ci-dessous.
La ligne 6 (T.value ...) est pour la sortie et n'est pas comptée (mais pour des raisons de simplicité, j'ai compté les balises textarea open et close, même si elles sont également affichées)
Comme pour le hasard: l'amulette est toujours dans la moitié droite de la grille et le joueur commence toujours dans la moitié gauche.
Cliquez sur la zone de texte (après l'avoir agrandie) pour démarrer et redémarrer le jeu.
EcmaScript 6 Snippet (Firefox uniquement)
EcmaScript 5 snippet (testé dans Chrome)
la source
Actionscript 3: 267 octets
Un exemple de travail est en ligne
var a:int,p:int,t;function g(){var r=Math.random;while(p==a){a=r()*80;p=r()*80}addEventListener("keyDown",function(e){if(a==p)return;if(e.keyCode==87&&p>15)p-=16if(e.keyCode==83&&p<64)p+=16if(e.keyCode==65&&p%16>0)p--if(e.keyCode==68&&(p+1)%16>0)p++print()});print()}
Voici un programme complet (espaces inclus pour la lisibilité) utilisant la fonction de jeu:
la source
Javascript:
307216Vous pouvez jouer dans l'extrait ci-dessous! Les chiffres à gauche sont juste pour que la console (chrome au moins) ne fusionne pas les lignes.
Pour exécuter le code:
Non-golfé:
Éditer 1: Lire les règles plus attentivement et réécrire mon code en conséquence
la source
SpecBAS -
428402 (hors impression,466425 lorsque compté)Utilise Q / A / O / P pour se déplacer respectivement vers le haut, le bas, la gauche ou la droite.
La ligne pour imprimer le donjon à la ligne 1 est la seule ligne qui peut être ignorée, mais qui a également joué au golf.
La référence à # 34 n’est qu’un moyen simple de mettre CHR $ (34) dans le code.
Merci @Thomas Kwa, je n'avais pas remarqué que la position de départ du joueur était aléatoire. Également utilisé des instructions IF distinctes pour éliminer quelques caractères.
la source
2 LET px=1: LET py=1: LET ax=2: LET ay=INT(RND*5)
et aussi en utilisantIF instead of ELSE IF
.Un autre C #,
221171170Voici une autre manière en C # avec les deux positions aléatoires. Je voulais montrer cela même si cette partie est 7 octets plus longue que la solution de Hand-E-Food.
La réponse de Hand-E-Food sera bien sûr plus courte dès qu'il utilisera Console.Read ().
L’inconvénient de Consol.Read est que le fait d’appuyer sur la touche Entrée requise entraîne l’impression du champ 2 fois de plus.
Mais je ne pense pas qu'il soit nécessaire d'imprimer uniquement sur (de vraies) entrées.
La navigation est effectuée par 8426 comme dans la solution Hand-E-Foods.
Edit: (ajout d'une nouvelle solution et déplacement de PrinterClass à la fin)
Edit2: (modification d'un octet de 14 et enregistrement de l'octet en commençant par le bas à droite) En
adaptant la technique de Mauris, il est possible de le réduire à 171 octets en C # (bien sûr maintenant sans les deux positions aléatoires):
La classe d'imprimante est presque la même chose, juste une nouvelle surcharge d'impression ...
la source
Ruby, 185
Voici un exemple Ruby aussi.
Je suis très nouveau chez Ruby, peut-être que quelqu'un sait mieux le faire :)
J'ai compté lineFeeds à 1 puisque le programme plantera, sinon ...
La navigation est faite par 8462. Vous devez envoyer une entrée à chaque fois avec enter.
la source
QBasic, 103 octets
Selon les règles du défi, le
Show
sous-programme n'est pas inclus dans le nombre d'octets, pas plus que l'Show p, q, a, b
appel (avec la nouvelle ligne suivante).Pour vous déplacer, entrez un nombre et appuyez sur Entrée:
1
pour aller à gauche,2
pour monter,3
pour aller à droite et4
pour descendre.Ce code n'indique pas l'état du jeu à la fin, lorsque le joueur a trouvé l'amulette. Pour le faire, ajoutez-en un autre
Show p, q, a, b
après laIF
déclaration.Explication
Laissez
a
,b
représenter les coordonnées de l'amulette etp
,q
les coordonnées du joueur. Le joueur commence à (0, 0) et l'amulette commence à la ligne 0, avec une colonne comprise entre 1 et 9 inclus, en fonction du chiffre 1 de l'heure actuelle.Le reste est juste un tas de math avec des conditions. La chose importante à retenir est que les conditions dans QBasic renvoient
0
false,-1
à true. Regardons la déclaration de mise à jour de la ligne player:Si
m=2
nous voulons monter en soustrayant 1 dep
, aussi longtemps quep>0
. De même, sim=4
nous voulons descendre en ajoutant 1 àp
, tant quep<4
. On peut obtenir le comportement souhaité en se multipliant. Si les deux facteurs sont présents-1
, leur produit sera1
ce que nous pouvons soustraire ou ajouterp
. Si l'une ou l'autre de ces conditions est remplie0
, le produit sera0
sans effet.De même, la condition pour déterminer si le joueur a trouvé l'amulette est:
Si l'une des conditions est vraie, leur somme sera non nulle (
-1
ou-2
) et donc, le programme retournera à la ligne 1. Une foisp
égala
etq
égalb
, les deux conditions seront0
, de sorte que leur somme sera0
et que le flux de contrôle pourra atteindre le fin du programme.la source