Simulez une bataille entre deux créatures

16

Bienvenue, brave golfeur de code! Aujourd'hui, vous vous tiendrez au milieu d'une grande bataille entre un gobelin et un elfe!

    goblin attacks elf!
    elf dodges!
    elf attacks goblin!
    elf hits goblin for 13 damage!
    goblin has 37 health left.
    goblin attacks elf!
    goblin hits elf for 1 damage!
    elf has 49 health left.
    elf attacks goblin!
    elf hits goblin for 19 damage!
    goblin has 18 health left.
    goblin attacks elf!
    goblin hits elf for 26 damage!
    elf has 23 health left.
    elf attacks goblin!
    elf hits goblin for 20 damage!
    goblin has been slain!

Le défi

Votre défi est de simuler une bataille, comme celle ci-dessus. Vous recevrez une entrée sous cette forme:

creatureName health strength defense accuracy agility

Par exemple, la bataille entre le gobelin et l'elfe serait:

goblin 50 40 35 3 2 elf 50 35 30 4 5

Les première et deuxième créatures alterneront les attaques.

  • Imprimer 'creatureName attaque otherCreatureName!'
  • Vérifiez si la créature esquive. La créature esquivera une attaque si (son temps d'agilité rand () divisé par 2) est supérieur à (la précision de l'attaquant multiplie rand ()).
    • Si la créature esquive, imprimez 'creatureName esquive!'
    • Sinon, calculez les dégâts infligés en soustrayant (la force de l'attaquant multipliée par rand ()) et (la défense du défenseur multipliée par rand () divisée par 2). Le minimum de dégâts est de 1. Imprimez 'creatureName frappe otherCreatureName pour (x) dégâts!' Imprimez ensuite «creatureName a (x) health left». sauf si la santé de la créature est de 0 ou moins, auquel cas ...
      • Si la santé de la créature est de 0 ou moins, imprimez 'creatureName a été tué!' et terminer le programme.

Règles

  • Le code le plus court gagne.
  • N'imprimez pas littéralement 'creatureName', mais remplacez-le par le nom de la créature. N'imprimez pas '(x) damage' ou '(x) health;' remplacez-les par le montant réel. (Je dois préciser cela parce que certaines personnes sont très créatives avec le pliage des règles.: P)
Poignée de porte
la source
2
Pourquoi compliquer la spécification en réduisant de moitié l'agilité et la défense?
Peter Taylor
@Peter Parce que sinon les batailles ont pris trop de temps.
Poignée de porte
2
Mon point était: pourquoi ne pas changer l' entrée par exemple en goblin 50 40 18 3 2 elf 50 35 15 4 5?
Peter Taylor
@Peter Meh, cela semblait trop étrange - pourquoi la défense serait-elle si inférieure? Quoi qu'il en soit, c'est un puzzle; aucune raison de ne pas: P
Poignée de porte
Je pense qu'il n'est pas clair si «creatureName a (x) de santé à gauche». devrait être imprimé au dernier tour (lorsque la créature est tuée), et au cas où cela devrait (je suppose que cela ne devrait pas) si (x) doit toujours être 0 ou il peut être un nombre négatif.
épidémie

Réponses:

4

APL ( 249 244 242)

Style procédural cette fois, donc (dans Dyalog au moins) vous devez le coller dans une fenêtre d'éditeur. Je l'ai nommé G(la première ligne est le nom, je l'ai inclus parce que c'est comme ça qu'il apparaît dans la fenêtre de l'éditeur donc il devrait probablement être compté).

g
⎕ML ← 3
DA ← {(⊂ ↑ ⍵), ⍎¨1 ↓ ⍵} ¨ ↓ 2 6⍴A⊂⍨ '' ≠ A ← ⍞
→ 5
⎕ ← (↑ D) 'esquives!'
AD ← DA
⎕ ← (↑ A) 'attaques', '!', ⍨ ↑ D
→ 4 / ⍨> /? A [6], D [5]
⎕ ← A [1], 'hits', D [1], 'for', 'damage!', ⍨D [2] - ← 1⌈ - /? A [3], ⌈D [4] ÷ 2
→ 12 / ⍨D [2] ≤0
⎕ ← D [1], «a», D [2], «la santé est partie!»
→ 5
⎕ ← D [1], 'a été tué!'

(modifier: utilisé des GOTO numériques au lieu des étiquettes de ligne. Il s'avère que (dans Dyalog au moins) tout ce qui définit une étiquette X:est défini Xsur le numéro de ligne, il pourrait donc aussi bien utiliser directement les numéros.)

marinus
la source
6

Perl, 254 + 1

for((@a[0..5],@b)=split;$a[1]>0;@c=@a,@a=@b,@b=@c){say"$a[0] attacks $b[0]!\n",rand$b[5]/2<rand$a[4]?do{($==rand($a[2])-rand$b[3]/2)<1and$==1;"$a[0] hits $b[0] for $= damage!\n$b[0] has ",($b[1]-=$=)>0?"$b[1] health left.":"been slain!"}:"$b[0] dodges!"}

Exécutez avec perl -nM5.010(ou perl -nE '<code>'). Par méta , le -ncommutateur compte comme un caractère supplémentaire. Pas d'astuces de golf sophistiquées dans ce code, sauf peut-être l'utilisation de $=comme variable de dégâts pour enregistrer un int.

Edit: Espérons que le calcul des dégâts soit correct maintenant.

Ilmari Karonen
la source
6

CoffeeScript 454 432

Passez une chaîne à bpour obtenir les résultats. Je pensais que ce serait plus amusant d'avoir une sortie graphique animée, alors j'ai monté une démo. Modifiez simplement la zone de saisie pour modifier les statistiques et les noms. Les images de jpg.to qui est l'API google-images non officielle.

Démo Super Action

simulateur de bataille en action

b=(s)->
 r=Math.random
 p=s.split ' '
 n=p.map Number
 l=''
 o=(x...)->l+=x.join(' ')+'!\n'
 while 1|i=!i
  c=(x)->n[i*6+x]*r()
  d=(x)->n[(i||6)+x]*r()
  t=->d(4)/2>c 5
  h=->Math.max c(2)-d(3)/2,1
  a=p[i*6]
  b=p[6+i*-6]
  o a,'attacks',b
  if c(5)/2>d 4
   e=Math.ceil h()
   q=n[(i||6)+1]-=e
   o a,'hits',b,'for',e,'damage'
   o b,'has',q,'health left'if q>0
  else
   o b,'dodges'
  if q<1
   o b,'has been slain'
   break
 l

Entrées recommandées (suggérez les vôtres):

charmander 50 40 25 3 2 bulbasaur 90 30 40 4 5
voldemort 9999 10 5 1 1 batman 20 50 10 1010 30
Brigand
la source
Wow c'est génial! : DI accepterait cette réponse si je pouvais en accepter deux, mais j'ai dit dans les règles que la plus courte serait acceptée, et je ne peux accepter qu'une seule réponse :( Donc +1. Et voldemort 9999haha: D
Poignée de porte
@Doorknob, en bonus supplémentaire, vous pouvez lui donner des chiffres comme 10e42, mais votre navigateur peut se figer ...
Brigand
6

Rubis, 292 264

v=$*
def p*a;puts a*' 'end
loop{a,b=v[0],v[6]
w=v.map &:to_i
p a,:attacks,b+?!
w[11]*rand/2>w[4]*rand ? (p b,:dodges!):(h=v[7]=w[7]-=d=[rand(w[2])-rand(w[9])/2,1].max
p a,:hits,b,:for,d,:damage!
p b,:has,h<1?"been slain!":"#{h} health left."
h<1&&exit)
v.rotate!6}

Ma première entrée de golf de code; comment cette définition de méthode analyse me dépasse :)

Est-il correct de lire l'entrée à partir des paramètres de ligne de commande (par exemple ruby battle.rb goblin 50 40 35 3 2 elf 50 35 30 4 5)?

Ideone run

épidémie
la source
Oui, ça va.
Poignée de porte
5

JavaScript; 347 341 333

Comme je le fais toujours, je vais commencer par ma propre solution:

for(m=prompt().split(' '),r=Math.random,a=console.log,c=0,d=6;;){if(a(m[c]+' attacks '+m[d]+'!'),r()*m[c+4]>r()*m[d+5]/2){if(a(m[c]+' hits '+m[d]+' for '+(h=Math.max(~~(r()*m[c+2]-r()*m[d+3]/2),1))+' damage!'),(m[d+1]-=h)<1){a(m[d]+' has been slain!');break}a(m[d]+' has '+m[d+1]+' health left.')}else a(m[d]+' dodges!');t=c;c=d;d=t}

EDIT: apparemment assigné console.logà une variable se casse sur certains navigateurs, voici donc le même code avec une déclaration de fonction à la place:

for(m=prompt().split(' '),r=Math.random,a=function(x){console.log(x)},c=0,d=6;;){if(a(m[c]+' attacks '+m[d]+'!'),r()*m[c+4]>r()*m[d+5]/2){if(a(m[c]+' hits '+m[d]+' for '+(h=Math.max(~~(r()*m[c+2]-r()*m[d+3]/2),1))+' damage!'),(m[d+1]-=h)<1){a(m[d]+' has been slain!');break}a(m[d]+' has '+m[d+1]+' health left.')}else a(m[d]+' dodges!');t=c;c=d;d=t}

Je pensais à le changer alert, mais ce serait juste mal: P

Poignée de porte
la source
je reçois un à Uncaught TypeError: Illegal invocationcause de a=console.log. ne seriez-vous pas obligé de lier l' consoleobjet comme contexte, par exemple a=console.log.bind(console)?
C5H8NNaO4
@ C5H Hmm, c'est bizarre. Ça marche pour moi.
Poignée de porte
Je viens de le vérifier dans Firefox, Safari et Chrome, dans Firefox ça marche =) Chrome me donne ci-dessus, et Safari une TypeError
C5H8NNaO4
@ C5H :( Je pourrais peut-être le remplacer par alert, mais ce serait très ennuyeux: P
Poignée de porte
: P Oui, ce serait en effet ennuyeux, mais au moins cela économiserait "6" caractères et éviterait le TypeError =) Mais je suppose que c'est OK, au moins il fonctionne sur Firefox =)
C5H8NNaO4
4

