Trouvez le résultat d'un jeu de guerre

15

Trouvez le résultat d'un jeu de guerre

Quand j'étais à l'école primaire, il y avait un jeu "Rock-Paper-Scissors" que nous jouions pendant les assemblées, en attendant notre professeur, à la récréation, etc. Nous l'appelions "Guerre". Après quelques recherches cependant, il s'avère que c'est une variante beaucoup plus simple du "Shotgun Game" (selon WikiHow) . Je vais l'appeler "Guerre" car les règles sont légèrement différentes:

2 personnes sont assises l'une en face de l'autre. Le but du jeu est de "tuer" l'autre joueur. Chaque tour, vous pouvez jouer l'un des 3 coups:

  • Recharger : Vous avez un pistolet qui détient un seul coup. Il doit être rechargé avant de pouvoir être tiré à chaque fois. Le rechargement lorsque vous avez déjà des munitions est légal, mais ne fait rien. Un rechargement était symbolisé en tapant sur vos tempes avec les deux mains. Chaque joueur commence avec 0 munitions.

  • Garde : Le seul mouvement sûr. Si vous êtes abattu alors que vous gardez, vous ne mourrez pas. La garde était symbolisée en croisant vos bras sur votre poitrine.

  • Feu : tirez avec votre arme. Pour réussir le tir, vous devez avoir rechargé depuis le dernier tir. Si votre adversaire recharge, vous gagnez. S'ils tirent également et que vous avez tous les deux des munitions, c'est un match nul. S'ils gardent, vous avez gaspillé les munitions. Bien que tirer sans munitions soit légal, cela ne fait rien et vous rend vulnérable comme le rechargement. Le tir était symbolisé en pointant l'autre joueur.

