Bots de code 3: Antipatterns de programmation parallèle

13

Nous saluons le retour! Je suis ravi de présenter le 3e défi CodeBots. Celui-ci a été longtemps en préparation. Ce défi sera divisé en 3 sections: la version courte, la version longue et des détails supplémentaires.

La version courte

Chaque concurrent écrira un programme de 24 commandes. Ces bots se déplaceront dans le monde entier et copieront leur code dans d'autres bots, tout en essayant d'empêcher d'autres bots de faire de même. L'une des commandes possibles est le no-op Flag. Si un bot a plus de vous Flagque n'importe quel autre bot Flag, vous obtenez un point. Vous gagnez en ayant le plus de points.

Tout ce qui précède était vrai pour les deux derniers défis. Cette fois-ci, les bots pourront exécuter plusieurs lignes de code en même temps.

La version longue

L'API

Chaque bot aura exactement 24 lignes, chaque ligne étant au format suivant:

$label command parameters //comments

Les étiquettes et les commentaires sont facultatifs et chaque commande a un nombre différent de paramètres. Tout est insensible à la casse.

Paramètres

Les paramètres sont saisis et peuvent être dans les formats suivants:

  1. Une valeur de 0 à 23.
  2. Une variable: A, B, C,D
  3. Une valeur utilisant l'addition: A+3ou2+C
  4. Une ligne de code, qui est désignée à l'aide du #signe ( #4représenterait la 5ème ligne, tandis #C+2que représenterait la ligne calculée par C+2).
  5. Vous pouvez utiliser un $labelau lieu de désigner une ligne de code.
  6. Variable ou ligne de code de votre adversaire, désignée par * . Votre adversaire est le bot du carré auquel vous faites face. ( *Breprésente la Bvaleur de votre adversaire , tandis que *#9représente la 10ème ligne de votre adversaire). S'il n'y a personne dans ce carré, la commande n'est pas exécutée.

Commandes

Déplacer V

Déplace le bot North+(V*90 degrees clockwise) . Le mouvement ne change pas de direction.

Tournez V

Transforme le bot V*90 degrees dans sens horaire.

Copier VW

Des copies tout ce qui est en Ven W. Si Vest un numéro de ligne, alors Wdoit être un numéro de ligne. Si Vest une variable ou une valeur, alorsW doit être une variable.

Drapeau

Ne fait rien.

Star de télévision

Démarre un nouveau thread attaché à la variable V. Immédiatement, et à chaque tour futur, le thread exécutera la commande en ligneV .

Si Vest déjà attaché à un thread, alors cette commande est un no-op. S'il Vs'agit d'une variable d'un adversaire, l'adversaire commencera un thread attaché à cette variable.

Arrêter V

Arrête le fil attaché à la variable Và la fin de ce tour.

Lock V

Empêche la ligne ou la variable Vd'être utilisée de quelque manière que ce soit, sauf par le thread qui a appelé Lock. Un appel ultérieur à Lockpar le même thread se déverrouille V. Les verrous ne peuvent pas être appelés sur les variables ou les lignes de l'adversaire.

Si Cond VW

Cela va tester Cond. Si la condition est vraie, elle déplacera le pointeur du thread vers le numéro de ligne V, sinon vers le numéro de ligne W. Cette ligne sera alors immédiatement exécutée.

Les conditions peuvent être X=Y, X<Y, !Xou ?X:

  1. X=Y teste si deux lignes sont du même type et du même bot, ou vous testez si deux valeurs égalent le même montant.
  2. X<Yteste si la valeur de Xest inférieure à Y.
  3. !Xteste si la variable ou la ligne Xest verrouillée (renvoie vrai si verrouillé)
  4. ?X teste si une variable donnée a un thread attaché

Détails supplémentaires

Interactions multithread

Les actions du même type sont exécutées en même temps. Les actions sont exécutées dans l'ordre suivant:

  1. Fermer à clé. Si plusieurs threads tentent de verrouiller une variable, ils échoueront tous. Si un thread déverrouille une variable alors qu'un autre tente de la verrouiller, la variable reste déverrouillée.

  2. Début. Si plusieurs threads tentent de démarrer un thread sur une variable, cela comptera comme un seul démarrage.

  3. Copie. Si deux threads copient tous les deux dans la même variable, la variable se terminera comme une valeur aléatoire. S'ils copient tous les deux sur la même ligne, aucun ne fonctionnera. Si un thread copie dans la même variable à partir de laquelle un autre thread copie, alors ce dernier thread copiera une valeur aléatoire. Si deux threads copient tous les deux à partir de la même variable, ils fonctionneront tous les deux correctement.

  4. Si. Tous les conditionnels seront testés simultanément, puis les variables de thread seront mises à jour après. L'exécution d'un Ifpeut entraîner l'ajout d'une action avec une priorité plus élevée. Les actions avec une priorité plus élevée seront exécutées avant de passer après le If, tandis que les actions avec une priorité plus faible seront exécutées après le If.

  5. Bouge toi. Plusieurs mouvements sur le même bot déplaceront le bot de la somme de tous les mouvements. Si plusieurs robots se retrouvent au même endroit, ils seront renvoyés à leur emplacement de départ.

  6. Tour. Plusieurs tours sur le même bot résumeront.

  7. Arrêtez. Plusieurs commandes d'arrêt sur la même variable compteront comme un seul arrêt.

Autres détails

Votre thread initial commence attaché à la Dvariable

Récursif avec un If(ayant une Ifdéclaration pointée sur lui-même) ne fera rien pour votre bot

Si un fil est arrêté après le verrouillage, ces verrous seront déverrouillés

Les actions pour utiliser une variable ou une ligne verrouillée ne feront rien.

Si un bot fait moins de 24 lignes, les lignes restantes seront remplies de Flag

Effectuer une écriture sur une variable qui est également attachée à un thread de départ aura en fait le thread démarrer son exécution sur la nouvelle valeur que le thread démarre le tour suivant.

Les robots sont placés dans un monde toroïdal selon le schéma suivant:

B...B...B...
..B...B...B.
B...B...B...

J'ai ajouté plusieurs exemples de robots qui sont commentés comme référence de langue.

Le contrôleur se trouve ici . J'y ai travaillé longtemps, mais il a probablement encore des bugs. Lorsque la spécification et le contrôleur se contredisent, la spécification est correcte.

Tableau d'affichage

1. 771  LockedScannerBot
2. 297  CopyAndSelfFlag
3. 289  DoubleTapBot
4. 197  ThreadCutterBot
5. 191  TripleThread
6. 180  ThickShelled
7. 155  Attacker
8. 99   RandomMover
9. 90   BananaBot
10. 56  LockedStationaryDoubleTap
Nathan Merrill
la source
Wow, au moins, DoubleTap semble bien meilleur que les échantillons!
Katenkyo
Que doit-il se passer si j'essaie de lire une variable verrouillée à partir d'un autre thread? Disons que je verrouille A puis dans un autre thread il y a MOVE A. Est-ce que A vaut 0 ou une valeur aléatoire ou le mouvement échoue-t-il ou ...?
Sparr
Idem sur ce qui se passe lorsqu'un thread atteint une ligne verrouillée par un autre thread. C'est un noop? Est-ce qu'il est ignoré?
Sparr
Est-ce que "Copier $ label A" devrait fonctionner? Il interprète comme "Copie # 11 A" qui n'est pas valide et bloque l'interprète, au lieu de "Copie 11 A" comme je l'espère.
Sparr
bug possible ... Il me semble que je peux lire mes propres lignes de drapeau pour les copier, même lorsqu'elles sont verrouillées par un autre thread.
Sparr

Réponses:

3

Scanner verrouillé Bot

Scanne l'ennemi aussi vite que possible et remplace les lignes par des drapeaux.

    Lock D
    Copy $a A
    Start A
    Copy $b B
    Start B

$d  Lock $d0
    Lock $d1    
$d0 Copy $flag *#C+1
$d1 If 1=1 $d0 $d0

$a  Lock A
    Lock $a0
    Lock $a1
    Lock $a2
$a0 Copy $flag *#C
$a1 Copy C+2 C
$a2 If !*#C $a1 $a0

$b  Lock B
    Lock $b0
    Lock $b1
    Lock $b2
$b0 Move C
$b1 Turn 1
$b2 If 1=1 $b0 $b0

$flag Flag
Le numéro un
la source
Je suis curieux de connaître le conditionnel dans votre thread A. ! * # C vérifie si la ligne #C de votre cible (votre C) est verrouillée, non? Comment est-ce utile?
Sparr
@Sparr Le thread A ne perd pas de temps à remplacer une ligne du code ennemi par un drapeau s'il est verrouillé.
TheNumberOne
Merci. J'ai mal lu la spécification concernant la vitesse des instructions If.
Sparr
3

DoubleTapBot

Ce bot a 3 fils: un pour se déplacer (A), les deux autres pour signaler (B et D). Drapeau B 1/2 tour, drapeau D 1/3 tour. Donc, à son tour, il doublera le drapeau de l'adversaire :).

Je suppose que C reviendra à 0 s'il dépasse 23.

Il devrait être assez sûr s'il a un certain tour pour se préparer (8 tours), car il gardera toujours au moins 2 threads (A et B) fonctionnant normalement.

Je ne peux pas l'essayer pour le moment, donc je ferai le test quand je serai de retour à la maison :)

Lock D          //Thread D locks itself
Copy 6 A        //Thread A will start line 6
Start A     
Copy 13 B       //Thread B will start line 13
Start B        
Copy 20 D       //Moving Thread D to an other part of the program
Lock A          //Thread A locks itself and the line it will be using
Lock #10
Lock #11
Lock #12
Move C          //Move in a pseudo random direction
Turn 1      //always turn to the right
If 1=1 #10 #10  //return to Move C
Lock B          //Thread B locks itself and the line it will be using
Lock #13
Lock #14
Copy #18 *#C    //Copy a flag to the Cth line of the opponent
If 1=1 #16 #16  //jump back to the copy
Flag   
Flag   
Copy C+1 C      //Increment C
Copy #19 *#C+1  //Copy a flag to the Cth+1 line of the opponent
If 1=1 #20 #20  //jump back to the increment
Flag 
Katenkyo
la source
Le numéro de verrouillage n'est pas une commande valide. J'ai mis # signes devant chacun des nombres. En outre, la commande est "Rotation", pas "Tour"
Nathan Merrill
@NathanMerrill Comment, c'est une faute de frappe, oubliez le #, merci de l'avoir signalé. Et pour tourner, modifiez votre message de manière à ce que vous écriviez Turn V Turns the bot V * 90 degrés dans le sens des aiguilles d'une montre. :)
Katenkyo
Oh, je l'ai fait. Le tour est en fait correct, alors, je vais revenir en arrière et mettre à jour le code
Nathan Merrill
Vous verrouillez 11,12,13 lorsque vous voulez verrouiller 10,11,12?
Sparr
Wow, merci de l'avoir signalé!
Katenkyo
2

Double robinet stationnaire verrouillé

Inspiré par le DoubleTapBot de @ Katenkyo, celui-ci abandonne quelques drapeaux et tout espoir de mouvement en retour pour verrouiller complètement ses propres fils afin qu'il ne puisse jamais être reprogrammé. Il est cependant toujours possible d'avoir des drapeaux ennemis écrits dans des zones de code sans boucle.

Lock $flag              // lock the only flag line, super important!
Lock D                  // lock thread D
Copy 10 A
Start A                 // start thread A at $Astart
Copy 17 B
Start B                 // start thread B at $Bstart
Lock $D1                // lock thread D lines
Lock $D2                // thread D should be safe on turn 8
$D1 Turn C              // Spin in place, once every 2 turns
$D2 If 0=0 $D1 $D1      // thread D loop
$Astart Lock A          // thread A starts here, locks itself
Lock $A1                // lock thread A lines
Lock $A2
Lock $A3                // thread A should be safe on turn 7
$A1 Copy $flag *#C      // ATTACK! once every 3 turns
$A2 Copy C+1 C          // increment C, used for attacks and turning
$A3 If 0=0 $A1 $A1      // thread A loop
$Bstart Lock B          // thread B starts here, locks itself
Lock $B1                // lock thread B lines
Lock $B2                // thread B should be safe on turn 8
$B1 Copy $flag *#C+12   // ATTACK! once every 2 turns
$B2 If 0=0 $B1 $B1      // thread B loop
$flag Flag
Sparr
la source
Haha, Verrouiller le drapeau est une très bonne idée, j'aurais dû y penser! Quoi qu'il en soit, je suis content que mon bot ait inspiré quelqu'un!
Katenkyo
@Katenkyo c'est une bonne idée si cela fonctionne, mais je ne pense pas que cela devrait fonctionner. Les règles telles qu'écrites suggèrent que si D verrouille la ligne de drapeau, A / B ne pourra pas copier à partir de celle-ci. Cependant, cela ne semble pas être le cas. Rapport de bug dans les commentaires de la question.
Sparr
1

Déménageur aléatoire

Se déplace dans une direction aléatoire

Copy 5 C
Copy 8 B
Start C
Move A // If you can't catch me, you can't modify me
If 1=1 #3 #3 //Continue to execute the above line
Start B
Copy 4 A
If 1=1 #6 #6 //Continue to execute the above line
Flag
Copy 5 A
If 1=1 #9 #9 //Continue to execute the above line
Nathan Merrill
la source
1

Épais décortiqué

Verrouille ses affaires autant qu'il le peut

Copy 5 B //Designating that the B thread will start on line 5
Start B //Starting the B thread
Lock C //Preventing C from being used
Copy A+1 A //The two threads are offset, meaning that the two threads shouldn't access this at the same time
Lock #A
Copy 2 B
Nathan Merrill
la source
1

Bot attaquant

Copie les drapeaux dans divers emplacements

Copy A+1 A // Increment A
Move A //Move in the Ath direction
Turn A //Rotate A times
Copy #8 *#A //Copy my flag over
Copy 23 D //Loop back to the beginning.  (I use 23 here as threads auto-increment)
Nathan Merrill
la source
0

Triple fil

Ce robot simple exécute trois threads tous avec le même code. Chaque thread attaque 1/3 de tour, se déplace 1/6, tourne 1/6 et fait la comptabilité 1/3.

Move 0
Start A
Start B
$loop Copy #A+9 *#C
Move C
Copy #A+9 *#C
Turn C
Copy C+1 C
If 0=0 $loop $loop
Sparr
la source
0

Banana Bot

Tente de lancer des bananes dans la roue ennemie avant que l'ennemi ne puisse rien faire. Sujette à être écrasée.

$d     If !*D $d1 $d0
$d0    Copy 24 *D
$d1    If !D $d2 $start
$d2    If !*B $d5 $d3
$d3    Copy 24 *B
$d4    Copy $d D

$start Lock D             //Banana's like to split.
       Copy $a A
       Start A
       Copy $b B
       Start B
       Lock $flag

$d5    Copy $start *C     //It's okay if enemy messes up our start.
       Copy $d d

$a     Lock A
$a1    Move C
       Turn 1
       Copy $a1 A

$b     Lock B
$b0    Copy C+1 C
       If !*#C $b0 $b1    //Banana's are good at slipping.
$b1    Copy $flag *#C
$b2    Copy $b0 B

$flag  Flag
Le numéro un
la source
0

Coupe-fil Bot

   Lock D
   Lock $f
   Copy 16 C
$S If ?*D $1 $2
   Move 1
   Copy $S D
$f Flag
$1 Stop *D
$2 If ?*A $3 $4
$3 Stop *A
$4 If ?*B $5 $6
$5 Stop *B
$6 Copy $f *#C
   Copy C+1 C
   If *#C=#C $E $6
   Copy 2 D
$E Start *D

Arrêtez tous les threads ennemis avant de remplir votre code.

MegaTom
la source
0

Copie et auto-indicateur

Ce bot exécute trois threads. Le thread D se déplace jusqu'à ce qu'il rencontre un ennemi, puis essaie de copier un drapeau en eux, puis se déplace dans une direction aléatoire. Le thread A copie son propre drapeau sur les lignes non essentielles du code du bot. Le fil B n'est qu'un compteur. La variable, l'indicateur et les lignes de code utilisées par chaque thread sont entièrement verrouillées dans les 15 premiers tours, et le bot écrase presque tout son code de démarrage avec ses propres indicateurs. Je ne pense pas qu'il soit possible de convertir ce bot en bannière d'une autre équipe après le tour 15 sans qu'un bot d'attaque dédié ne fasse rien d'autre que d'y écrire des drapeaux.

    Lock D              // Lock D thread
    Copy $AS A
    Start A             // Start A thread at $AS
    Start B             // B is just a counter
    Copy $DL D          // Jump to D thread startup code
$DC Start B             // Don't let B thread get stopped
$D0 If !*#B $D1 $D2
$D1 Copy $DF *#B
$D2 If !*#B+6 $D3 $DM
$D3 Copy $DF *#B
$DM Move B              // Move some direction after attacking
$DA Move 0              // Move north ...
    If ?*D $DC $DA      // until we hit a live target
$DF Flag                // Flag to copy
$DL Lock #B+3           // Lock the D thread's lines
    If B<12 $DL $DA     // jump to `Move 0` when D thread is safe
$AS Lock A
$AL Lock #B+20
    If B<4 $AL $AD
    Copy 23 B           // reset B so A doesn't overwrite its own code
$AF Flag
    Flag
$AD Copy $AF #B+1       // Copy a safe flag over every unused line of code
    If B<18 $AD $AF
Sparr
la source
Move 0c'est aller vers le nord, pas vers l'avant.
MegaTom
@MegaTom aha, merci. J'ai manqué ça.
Sparr