Python: 393

J'ai serré un peu plus fort, si j'en avais 3, je pourrais probablement le print = praccourcir de quelques autres, mais je ne pense pas qu'il reste beaucoup de choses dans celui-ci.

393:

from random import randrange as r
x = input().split()
t=range
a,b=6,0
for i in t(1,6)+t(7,12):x[i]=int(x[i])
while x[b+1] > 0:
 a,b=b,a;print x[a]+" attacks "+x[b]
 if r(x[a+5]/2)>r(x[b+5]):print x[a]+' dodges!';continue
 d=max(r(x[a+2])-r(x[b+3]/2),1);print x[a]," hits ",x[b]," for ",d," damage!";x[b+1]-=d
 if x[b+1]>0:print x[b]," has ",x[b+1]," health left."
print x[b]," has been slain"

399:

from random import randrange as r
x = raw_input().split()
t=range
a,b=6,0
for i in t(1,6)+t(7,12):x[i]=int(x[i])
while x[b+1] > 0:
 a,b=b,a;print x[a]+" attacks "+x[b]
 if r(x[a+5]/2) > r(x[b+5]):print x[a]+' dodges!';continue
 d=max(r(x[a+2])-r(x[b+3]/2),1);print x[a]," hits ",x[b]," for ",d," damage!";x[b+1]-=d                        if x[b+1]>0:print x[b]," has ",x[b+1]," health left."