Cela se jouait de la même manière que le RPS, en ce que chaque joueur rejette simultanément son choix (nous nous tapotions les jambes deux fois entre les tours pour garder le rythme les uns avec les autres, mais ce n'est pas important pour le défi).

Le défi:

Votre tâche est de trouver le résultat d'un jeu de guerre. Il peut s'agir d'une fonction ou d'un programme complet.

Contribution

  • L'option choisie par chaque joueur à chaque tour sera représentée par un caractère / chaîne:

    • r : recharger

    • g : garde

    • f : feu

  • L'entrée sera une liste de paires, une chaîne délimitée / non délimitée ou toute autre chose le long de ces lignes.

Un exemple d'entrée en Python pourrait être [("r", "g"), ("f", "r")], ce qui signifie qu'au premier tour, le premier joueur rechargé et le deuxième joueur gardé. Au deuxième tour, le premier joueur tire, tandis que le deuxième joueur recharge. Le joueur un gagne ce match. Pourrait éventuellement l'entrée même être représentée comme "r g f r", "rgfr", "rg fr" "rg-fr"...

Vous pouvez supposer ce qui suit:

  • La saisie correspondra au format choisi et ne contiendra que des caractères valides.

  • Quelqu'un mourra dans les 100 tours.

Vous ne pouvez cependant pas supposer que les virages se terminent lorsque quelqu'un décède.

Production

Une valeur indiquant qui a gagné (ou qui a gagné en premier *). Vous pouvez choisir les éléments à afficher pour chaque scénario, mais vous devez tenir compte des éléments suivants:

  • Le joueur 1 gagne

  • Le joueur 2 gagne

  • Ils s'entretuent (dessine)

Chaque résultat doit avoir une valeur de district et doit toujours être le même pour chaque scénario.

À titre d'exemple: vous pouvez générer des résultats 1lorsque le joueur 1 gagne, 2lorsque le joueur 2 gagne et 0en cas d'égalité. Vous devez ensuite toujours sortir 1lorsque le joueur 1 gagne, 2lorsque le joueur 2 gagne et 0en cas d'égalité.

Il peut être retourné ou imprimé sur la sortie standard. La fin des espaces blancs est très bien.

Juste pour que ce soit clair, le seul scénario qui mène à un match nul est si les deux joueurs tirent, et les deux ont des munitions.

*Étant donné que dans ce défi, les tours peuvent continuer après la mort de quelqu'un, il est possible que plus d'un joueur gagne finalement. Vous devez trouver qui a gagné en premier selon l'entrée.

Cas de test (en supposant 1que P1 gagne, 2lorsque P2 gagne et 0pour un match nul):

"rg fr" => 1 (P1 shot P2 while they were reloading)

"rg ff" => 1 (They both shot, but only P1 had ammo)

"rr ff" => 0 (Both had ammo and shot each other)

"rr ff rr fg" => 0 (Both had ammo and shot each other. Everything after the first win is ignored)

"rr fg rf" => 2 (P2 shot P1 while they were reloading)

"rf gg rr fg rr fr" => 1
    (P2 tried to shoot but didn't have any ammo, then they both guarded, then they both reloaded, then P2 blocked a shot, then they both reloaded again [but P2 still only has 1 ammo!], then P1 shoots P2 while they're reloading.

"rr gf fr rf gg rg ff" => 1
       ^ Player 1 wins here. The rest to the right has no effect on the output

C'est du golf de code, donc le plus petit nombre d'octets gagne!

Notez que, comme le montrent les cas de test, vous devez gérer les mouvements "stupides". Il est parfaitement valable pour un joueur d'essayer de tirer lorsqu'il n'a pas de munitions, ou de recharger 2 tours de suite (et d'accumuler une seule munition).

Carcigenicate
la source
Suis-je en train de manquer quelque chose ou la sortie peut-elle être déterminée uniquement à partir du dernier tour?
xnor
@Mis à jour la question. Et non, puisque vous devez savoir si un joueur a des munitions ou non. Je me rends compte cependant que vous pouvez supposer quel joueur a des munitions en fonction du fait que c'est le dernier tour. En fait, j'ai changé les règles à la dernière minute, ce qui a permis de supposer que l'entrée prendrait fin lorsque quelqu'un mourrait. Je le regrette maintenant.
Carcigenicate
Continuons cette discussion dans le chat .
xnor
3
C'est très similaire à marquer un jeu de charge, de défense et de tir . Les seules différences sont que l'autre défi a des armes à feu avec plus d'un coup et que tirer avec une arme vide est considéré comme de la triche et perd le jeu.
Dennis
Pouvons-nous prendre deux entrées distinctes pour deux joueurs au lieu de tours, par exemple {"rff","rgf"}?
betseg

Réponses:

2

Rétine , 36 octets

s`(?<=r..([^f]..)*)f
!
A`g
G1`!
\w
_

Le format d'entrée doit être des paires séparées par des sauts de ligne, par exemple

rr
fr

La sortie est le !_joueur 1 gagne, _!si le joueur 2 gagne et !!s'il y a match nul.

Essayez-le en ligne! (Une suite de tests qui utilise la séparation d'espace pour plus de commodité.)

J'ai dû complètement ignorer ce défi. Je suis sûr que j'aurais essayé cela à Retina plus tôt sinon. :)

Explication

s`(?<=r..([^f]..)*)f
!

Nous commençons par marquer les plans "valides" en transformant le premier faprès chacun ren !. Nous le faisons en faisant correspondre chacun d' fentre eux qui peut trouver un rsur le même joueur sans en croiser un autre f. Limiter la recherche à rs sur le même joueur est facile en faisant toujours trois caractères à la fois.

A`g

Maintenant, nous rejetons tous les tours dans lesquels quelqu'un s'est gardé, car le tour de fin ne peut pas être l'un d'entre eux.

G1`!

Maintenant, nous ne gardons que le premier tour qui contient un !. Si un tir valide se produit (et nous savons que personne ne garde), le jeu se termine.

\w
_

Enfin, nous devons consolider la chaîne pour donner des sorties cohérentes, et nous le faisons simplement en transformant les non- !caractères (soit rou f) en _.

Martin Ender
la source
5

Python, 139 octets

c=d=0
for i in input():
 b=(c&(i=='fr'))-(d&(i=='rf'));p,q=i
 if b|(i=='ff')&c&d:print b;break
 c,d=(p=='r',i!='fg')[c],(q=='r',i!='gf')[d]

Prend l'entrée sur stdin sous la forme d'une liste de chaînes de 2 caractères (par exemple. ['Rf', 'rr', 'rg', 'ff']). Génère 1 si le joueur 1 gagne, -1 si le joueur 2 gagne et 0 pour un match nul.

Explication: Vérifiez d' abord si quelqu'un a tiré une balle, si c'est le cas, le jeu se termine. Ensuite, nous déterminons si les joueurs ont rechargé leurs armes ou gaspillé leurs munitions.

Ceci est mon premier article sur codegolf :)

