Symuluj bitwę między dwoma stworzeniami

16

Witaj, dzielny golfista! Dziś staniesz w środku wielkiej bitwy między goblinem a elfem!

    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!

Wyzwanie

Twoim wyzwaniem jest symulacja bitwy, takiej jak powyższa. Otrzymasz dane wejściowe w tym formularzu:

creatureName health strength defense accuracy agility

Na przykład bitwa między goblinem a elfem byłaby następująca:

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

Pierwsze i drugie stworzenie będzie naprzemiennie atakowało.

  • Drukuj „creatureName atakuje otherCreatureName!”
  • Sprawdź, czy stwór unika. Stworzenie uniknie ataku, jeśli (jego czas zręczności rand () podzielony przez 2) jest większy niż (razy celność atakującego rand ()).
    • Jeśli stwór uchyli się, wypisz „creatureName unika!”
    • W przeciwnym razie obliczyć zadane obrażenia, odejmując (razy siła atakującego rand ()) i (czas obrony obrońcy rand () podzielony przez 2). Minimalne obrażenia to 1. Wydrukuj „creatureName uderza otherCreatureName dla (x) obrażeń!” Następnie wydrukuj „creatureName ma (x) zdrowia.” chyba że zdrowie stworzenia wynosi 0 lub mniej, w takim przypadku ...
      • Jeśli zdrowie stwora wynosi 0 lub mniej, wydrukuj „creatureName zostało zabite!” i zakończ program.

Zasady

  • Najkrótszy kod wygrywa.
  • Nie drukuj dosłownie „creatureName”, lecz zamień go na nazwę stworzenia. Nie drukuj „(x) obrażeń” lub „(x) zdrowia;” zastąp je rzeczywistą kwotą. (Muszę to określić, ponieważ niektórzy ludzie są bardzo kreatywni w naginaniu reguł.: P)
Klamka
źródło
2
Po co komplikować specyfikację, zmniejszając o połowę zwinność i obronę?
Peter Taylor,
@Peter Ponieważ w przeciwnym razie bitwy trwały zbyt długo.
Klamka
2
Chodzi mi o to: dlaczego nie zmienić danych wejściowych np. Na goblin 50 40 18 3 2 elf 50 35 15 4 5?
Peter Taylor,
@Peter Meh, to wydawało się zbyt dziwne - dlaczego obrona miałaby być o wiele niższa? W każdym razie jest to łamigłówka; nie ma powodu, aby nie: P
Klamka
Myślę, że nie jest jasne, czy „CreatureName ma (x) zdrowia”. powinien być wydrukowany w ostatniej rundzie (gdy stworzenie jest zabijane), aw przypadku, gdy powinien (zakładałem, że nie powinien), czy (x) powinno zawsze mieć wartość 0 lub może być liczbą ujemną.
epidemia

Odpowiedzi:

4

APL ( 249 244 242)

Tym razem styl proceduralny, więc (przynajmniej w Dyalogu) musisz wkleić to do okna edytora. Nazwałem go G(pierwszy wiersz to nazwa, załączyłem go, ponieważ tak pokazuje się w oknie edytora, więc prawdopodobnie należy go policzyć).

sol
⎕ML ← 3
DA ← {(⊂ ↑ ⍵), ⍎¨1 ↓ ⍵} ¨ ↓ 2 6⍴A⊂⍨ '' ≠ A ← ⍞
→ 5
⎕ ← (↑ D) „uchyla się!”
AD ← DA
⎕ ← (↑ A) „ataki”, „!”, ⍨ ↑ D
→ 4 / ⍨> /? A [6], D [5]
⎕ ← A [1], „trafienia”, D [1], „za”, „uszkodzenie!”, ⍨D [2] - ← 1⌈ - /? A [3], ⌈D [4] ÷ 2
→ 12 / ⍨D [2] ≤0
⎕ ← D [1], „ma”, D [2], „zdrowie zostało!”
→ 5
⎕ ← D [1], „został zabity!”

(edytuj: używane numeryczne GOTO zamiast etykiet linii. Okazuje się, że (przynajmniej w Dyalogu) wszystko, co X:robi etykieta , jest ustawione Xna numer linii, więc równie dobrze można użyć liczb bezpośrednio.)

marinus
źródło
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!"}

Uruchom z perl -nM5.010(lub perl -nE '<code>'). Za meta , to -nliczy się jako jeden dodatkowy przełącznik charakteru. Żadnych fantazyjnych sztuczek golfowych w tym kodzie, z wyjątkiem użycia $=jako zmiennej obrażeń do uratowania int.