print x[b]," has been slain"

Je pense que les gens ignorent que si vous avez un bon état dans la boucle, vous n'avez pas besoin de vérifier si la cible est inférieure à la santé.


la source
Je vérifie l'état de santé deux fois, dans l'en-tête de la boucle pour terminer la bataille, et dans la boucle pour imprimer "a été tué" ou "hits ...", car le double contrôle de santé est plus court qu'une console supplémentaire.log
C5H8NNaO4
4

JavaScript: 340 306

339:

for(m=Math.random,a=prompt().split(" "),c=[a,a.splice(6)],e;0<+c[0][1]&&0<+c[1][1];)c.reverse(),console.log(c[0][0]+" attacks "+c[1][0]+"!\n"+(c[0][4]*m()<c[1][5]*m()/2?c[1][0]+" dodges!":c[0][0]+" hits "+c[1][0]+" for "+(e=1+(c[0][2]*m()-c[1][3]*m()/2|0))+" damage!\n"+c[1][0]+" has "+(0>(c[1][1]-=e)?"been slain!":c[1][1]+" health left.")))

306:

for(var m=Math.random,a=prompt().split(" "),b=a.splice(6),d,e;0<+a[1]&&0<+b[1];d=a,a=b,b=d)console.log(a[0]+" attacks "+b[0]+"!\n"+(a[4]*m()<b[5]*m()/2?b[0]+" dodges!":a[0]+" hits "+b[0]+" for "+(e=a[2]*m()-b[3]*m()/2|0,e<=0?e=1:e)+" damage!\n"+b[0]+" has "+(0>(b[1]-=e)?"been slain!":b[1]+" health left.")))