accro aux mathématiques
la source
4

JavaScript (ES6), 108 107 93 91 89 85 octets

Enregistré 4 octets avec l'aide de Titus

Prend l'entrée comme un tableau de chaînes de 2 caractères décrivant les mouvements joués par chaque joueur.

b=>b.map(c=>w=w||b&'312'[b=(s='0210231')[m='ffrfgrrggf'.search(c)]|s[m-2]&b,m],w=0)|w

Retour:

  • 1 si le joueur 1 gagne
  • 2 si le joueur 2 gagne
  • 3 pour un match nul

Comment ça fonctionne

Nous maintenons un masque de bits bdécrivant qui a une balle chargée:

  • bit # 0: le joueur 1 a une balle
  • bit # 1: le joueur 2 a une balle

Nous utilisons la séquence De Bruijn 'ffrfgrrggf' pour identifier les 9 combinaisons possibles de mouvements. Nous utilisons des bitmasks OR et AND pour mettre à jour en bfonction de la combinaison de mouvements. Nous utilisons un troisième ensemble de bitmasks qui sont ET bpour déterminer le gagnant w. (Les trois seules combinaisons gagnantes étant ff, fret rf.)

Il convient de noter que les masques OR et AND peuvent être stockés avec le même motif, décalés de deux positions.

 Index in | Combination | Bullet   | Bullet  | Winner
 sequence |             | AND mask | OR mask | mask
----------+-------------+----------+---------+--------
    0     |     ff      |    0     |    0    |   3
    1     |     fr      |    0     |    2    |   1
    2     |     rf      |    0     |    1    |   2
    3     |     fg      |    2     |    0    |   0
    4     |     gr      |    1     |    2    |   0
    5     |     rr      |    0     |    3    |   0
    6     |     rg      |    2     |    1    |   0
    7     |     gg      |    3     |    0    |   0
    8     |     gf      |    1     |    0    |   0

Cas de test

