Magie: Der Sammelkampf mit Fähigkeiten

16

verbunden

Tor:

Bei zwei Kreaturen mit optionalen Kampffähigkeiten werden eindeutige, aber konsistente Werte zurückgegeben, die angeben, welche Kreaturen gegebenenfalls gestorben sind.

Eingang:

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

Jede Kreatur wird in der Form von gegeben [P,T,"<abilities>"]. Es wird in der Form sein [P,T], [P,T,""]oder [P,T,0]wenn es keine Fähigkeiten hat, deine Wahl in der Form. P ist eine ganze Zahl> = 0, T ist eine ganze Zahl> = 1. <abilities>ist eine Teilmenge von "DFI"oder kann auf Wunsch über eine einzelne Zahl / Bitfolge dargestellt werden. Die Reihenfolge der Flaggen liegt ebenfalls bei Ihnen.

Kampfmechanik:

Jede Kreatur hat zwei Werte, Kraft und Zähigkeit in dieser Reihenfolge und optionale Fähigkeiten. Die Stärke einer Kreatur ist> = 0. Die Zähigkeit einer Kreatur ist> = 1.

Jede Kreatur fügt der gegnerischen Kreatur gleichzeitig Schaden in Höhe ihrer Stärke zu (es sei denn, man hat einen Erstschlag ausgeführt). Wenn der Wert größer oder gleich der Zähigkeit des Gegners ist, stirbt er (sofern er nicht unzerstörbar ist).

Beispiel: Alice ist a 2/2, Bob ist a 3/4, beide ohne Fähigkeiten. Alice fügt Bob 2 Schadenspunkte zu und erhält 3 Schadenspunkte zurück. Alice's Zähigkeit ist 2, also wird es sterben, Bob's Zähigkeit ist 4, also wird es leben.

Es gibt nur 3 optionale Fähigkeiten, die wir berücksichtigen werden (obwohl es mehr im Spiel gibt). Dies werden Ein-Zeichen-Flags sein:

  • [D] eathtouch: Jeder Schaden (X> 0) gilt als tödlich.
  • [F] irst Strike: Verursacht zuerst seinen Schaden und kann die andere Kreatur töten, bevor sie zurückgreifen kann. Wenn beide Kreaturen einen Erstschlag haben, löse den Kampf wie gewohnt.
  • [I] unzerstörbar: Keine Schadensmenge gilt als tödlich, einschließlich Todesberührung.

Ausgabe:

Beliebiger konsistenter Wert für jeden der folgenden vier Fälle. Geben Sie bitte die vier Werte in Ihrer Antwort an. Beispiel für einen Rückgabewert in Parens:

  • Keine der Kreaturen ist gestorben (0)
  • 1. Kreatur gestorben (1)
  • 2. Kreatur gestorben (2)
  • Beide Kreaturen starben (3)

Regeln:

  • Bei der Eingabe sind garantiert zwei korrekt formatierte Kreaturen vorhanden.
  • Wenn Sie Charaktere für Fähigkeiten verwenden, können Sie davon ausgehen, dass diese nach Ihren Wünschen sortiert sind. Geben Sie jedoch gegebenenfalls die verwendete Reihenfolge an.
  • Wenn Sie eine Zahl / Bitfolge für Fähigkeiten verwenden, geben Sie an, welche Codierung Sie verwenden. zB: 111ist D/F/I, 7ist D/F/I, etc.
  • Wenn eine Kreatur keine Fähigkeiten besitzt, kann sie auch als [P,T, ""]oder in der entsprechenden Anzahl genommen werden
  • Standardschlupflöcher verboten
  • Das ist also gewinnt der kürzeste Code.

Beispiele:

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
Veskah
quelle
1
@ user71546 Ja. Es gibt ein bisschen mehr Regeln, aber in MtG ist "Can'ts" wichtiger als "Cans". So funktionell, ignoriert Indestructible Deathstrike. Bearbeitet, um genauer zu sein
Veskah
1
@ fəˈnəˈtɛk, es nimmt immer noch Schaden, es stirbt einfach nicht daran. Wohlgemerkt, die Frage stellt auch die Regel falsch. Es sollte " [unzerstörbar] bleibende Karten werden nicht durch tödlichen Schaden zerstört, und sie ignorieren die auf tödlichen Schaden basierende Aktion ".
Peter Taylor
4
" Wenn eine Kreatur keine Fähigkeiten hat, muss sie als [P, T] analysiert werden. [P, T," "] ist ungültig " ist eine schlechte Regel. Es diskriminiert Sprachen mit starker Typisierung ohne Nutzen.
Peter Taylor
2
@PeterTaylor Ich möchte gezackte Arrays behalten, aber Sie haben Recht, dass es nicht besser wird. Daher wurde die Regel entfernt
Veskah
1
@Veskah Kann ich "D", "F", "I" als Zahlen verwenden? D => 0, F => 1, I => 2
Luis Felipe De Jesus Munoz

Antworten:

6

Perl 5 , 248 Bytes

... ohne Leerzeichen und Zeilenumbrüche:

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 }

Probieren Sie es online!

Meine ungolfed Version mit den zehn Tests von @Veskah (OP) besteht die folgenden Tests:

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
Kjetil S.
quelle
4

JavaScript, 137 125 120 111 Bytes

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)

Ich benutze Bitmap-Nummern für Fähigkeiten D = 4 F = 2 I = 1 "DFI"wäre 7. Meine Ausgabe ist Weder Gestorben 0, 1. Gestorben 1, 2. Gestorben 2, Beide sind gestorben 3.

Tests mit:

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)

Dies war mein erster Arbeitscode

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

