Magic: The Gathering Combat with Abilities


16

Terkait

Tujuan:

Diberi dua makhluk dengan kemampuan bertarung opsional, kembalikan nilai-nilai unik namun konsisten yang mewakili makhluk mana yang mati, jika ada.

Memasukkan:

#Longest form:
[[P,T, "<abilities>"], [P,T, "<abilities>"]]
#Shortest form:
[[P,T], [P,T]]

Setiap makhluk akan diberikan dalam bentuk [P,T,"<abilities>"]. Itu akan dalam bentuk [P,T],, [P,T,""]atau [P,T,0]jika tidak memiliki kemampuan, pilihan Anda pada formulir. P adalah bilangan bulat> = 0, T adalah bilangan bulat> = 1. <abilities>adalah bagian dari "DFI", atau dapat direpresentasikan melalui satu nomor / bitstring jika Anda inginkan. Urutan bendera juga terserah Anda.

Mekanisme Memerangi:

Setiap makhluk memiliki dua statistik, Kekuatan dan Ketangguhan dalam urutan itu, dan kemampuan opsional. Kekuatan makhluk adalah> = 0. Ketangguhan makhluk adalah> = 1.

Setiap makhluk akan secara bersamaan melakukan kerusakan yang sama dengan kekuatannya untuk makhluk lawan (kecuali jika seseorang memiliki serangan pertama). Jika nilainya lebih dari atau sama dengan ketangguhan lawan, itu akan mati (kecuali jika tidak bisa dihancurkan).

Contoh: Alice adalah a 2/2, Bob adalah a3/4 , keduanya tanpa kemampuan. Alice akan melakukan 2 kerusakan pada Bob dan mengambil 3 kerusakan sebagai balasannya. Ketangguhan Alice adalah 2 sehingga ia akan mati, ketangguhan Bob adalah 4 sehingga ia akan hidup.

Hanya ada 3 kemampuan opsional yang akan kami pertimbangkan untuk ini (meskipun ada lebih banyak dalam permainan). Ini akan menjadi satu bendera karakter:

  • [D] eathtouch: Sejumlah kerusakan (X> 0) dianggap mematikan.
  • [F] Strike pertama: Akan menangani kerusakannya terlebih dahulu, mampu membunuh makhluk lain sebelum dapat menyerang kembali. Jika kedua makhluk memiliki Serangan Pertama, Selesaikan pertempuran seperti biasa.
  • [I] ndestructible: Tidak ada jumlah kerusakan yang dianggap mematikan, termasuk Deathtouch.

Keluaran:

Nilai yang konsisten untuk masing-masing dari empat kasus berikut. Tolong sebutkan empat nilai dalam jawaban Anda. Contoh nilai balik dalam parens:

  • Tidak ada makhluk yang mati (0)
  • Makhluk ke-1 meninggal (1)
  • Makhluk ke-2 meninggal (2)
  • Kedua makhluk itu mati (3)

Aturan:

  • Input dijamin memiliki dua makhluk yang diformat dengan benar.
  • Jika Anda menggunakan karakter untuk kemampuan, Anda dapat menganggap mereka dipesan sesuai keinginan tetapi memposting urutan yang digunakan jika relevan.
  • Jika Anda menggunakan angka / bitstring untuk kemampuan, poskan penyandian apa yang Anda gunakan. mis: 111is D/F/I, 7isD/F/I , etc.
  • Jika seekor makhluk tidak memiliki kemampuan, Ia juga dapat dianggap sebagai [P,T, ""] atau jumlah yang setara
  • Standard Loopholes Forbidden
  • Ini adalah sehingga kode terpendek menang.

Contoh:

Input: [[2,2], [1,1]]
Output: 2nd Dies

Input: [[0,2], [0,1]] #0/2 vs 0/1
Output: Neither Die

Input: [[2,1], [2,1]] #2/1 vs 2/1
Output: Both Die

Input: [[1,1, "D"], [2,2]] #1/1 Deathtoucher vs 2/2 
Output: Both Die

Input: [[2,2], [0,1, "D"]] #2/2 vs 0/1 Deathtoucher
Output: 2nd Dies

Input: [[2,2], [1,1, "DF"]] #2/2 vs 1/1 Deathtouch First-striker 
Output: 1st Dies

Input: [[0,2, "D"], [0,1, "DF"]] #0/2 Deathtoucher vs 0/1 Deathtouch First-striker
Output: Neither Die