Edycja: Mam nadzieję, że obliczanie obrażeń jest teraz prawidłowe.

Ilmari Karonen
źródło
6

CoffeeScript 454 432

Przekaż ciąg znaków, baby uzyskać wyniki. Pomyślałem, że fajniej byłoby mieć animowaną grafikę, więc przygotowałem demo. Wystarczy zmienić pole wprowadzania, aby zmienić statystyki i nazwy. Zdjęcia z jpg.to, który jest nieoficjalnym API Google-images.

Super Action Demo

symulator bitwy w akcji

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

Zalecane dane wejściowe (zaproponuj własne):

charmander 50 40 25 3 2 bulbasaur 90 30 40 4 5
voldemort 9999 10 5 1 1 batman 20 50 10 1010 30
Bandyta
źródło
Wow to świetnie! : DI zaakceptowałbym tę odpowiedź, gdybym mógł zaakceptować dwie, ale powiedziałem w zasadach, że najkrótsza zostanie zaakceptowana, i mogę zaakceptować tylko jedną odpowiedź :( Więc +1. I voldemort 9999haha: D
Klamka
@Doorknob, jako dodatkowy bonus, możesz nadać mu takie liczby 10e42, ale twoja przeglądarka może się zawiesić ...
Brigand
6

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

Mój pierwszy wpis do golfa; jak ta definicja metody analizuje jest poza mną :)

Czy można odczytać dane wejściowe z parametrów wiersza polecenia (np. ruby battle.rb goblin 50 40 35 3 2 elf 50 35 30 4 5)?

Ideone run

epidemia
źródło
Tak, w porządku.
Klamka
5

JavaScript; 347 341 333

Jak zawsze, zacznę od własnego rozwiązania:

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}

EDYCJA: najwyraźniej przypisywanie console.logdo zmiennej przerywa w niektórych przeglądarkach, więc oto ten sam kod z deklaracją funkcji:

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}

Myślałem o zmianie na alert, ale byłoby to po prostu złe: P

Klamka
źródło
dostaję z Uncaught TypeError: Illegal invocationpowodu a=console.log. czy nie musiałbyś powiązać consoleobiektu jako kontekstu, np. a=console.log.bind(console)?
C5H8NNaO4
@ C5H Hmm, to dziwne. Mi to pasuje.
Klamka
Właśnie sprawdziłem to w Firefox, Safari i Chrome, w Firefox działa =) Chrome daje mi powyżej, a Safari TypeError
C5H8NNaO4
@ C5H :( Może mógłbym go zastąpić alert, ale byłoby to bardzo denerwujące: P
Klamka
: P Tak, to byłoby irytujące, ale przynajmniej uratowałoby znaki „6” i uniknęło TypeError =) Ale chyba jest OK, przynajmniej działa na Firefox =)
C5H8NNaO4
4

Python: 393

Ścisnąłem trochę mocniej, gdybym miał 3, prawdopodobnie mógłbym to zrobić, print = paby skrócić go o kilka więcej, ale nie sądzę, żeby zostało w tym wiele.

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"

Myślę, że ludzie pomijają to, że jeśli masz dobry stan w pętli, nie musisz sprawdzać, czy cel jest poniżej zdrowia.


źródło
Dwukrotnie sprawdzam zdrowie, w nagłówku pętli, aby zakończyć bitwę, i w pętli do wydrukowania albo „został zabity”, albo „trafił ...”, ponieważ podwójna kontrola zdrowia jest krótsza niż dodatkowa
konsola. Log
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.")))

Przykładowe dane wyjściowe:

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!   

Edytuj notatki: znak +1, brakowało mi „!” po „uchyla się”
Oh i zapomniałem faktycznie wstawić wyjście po „Przykładowym wyjściu”
Zmieniłem nagłówek na JavaScript, jak sugeruje @tbodt

C5H8NNaO4
źródło
Dlaczego nie nazwiesz go JavaScript, aby uniknąć mylących ludzi?
tbodt
@tbodt Nie myślałem, że to pomyliłoby ludzi =) Zamiast tego zmieniłem go na JavaScript
C5H8NNaO4
3

R: 387 znaków

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}

Lub w pełni rozwinięty, z wcięciami i komentarzami, aby wszystko było bardziej zrozumiałe:

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
źródło
2

C # - 464 453 znaków

Po kilku nocach nie wydaje mi się, aby zbliżyć się do innych wpisów (co nie jest zaskakujące dla C #). Podejrzewam, że wciąż jest miejsce na ulepszenia. Żadnych szczególnie sprytnych sztuczek.

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!");}}}

Skomentowano:

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
źródło
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])
Przywróć Monikę
źródło