Code Bots 3: Antipatterns de programação paralela

13

Bem vindo de volta! Estou animado para apresentar o terceiro desafio do CodeBots. Este foi um longo tempo em construção. Esse desafio será dividido em 3 seções: a versão curta, a versão longa e detalhes adicionais.

A versão curta

Cada concorrente escreverá um programa de 24 comandos. Esses bots se moverão ao redor do mundo e copiarão seu código em outros bots, enquanto tentam impedir que outros bots façam o mesmo. Um dos comandos possíveis é o no-op Flag. Se um bot tem mais do Flagque qualquer outro bot Flag, você ganha um ponto. Você ganha por ter mais pontos.

Tudo isso foi verdade nos dois últimos desafios. Desta vez, os bots poderão executar várias linhas de código ao mesmo tempo.

A versão longa

A API

Cada bot terá exatamente 24 linhas, onde cada linha está no seguinte formato:

$label command parameters //comments

Rótulos e comentários são opcionais e cada comando possui um número diferente de parâmetros. Tudo faz distinção entre maiúsculas e minúsculas.

Parâmetros

Os parâmetros são digitados e podem estar nos seguintes formatos:

  1. Um valor de 0 a 23.
  2. Uma variável de: A, B, C,D
  3. Um valor usando adição: A+3ou2+C
  4. Uma linha de código, que é designada usando o #sinal ( #4representaria a quinta linha, enquanto #C+2representaria a linha calculada por C+2).
  5. Você pode usar um em $labelvez de designar uma linha de código.
  6. A variável ou linha de código do seu oponente, designada por *. Seu oponente é o bot no quadrado que você está enfrentando. ( *Brepresenta o Bvalor do seu oponente , enquanto *#9representa a 10ª linha do seu oponente). Se não houver ninguém nesse quadrado, o comando não será executado.

Comandos

Move V

Move o bot North+(V*90 degrees clockwise). O movimento não muda de direção.

Turn V

Gira o bot V*90 degreesno sentido horário.

Copiar VW

Copia o que estiver Vdentro W. Se Vé um número de linha, Wdeve ser um número de linha. Se Vé uma variável ou valor, Wdeve ser uma variável.

Bandeira

Faz nada.

Iniciar V

Inicia um novo thread anexado à variável V. Imediatamente e em cada turno futuro, o encadeamento executará o comando on-line V.

Se Vjá estiver anexado a um encadeamento, esse comando não será utilizado. Se Vfor a variável de um oponente, o oponente iniciará um segmento anexado a essa variável.

Stop V

Interrompe o encadeamento anexado à variável Vno final deste turno.

Bloqueio V

Impedir que a linha ou variável Vseja usada de qualquer forma, exceto pelo encadeamento chamado Lock. Uma chamada subsequente para Lockpelo mesmo encadeamento é desbloqueada V. Bloqueios não podem ser chamados nas variáveis ​​ou linhas do oponente.

Se Cond VW

Isso testará Cond. Se a condição for verdadeira, o ponteiro da linha será movido para o número da linha V, caso contrário, para o número da linha W. Essa linha será executada imediatamente.

Condicionais pode ser X=Y, X<Y, !X, ou ?X:

  1. X=Y testa se duas linhas são do mesmo tipo e do mesmo bot ou você testa se dois valores são iguais à mesma quantidade.
  2. X<Ytesta se o valor de Xé menor que Y.
  3. !Xtesta se a variável ou linha Xestá bloqueada (retorna true se bloqueada)
  4. ?X testa se uma determinada variável tem um thread anexado a ela

detalhes adicionais

Interações multithread

Ações do mesmo tipo são executadas ao mesmo tempo. As ações são executadas na seguinte ordem:

  1. Bloquear. Se vários threads tentarem bloquear uma variável, todos eles falharão. Se um encadeamento está desbloqueando uma variável enquanto outro está tentando bloqueá-la, a variável permanecerá desbloqueada.

  2. Começar. Se vários encadeamentos tentarem iniciar um encadeamento em uma variável, ele contará como um único início.

  3. Cópia de. Se dois threads copiam para a mesma variável, a variável termina como um valor aleatório. Se os dois copiarem para a mesma linha, nenhum deles funcionará. Se um encadeamento copiar para a mesma variável de que outro encadeamento estiver copiando, o último encadeamento copiará um valor aleatório. Se dois threads estiverem copiando da mesma variável, ambos funcionarão bem.

  4. E se. Todos os condicionais serão testados simultaneamente e, em seguida, as variáveis ​​de thread serão atualizadas posteriormente. A execução de um Ifpode fazer com que uma ação com maior prioridade seja adicionada. As ações com maior prioridade serão executadas antes de passar o If, enquanto as ações com menor prioridade serão executadas após o If.

  5. Mover. Vários movimentos no mesmo bot moverão o bot a soma de todos os movimentos. Se vários bots acabarem no mesmo local, eles serão retornados ao local inicial.

  6. Virar. Várias rodadas no mesmo bot serão somadas.

  7. Pare. Vários comandos de parada na mesma variável contam como uma única parada.

Outros detalhes

Seu encadeamento inicial começa anexado à Dvariável

A repetição com um If(tendo uma Ifdeclaração apontada para si) fará com que o seu bot não faça nada

Se um encadeamento for interrompido após o bloqueio, esses bloqueios serão desbloqueados

Ações para usar uma variável ou linha bloqueada não farão nada.

Se um bot for menor que 24 linhas, as linhas restantes serão preenchidas com Flag

A execução de uma gravação em uma variável que também está anexada a um encadeamento inicial fará com que o encadeamento inicie sua execução no novo valor, à medida que o encadeamento inicia na próxima curva.

Os bots são colocados em um mundo toroidal no seguinte padrão:

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

Adicionei vários exemplos de bots comentados como referência de idioma.

O controlador está localizado aqui . Eu trabalhei muito tempo nisso, mas provavelmente ainda tem bugs. Quando a especificação e o controlador contradizem, a especificação está correta.

Placar

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
fonte
Uau, pelo menos, o DoubleTap parece muito melhor do que amostras!
precisa
O que deve acontecer se eu tentar ler uma variável bloqueada de outro thread? Digamos que BLOQUEIO A e, em outro segmento, há um MOVIMENTO A. A avalia como 0 ou um valor aleatório ou a movimentação falha ou ...?
Sparr
Idem sobre o que acontece quando um segmento atinge uma linha bloqueada por outro segmento. É um noop? Será ignorado?
Sparr
"Copiar $ rótulo A" deve funcionar? Ele interpreta como "Copy # 11 A" que não é válido e trava o intérprete, em vez de "Copy 11 A" como eu esperava.
Sparr
possível erro ... Parece que consigo ler minhas próprias linhas de bandeira para copiá-las, mesmo quando estão bloqueadas por outro segmento.
Sparr

Respostas:

3

Bot de scanner bloqueado

Digitaliza o inimigo o mais rápido possível e substitui as linhas por bandeiras.

    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
O número um
fonte
Estou curioso sobre o condicional no seu tópico. ! * # C verifica se a linha #C (seu C) do seu alvo está bloqueada, certo? Como isso é útil?
Sparr
@Sparr O segmento A não perde tempo substituindo uma linha do código inimigo por uma bandeira se estiver bloqueada.
precisa
Obrigado. Eu li errado as especificações originalmente sobre a velocidade das declarações If.
Sparr
3

DoubleTapBot

Este bot possui 3 threads: um para mover (A), os outros dois para sinalizar (B e D). B bandeira 1/2 volta, D bandeira 1/3 volta. Então, em algum turno, ele dobrará a bandeira do oponente :).