Input: [[2,2], [2,2, "F"]] #2/2 vs 2/2 First-striker
Output: 1st Dies

Input: [[2,2, "I"], [1,1, "DF"]] #2/2 Indestructible vs 1/1 Deathtouch First-striker
Output: 2nd Dies

Input: [[9999,9999], [1,1, "I"]] #9999/9999 vs 1/1 Indestructible
Output: Neither Die

Input: [[2,2, "F"], [1,1, "F"]] #2/2 First-Striker vs 1/1 First-Striker
Output: 2nd Dies

#9/9 Deathtouch, Indestructible First-Striker vs 9/9 Deathtouch, Indestructible First-Striker
Input: [[9,9, "DFI"], [9,9, "DFI"]] 
Output: Neither Die

1
@ user71546 Ya. Ada sedikit lebih banyak aturan yang terlibat, tetapi dalam MtG, "Can'ts" truf "Cans." Jadi secara fungsional, Indestructible mengabaikan Deathstrike. Diedit agar lebih eksplisit
Veskah

1
@ fəˈnɛtɪk, masih perlu kerusakan, hanya saja tidak mati karenanya. Ingat, pertanyaan itu juga salah menyebutkan aturan. Seharusnya " permanen [tidak bisa dihancurkan] tidak dihancurkan oleh kerusakan mematikan, dan mereka mengabaikan tindakan berbasis negara yang memeriksa kerusakan mematikan ".
Peter Taylor

4
" Jika makhluk tidak memiliki kemampuan, itu harus diuraikan sebagai [P, T]. [P, T," "] tidak valid " adalah aturan yang buruk. Ini mendiskriminasi bahasa dengan pengetikan yang kuat tanpa manfaat.
Peter Taylor

2
@PeterTaylor Saya ingin menjaga array bergerigi tetapi Anda benar bahwa itu tidak membuatnya lebih baik. Dengan demikian aturan telah dihapus
Veskah

1
@Veskah Bisakah saya menganggap "D", "F", "I" sebagai angka? D => 0, F => 1, I => 2
Luis felipe De jesus Munoz

Jawaban:


6

Perl 5 , 248 byte

... tanpa spasi dan baris baru:

sub c{eval'
(P,T,A,p,t,a)=@_;
     A=~/F/&&a!~/F/&&a!~/I/ ? c( P,2e9,A=~s/F//r,p,t, a         )
    :a=~/F/&&A!~/F/&&A!~/I/ ? c( P,T, A,        p,2e9,a=~s/F//r )
    : do{
        P=1e9 ifA=~/D/&&P>0;
        p=1e9 ifa=~/D/&&p>0;
        T=3e9 ifA=~/I/;
        t=3e9 ifa=~/I/;
        T-=p;
        t-=P;
        T>0&&t>0  ? 0
            : T>0 ? 2
            : t>0 ? 1
            :       3
}'=~s,[pta],\$$&,gri }

Cobalah online!

Versi ungolfed saya dengan sepuluh tes dari @Veskah (OP), tes lolos:

sub co { #combat
    my($p1,$t1,$a1, $p2,$t2,$a2)=@_; #p=power, t=toughness, a=abilities
    $a1=~s/F// and $a2=~s/F// if "$a1$a2"=~/F.*F/; #both F, no F
    return co($p1,2e9,$a1=~s/F//r, $p2,$t2,$a2        ) if $a1=~/F/ && $a2!~/I/;
    return co($p1,$t1,$a1,         $p2,2e9,$a2=~s/F//r) if $a2=~/F/ && $a1!~/I/;
    $p1=1e9 if $a1=~/D/ and $p1>0;
    $p2=1e9 if $a2=~/D/ and $p2>0;
    $t1=3e9 if $a1=~/I/;
    $t2=3e9 if $a2=~/I/;
    $t1-=$p2;
    $t2-=$p1;
    $t1<=0 && $t2<=0 ? "Both Die"
   :$t1<=0           ? "1st Dies"
   :$t2<=0           ? "2nd Dies"
                     : "Neither Die"
}

my @test=map{[/Input: .*? (\d+),(\d+)(?:,\s*"([FDI]+)")?
                      .*? (\d+),(\d+)(?:,\s*"([FDI]+)")?
           .*? Output: \s* (1st.Dies|2nd.Dies|Both.Die|Neither.Die)? /xsi]}
         split/\n\n/,join"",<DATA>;
my $t=0;
for(@test){ $t++;
  my $r=co(@$_);#result
  $r=~s,0,Neither Die,; $r=~s,3,Both Die,;
  print $$_[-1]=~/^$r/
    ? "Ok $t\n"
    : "Not ok, combat $t --> $r, wrong! (".join(",",@$_).")\n"
}
__DATA__
Input: [[2,2], [1,1]]
Output: 2nd Dies

Input: [[0,2], [0,1]] #0/2 vs 0/1
Output: Neither Die

Input: [[2,1], [2,1]] #2/1 vs 2/1
Output: Both Die

Input: [[1,1, "D"], [2,2]] #1/1 Deathtoucher vs 2/2
Output: Both Die

Input: [[2,2], [0,1, "D"]] #2/2 vs 0/1 Deathtoucher
Output: 2nd Dies

Input: [[2,2], [1,1, "DF"]] #2/2 vs 1/1 First-strike, Deathtoucher
Output: 1st Dies

Input: [[2,2], [2,2, "F"]] #2/2 vs 2/2 First-striker
Output: 1st Dies

Input: [[2,2, "I"], [1,1, "DF"]] #2/2 Indestructible vs 1/1 First-strike, Deatht.
Output: 2nd Dies

Input: [[99999,99999], [1,1, "I"]] #99999/99999 vs 1/1 Indestructible
Output: Neither Die

Input: [[2,2, "F"], [1,1, "F"]] #2/2 First-Striker vs 1/1 First-Striker
Output: 2nd Dies

4

JavaScript, 137 125 120 111 byte

i=>(k=(a,b)=>!(b[2]%2)&&a[0]/(a[2]<=3)>=b[1],[c,d]=i,g=c[2]&2,h=k(c,d),j=k(d,c),d[2]&2-g&&(g?h&&2:j&&1)||j+2*h)

Saya menggunakan nomor bitmap untuk kemampuan D = 4 F = 2 I = 1 lakukan "DFI"akan 7. Output saya adalah Tidak Meninggal 0, Meninggal 1 1, Meninggal 2 2, Keduanya mati3 .

Tes dengan:

f([[2, 2, 0], [1,1, 0]]); // 2
f([[0, 2, 0], [0,1, 0]]); // 0
f([[2, 1, 0], [2,1, 0]]); // 3
f([[1, 1, 4], [2,2, 0]]); // 3
f([[2, 2, 0], [0,1, 4]]); // 2
f([[2, 2, 0], [1,1, 6]]); // 1
f([[2, 2, 0], [2,2, 2]]); // 1
f([[2, 2, 1], [1,1, 6]]); // 2
f([[99999, 99999, 0], [1,1, 1]]); // 0
f([[2, 2, 2], [1,1, 2]]); // 2)

Ini adalah kode kerja saya yang pertama

const kills = (c1, c2) => { // Return true if c1 kills c2
    if (c2[2] % 2) {
        console.log("Indestructible");
        return false;
    }
    const c1p = c1[0] / (c1[2] <= 3); // Infinity if Deathtoucher && P > 0
    const c2t = c2[1];
    return c1p >= c2t;
}
const f = (input) => {
    console.log("Match:", input);
    const [c1, c2] = input;
    const f1 = (c1[2] & 2);
    const f2 = (c2[2] & 2);
    if (f2 !== f1) {
        if (f1) {
            if (kills(c1, c2)) {
                console.log("c1 killed c2 in first round");
                return 2;
            }
        } else {
            if (kills(c2, c1)) {
                console.log("c2 killed c1 in first round");
                return 1;
            }
        }
    }
    return kills(c2, c1) + 2 * kills(c1, c2);
};

Yang saya kurangi menjadi perantara ini:

const f = i => {
    const k = (a, b) => !(b[2] % 2) && a[0] / (a[2] <= 3) >= b[1];
    const [c, d] = i;
    const g = c[2] & 2;
    const h = k(c, d);
    const j = k(d, c);
    return d[2] & 2 - g &&
        (g  ? h && 2
            : j && 1
        ) || j + 2 * h
}

Selamat datang di PPCG! Dan solusi pertama yang sangat bagus :) Saya dapat melihat beberapa potensi untuk bermain golf lebih lanjut tetapi saya menggunakan ponsel saya, setelah beberapa gelas bir jadi tidak dapat menguji dengan benar.
Shaggy

Berikut adalah penghematan 7 byte cepat, meskipun: tio.run/##bc/RbsIgFAbg@z0FuxgBd7RwNEu2SPcgjERKtak1ZVHjle/…
Shaggy

@ Shaggy. Yang bagus! Tentu saja operator koma - apa noob saya.
James

1
Kami semua baru sekali :)
Shaggy

3

JavaScript (ES6), 83 76 byte

Mengambil input sebagai 6 argumen berbeda: 2 x (Power, Toughness, Abilities). Kemampuan diharapkan sebagai bitmasks dengan:

  • 1
  • 2
  • 4

0123

(p,t,a,P,T,A)=>(x=A<4&&p>=T|a&!!p)&(y=a<4&&P>=t|A&!!P)&&(a^A)&2?a+2>>1:x*2+y

Cobalah online!

Berkomentar

(p, t, a, P, T, A) => // (p, t, a) = arguments for the first player (P1)
                      // (P, T, A) = arguments for the second player (P2)
  ( x =               // x is a flag which means 'P1 can kill P2',
                      // regardless of the 'First Strike' abilities
    A < 4 &&          // it is set to 1 if P2 is not Indestructible and:
    p >= T |          //   the power of P1 is greater than or equal to the toughness of P2
    a & !!p           //   or the power of P1 is not zero and P1 has the Death Touch
  ) &                 //
  ( y = a < 4 &&      // y is the counterpart of x and is computed the same way
    P >= t |          //
    A & !!P           //
  ) &&                // if both x and y are set
  (a ^ A) & 2 ?       // and exactly one player has the First Strike:
    a + 2 >> 1        //   return 2 if P1 has the First Strike, or 1 otherwise
  :                   // else:
    x * 2 + y         //   return the default outcome: x * 2 + y

3

C (gcc) , 114 113 95 byte

Banyak bermain golf berkat ceilingcat dan Logern.

g(Z{return F&1|F&4&&!(f&4||P<t)||!(f&2)&T>p;}
f(Z{return g(Z+2*g(p,t,f,P,T,F);}

Kompilasi dengan -DZ=P,T,F,p,t,f).

Cobalah online!

Kami memeriksa (secara independen, karena simetri mekanisme pertempuran) apakah masing-masing makhluk selamat dari pertempuran, yang terjadi jika keduanya benar:

  • makhluk itu tidak bisa dihancurkan;
  • makhluk memiliki serangan pertama DAN yang lain tidak DAN kekuatannya lebih besar atau sama dengan kekuatan orang lain (karena itu kita dapat mengabaikan sentuhan kematian orang lain);
  • makhluk lain tidak memiliki sentuhan maut DAN kekuatannya kurang dari ketangguhan kita.

(Kondisi sebelumnya lebih penting).

Inputnya adalah kekuatan dan ketangguhan sebagai bilangan bulat, dan kemampuan sebagai bitfield (1 = Tidak bisa dihancurkan, 2 = Sentuhan maut, 4 = Serangan pertama), outputnya juga merupakan bitfield (1 = Makhluk pertama bertahan, 2 = Makhluk kedua bertahan).


1
Menggunakan makro -DZ=P,T,F,p,t,f) 96 byte-Cobalah secara online!
Logern

Menggunakan P=…alih-alih return …dan menghapus baris baru membawa Anda ke 85 byte.

Juga, -3 byte dengan mengganti operator logika &&, ||dengan bitwise &,|

2

Retina 0.8.2 , 123 byte

\d+
$*
(.*1)(.*;)(.*1)
$3$2$1
F(.*)F
$1
1+D
1
1*(,1+)I
$1
(1+)(F?;1*,)(1+)
$3$2$1
(1*)1*,\1(1+)?
$#2
0(F)?;0(F)?
$#1;$#2
F

Cobalah online! Link meliputi uji kasus, meskipun saya sudah diganti 9untuk 99999untuk kecepatan. Masukan menggunakan huruf DFImeskipun Dharus mendahului I. Output dalam format 1untuk bertahan dan 0untuk mati. Penjelasan:

\d+
$*

Mengkonversi statistik untuk unary.

(.*1)(.*;)(.*1)
$3$2$1

Bertukar statistik sementara.

F(.*)F
$1

Dua Fs membatalkan.

1+D
1

Death Touch menurunkan Ketangguhan lawan menjadi 1.

1*(,1+)I
$1

menurunkan indestructable Daya lawan untuk 0.

(1+)(;1*,)(1+)
$3$2$1

Beralih kembali Ketangguhan, jadi sekarang Anda memiliki P2, T1, F1, P1, T2, F2

(1*)1*,\1(1+)?
$#2

Jika Ketangguhan lebih tinggi dari lawan Daya maka bertahan.

0(F)?;0(F)?
$#1;$#2

Jika kedua akan mati, satu dengan First Strike bertahan.

F

Kalau tidak, First Strike tidak ada bedanya.


1

C ++, 177 131 127 121 byte

Inilah solusi tidak begitu singkat saya di C ++. Kemampuan adalah 3 bit untuk setiap makhluk:

  1. D = 0x1 (0001)
  2. F = 0x2 (0010)
  3. I = 0x4 (0100)

Dan itu hanya mengembalikan 0 : jika mati tidak ada, 1 : jika pertama makhluk mati, 2 : jika mati makhluk kedua dan 3 : jika kedua makhluk mati.

[](int p,int t,int a,int r,int k,int b){return(a&2&&b^4)^(b&2&&a^4)?1+(a&2):((t<r||b&1&&r)&&a^4)+((k<p||a&1&&p)&&b^4)*2;}

Cobalah online!

C ++, 85 81 bytes (Alternatif)

Dengan sedikit kecurangan dan menangkap variabel dalam lambda dan tidak lulus mereka sebagai argumen adalah mungkin untuk turun ke 81 byte. Saya tidak tahu apakah itu solusi yang dapat diterima jadi saya posting sebagai alternatif.

[&]{s=(a&2&&b^4)^(b&2&&a^4)?1+(a&2):((t<r||b&1&&r)&&a^4)+((k<p||a&1&&p)&&b^4)*2;}

Cobalah online!


Ini adalah kode-golf , peretasan seperti itu diharapkan, jika tidak diperlukan, untuk bersaing ... kecuali jika Anda menggunakan bahasa kode-golf yang dibuat khusus, yang sedikit mengubah permainan.
3D1T0R

1

Perl 5, 245 byte

$F[0]*=$F[4]if$F[2]=~/D/;$F[3]*=$F[1]if$F[5]=~/D/;$F[3]=0 if$F[2]=~/I/;$F[0]=0 if$F[5]=~/I/;$F[4]-=$F[0]if$F[2]=~/F/;$F[1]-=$F[3]if$F[5]=~/F/;if($F[1]>0&&$F[4]>0){$F[4]-=$F[0]if$F[2]!~/F/;$F[1]-=$F[3]if$F[5]!~/F/}$_=(0+($F[1]<=0)).(0+($F[4]<=0))

Jalankan dengan -lapE

Tidak Terkumpul:

# Takes input in one lines, of the form:
# PPP TTT "<abilities>" PPP TTT "<abilities>"

$F[0] *= $F[4] if $F[2] =~ /D/;
$F[3] *= $F[1] if $F[5] =~ /D/;

$F[3] = 0 if $F[2] =~ /I/;
$F[0] = 0 if $F[5] =~ /I/;

$F[4] -= $F[0] if $F[2] =~ /F/;
$F[1] -= $F[3] if $F[5] =~ /F/;

if ($F[1] > 0 && $F[4] > 0) {
    $F[4] -= $F[0] if $F[2] !~ /F/;
    $F[1] -= $F[3] if $F[5] !~ /F/;
}

$_ = (0+ ($F[1] <= 0)) . (0+ ($F[4] <= 0));

"Deathtouch" diterjemahkan menjadi "kekuatan Anda sekarang dikalikan dengan ketangguhan musuh Anda", dan "dihancurkan" diterjemahkan menjadi "kekuatan musuh Anda sekarang nol", dengan mengambil preseden yang terakhir. Kode berjalan dua putaran, di mana hanya yang pertama-striker mendapatkan serangan, dan lainnya di mana hanya non-pertama-striker dapat menyerang. Jika hasil putaran pertama di kematian, putaran kedua tidak terjadi. Karena kita sudah ditangani dengan deathtouch dan dihancurkan di awal, "kematian" adalah yang sederhana seperti memeriksa apakah ketangguhan lebih besar dari nol atau tidak.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.