Exemple de sortie:

goblin attacks elf!
elf dodges!
elf attacks goblin!
elf hits goblin for 21 damage!
goblin has 29 health left.
goblin attacks elf!
elf dodges!
elf attacks goblin!
elf hits goblin for 15 damage!
goblin has 14 health left.
goblin attacks elf!
goblin hits elf for 1 damage!
elf has 49 health left.
elf attacks goblin!
elf hits goblin for 16 damage!
goblin has been slain!   

Modifier les notes: +1 caractère, j'ai raté le "!" après "esquive"
Oh et j'ai oublié de mettre une sortie après "Exemple de sortie"
Changé l'en-tête en JavaScript, comme le suggère @tbodt

C5H8NNaO4
la source
Pourquoi ne l'appelez-vous pas JavaScript pour éviter de dérouter les gens?
tbodt
@tbodt Je ne pensais pas que cela perturberait les gens =) Changé à la place en Javascript
C5H8NNaO4
3

R: 387 caractères

a=scan(,"");i=as.integer;r=runif;C=cat;X=data.frame(i(a[2:6]),i(a[8:12]));z=1;Y=c(a[1],a[7]);repeat{p=1+z%%2;n=X[,p];m=X[,-p];N=Y[p];M=Y[-p];C(N,"attacks",M,"\n");if(r(1)*n[5]<r(1)*m[5]/2){C(M,"dodges!\n")}else{C(N,"hits",M,"for",d<-max(round(n[2]*r(1)-m[3]*r(1)/2),1),"damages!\n");h=max(m[1]-d,0);if(h){C(M,"has",X[1,-p]<-h,"health left\n")}else{C(M,"has been slained!");break}};z=z+1}

Ou bien développé, avec des indentations et des commentaires, pour clarifier les choses:

a=scan(,"")                        # Read stdin as character vector
i=as.integer
r=runif
C=cat
X=data.frame(i(a[2:6]),i(a[8:12])) # Data frame with opponents stats
z=1                                # Turn counter 
Y=c(a[1],a[7])                     # Vector of opponents name
repeat{                            # shorter than while(T)
    p=1+z%%2                       # R indexing starts with 1 not 0
    n=X[,p]                        # Attacking opponent stats
    m=X[,-p]                       # Defending opponent stats
    N=Y[p]                         # Attacking opponent name
    M=Y[-p]                        # Defending opponent name
    C(N,"attacks",M,"\n")          # By default, cat separates elements with a space
    if(r(1)*n[4]<r(1)*m[5]/2){
        C(M,"dodges!\n")
    }else{
        C(N,"hits",M,"for",d<-max(round(n[2]*r(1)-m[3]*r(1)/2),1),"damages!\n")
        h=max(m[1]-d,0)            # Health after the strike
        if(h){                     # If health is not 0
            C(M,"has",X[1,-p]<-h,"health left\n")
        }else{                     # If it is
            C(M,"has been slained!")
            break
            }
    }
    z=z+1
}
plannapus
la source
2

C # - 464 453 caractères

Après quelques nuits, je n'arrive pas à me rapprocher des autres entrées (pas surprenant pour C #). Je pense qu'il y a encore place à amélioration. Pas de trucs particulièrement intelligents.

using System;using System.Linq;class P{static void Main(string[]a){int D,h=1,z=6;
var n=a.Select(x=>int.TryParse(x,out D)?D:0).ToList();var r=new Random();Func<int>
R=()=>r.Next(101);for(;h>0;z=z>0?0:6){D=(n[8-z]*R()-n[3+z]*R()/2)/100;var d=n[5+z]
*R()/2>n[10-z]*R();h=d?h:n[1+z]-=D=D<1?1:D;Console.Write("{0} attacks {1}!\n"+(d?
"{1} dodges!\n":"{0} hits {1} for {2} damage!\n")+(d?"":"{1} has {3}\n"),a[6-z],a
[z],D,h>0?h+" health left.":"been slain!");}}}

Commenté:

using System;
using System.Linq;
class P
{
    static void Main(string[] a)
    {
        int D, // string to int parsing and attack damage 
            h = 1, // health 
            z = 6; // index

        // painful requirement to convert the input strings to integers
        var n = a.Select(x => int.TryParse(x, out D) ? D : 0).ToList();

        // set up a function to return a new random number
        var r = new Random();
        Func<int> R = () => r.Next(101);

        // we'll exit the loop when the defender's health (h) is <= 0.
        // z is used as an index offset to get values out of the list, it flips between 0 an 6 each round
        for (; h > 0; z = z > 0 ? 0 : 6)
        {
            // calculate damage
            D = (n[8 - z] * R() - n[3 + z] * R() / 2) / 100;

            // see if defender dodges
            var d = n[5 + z] * R() / 2 > n[10 - z] * R();

            // subtract health from defender if necessary. store health of defender in h
            h = d ? h : n[1 + z] -= D = D < 1 ? 1 : D;

            // print the round
            Console.Write(
                "{0} attacks {1}!\n" + (d ? "{1} dodges!\n" : "{0} hits {1} for {2} damage!\n") + 
                (d ? "" : "{1} has {3}\n"), a[6 - z], a[z], D, h > 0 ? h + " health left." : "been slain!");
        }
    }
}
Igby Largeman
la source
1

Python 3, 314

from random import*
r=random
p=print
I=input().split()
H=1
while H>0:s,a,H,D,G=map(int,I[2:5:2]+I[7::2]);N=I[6];p(I[0],"attacks",N+"!");I=I[6:]+I[:6];X=max(int(s*r()-D*r()/2),1)*(G*r()/2<a*r());I[1]=H=H-X;X<1and p(N,"dodges!")or p(I[6],"hits",N,"for",X,"damage!\n"+N,"has",["been slain!","%s health left."%H][H>0])
Réintégrer Monica
la source