Presumo que C retornará a 0 se exceder 23.

Deve ser bastante seguro se houver alguma volta para se preparar (8 turnos), pois ele sempre manterá pelo menos 2 threads (A e B) funcionando normalmente.

Não posso tentar no momento, por isso farei o teste quando voltar para casa :)

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
fonte
O número do bloqueio não é um comando válido. Coloquei # sinais antes de cada um dos números. Além disso, o comando é "Girar", não "Turn"
Nathan Merrill
@ NathanMerrill Como, isso é um erro de digitação, esqueça o #, obrigado por apontar. E, por sua vez, modifique sua postagem para que você tenha escrito Turn V Gira o bot V * 90 graus no sentido horário. :)
Katenkyo
Eu fiz. Por sua vez, é realmente correto, então, eu vou voltar e atualizar o código
Nathan Merrill
Você está bloqueando 11,12,13 quando pretende bloquear 10,11,12?
Sparr
Uau, obrigado por apontar isso!
precisa
2

Torneira dupla estacionária bloqueada

Inspirado no DoubleTapBot do @ Katenkyo, este abre mão de algumas bandeiras e qualquer esperança de movimento em troca de bloquear completamente seus próprios threads, para que nunca possa ser reprogramado. No entanto, ainda é possível ter bandeiras de inimigos gravadas em áreas de código sem loop.

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
fonte
Haha, Bloquear a bandeira é uma boa ideia, eu deveria ter pensado nisso! Enfim, fico feliz que meu bot tenha inspirado alguém!
precisa
@ Katenkyo, é uma boa ideia se funcionar, mas não acho que deva funcionar. As regras escritas sugerem que, se D bloqueia a linha da bandeira, o A / B não poderá copiar dela. No entanto, isso não parece ser o caso. Relatório de bug nos comentários da pergunta.
Sparr
1

Random Mover

Move-se em uma direção aleatória psu

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
fonte
1

Casca grossa

Bloqueia suas coisas o máximo que pode

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
fonte
1

Bot do atacante

Copia sinalizadores em vários locais

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
fonte
0

Linha Tripla

Este bot simples executa três threads, todos com o mesmo código. Cada thread ataca 1/3 turnos, move 1/6, gira 1/6 e faz a contabilidade 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
fonte
0

Banana Bot

Tentativas de jogar bananas na roda inimiga antes que o inimigo possa fazer qualquer coisa. Propenso a ser esmagado.

$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
O número um
fonte
0

Bot de cortador de linha

   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

Pare todos os segmentos inimigos antes de preencher com seu código.

MegaTom
fonte
0

Cópia e sinalização automática

Este bot executa três threads. O segmento D se move até esbarrar em um inimigo, depois tenta copiar uma bandeira neles e depois move uma direção aleatória. O segmento A copia seu próprio sinalizador sobre linhas não essenciais do código do bot. O segmento B é apenas um contador. A variável, sinalizador e linhas de código usadas por cada encadeamento são totalmente bloqueadas nas primeiras 15 voltas, e o bot substitui quase todo o seu código de inicialização com seus próprios sinalizadores. Não acho que seja possível converter esse bot no banner de outra equipe após o turno 15 sem que um bot de ataque dedicado faça nada além de escrever sinalizadores nele.

    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
fonte
Move 0é mover para o norte, não para a frente.
MegaTom 17/06/2015
@MegaTom aha, obrigado. Eu senti falta disso.
Sparr