2つのクリーチャー間の戦いをシミュレートする


16

Brave Code Golferさん、ようこそ!今日、あなたはゴブリンとエルフの間の素晴らしい戦いの真っstand中に立つでしょう!

    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!

チャレンジ

あなたの課題は、上記のような戦闘をシミュレートすることです。次の形式で入力を受け取ります。

creatureName health strength defense accuracy agility

たとえば、ゴブリンとエルフの戦いは次のようになります。

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

最初と2番目のクリーチャーは攻撃を交互に行います。

  • 「creatureNameがotherCreatureNameを攻撃します!」
  • クリーチャーがかわすかどうかを確認します。クリーチャーは、(敏a性にrand()を2で割った値)が(攻撃者の精度にrand()を掛けた値)より大きい場合、攻撃を避けます。
    • クリーチャーが回避した場合、「creatureName dodges!」と印刷します。
    • それ以外の場合は、(攻撃者の強度にrand()を掛けた値)と(防御側の防御時間にrand()を2で割った値)を引いて、与えられたダメージを計算します。最小ダメージは1です。「creatureName hits otherCreatureName for(x)damage!」次に、「creatureName has(x)health left。」と出力します。クリーチャーのヘルスが0以下の場合を除き、その場合は...
      • クリーチャーのヘルスが0以下の場合、「creatureName has been slain!」と印刷します。そしてプログラムを終了します。

ルール

  • 最短のコードが優先されます。
  • 文字通り「creatureName」を印刷せず、クリーチャーの名前に置き換えます。「(x)damage」または「(x)health;」を出力しないでください 実際の金額に置き換えてください。(一部の人々はルールを曲げることに非常に創造的であるため、これを指定する必要があります。

2
アジリティとディフェンスを半分にして仕様を複雑にするのはなぜですか?
ピーターテイラー

@Peterそれ以外の場合、戦闘に時間がかかりすぎたからです。
ドアノブ

2
私のポイントは:なぜ変化しない入力に例えばgoblin 50 40 18 3 2 elf 50 35 15 4 5
ピーターテイラー

@Peter Meh、それはあまりにも奇妙に思えた-なぜ防御はそれほど低くなるのでしょうか?とにかく、それはパズルです。しない理由:P
ドアノブ

「creatureNameに(x)個のヘルスが残っている」かどうかは明らかではないと思います。最後のラウンド(クリーチャーが殺されたとき)に印刷する必要があり、(x)が常に0であるか、負の数になる可能性がある場合(そうでないと仮定した場合)に印刷する必要があります。
疫学者

回答:


4

APL(249 244 242)

今回は手続き型なので、(少なくともDyalogでは)これをエディターウィンドウに貼り付ける必要があります。名前を付けましたG(最初の行は名前です。編集ウィンドウに表示されるので、おそらくカウントされるはずなので、含めました)。

G
⎕ML←3
DA←{(⊂↑⍵)、⍎¨1↓⍵}¨↓26⍴A⊂⍨ ''≠A←⍞
→5
⎕←(↑D)「ダッジ!」
AD←DA
⎕←(↑A) 'attacks'、 '!'、⍨↑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]、 'has'、D [2]、 'health left!'
→5
⎕←D [1]、「殺された!」

(編集:行ラベルの代わりに数値GOTOを使用しました。(少なくともDyalogでは)ラベルの定義はすべて行番号にX:設定さXれるため、直接番号を使用することもできます。)


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

perl -nM5.010(またはperl -nE '<code>')で実行します。metaごとに、-nスイッチは1つの余分な文字としてカウントされます。$=を保存するためのダメージ変数としての使用を除いて、このコードには派手なゴルフのトリックはありませんint

編集:うまくいけば、ダメージの計算が正しくなりました。


6

CoffeeScript 454 432

文字列を渡しbて結果を取得します。グラフィックアニメーション出力を作成する方が楽しいと思ったので、デモを作成しました。入力ボックスを変更して、統計と名前を変更するだけです。非公式のgoogle-images APIであるjpg.toの写真。

スーパーアクションデモ

アクションの戦闘シミュレーター

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

推奨される入力(自分で提案する):

charmander 50 40 25 3 2 bulbasaur 90 30 40 4 5
voldemort 9999 10 5 1 1 batman 20 50 10 1010 30

うわー、それは素晴らしい!:DIは、私は2つを受け入れることができれば、この答えを受け入れるが、私は最短で受け入れられることをルールに言って、私は唯一の答えを受け入れることができます:(だから、1となります。voldemort 9999(笑):D
ドアノブ

@Doorknob、追加ボーナスとして、のような数字を付けることができ10e42ますが、ブラウザがフリーズする可能性があります...-
ブリガンド

6

ルビー、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}

私の最初のコードゴルフエントリー。そのメソッド定義の解析方法は私を超えています:)

コマンドラインパラメータ(例ruby battle.rb goblin 50 40 35 3 2 elf 50 35 30 4 5)から入力を読み取っても大丈夫ですか?

イデオネラン


はい、大丈夫です。
ドアノブ

5

JavaScript; 347 341 333

いつものように、私は自分の解決策から始めましょう。

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}

編集:console.logいくつかのブラウザでは明らかに変数に代入すると壊れるので、代わりに関数宣言を使用した同じコードを次に示します。

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}

私はそれをに変えることを考えていましたalertが、それはただの悪でしょう:P


Uncaught TypeError: Illegal invocationために取得しa=console.logます。たとえば、consoleオブジェクトをコンテキストとしてバインドする必要はありa=console.log.bind(console)ませんか?
C5H8NNaO4

@ C5Hうーん、それは奇妙です。わたしにはできる。
ドアノブ

Firefox、Safari、Chromeでチェックしただけで、Firefoxでは動作します=)Chromeは上記を提供し、SafariはTypeError
C5H8NNaO4

C5H @ :(たぶん私はでそれを置き換えることができますalertが、それは非常に迷惑になります:P
ドアノブ

:P確かに迷惑だろうが、少なくともそれが「6」の文字を保存し、TypeError例外を回避しますはい=)しかし、私はその[OK]を推測するには、少なくとも、それは、Firefox =)上で動作します
C5H8NNaO4

4

Python:393

私はもう少し強く絞った。もし3があれば、おそらくもう少しprint = p短くすることができるだろうが、この中にあまり残っているとは思わない。

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"

ループ内に良好な状態があれば、ターゲットがヘルスを下回っているかどうかを確認する必要はないと人々はスキップしていると思います。


ダブルヘルスチェックは追加のconsole.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.")))

サンプル出力:

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!   

メモを編集:+1文字、「!」を見逃した 「ダッジ」の後
ああ、私は「サンプル出力」の後に実際に出力を置くのを忘れました
@tbodtが示唆するように、ヘッダーをJavaScriptに変更しました


なぜ人々を混乱させないためにJavaScriptと呼ばないのですか?
tbodt

@tbodt人を混乱させるとは思わなかった=)代わりにJavascriptに変更した
C5H8NNaO4

3

R:387文字

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}

または、インデントとコメントを使用して、物事を明確にするために完全に開発されました:

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
}

2

C#-464 453文字

これに数泊した後、他のエントリに近づくことさえできないようです(C#にとっては驚くことではありません)。まだ改善の余地があると思います。特に巧妙なトリックはありません。

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

コメント:

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

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])
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.