Was ich auf dieses Zwischenprodukt reduziert habe:

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
}
James
quelle
Willkommen bei PPCG! Und sehr schöne erste Lösung :) Ich sehe ein gewisses Potenzial für weiteres Golfen, aber ich bin auf meinem Handy, nach ein paar Bier, kann es also nicht richtig testen.
Shaggy
Hier ist eine schnelle Einsparung von 7 Byte: tio.run/##bc/RbsIgFAbg@z0FuxgBd7RwNEu2SPcgjERKtak1ZVHjle/…
Shaggy
@Zottelig. Schön! Natürlich der Kommaoperator - was für ein Noob ich bin.
James
1
Wir waren alle einmal neu :)
Shaggy
3

JavaScript (ES6), 83-76 Byte

Nimmt Eingaben als 6 verschiedene Argumente auf: 2 x (Kraft, Zähigkeit, Fähigkeiten). Fähigkeiten werden als Bitmasken erwartet mit:

  • 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

Probieren Sie es online!

Kommentiert

(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
Arnauld
quelle
3

C (GCC) , 114 113 95 Bytes

Viel Golf dank Ceilingcat und 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);}

Kompilieren mit -DZ=P,T,F,p,t,f).

Probieren Sie es online!

Wir überprüfen (unabhängig, aufgrund der Symmetrie der Kampfmechanik), ob jede der Kreaturen den Kampf überlebt. Dies geschieht, wenn eine der beiden Bedingungen erfüllt ist:

  • die Kreatur ist unzerstörbar;
  • die Kreatur hat den ersten Schlag UND die andere nicht UND ihre Kraft ist größer oder gleich der Härte der anderen (daher können wir die Todesberührung der anderen ignorieren);
  • andere Kreaturen haben keine Todesberührung UND ihre Kraft ist geringer als unsere Zähigkeit.

(Die früheren Bedingungen sind wichtiger).

Die Eingaben sind Kraft und Zähigkeit als ganze Zahlen und Fähigkeiten als Bitfeld (1 = unzerstörbar, 2 = Todesberührung, 4 = Erstschlag), die Ausgabe ist auch ein Bitfeld (1 = Erste Kreatur überlebt, 2 = Zweite Kreatur überlebt).

Max Yekhlakov
quelle
1
Verwenden eines Makros -DZ=P,T,F,p,t,f) 96 Bytes-Probieren Sie es online!
Logern
Verwenden P=…statt return …und das Newline Entfernen führt zu 85 Byte.
Auch -3 Bytes durch logische Operatoren ersetzt &&, ||mit bitweise &,|
2

Retina 0.8.2 , 123 Bytes

\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

Probieren Sie es online! Link enthält Testfälle, obwohl ich ersetzt habe 9für 99999für die Geschwindigkeit. Eingabe verwendet die Buchstaben DFIobwohl Dmuss precede I. Die Ausgabe erfolgt im Format 1für Überlebende und 0für Dies. Erläuterung:

\d+
$*

Konvertieren Sie die Statistiken in unary.

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

Tauschen Sie die Statistiken vorübergehend aus.

F(.*)F
$1

Zwei Fs streichen aus.

1+D
1

Todesberührung senkt die Zähigkeit des Gegners auf 1.

1*(,1+)I
$1

Unzerstörbar verringert die Kraft des Gegners auf 0.

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

Schalten Sie die Zähigkeit zurück, so dass Sie jetzt P2, T1, F1, P1, T2, F2 haben

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

Wenn die Zähigkeit höher ist als die Stärke des Gegners, überlebt sie.

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

Wenn beide sterben würden, überlebt der mit First Strike.

F

Ansonsten macht First Strike keinen Unterschied.

Neil
quelle
1

C ++, 177 131 127 121 Bytes

Hier ist meine nicht so kurze Lösung in C ++. Fähigkeiten sind 3 Bits für jede Kreatur:

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

Und es gibt einfach 0 zurück : wenn niemand stirbt, 1 : wenn die ersten Kreaturen sterben, 2 : wenn die zweiten Kreaturen sterben und 3 : wenn beide Kreaturen sterben.

[](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;}

Probieren Sie es online!

C ++, 85 81 Bytes (alternativ)

Durch leichtes Betrügen und Erfassen der Variablen in Lambda, ohne sie als Argumente zu übergeben, können 81 Byte erreicht werden. Ich weiß nicht, ob das eine akzeptable Lösung ist, also poste ich sie als Alternative.

[&]{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;}

Probieren Sie es online!

DimChtz
quelle
Dies ist Code-Golf . Solche Hacks werden erwartet, wenn sie nicht benötigt werden, um am Wettbewerb teilzunehmen ... es sei denn, Sie verwenden speziell entwickelte Code-Golf-Sprachen, die das Spiel ein wenig verändern.
3D1T0R
1

Perl 5, 245 Bytes

$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))

Laufen Sie mit -lapE

Ungolfed:

# 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));

"Todesberührung" bedeutet "Ihre Kraft wird jetzt mit der Zähigkeit Ihres Feindes multipliziert", und "unzerstörbar" bedeutet "die Kraft Ihres Feindes ist jetzt Null", wobei letzteres Vorrang hat. Der Code führt zwei Runden aus, eine, in der nur die Erstschlagenden angreifen können, und die andere, in der nur Nicht-Erstschlagende angreifen können. Wenn die erste Runde zum Tod führt, findet die zweite Runde nicht statt. Da wir uns bereits zu Beginn mit der Todesberührung befasst haben und unzerstörbar sind, ist "Tod" so einfach wie die Überprüfung, ob die Zähigkeit größer als Null ist oder nicht.

Silvio Mayolo
quelle