Arnauld
la source
@Carcigenicate Cela devrait être corrigé pour les deux cas défaillants. Cependant, je reviens maintenant 0(personne n'a été abattu) ou 3(les joueurs s'entretuent) en cas d'égalité. Je ne sais pas si cela est autorisé. Sinon, je peux revenir à la w%3place.
Arnauld
Je voulais 1 sortie par scénario. Je garantis cependant que quelqu'un sera toujours abattu, il n'est donc pas nécessaire de rendre compte de ce cas. Le seul cas menant à un match nul est lorsque les deux se tirent dessus et que les deux ont des munitions.
Carcigenicate
Le &masque peut être 0 pour fr,rf,ff. '312'['0210231'[m='ffrfgrrggf'.search(c)]|'233331'[m-3]&b]ou '123'['2100231'[m='frffgrrggf'.search(c)]|'233331'[m-3]&b]enregistrez un octet; mais fonctionnent-ils?
Titus
@Titus Fait intéressant, l'application du masque OU avant le masque ET fonctionnerait pour tous les cas de test existants. Mais cela échouerait pour quelque chose comme["rr","fg","fr","rf"]
Arnauld
&a une priorité plus élevée que |, donc changer l'ordre ne devrait rien y changer (à part sauvegarder l'octet). Mais la mission manquait dans mon code. Essayez ...'123'[b='2100231'....
Titus
2

Perl 6 , 71 62 octets

{&[<=>](|map {m/r[..[r|g]]*.$^f/.to//∞},/[r|f]f/,/.f[r|f]/)}

Solution basée sur Regex.

Prend l'entrée sous forme de chaîne dans le formulaire "rg fr".
Les trois sorties possibles sont les valeurs ENUM More(joueur 1 won), Less(joueur 2 won), Same(tirage au sort) - qui se transforment en ces mots lors de l' impression, ou dans 1, -1, 0quand sous la contrainte aux chiffres.

Essayez-le en ligne!

Comment ça fonctionne

  • map { m/r[..[r|g]]*.$^f/.to // ∞ }, /[r|f]f/, /.f[r|f]/

    Effectue deux correspondances d'expression régulière sur l'entrée. Après interpolation, les deux expressions régulières sont:

    • r[..[r|g]]*.[r|f]f - Correspond au premier tir réussi du joueur 2.
    • r[..[r|g]]*..f[r|f] - Correspond au premier tir réussi du joueur 1.

    Dans chaque cas, il renvoie la position finale de la correspondance ( .to), ou l'infini s'il n'y a pas de correspondance.

  • &[<=>](|   )

    Applique l' <=>opérateur aux deux positions finales de correspondance. Elle retourne une valeur dans la Orderenum ( More, Less, ou Same), selon que le premier argument est supérieur, inférieur ou égal au second.

smls
la source
Soigné. Par curiosité, comment tapez-vous le symbole de l'infini? Clavier spécial, ou tapez-vous alt + some number? Et utilisez-vous réellement des caractères comme celui-ci dans le code Perl commun, ou est-ce juste pour le golf?
Carcigenicate
@Carcigenicate: Mon schéma de clavier personnalisé me permet de le saisir en appuyant sur les quatre touches [Menu] i n f(cela s'appelle une séquence de composition ). Cependant, tous les symboles Perl 6 ont des versions ASCII - par exemple Infet sont des synonymes - il n'est donc pas nécessaire d'utiliser des symboles Unicode dans le code Perl 6. Je l'aime juste ... :)
smls
Ahh. C'est une chose qui m'a jeté sur Perl était le symbole de l'infini. Je pensais que c'était une exigence, qui semblait inutilement compliquée. Peut-être que lorsque je m'ennuierai de Clojure, j'essaierai Perl. J'ai vu beaucoup de code Perl récemment.
Carcigenicate
@Carcigenicate: sachez que Perl 6 est fondamentalement un nouveau langage qui n'est pas rétrocompatible avec Perl, et son interprète est toujours lent (et pour certaines fonctionnalités, bogué). Perl, actuellement à la version v5.24, continue d'être géré séparément.
smls
OK merci. Bon à savoir.
Carcigenicate
2

Haskell , 101 91 87 octets

n!(c:r)|'g'>c=n:1!r|'g'<c=1:0!r|1<3=2:n!r
_!r=[]
a#b=[x|x@(y,z)<-zip(1!a)$1!b,2>y+z]!!0

Essayez-le en ligne! La fonction infixe #prend deux chaînes représentant les actions de chacun des deux joueurs et retourne (0,1)si le joueur 1 gagne, (1,0)pour le joueur 2 et (0,0)pour un match nul.

Exemple d'utilisation:

Prelude> "rgrfrf" # "fgrgrr"
(0,1)

Explication:

La fonction infixe !traduit une séquence d'actions 'r'(rechargement), 'f'(feu) et 'g'(garde) en une séquence d'actions observables 0(feu réel), 1(aucune action) et 2(garde), où une action incendie n'est comptée que comme une action incendie réelle si une balle est chargée, et comme aucune action sinon. Pour y parvenir, le premier argument nest de savoir 0si une balle est chargée et 1si le pistolet n'est pas chargé. De cette façon, chacun 'f'peut simplement être remplacé par le courant n. ( n=0-> chargé -> feu réel -> 0, n=1-> déchargé -> aucune action -> 1)

n ! (c:r)                -- n is 0 or 1, c is 'f', 'g' or 'r' and r the rest of the string
    |'g'>c = n : (1 ! r) -- c is smaller 'g', so it must be 'f'. append n to the list
                         --  and set load status to 1 (unloaded)
    |'g'<c = 1 : (0 ! r) -- c is larger 'g', so it must be 'r'. append 1 (no action)
                         --  and set load status to 0 (loaded)
    |1<3   = 2 : (n ! r) -- c must be equal to 'g'. append 2 (guard)
                         --  and leave the load status unchanged
_ ! r = []               -- base case for recursion

Les neuf possibilités qui en résultent sont alors

  • (0,0): Les deux joueurs tirent et meurent, la partie se termine.
  • (0,1)ou (1,0): Un joueur tire sur l'autre, la partie se termine.
  • (0,2)ou (2,0): Un joueur tire mais les autres gardes, le jeu continue.
  • (1,1), (1,2), (2,1)Ou (2,2): Aucun joueur tire, jeu continue.

Par conception, la somme des options de fin de jeu est inférieure à 2 et la somme de chaque possibilité de poursuite de jeu est supérieure ou égale à 2. Le résultat du jeu est alors le premier tuple avec une somme inférieure à 2.

a#b=[x|         -- build the list of all x
    x@(y,z) <-  -- where x is an alias for the tuple (y,z) which is drawn from the list
    zip (1!a)   -- of tuples where the first component is from 1!a = eg. [1,2,1,0,1,0] 
        (1!b)   -- and the second from 1!b = eg. [1,2,1,2,1,1]
    , 2 > y+z]  -- and y+z are smaller 2.
    !!0         -- return the first element of this list
Laikoni
la source
1

Lot, 249 octets

@echo off
set g=goto gg
set/ax=y=0
:gg
shift&goto %1
:fg
set x=0
%g%
:gf
set y=0
%g%
:rr
set/ax=y=1
%g%
:fr
if %x%==1 exit/b1
:gr
set y=1
%g%
:rf
if %y%==1 exit/b2
:rg
set x=1
%g%
:ff
set/az=3-x-x-y
if %z%==3 %g%
exit/b%z%

L'entrée se présente sous la forme de paires de caractères pour chaque tour et les sorties par niveau d'erreur (0 = match nul, 1 = joueur 1, 2 = joueur 2). xet ygardez une trace de si le joueur a des munitions, donc quand les deux tirent, le résultat est 3-x-x-y, à moins que ce ne soit 3, auquel cas nous continuons. À la ligne 5, j'abuse l'analyseur syntaxique de Batch - %1(qui est le mouvement en cours) est substitué avant que l' shiftinstruction ne s'exécute et ne la supprime, donc nous allons toujours à la bonne étiquette.

Neil
la source
1

Clojure, 168 octets

#(reduce(fn[[l L r R][a A]](if(and l L)(let[M(fn[r a A](if(and(= a \f)r)[nil(= A \g)][(or(= a \r)r)1]))[r L](M r a A)[R l](M R A a)][l L r R])[l L r R]))[1 1 nil nil]%)

Moins de golf (si les deux personnes sont en vie, nous utilisons Mpour mettre à jour leurs munitions et l'état de vie de l'ennemi, sinon nous retournons le statut actuel):

(def f (fn[A] (reduce
                (fn [[l1 l2 r1 r2] [a1 a2]]
                  (if (and l1 l2)
                    (let[M (fn [r1 a1 a2]
                             (if (and(= a1 \f)r1)
                               [false (= a2 \g)]        ; we lost the ammo, a2 lives if he was guarding
                               [(or(= a1 \r)r1) true])) ; we might gain or keep ammo, a2 lives no matter what
                         [r1 l2] (M r1 a1 a2)
                         [r2 l1] (M r2 a2 a1)]
                      [l1 l2 r1 r2])
                    [l1 l2 r1 r2]))
                [true true false false] A)))

Exemple d'utilisation (le premier élément indique si le joueur 1 est vivant à la fin du jeu, le deuxième élément indique si le joueur 2 est vivant, les 3e et 4e indiquent le statut des munitions qui n'est pas pertinent pour déterminer le gagnant):

(-> (for[[a b s] (partition 3 "rr fg rf fr ")][a b]) f (subvec 0 2))

Mise à jour: Eh bien regardez ça, cela loopa une longueur identique! Je trouve la reduceversion plus facile à développer car vous pouvez facilement inspecter les états intermédiaires si vous utilisez reductions.

#(loop[l 1 L 1 r nil R nil[[a A]& I]%](if(and l L)(let[M(fn[r a A](if(and(= a \f)r)[nil(= A \g)][(or(= a \r)r)1]))[r L](M r a A)[R l](M R A a)](recur l L r R I))[l L]))
NikoNyrh
la source
J'attendais! C'est dense, wow.
Carcigenicate
Hehe merci, ça m'ennuie encore de devoir répéter [l1 l2 r1 r2](ses valeurs modifiées à letet ses valeurs d'origine) et ces fnsignatures.
NikoNyrh
Du moins pour ce dernier, c'est pourquoi je privilégie loop. Je trouve que cela conduit à un code plus net. Dès que j'ai besoin de plier avec plus d'un accumulateur, je change.
Carcigenicate
1

PHP, 107 101 90 octets

en utilisant un masque de bits $ d pour l'état de chargement et une séquence DeBruijn pour les mouvements de tir.

for(;!$x=$d&strpos(_frff,$m=$argv[++$i]);)$d=$d&g<$m|h<$m|2*($d/2&f<$m[1]|g<$m[1]);echo$x;

prend l'entrée comme arguments de ligne de commande à 2 caractères, exécutez avec -nr.

1 = le joueur 1 gagne
2 = le joueur 2 gagne
3 = match nul

panne

for(;!$x=$d&strpos(_frff,       // 1. $x=someone dies, loop while not
    $m=$argv[++$i]          // loop throug moves
);)
    $d=
        $d&g<$m|h<$m            // 2. unload/reload Player 1 = bit 0
    |2*(
        $d/2&f<$m[1]|g<$m[1]    // 3. unload/reload Player 2 = bit 1
    );
echo$x;
  • Séquence DeBruijn fr:: position = 1 = P1 se déclenche; rf= position 2 = feux P2, ff= position 3 = les deux feux
  • g<$m<=> f<$m[0]( f<$mest toujours vrai, car il y a un deuxième caractère).
Titus
la source
0

Python, 200 octets

def war_game(turns):
    turn=0
    player1=True
    player2=True
    ammo1=False
    ammo2=False
    while turn<len(turns):
        if turns[turn][0]=='f' and ammo1==True and turns[turn][1]!='g':
            player2=False
        elif turns[turn][0]=='f' and turns[turn][1]=='g':
            ammo1=False
        elif turns[turn][0]=='r':
            ammo1=True
        if turns[turn][1]=='f' and ammo1==True and turns[turn][0]!='g':
            player1=False
        elif turns[turn][1]=='f' and turns[turn][0]=='g':
            ammo2=False            
        elif turns[turn][1]=='r':
            ammo2=True
        if player2==False or player1==False:
            break
        turn+=1
    if player1==True and player2==False:
        print('Player 1 wins')
        return 1
    elif player1==False and player2==True:
        print('Player 2 wins')
        return 2
    print('Draw')
    return 0
Galo
la source
2
Bienvenue sur le site. Le concours est marqué en nombre d'octets, donc je recommanderais d'inclure un nombre d'octets dans votre titre et d'essayer de le minimiser en réduisant la longueur des noms de variables. Vous devez également inclure la langue dans laquelle vous avez écrit ceci (ressemble à Python3 pour moi).
Post Rock Garf Hunter
2
Comme mentionné ci-dessus, il s'agit d'un concours qui peut rendre le plus petit programme possible pour accomplir la tâche. Vous utilisez des noms complets comme turnsau lieu de simplement t, ce qui signifie que le programme est beaucoup plus grand que nécessaire. Veuillez également commencer votre soumission avec quelque chose comme #Python 2, 200 bytes(en supposant que ce soit 2 et que le programme est de 200 octets) afin que la langue que vous utilisez soit claire.
Carcigenicate
0

Clojure, 180 173 octets

(fn[t](loop[z nil x nil[[c v]& r]t](let[k #(and %3(= %\f)(not= %2\g))h #(and(not= %\f)(or %2(= %\r)))q(k v c x)w(k c v z)](cond(and q w)0 q 2 w 1 1(recur(h c z)(h v x)r)))))

-7 octets en changeant la fonction en fonction complète au lieu d'utiliser une macro. Cela m'a permis de créer les macros des fonctions internes, ce qui économise un peu.

Il s'agit d'une solution très littérale. Je suis un peu bloqué depuis que je viens d'écrire une version complète du jeu, et c'est essentiellement une version considérablement allégée de l'algorithme que j'ai utilisé. Il y a probablement beaucoup d'optimisations que je pourrais faire, mais j'en suis assez satisfait. Voir le code pré-golfé pour l'explication.

(defn outcome [turns] ; Take input as ["rr" "ff"]
  (loop [p1-ammo? false ; Keep track of if each player has ammo
         p2-ammo? false
         [[p1-move p2-move] & rest-turns] turns] ; Deconstruct the turns out

    (let [killed? (fn [m m2 a] (and a (= m \f) (not= m2 \g))) ; Function that checks if one player killed the other
          has-ammo? (fn [m a] (and (not= m \f) (or a (= m \r)))) ; Function that decides if a player has ammo in the
                                                                 ;  next turn
          p1-killed? (killed? p2-move p1-move p2-ammo?) ; Check if each player was killed.
          p2-killed? (killed? p1-move p2-move p1-ammo?)]

      (cond ; Check who (if any) died. If no one died, recur to next turn.
        (and p1-killed? p2-killed?) 0
        p1-killed? 2
        p2-killed? 1
        :else (recur (has-ammo? p1-move p1-ammo?)
                     (has-ammo? p2-move p2-ammo?)
                     rest-turns)))))
Carcigenicate
la source