The Rock, Paper, Scissors, Lizard, Spock Torneio da Epicness


98

Classificação mais recente @ 02-08-2014 12:00

| Pos # | Author               | Name                    | Language   | Score | Win   | Draw  | Loss  | Avg. Dec. Time |
+-------+----------------------+-------------------------+------------+-------+-------+-------+-------+----------------+
| 1st   | Emil                 | Pony                    | Python2    | 064   | 064   | 000   | 005   | 0026.87 ms     |
| 2nd   | Roy van Rijn         | Gazzr                   | Java       | 062   | 062   | 001   | 006   | 0067.30 ms     |
| 2nd   | Emil                 | Dienstag                | Python2    | 062   | 062   | 001   | 006   | 0022.19 ms     |
| 4th   | ovenror              | TobiasFuenke            | Python2    | 061   | 061   | 001   | 007   | 0026.89 ms     |
| 5th   | PhiNotPi             | BayesianBot             | Perl       | 060   | 060   | 000   | 009   | 0009.27 ms     |
| 6th   | Claudiu              | SuperMarkov             | Python2    | 058   | 058   | 001   | 010   | 0026.77 ms     |
| 7th   | histocrat            | Alternator              | Ruby       | 057   | 057   | 001   | 011   | 0038.53 ms     |
| 8th   | histocrat            | LeonardShelby           | Ruby       | 053   | 053   | 000   | 016   | 0038.55 ms     |
| 9th   | Stretch Maniac       | SmarterBot              | Java       | 051   | 051   | 002   | 016   | 0070.02 ms     |
| 9th   | Martin Büttner       | Markov                  | Ruby       | 051   | 051   | 003   | 015   | 0038.45 ms     |
| 11th  | histocrat            | BartBot                 | Ruby       | 049   | 049   | 001   | 019   | 0038.54 ms     |
| 11th  | kaine                | ExcitingishBot          | Java       | 049   | 049   | 001   | 019   | 0065.87 ms     |
| 13th  | Thaylon              | UniformBot              | Ruby       | 047   | 047   | 001   | 021   | 0038.61 ms     |
| 14th  | Carlos Martinez      | EasyGame                | Java       | 046   | 046   | 002   | 021   | 0066.44 ms     |
| 15th  | Stretch Maniac       | SmartBot                | Java       | 045   | 045   | 001   | 023   | 0068.65 ms     |
| 16th  | Docopoper            | RoboticOboeBotOboeTuner | Python2    | 044   | 044   | 000   | 025   | 0156.55 ms     |
| 17th  | Qwix                 | Analyst                 | Java       | 043   | 043   | 001   | 025   | 0069.06 ms     |
| 18th  | histocrat            | Analogizer              | Ruby       | 042   | 042   | 000   | 027   | 0038.58 ms     |
| 18th  | Thaylon              | Naan                    | Ruby       | 042   | 042   | 004   | 023   | 0038.48 ms     |
| 20th  | Thaylon              | NitPicker               | Ruby       | 041   | 041   | 000   | 028   | 0046.21 ms     |
| 20th  | bitpwner             | AlgorithmBot            | Python2    | 041   | 041   | 001   | 027   | 0025.34 ms     |
| 22nd  | histocrat            | WereVulcan              | Ruby       | 040   | 040   | 003   | 026   | 0038.41 ms     |
| 22nd  | Ourous               | QQ                      | Cobra      | 040   | 040   | 003   | 026   | 0089.33 ms     |
| 24th  | Stranjyr             | RelaxedBot              | Python2    | 039   | 039   | 001   | 029   | 0025.40 ms     |
| 25th  | JoshDM               | SelfLoathingBot         | Java       | 038   | 038   | 001   | 030   | 0068.75 ms     |
| 25th  | Ourous               | Q                       | Cobra      | 038   | 038   | 001   | 030   | 0094.04 ms     |
| 25th  | Ourous               | DejaQ                   | Cobra      | 038   | 038   | 001   | 030   | 0078.31 ms     |
| 28th  | Luis Mars            | Botzinga                | Java       | 037   | 037   | 002   | 030   | 0066.36 ms     |
| 29th  | kaine                | BoringBot               | Java       | 035   | 035   | 000   | 034   | 0066.16 ms     |
| 29th  | Docopoper            | OboeBeater              | Python2    | 035   | 035   | 002   | 032   | 0021.92 ms     |
| 29th  | Thaylon              | NaanViolence            | Ruby       | 035   | 035   | 003   | 031   | 0038.46 ms     |
| 32nd  | Martin Büttner       | SlowLizard              | Ruby       | 034   | 034   | 004   | 031   | 0038.32 ms     |
| 33rd  | Kyle Kanos           | ViolentBot              | Python3    | 033   | 033   | 001   | 035   | 0032.42 ms     |
| 34th  | HuddleWolf           | HuddleWolfTheConqueror  | .NET       | 032   | 032   | 001   | 036   | 0029.86 ms     |
| 34th  | Milo                 | DogeBotv2               | Java       | 032   | 032   | 000   | 037   | 0066.74 ms     |
| 34th  | Timmy                | DynamicBot              | Python3    | 032   | 032   | 001   | 036   | 0036.81 ms     |
| 34th  | mccannf              | YAARBot                 | JS         | 032   | 032   | 002   | 035   | 0100.12 ms     |
| 38th  | Stranjyr             | ToddlerProof            | Java       | 031   | 031   | 010   | 028   | 0066.10 ms     |
| 38th  | NonFunctional User2..| IHaveNoIdeaWhatImDoing  | Lisp       | 031   | 031   | 002   | 036   | 0036.26 ms     |
| 38th  | john smith           | RAMBOBot                | PHP        | 031   | 031   | 002   | 036   | 0014.53 ms     |
| 41st  | EoinC                | SimpleRandomBot         | .NET       | 030   | 030   | 005   | 034   | 0015.68 ms     |
| 41st  | Martin Büttner       | FairBot                 | Ruby       | 030   | 030   | 006   | 033   | 0038.23 ms     |
| 41st  | Docopoper            | OboeOboeBeater          | Python2    | 030   | 030   | 006   | 033   | 0021.93 ms     |
| 44th  | undergroundmonorail  | TheGamblersBrother      | Python2    | 029   | 029   | 000   | 040   | 0025.55 ms     |
| 45th  | DrJPepper            | MonadBot                | Haskel     | 028   | 028   | 002   | 039   | 0008.23 ms     |
| 46th  | Josef E.             | OneBehind               | Java       | 027   | 027   | 007   | 035   | 0065.87 ms     |
| 47th  | Ourous               | GitGudBot               | Cobra      | 025   | 025   | 001   | 043   | 0053.35 ms     |
| 48th  | ProgramFOX           | Echo                    | .NET       | 024   | 024   | 004   | 041   | 0014.81 ms     |
| 48th  | JoshDM               | SelfHatingBot           | Java       | 024   | 024   | 005   | 040   | 0068.88 ms     |
| 48th  | Trimsty              | Herpetologist           | Python3    | 024   | 024   | 002   | 043   | 0036.93 ms     |
| 51st  | Milo                 | DogeBot                 | Java       | 022   | 022   | 001   | 046   | 0067.86 ms     |
| 51st  | William Barbosa      | StarWarsFan             | Ruby       | 022   | 022   | 002   | 045   | 0038.48 ms     |
| 51st  | Martin Büttner       | ConservativeBot         | Ruby       | 022   | 022   | 001   | 046   | 0038.25 ms     |
| 51st  | killmous             | MAWBRBot                | Perl       | 022   | 022   | 000   | 047   | 0016.30 ms     |
| 55th  | Mikey Mouse          | LizardsRule             | .NET       | 020   | 020   | 007   | 042   | 0015.10 ms     |
| 55th  | ja72                 | BlindForesight          | .NET       | 020   | 020   | 001   | 048   | 0024.05 ms     |
| 57th  | robotik              | Evolver                 | Lua        | 019   | 019   | 001   | 049   | 0008.19 ms     |
| 58th  | Kyle Kanos           | LexicographicBot        | Python3    | 018   | 018   | 003   | 048   | 0036.93 ms     |
| 58th  | William Barbosa      | BarneyStinson           | Lua        | 018   | 018   | 005   | 046   | 0005.11 ms     |
| 60th  | Dr R Dizzle          | BartSimpson             | Ruby       | 017   | 017   | 001   | 051   | 0038.22 ms     |
| 60th  | jmite                | IocainePowder           | Ruby       | 017   | 017   | 003   | 049   | 0038.50 ms     |
| 60th  | ArcticanAudio        | SpockOrRock             | PHP        | 017   | 017   | 001   | 051   | 0014.19 ms     |
| 60th  | Dr R Dizzle          | BetterLisaSimpson       | Ruby       | 017   | 017   | 000   | 052   | 0038.23 ms     |
| 64th  | Dr R Dizzle          | LisaSimpson             | Ruby       | 016   | 016   | 002   | 051   | 0038.29 ms     |
| 65th  | Martin Büttner       | Vulcan                  | Ruby       | 015   | 015   | 001   | 053   | 0038.26 ms     |
| 65th  | Dr R Dizzle          | Khaleesi                | Ruby       | 015   | 015   | 005   | 049   | 0038.29 ms     |
| 67th  | Dr R Dizzle          | EdwardScissorHands      | Ruby       | 014   | 014   | 002   | 053   | 0038.21 ms     |
| 67th  | undergroundmonorail  | TheGambler              | Python2    | 014   | 014   | 002   | 053   | 0025.47 ms     |
| 69th  | cipher               | LemmingBot              | Python2    | 011   | 011   | 002   | 056   | 0025.29 ms     |
| 70th  | Docopoper            | ConcessionBot           | Python2    | 007   | 007   | 000   | 062   | 0141.31 ms     |
+-------+----------------------+-------------------------+------------+-------+-------+-------+-------+----------------+
Total Players: 70
Total Matches Completed: 2415
Total Tourney Time: 06:00:51.6877573

Notas dos torneios

Bots excluídos

  • BashRocksBot - ainda não se alegra com o .net executando scripts cygwin bash
  • CounterPreferenceBot - aguardando correção de bug
  • RandomlyWeighted - aguardando correção de bug
  • CasinoShakespeare - excluído porque requer uma conexão ativa à Internet

Pergunta publicada original

Você foi até a casa de seus amigos para o confronto mais épico de todos os tempos: Rock, Paper, Scissors, Lizard, Spock. No verdadeiro estilo nerd-tastic do BigBang, nenhum dos jogadores está jogando sozinho, mas criou bots de console para jogar em seu nome. Você sacou sua chave USB e a entregou ao Sheldor the Conqueror para inclusão no showdown. Penny desmaia. Ou talvez Howard desmaie. Não julgamos aqui no apartamento de Leonard.

Regras

Aplicam-se as regras padrão Pedra, Papel, Tesoura, Lagarto e Spock.

  • Tesoura de corte de papel
  • Papel cobre Rock
  • Esmaga rochas Lagarto
  • Veneno de lagarto Spock
  • Spock esmaga tesoura
  • Tesoura decapita Lagarto
  • Lagarto come papel
  • Papel nega Spock
  • Spock vaporiza a rocha
  • Pedra esmaga Tesoura

Regras RPSLV

O bot de cada jogador jogará uma partida contra o outro bot no torneio.

Cada partida consistirá em 100 iterações de um jogo RPSLV.

Após cada partida, o vencedor é o jogador que ganhou o maior número de jogos / mãos em 100.

Se você vencer uma partida, você receberá 1 ponto na tabela de classificação. No resultado de uma partida empatada, nenhum jogador ganhará um ponto.

Requisitos de bot

Seu bot deve ser executável na linha de comando.

A caixa * nix de Sheldor morreu, então estamos executando o Windows 8 Gaming Laptop para garantir que a solução fornecida possa funcionar no Windows. A Sheldor ofereceu graciosamente a instalação de quaisquer tempos de execução necessários (dentro do razoável) para poder executar sua solução. (.NET, Java, Php, Python, Ruby, PowerShell ...)

Entradas

No primeiro jogo de cada partida, nenhum argumento é fornecido ao seu bot. Em cada jogo subseqüente de cada partida: - Arg1 conterá o histórico de suas mãos / decisões de bots nesta partida. - Arg2 conterá o histórico das mãos / decisões de seus oponentes nesta partida.

O histórico será representado por uma sequência de letras maiúsculas representando as possíveis mãos que você pode jogar.

 | R | Rock     |
 | P | Paper    |
 | S | Scissors |
 | L | Lizard   |
 | V | Spock    |

Por exemplo

  • Jogo 1: MyBot.exe
  • Jogo 2: MyBot.exe SV
  • Jogo 3: MyBot.exe SS VL
  • Jogo 4: MyBot.exe SSR VLS

Resultado

Seu bot deve escrever uma resposta de um único personagem representando sua "mão" para cada jogo. O resultado deve ser gravado em STDOUT e o bot deve sair. Letras maiúsculas válidas estão abaixo.

 | R | Rock     |
 | P | Paper    |
 | S | Scissors |
 | L | Lizard   |
 | V | Spock    |

No caso em que seu bot não retorna uma mão válida (ou seja, 1 das 5 letras maiúsculas acima, você perde automaticamente essa mão e a partida continua.

No caso em que ambos os bots não retornam uma mão válida, o jogo é considerado empate e a partida continua.

Formato de correspondência

Cada bot enviado jogará uma partida contra o outro bot no torneio.

Cada partida durará exatamente 100 jogos.

As partidas serão disputadas anonimamente, você não terá um conhecimento avançado do bot específico contra o qual está jogando, no entanto, poderá usar toda e qualquer informação que puder obter de sua tomada de decisão durante o histórico da partida atual para alterar sua estratégia contra o seu adversário. oponente. Você também pode acompanhar o histórico de seus jogos anteriores para criar padrões / heurísticas, etc ... (Veja as regras abaixo)

Durante um único jogo, o mecanismo de orquestração executará seu bot e o de seus oponentes separados por 100 milissegundos e comparará os resultados para evitar colisões de PRNG no mesmo idioma / tempo de execução. (isso realmente aconteceu comigo durante o teste).

Julgamento e restrições

O Dr. Sheldon Cooper, disfarçado de Sheldor, o Conquistador, gentilmente se ofereceu para supervisionar o andamento do torneio. Sheldor, o Conquistador, é um supervisor justo e justo (principalmente). Todas as decisões de Sheldor são finais.

O jogo será realizado de maneira justa e adequada:

  • Seu script / programa bot será armazenado no mecanismo de orquestração em uma subpasta Players\[YourBotName]\
  • Você pode usar a subpasta Players\[YourBotName]\datapara registrar quaisquer dados ou histórico de jogos do torneio atual à medida que prossegue. Os diretórios de dados serão eliminados no início de cada corrida do torneio.
  • Você não pode acessar o diretório de jogadores de outro jogador no torneio
  • Seu bot não pode ter um código específico que tenha como alvo outro comportamento específico de bots
  • Cada jogador pode enviar mais de um bot para jogar, desde que não interaja ou não se ajude.

Editar - restrições adicionais

  • Em relação a desistências, elas não serão suportadas. Seu bot deve jogar uma das 5 mãos válidas. Vou testar cada bot fora do torneio com alguns dados aleatórios para garantir que eles se comportem. Quaisquer bots que lançam erros (ou seja, perdem erros) serão excluídos do torneio até que sejam corrigidos.
  • Os bots podem ser derivados desde que sejam sucintamente diferentes em seu comportamento. Bots (inclusive em outros idiomas) que executam exatamente o mesmo comportamento de um bot existente serão desqualificados
  • Já existem bots de spam para o seguinte, então não reenvie
    • Rock - Bart Simpson
    • Papel - LisaSimpson
    • Tesoura - EdwardSchandhands
    • Spock - Vulcan
    • Lagarto - Khaleesi
    • Pseudo-aleatório - SimpleRandomBot & FairBot
    • Psuedo Random RPS - ConservativeBot
    • Psuedo Random LV - Barney Stinson
  • Os robôs não podem chamar serviços de terceiros ou recursos da Web (ou qualquer outra coisa que diminua significativamente a velocidade / tempo de tomada de decisão das correspondências). CasinoShakespeareé a única exceção, pois esse bot foi enviado antes da adição dessa restrição.

Sheldor atualizará esta pergunta o mais rápido possível com os resultados do torneio, à medida que mais bots forem enviados.

Programa de Orquestração / Controle

O programa de orquestração, juntamente com o código fonte de cada bot, está disponível no github.

https://github.com/eoincampbell/big-bang-game

Detalhes da submissão

Seu envio deve incluir

  • O nome do seu bot
  • Seu código
  • Um comando para
    • execute seu bot a partir do shell, por exemplo
    • ruby myBot.rb
    • python3 myBot.py
    • OU
    • primeiro compile seus dois e depois execute-o. por exemplo
    • csc.exe MyBot.cs
    • MyBot.exe

Envio de amostra

BotName: SimpleRandomBot
Compile: "C:\Program Files (x86)\MSBuild\12.0\Bin\csc.exe" SimpleRandomBot.cs
Run:     SimpleRandomBot [Arg1] [Arg2]

Código:

using System;
public class SimpleRandomBot
{
    public static void Main(string[] args)
    {
        var s = new[] { "R", "P", "S", "L", "V" };
        if (args.Length == 0)
        {
            Console.WriteLine("V"); //always start with spock
            return;
        }
        char[] myPreviousPlays = args[0].ToCharArray();
        char[] oppPreviousPlays = args[1].ToCharArray();
        Random r = new Random();
        int next = r.Next(0, 5);
        Console.WriteLine(s[next]);
    }
}

Esclarecimento

Qualquer dúvida, pergunte nos comentários abaixo.


7
Como é a história quando um jogador perde a mão?
histocrat

1
Eu ia me esforçar ao máximo com uma abordagem analítica, mas a maioria dos bots aqui são estúpidos o suficiente para derrotar a IA inteligente.
fofo

1
Só porque nunca estou na liderança de qualquer desafio KotH em que participei, tirei uma captura de tela como lembrança.
Kyle Kanos

3
Vou correr outro torneio hoje à noite e postar os resultados completos do jogo no pastebin ... o próximo lote terá cerca de 450 jogos, mas deve ser um pouco mais rápido, pois eu implementei algumas coisas de paralelização no programa de controle
Eoin Campbell

3
Se não me engano, parece haver um bug sério no script de orquestração: As histórias dos jogadores 1 e 2 sempre são passadas para os bots como primeiro e segundo argumentos, respectivamente, enquanto que, de acordo com as regras, os bots devem sempre ter seus própria história primeiro. Agora o jogador 2 está efetivamente tentando se vencer. (Fiquei um pouco desconfiado porque meu bot venceu todas as partidas em que estava o jogador 1, perdendo metade das outras partidas.) #
292 Emil

Respostas:


26

Pônei (Python 2)

Isso se baseia em um bot de pedra-papel-tesoura que escrevi há algum tempo para um desafio de programação no final de uma aula on-line do Udacity . Mudei para incluir Spock e lagarto e fiz algumas melhorias.

O programa possui 11 estratégias simples diferentes, cada uma com 5 variantes. Ele escolhe dentre estes, com base em quão bem eles teriam se saído nas últimas rodadas.

Eu removi uma estratégia de fallback que jogava aleatoriamente contra oponentes mais fortes. Eu acho que é mais divertido assim.

import sys

# just play Spock for the first two rounds
if len(sys.argv)<2 or len(sys.argv[1])<2: print 'V'; sys.exit()

# initialize and translate moves to numbers for better handling:
my_moves, opp_moves = sys.argv[1], sys.argv[2]
moves = ('R', 'P', 'S', 'V', 'L')   
history = zip([moves.index(i) for i in my_moves],
              [moves.index(i) for i in opp_moves])

# predict possible next moves based on history
def prediction(hist):
    N = len(hist)    

    # find longest match of the preceding moves in the earlier history
    cand_m = cand_o = cand_b = range(N-1)
    for l in xrange(1,min(N, 20)):
        ref = hist[N-l]
        cand_m = ([c for c in cand_m if c>=l and hist[c-l+1][0]==ref[0]]
                  or cand_m[-1:])
        cand_o = ([c for c in cand_o if c>=l and hist[c-l+1][1]==ref[1]]
                  or cand_o[-1:])
        cand_b = ([c for c in cand_b if c>=l and hist[c-l+1]==ref]
                  or cand_b[-1:])

    # analyze which moves were used how often
    freq_m, freq_o = [0]*5, [0]*5
    for m in hist:
        freq_m[m[0]] += 1
        freq_o[m[1]] += 1

    # return predictions
    return ([hist[-i][p] for i in 1,2 for p in 0,1]+   # repeat last moves
            [hist[cand_m[-1]+1][0],     # history matching of my own moves
             hist[cand_o[-1]+1][1],     # history matching of opponent's moves
             hist[cand_b[-1]+1][0],     # history matching of both
             hist[cand_b[-1]+1][1],
             freq_m.index(max(freq_m)), # my most frequent move
             freq_o.index(max(freq_o)), # opponent's most frequent move
             0])                        # good old rock (and friends)


# what would have been predicted in the last rounds?
pred_hist = [prediction(history[:i]) for i in xrange(2,len(history)+1)]

# how would the different predictions have scored?
n_pred = len(pred_hist[0])
scores = [[0]*5 for i in xrange(n_pred)]
for pred, real in zip(pred_hist[:-1], history[2:]):
    for i in xrange(n_pred):
        scores[i][(real[1]-pred[i]+1)%5] += 1
        scores[i][(real[1]-pred[i]+3)%5] += 1
        scores[i][(real[1]-pred[i]+2)%5] -= 1
        scores[i][(real[1]-pred[i]+4)%5] -= 1

# return best counter move
best_scores = [list(max(enumerate(s), key=lambda x: x[1])) for s in scores]
best_scores[-1][1] *= 1.001   # bias towards the simplest strategy    
if best_scores[-1][1]<0.4*len(history): best_scores[-1][1] *= 1.4
strat, (shift, score) = max(enumerate(best_scores), key=lambda x: x[1][1])
print moves[(pred_hist[-1][strat]+shift)%5]

Correr como:

python Pony.py

Edit : Fiz uma pequena alteração colocando um viés em direção à estratégia mais simples (ou seja, sempre jogue a mesma jogada) em casos inseguros. Isso ajuda um pouco a não tentar encontrar padrões excessivamente complicados onde não existem, por exemplo, em bots como o ConservativeBot.

Nota : Tentei explicar a estratégia básica de correspondência do histórico que esse bot usa na postagem para meu outro bot Dienstag .


3
Uma taxa de ganho de 96% é excelente.
AndoDaan

Muito agradável. Você pode gostar de Iocaine Powder , se ainda não o viu.
wchargin 31/07

@WChargin, é claro. :) Quando escrevi meu código original, eu havia lido sobre o pó de cocaína alguns anos antes e me lembrei vagamente da idéia geral. Então, Pony é realmente inspirado por ele, se não muito diretamente. Como se vê, eles são muito semelhantes. Acho que o meu tem um repertório mais amplo de estratégias, enquanto a Iocaína em Pó tem um nível inteligente de raciocínio meta-meta que eu não incluí.
Emil

20

Markov, Ruby

Examina os dois últimos movimentos do oponente e determina os possíveis (e mais prováveis) acompanhamentos. Se a combinação não foi escolhida antes, ele apenas usa todos os movimentos do oponente (até agora). Então ele coleta todas as respostas possíveis para essas e escolhe uma aleatória.

responses = {
  'R' => ['P', 'V'],
  'P' => ['S', 'L'],
  'S' => ['R', 'V'],
  'L' => ['S', 'R'],
  'V' => ['P', 'L']
}

if ARGV.length == 0 || (history = ARGV[1]).length < 3
    choices = ['R','P','S','L','V']
else
    markov = Hash.new []
    history.chars.each_cons(3) { |chars| markov[chars[0..1].join] += [chars[2]] }

    choices = []
    likely_moves = markov.key?(history[-2,2]) ? markov[history[-2,2]] : history.chars
    likely_moves.each { |move| choices += responses[move] }
end

puts choices.sample

Corra como

markov.rb

E então eu uso esse programa para determinar o movimento mais possível que farei a seguir, descobrir o que você fará e finalmente encontrar uma maneira de vencer o que você fará e fazer um loop infinito a coisa toda novamente, novamente e novamente.
Jamie

@ Jamie Você quer dizer como esse cara? codegolf.stackexchange.com/a/35295/8478
Martin Ender

Você adivinha. (o comentário não foi tempo suficiente para ser postado)
Jamie

19

ConservativeBot, Ruby

Coisas novas são coisas ruins.

puts ['R','P','S'].sample

Corra como

ruby conservative.rb

A versão OG é a melhor versão.
maxywb

13

Fã de Guerra nas Estrelas - Ruby

Dane-se, Spock

puts ['R','P','L','S'].sample

Execute-o como:

ruby starwarsfan.rb

Adicionado ao Controller
Eoin Campbell

você pode reverter pela resposta edit - apenas comentarei aqui quando os adicionar.
Eoin Campbell

Por que R e S? : P
cjfaure

@mardavi É um fã de Star Wars porque não usa Spock.
William Barbosa

ah, você está certo (é claro). Eu li muito rápido, meu erro (mas sem consequências felizmente)
mardavi

13

Barney Stinson - Lua

Eu só tenho uma regra: o novo é sempre melhor. Dane-se o velho Jo Ken Po ou como quiser.

math.randomseed(os.time())
print(math.random() > 0.5 and "V" or "L")

Execute-o como:

lua legenwaitforitdary.lua

8

Bot chato (Java)

Ele assume que todos sempre jogam a mesma coisa e planejam de acordo. Ele geralmente pega pedras em gravatas, porque todos os outros, certo?

public class BoringBot
{
    public static void main(String[] args)
    {
        int Rock=0;
        int Paper=0;
        int Scissors=0;
        int Lizard=0;
        int Spock=0;

        if (args.length == 0)
        {
            System.out.print("P");
            return;
        }

        char[] oppPreviousPlays = args[1].toCharArray();

        for (int j=0; j<oppPreviousPlays.length; j++) {
            switch(oppPreviousPlays[j]){
                case 'R': Rock++; break;
                case 'P': Paper++; break;
                case 'S': Scissors++; break;
                case 'L': Lizard++; break;
                case 'V': Spock++;
            }
        }

        int Best = Math.max(Math.max(Lizard+Scissors-Spock-Paper,
                                     Rock+Spock-Lizard-Scissors),
                            Math.max(Math.max(Paper+Lizard-Spock-Rock,
                                              Paper+Spock-Rock-Scissors),
                                     Rock+Scissors-Paper-Lizard));

        if (Best== Lizard+Scissors-Spock-Paper){
            System.out.print("R"); return;
        } else if (Best== Rock+Spock-Lizard-Scissors){
            System.out.print("P"); return;
        } else if (Best== Paper+Lizard-Spock-Rock){
            System.out.print("S"); return;
        } else if(Best== Paper+Spock-Rock-Scissors){
            System.out.print("L"); return;
        } else {
            System.out.print("V"); return;
        }
    }
}

Observe que, se essa é uma estratégia que outra pessoa já está usando, informe-me e eu a excluirei. Parece o óbvio que eu ainda não vi.
24514 kaine

é esse c #. suas propriedades .length estão erradas. e há nenhum métodomax
Eoin Campbell

@EoinCampbell É java, eu tenho jogado com ambos e aparentemente esqueci quais comandos pertencem a quais.
24514 kaine

Ah legal. deixe comigo e eu incluirei.
Eoin Campbell

ainda quebrado. executando jre8 - java BoringBot.java - Erro: Não foi possível localizar ou carregar a classe principal D: \ Meu Software Dev \ jogo de big bang \ BigBang.Orchestrator \ bin \ Debug \ Players \ BoringBot \ BoringBot.java -
Eoin Campbell

8

Iocaína em pó, Ruby

insira a descrição da imagem aqui

Baseado na estratégia RPS (roubada descaradamente) aqui . A aparência do bot escolhe um palpite idêntico ao bot de Markov, mas assume que o oponente adivinhou o que escolherá e escolhe uma jogada para vencê-la de acordo.

Observe que eu apenas adaptei a idéia básica da estratégia vinculada, não a segui em detalhes.

responses = {
  'R' => ['P', 'V'],
  'P' => ['S', 'L'],
  'S' => ['R', 'V'],
  'L' => ['S', 'R'],
  'V' => ['P', 'L']
}

if ARGV.length == 0 || (history = ARGV[1]).length < 3
    choices = ['R','P','S','L','V']
else
    markov = Hash.new []
    history.chars.each_cons(3) { |chars| markov[chars[0..1].join] += [chars[2]] }

    choices = []
    likely_moves = markov.key?(history[-2,2]) ? markov[history[-2,2]] : history.chars
    likely_moves.each { |move| choices += responses[move] }
end

myChoice = choices.sample 
theirChoice = responses[myChoice].sample
actualChoice = responses[theirChoice].sample
puts actualChoice

Corra como

iocaine.rb

5
Você continua usando essa palavra. Eu não acho que significa o que você pensa que significa.
28714 JoshDM

2
O poder real da Iocaína em Pó era que ele alterna entre o uso do markov e o beating-markov. Ele começa como um markov inteligente, mas quando percebe (começa a perder), ele entra no modo de bater o markov. Deve ser fácil adicionar.
Roy van Rijn

Ahh, esperto! Não vou mentir, eu só ouvi Iocaine me descrever, na verdade não a olhei em detalhes. Sinta-se à vontade para modificar meu código se desejar ou enviar o seu próprio e obter o crédito!
jmite

8

HuddleWolfTheConqueror - C #

O HuddleWolf está de volta e melhor do que nunca. Ele derrotará Sheldor, o Conquistador, em seu próprio jogo bobo. O HuddleWolf é inteligente o suficiente para identificar e combater os spammerbots. Para oponentes mais inteligentes, HuddleWolf usa seu conhecimento das estatísticas básicas da 5ª série e utiliza uma jogada de dados ponderada com base na história dos jogos da oposição.

using System;
using System.Collections.Generic;
using System.Linq;

public class HuddleWolfTheConqueror
{

    public static readonly char[] s = new[] { 'R', 'P', 'S', 'L', 'V' };

    public static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            Console.WriteLine(pickRandom());
            return;
        }

        char[] myPlays = args[0].ToCharArray();
        char[] oppPlays = args[1].ToCharArray();

        char tryPredict = canPredictCounter(oppPlays);
        if (tryPredict != '^')
        {
            Console.WriteLine(tryPredict);
        }
        else
        {
            Console.WriteLine(pickRandom());
        }
        return;
    }


    public static char canPredictCounter(char[] history)
    {
        // don't predict if insufficient data
        if (history.Length < 5)
        {
            return '^';
        }

        // calculate probability of win for each choice
        Dictionary<char, double> dic = getBestProabability(history);

        // get item with highest probability of win
        List<char> maxVals = new List<char>();
        char maxVal = '^';
        double mostFreq = 0;
        foreach (var kvp in dic)
        {
            if (kvp.Value > mostFreq)
            {
                mostFreq = kvp.Value;
            }
        }
        foreach (var kvp in dic)
        {
            if (kvp.Value == mostFreq)
            {
                maxVals.Add(kvp.Key);
            }
        }

        // return error
        if (maxVals.Count == 0)
        {
            return maxVal;
        }

        // if distribution is not uniform, play best play
        if (maxVals.Count <= 3)
        {
            Random r = new Random(Environment.TickCount);
            return maxVals[r.Next(0, maxVals.Count)];
        }

        // if probability is close to uniform, use weighted dice roll
        if (maxVals.Count == 4)
        {
            return weightedRandom(dic);
        }

        // if probability is uniform, use random dice roll
        if (maxVals.Count >= 5)
        {
            return pickRandom();
        }

        // return error
        return '^';
    }

    public static Dictionary<char, double> getBestProabability(char[] history)
    {
        Dictionary<char, double> dic = new Dictionary<char, double>();
        foreach (char c in s)
        {
            dic.Add(c, 0);
        }
        foreach (char c in history)
        {
            if (dic.ContainsKey(c))
            {
                switch(c)
                {
                    case 'R' : 
                        dic['P'] += (1.0/(double)history.Length);
                        dic['V'] += (1.0/(double)history.Length);
                        break;
                    case 'P' : 
                        dic['S'] += (1.0/(double)history.Length);
                        dic['L'] += (1.0/(double)history.Length);
                        break;
                    case 'S' : 
                        dic['V'] += (1.0/(double)history.Length);
                        dic['R'] += (1.0/(double)history.Length);
                        break;
                    case 'L' : 
                        dic['R'] += (1.0/(double)history.Length);
                        dic['S'] += (1.0/(double)history.Length);
                        break;
                    case 'V' : 
                        dic['L'] += (1.0/(double)history.Length);
                        dic['P'] += (1.0/(double)history.Length);
                        break;
                    default : 
                        break;

                }
            }
        }
        return dic;
    }

    public static char weightedRandom(Dictionary<char, double> dic)
    {
        Random r = new Random(Environment.TickCount);
        int next = r.Next(0, 100);
        int curVal = 0;
        foreach (var kvp in dic)
        {
            curVal += (int)(kvp.Value*100);
            if (curVal > next)
            {
                return kvp.Key;
            }
        }
        return '^';
    }

    public static char pickRandom()
    {
        Random r = new Random(Environment.TickCount);
        int next = r.Next(0, 5);
        return s[next];
    }
}

8

Criança pequena

Esse bot bastante estúpido assume que está jogando com uma criança que "perseguirá" seus movimentos, sempre tentando vencer o que foi jogado pela última vez. Se o bot for batido várias vezes seguidas, ele salta para um novo ponto no padrão. É baseado na minha estratégia de sempre derrotar meu irmão muito mais novo. :)

EDIT :: Alterada a duração de uma sequência de perdas necessária para saltar para lançamentos aleatórios. Também foi corrigido um erro grave com o salto aleatório.

Salve como ToddlerProof.java, compile e execute comjava ToddlerProof [me] [them]

import java.util.HashMap;
public class ToddlerProof
{
    char[] moves = new char[]{'R', 'P', 'S', 'L', 'V'};
    public static void main(String[] args)
    {
        if(args.length<1) //first Round
        {
            System.out.print('V');//Spock is best
            return;
        }
        else
        {
            String them = args[1];
            String me = args[0];
            int streak = 0;

            HashMap<Character, Character> nextMove = new HashMap<Character, Character>();
            //Next move beats things that beat my last move
            nextMove.put('L', 'V');
            nextMove.put('V', 'S');
            nextMove.put('S', 'P');
            nextMove.put('P', 'R');
            nextMove.put('R', 'L');
            //Check if last round was a tie or the opponent beat me
            int lastResult = winner(me.charAt(me.length()-1), them.charAt(them.length()-1));
            if(lastResult == 0)
            {
                //tie, so they will chase my last throw
                System.out.print(nextMove.get(me.charAt(me.length()-1)));

                return;
            }
            else if(lastResult == 1)
            {
                //I won, so they will chase my last throw
                System.out.print(nextMove.get(me.charAt(me.length()-1)));


                return;
            }

            else{
                //I lost
                //find streak
                for(int i = 0; i<me.length(); i++)
                {
                    int a = winner(me.charAt(i), them.charAt(i));
                    if(a >= 0) streak = 0;
                    else streak++;
                }
                //check lossStreak
                //If the streak is 2, then a rotation will make it even.
                //if it is >2, something bad has happened and I need to adjust.
                if(streak>2)
                {
                    //if they are on to me, do something random-ish
                    int r = (((them.length()+me.length()-1)*13)/7)%4;
                    System.out.print(move[r]);
                    return;
                }
                //otherwise, go on with the plan
                System.out.print(nextMove.get(me.charAt(me.length()-1)));
                return;
            }
        }
    }
    public static int winner(char me, char them)
    {
        //check for tie
        if(me == them) return 0;
        //check if they won
        if(me=='V' && (them == 'L' || them == 'P')) return -1;
        if(me=='S' && (them == 'V' || them == 'R')) return -1;
        if(me=='P' && (them == 'S' || them == 'L')) return -1;
        if(me=='R' && (them == 'P' || them == 'V')) return -1;
        if(me=='L' && (them == 'R' || them == 'S')) return -1;
        //otherwise, I won
        return 1;
    }
}

1
Deveríamos estar usando print ou println? ... Eu não tinha certeza.
24514 kaine

Hummm. Eu imaginaria que ambos funcionariam, mas eu podia ver a impressão ficando bagunçada se o programa de controle capturasse a nova linha em vez do personagem. Obrigado por apontar isso, vou editar meu código por precaução #
Stranjyr

@ Stranjyr, houve alguns erros em sua última execução. Ele não bombardeou o programa de controle, mas se você pesquisar no histórico por "ToddlerProof plays n", parece que seu bot estava retornando nulo para determinadas mãos e fechando automaticamente a mão. O exemplo de jogo é "Echo & ToddlerProof", onde o Echo tocou "LVSPRLV" antes que seu bot começasse a cagar.
Eoin Campbell

@Eion Campbell Obrigado por mencionar. Vi isso antes, quando você postou os logs do torneio com falha e acho que foi corrigido. Ocorreu um erro no qual, se perdesse mais de 5 em linha reta, em vez de pular para uma jogada aleatória, apenas lançava um valor inválido. E então, porque isso a fez perder, lançou outro valor inválido. Um ciclo vicioso.
Stranjyr

Legal. Atualize-o no programa de controle agora.
Eoin Campbell

8

Bart Simpson

"Bom e velho rock! Nada supera o rock!"

puts 'R'

Correr como

ruby DoTheBartman.rb

Lisa Simpson

"Pobre e previsível Bart. Sempre escolhe o rock."

puts 'P'

Correr como

ruby LisaSimpson.rb

Better Lisa Simpson

Eu me senti mal por tornar Lisa tão estúpida, então eu permiti que ela escolhesse aleatoriamente entre as duas mãos que baterão rock. Ainda estúpida, mas ela é uma Simpson, afinal. Talvez um giz de cera tenha ficado preso em seu cérebro?

puts ['P','V'].sample

Correr como

ruby BetterLisaSimpson.rb

2
Conflito de nome menor . +1 de qualquer maneira.
Martin Ender

@ MartinBüttner Porra, não percebi isso. Os programas ainda parecem fazer coisas diferentes - e pelo menos Lisa aqui pode se sentir mais superior ao vencer duas versões diferentes de seu irmão.
Dr R Dizzle

1
Sheldor concorda ... haverá um BartBot e Bart Simpson :)
Eoin Campbell

3
Temos apenas o BortBot.
28414 JoshDM

1
Estes serão massacrados por markov :) #
Cruncher

7

Eco

Escrito em C #. Compile com csc Echo.cs. Corra comoEcho.exe ARG1 ARG2 .

Na primeira execução, o Echo usa uma opção aleatória. Toda corrida após a primeira, o Echo simplesmente repete a última ação do oponente.

using System;

namespace Echo
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Random r = new Random();
                string[] options = new string[] { "R", "P", "S", "L", "V" };
                Console.WriteLine(options[r.Next(0, options.Length)]);
            }
            else if (args.Length == 2)
            {
                string opponentHistory = args[1];
                Console.WriteLine(opponentHistory[opponentHistory.Length - 1]);
            }
        }
    }
}

7

Vulcan, Ruby

Meus dedos estão colados.

puts 'V'

Corra como

ruby vulcan.rb

(Eu acho que essa é a única estratégia de personagem para a sua configuração de fundo.)


Precisa olhar para os episódios para ver se alguém nasceu com a língua bifurcada. LizardMan FTW !!!
Eoin Campbell

3
Mas não é assim que todo mundo no big bang toca?
kaine

2
@anotherguest Isso é o que eu quis dizer com "esta é a única estratégia no personagem".
Martin Ender

6

Tiranossauro, Godzilla, Barney ... Regra dos lagartos. Ocasionalmente, eles se metem em problemas e precisam ligar para Spock ou jogar Rocks

using System;
public class LizardsRule
{
    public static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            Console.WriteLine("L");
            return;
        }
        char[] oppPreviousPlays = args[1].ToCharArray();
        var oppLen = oppPreviousPlays.Length;
        if (oppPreviousPlays.Length > 2
            && oppPreviousPlays[oppLen - 1] == 'R'
            && oppPreviousPlays[oppLen - 2] == 'R'
            && oppPreviousPlays[oppLen - 3] == 'R')
        {
            //It's an avalance, someone call Spock
            Console.WriteLine("V");
            return;
        }

        if (oppPreviousPlays.Length > 2
                && oppPreviousPlays[oppLen - 1] == 'S'
                && oppPreviousPlays[oppLen - 2] == 'S'
                && oppPreviousPlays[oppLen - 3] == 'S')
        {
            //Scissors, Drop your tail and pick up a rock
            Console.WriteLine("R");
            return;
        }

        //Unleash the Fury Godzilla
        Console.WriteLine("L");     
    }
}

6

BayesianBot, Perl (agora v2!)

Acima de tudo, este é um programa único. Nele, você verá a brilhante fusão de estatísticas e a horrível forma de programação. Além disso, esse bot provavelmente quebra muitas regras das estatísticas bayesianas, mas o nome parece mais legal.

A essência do núcleo desse bot é a criação de 250 modelos preditivos diferentes. Cada modelo assume a forma de "Dado que joguei rock no último turno e meu oponente jogou tesoura há dois turnos atrás, esta é a distribuição de probabilidade para o próximo movimento do meu oponente". Cada distribuição de probabilidade assume a forma de uma distribuição Dirichlet multidimensional.

A cada turno, as previsões de todos os modelos aplicáveis ​​(normalmente 10) são multiplicadas para formar uma previsão geral, que é usada para determinar quais movimentos têm o maior retorno esperado.

Edit 1: Nesta versão, mudei a distribuição anterior e tornei o bot mais randomizado quando está perdendo.

Existem algumas coisas que podem estar sujeitas a melhorias, como o número de modelos (250 é apenas um número de 3 dígitos), a escolha da distribuição anterior (atualmente Dir (3,3,3,3,3)) e o método de fusão de previsões. Além disso, nunca me preocupei em normalizar nenhuma das distribuições de probabilidade, o que é bom por enquanto, porque estou multiplicando-as.

Não tenho grandes expectativas, mas espero que este bot seja capaz de se sair bem.

my ($phist, $ohist) = @ARGV;

my %text2num = ('R',0,'V',1,'P',2,'L',3,'S',4);  #the RVPLS ordering is superior
my @num2text = ('R','V','P','L','S');

@phist = map($text2num{$_},split(//,$phist));
@ohist = map($text2num{$_},split(//,$ohist));

$lowerlimit = 0;
for($lowerlimit..~~@phist-3){$curloc=$_;
 $result = $ohist[$curloc+2];
 @moveset = ($ohist[$curloc],$ohist[$curloc+1],$phist[$curloc],$phist[$curloc+1]);
 for(0..3){$a=$_;
  for(0..$a){$b=$_;
   $predict[$a][$b][$moveset[$a]][$moveset[$b]][$result]++;
  }
 }
}

@recentmoves = ($ohist[-2],$ohist[-1],$phist[-2],$phist[-1]);

@curpred = (1,1,1,1,1);

for(0..3){$a=$_;
 for(0..$a){$b=$_;
  for(0..4){$move=$_;
   $curpred[$move] *= $predict[$a][$b][$recentmoves[$a]][$recentmoves[$b]][$move]/3+1;
  }
 }
}

@bestmove = (0,0,0,0,0);
for(0..4){
 $bestmove[$_] = $curpred[$_]/2+$curpred[$_-1]+$curpred[$_-2];
}

$max = 0;
for(0..4){
 if($bestmove[$_]>$max){
  $max = $bestmove[$_];
 }
}
@options=();
$offset=0;
if(($ohist[-1] - $phist[-1])%5 < 2 && ($ohist[-2] - $phist[-2])%5 < 2 && ($ohist[-3] - $phist[-3])%5 < 2){  #frequentist alert!
 $offset=int(rand(3));
}
for(0..4){
 if($bestmove[$_] == $max){
  push(@options,$num2text[($_+$offset)%5]);
 }
}
$outputb = $options[int(rand(~~@options))];

print "$outputb";

Eu tenho executado este programa da seguinte forma:

perl BayesianBot.plx

5

DynamicBot

O bot dinâmico está quase sempre mudando. Realmente odeia se repetir

import sys, random
choices = ['L','V','S','P','R'] * 20
if len(sys.argv) > 1:
    my_history = sys.argv[1]
    [choices.remove(my_history[-1]) for i in range(15)]
print(choices[random.randrange(len(choices))])

Idioma: Python 3.4.1

Comando: python dynamicbot.py <history>ou python3 dynamicbot.py <history>dependendo do seu sistema


Sim, pensei sobre isso.
Veja

5

SmartBot - Java

Minha primeira entrada para qualquer coisa neste site!

Embora não seja um nome muito criativo ...

O SmartBot encontra sequências de movimentos em que os movimentos do oponente e / ou de si são semelhantes aos últimos movimentos feitos e planejados de acordo.

name = SmartBot

Acho que para executá-lo, me corrija se estiver errado.

java -jar SmartBot.jar

import java.util.ArrayList;
public class SmartBot {
    public static void main(String[] args) {
        if(args.length ==0){
            System.out.print("L");
            return;
        }
        if(args[0].length()<3){
            String[] randLetter = new String[]{"R","P","S","L","V"};
            System.out.print(randLetter[(int) Math.floor(Math.random()*5)]);
            return;
        }
        String myHistory = args[0];
        String otherHistory = args[1];

        double rScore,pScore,sScore,lScore,vScore;//score - highest = highest probability of next opponent move
        rScore = pScore = sScore = lScore = vScore = 0;
        lScore = .001;
        ArrayList<ArrayList<Integer>> moveHits = new ArrayList<ArrayList<Integer>>();
        for(int g = 0;g<2;g++){
            for(int i=1;i<(myHistory.length() / 2) + 1;i++){
                if(g==0){
                    moveHits.add(findAll(myHistory.substring(myHistory.length() - i),myHistory));
                }
                else{
                    moveHits.add(findAll(otherHistory.substring(otherHistory.length() - i),otherHistory));
                }
            }
            for(int i = 0; i < moveHits.size();i++){
                int matchingMoves = i+1;
                ArrayList<Integer> moveIndexes = moveHits.get(i);
                for(Integer index:moveIndexes){
                    if(index+matchingMoves +1<= otherHistory.length()){
                        char nextMove = otherHistory.charAt(index + matchingMoves-1);
                        if(nextMove=='R'){rScore = rScore + matchingMoves;}
                        if(nextMove=='P'){pScore = pScore + matchingMoves;}
                        if(nextMove=='S'){sScore = sScore + matchingMoves;}
                        if(nextMove=='L'){lScore = lScore + matchingMoves;}
                        if(nextMove=='V'){vScore = vScore + matchingMoves;}
                    }
                }
            }
        }
        if(rScore >= pScore && rScore >= sScore && rScore >= lScore && rScore >= vScore){
            System.out.print("V");
            return;
        }
        if(pScore >= rScore && pScore >= sScore && pScore >= lScore && pScore >= vScore){
            System.out.print("L");
            return;
        }
        if(sScore >= pScore && sScore >= rScore && sScore >= lScore && sScore >= vScore){
            System.out.print("R");
            return;
        }
        if(vScore >= pScore && vScore >= sScore && vScore >= lScore && vScore >= rScore){
            System.out.print("L");
            return;
        }
        if(lScore >= pScore && lScore >= sScore && lScore >= rScore && lScore >= vScore){
            System.out.print("S");
        }
        return;
    }
    public static ArrayList<Integer> findAll(String substring,String realString){
        ArrayList<Integer> ocurrences = new ArrayList<Integer>();
        Integer index = realString.indexOf(substring);
        if(index==-1){return ocurrences;}
        ocurrences.add(index+1);
        while(index!=-1){
            index = realString.indexOf(substring,index + 1);
            if(index!=-1){
                ocurrences.add(index+1);
            }
        }
        return ocurrences;
    }
}

Ele atribui uma pontuação para cada próximo movimento possível pelo número de vezes que padrões semelhantes ocorreram.

Favorece ligeiramente o lagarto.


Acredito que é assim que você executa, se você o jar primeiro. Se você simplesmente compilá-lo primeiro, então java ABotdeve funcionar (lembre-se o nome do arquivo o mesmo que a classe pública)
Justin

Obrigado! Como um programador relativamente novo, eu não estava ciente disso.
Stretch Maniac

5

SpockOrRock - PHP

SpockOrRock

Quando jogado no mundo real, a maioria das pessoas instintivamente escolhe uma tesoura. Este bot escolhe Spock ou Rock para vencer o jogador médio. Não se preocupa com as rodadas anteriores.

correr com php spockorrock.php

<?php

//Pick either Spock or Rock
if (rand(0,1) == 0)     echo("R\n");
else                    echo("V\n");


?>

4

SlowLizard, Ruby

Depois de começar com o Lizard, ele sempre escolhe um movimento aleatório que supera o movimento anterior do oponente.

responses = {
  'R' => ['P', 'V'],
  'P' => ['S', 'L'],
  'S' => ['R', 'V'],
  'L' => ['S', 'R'],
  'V' => ['P', 'L']
}

if ARGV.length == 0
  puts 'L'
else
  puts responses[ARGV[1][-1]].sample
end

Corra como

ruby slowlizard.rb

4

LexicographicBot

Este bot gosta de pedir suas cartas, então ele escolherá uma resposta que é 1 maior do que seu oponente deu na rodada anterior - a menos que o oponente tenha escolhido Vulcan, ele escolhe aleatoriamente uma resposta.

import sys
import random

choices = ["L", "P", "R", "S", "V"]

total = len(sys.argv)
if total==1:
    print("L")
    sys.exit()

opponent = sys.argv[2]
opponent_last = opponent[-1]

if opponent_last == choices[-1]:
    print(random.choice(choices))
else:
    next = choices.index(opponent_last)+1
    print(choices[next])

Isso espera que a mão do oponente seja distribuída em segundo:

                           me
                            v
python LexicographicBot.py SR RV
                              ^
                            opponent

@ MartinBüttner: Comando adicionado! Eu tenho estado bastante ocupado no trabalho tentando publicar algo, daí o desaparecimento.
Kyle Kanos

quebra na primeira execução sem argumentos. Traceback (última chamada mais recente): arquivo "LexicographicBot \ LexicographicBot.py", linha 10, no <module> oponente = sys.argv [2] IndexError: list index out of range
Eoin Campbell

@EoinCampbell: esqueci a cláusula de saída na primeira execução, foi adicionada e deve funcionar bem agora.
Kyle Kanos

4

Werevulcan - Ruby

Correr como ruby werevulcan.rb

@rules = {

  'L' => %w[V P],
  'P' => %w[V R],
  'R' => %w[L S],
  'S' => %w[P L],
  'V' => %w[R S]
}

@moves = @rules.keys

def defeats?(move1, move2)
  @rules[move1].include?(move2)
end

def score(move1, move2)
  if move1 == move2
    0
  elsif defeats?(move1, move2)
    1
  else
    -1
  end
end

def move
  player, opponent = ARGV

  # For the first 30 rounds, pick a random move that isn't Spock
  if player.to_s.size < 30
    %w[L P R S].sample
  elsif opponent.chars.to_a.uniq.size < 5
    exploit(opponent)
  else
    # Pick a random move that's biased toward Spock and against lizards
    %w[L P P R R S S V V V].sample
  end

end

def exploit(opponent)
  @moves.shuffle.max_by{ |m| opponent.chars.map{|o| score(m,o) }.reduce(:+) }
end

puts move

O werevulcan parece normal durante o dia, mas quando a lua nasce, seus ouvidos ficam pontudos e seus movimentos ficam mais lógicos.


4

Analogizador - Ruby

Corra com ruby analogizer.rb. Fiz uma correção lógica no código, mas não faço ideia por que houve erros nisso.

@rules = {

  'L' => %w[V P],
  'P' => %w[V R],
  'R' => %w[L S],
  'S' => %w[P L],
  'V' => %w[R S]
}

@moves = @rules.keys

def defeats?(move1, move2)
  @rules[move1].include?(move2)
end

def score(move1, move2)
  if move1 == move2
    0
  elsif defeats?(move1, move2)
    1
  else
    -1
  end
end

def move
  player, opponent = ARGV

  case player.to_s.size
  # Throw six lizards in the beginning to confuse opponent
  when 0..5
    'L'
  when 6
    'V'
  when 7
    'S'
  when 8
    'P'
  when 9
    'R'
  else
    analyze_history(player.chars.to_a, opponent.chars.to_a)
  end

end

def analyze_history(player, opponent)
  my_last_move = player.last
  predicted_moves = Hash.new {0}
  opponent_reactions = player.zip(opponent.drop(1))

  # Check whether opponent tended to make a move that would've beaten, lost, or tied my last move
  opponent_reactions.each do |my_move, reaction|
    score = score(reaction, my_move)
    analogous_moves = @moves.select { |move| score == score(move, my_last_move) }
    analogous_moves.each { |move| predicted_moves[move] += 1 }
  end

  # Assume if an opponent has never made a certain move, it never will
  @moves.each { |m| predicted_moves[m] = 0 unless opponent.include?(m) }

  # Pick the move with the best score against opponent's possible moves, weighted by their likelihood, picking randomly for ties
  @moves.shuffle.max_by{ |m| predicted_moves.map { |predicted, freq| score(m, predicted) * freq }.reduce(0,:+) }

end

puts move

Supõe que o bot oponente esteja sempre reagindo ao meu movimento anterior e escolhendo algo que o derrote, algo que o perca, ou o mesmo movimento, possivelmente de um conjunto restrito de movimentos possíveis. Em seguida, ele escolhe a melhor jogada, considerando essa suposição.

Exceto que os dez primeiros movimentos são codificados: primeiro, eu finjo que só conheço lagarto, depois presumo que meu oponente sempre jogue algo para vencer a última coisa que joguei até ter dados suficientes para uma análise adequada.


4

Java - SelfLoathingBot

BotName: SelfLoathingBot
Compile: Save as 'SelfLoathingBot.java'; compile.
Run:     java SelfLoathingBot [me] [them]

Bot começa aleatoriamente, então ~ 33% para se tornar aleatório, ou ~ 33% para jogar uma tática vencedora contra qualquer uma das jogadas imediatamente anteriores, com 50% de escolha da tática vencedora.

import java.util.Random;

public class SelfLoathingBot {

    static final Random RANDOM = new Random();

    private static char randomPlay() {

        switch (RANDOM.nextInt(5)) {

            case 0 : return 'R';

            case 1 : return 'P';

            case 2 : return 'S';

            case 3 : return 'L';

            default : return 'V';
        }
    }

    private static char antiPlay(String priorPlayString) {

        char[] priorPlays = priorPlayString.toCharArray();

        int choice = RANDOM.nextInt(2);

        switch (priorPlays[priorPlays.length - 1]) {

            case 'R' : return choice == 0 ? 'P' : 'V'; 

            case 'P' : return choice == 0 ? 'S' : 'L';

            case 'S' : return choice == 0 ? 'V' : 'R';

            case 'L' : return choice == 0 ? 'R' : 'S';

            default : return choice == 0 ? 'L' : 'P'; // V        
        }
    }

    public static void main(String[] args) {

        int choice = args.length == 0 ? 0 : RANDOM.nextInt(3);

        char play;

        switch (choice) {

            case 1 :

                // 33.3% chance Play myself
                play = antiPlay(args[0]);
                break;

            case 2 :

                // 33.3% chance Play opponent just in case opponent is screwy like that
                play = antiPlay(args[1]);
                break;

            default :

                // 33.3% chance 100% Random
                play = randomPlay();
        }

        System.out.print(play);
        return;
    }
}

4

O analista

O analista analisa algumas coisas e faz algumas coisas para tentar vencê-lo.

compilar javac Analyst.javae executar comojava Analyst

import java.util.Random;

public class Analyst{
    public static void main(String[] args){
        char action = 'S';

        try{
            char[] enemyMoves = null, myMoves = null;

            //first move is random
            if(args.length == 0){
                System.out.print(randomMove());
                System.exit(0);
            //moves 2-3 will beat their last move
            }else if(args[0].length() < 8){
                System.out.print(counterFor(args[1].charAt(args[1].length()-1)));
                System.exit(0);
            //following moves will execute some analyzation stuff
            }else{
                //get previous moves
                myMoves = args[0].toCharArray();
                enemyMoves = args[1].toCharArray();
            }

            //test if they're trying to beat our last move
            if(beats(enemyMoves[enemyMoves.length-1], myMoves[myMoves.length-2])){
                action = counterFor(counterFor(myMoves[myMoves.length-1]));
            }
            //test if they're copying our last move
            else if(enemyMoves[enemyMoves.length-1] == myMoves[myMoves.length-2]){
                action = counterFor(myMoves[myMoves.length-1]);
            }
            //else beat whatever they've done the most of
            else{
                action = counterFor(countMost(enemyMoves));
            }

            //if they've beaten us for the first 40 moves, do the opposite of what ive been doing
            if(theyreSmarter(myMoves, enemyMoves)){
                action = counterFor(action);
            }

        //if you break my program do something random
        }catch (Exception e){
            action = randomMove();
        }

        System.out.print(action);
    }

    private static char randomMove(){
        Random rand = new Random(System.currentTimeMillis());
        int randomMove = rand.nextInt(5);

        switch (randomMove){
            case 0: return 'R';
            case 1: return 'P';
            case 2: return 'S';
            case 3: return 'L';
            default: return 'V';
        }
    }

    private static char counterFor(char move){
        Random rand = new Random(System.currentTimeMillis());
        int moveSet = rand.nextInt(2);

        if(moveSet == 0){
            switch (move){
                case 'R': return 'P'; 
                case 'P': return 'S'; 
                case 'S': return 'R'; 
                case 'L': return 'R'; 
                default: return 'P';
            }
        }else{
            switch (move){
                case 'R': return 'V'; 
                case 'P': return 'L'; 
                case 'S': return 'V'; 
                case 'L': return 'S'; 
                default: return 'L';
            }
        }
    }

    private static boolean beats(char move1, char move2){
        if(move1 == 'R'){
            if((move2 == 'S') || (move2 == 'L')){
                return true;
            }else{
                return false;
            }
        }else if(move1 == 'P'){
            if((move2 == 'R') || (move2 == 'V')){
                return true;
            }else{
                return false;
            }
        }else if(move1 == 'S'){
            if((move2 == 'L') || (move2 == 'P')){
                return true;
            }else{
                return false;
            }
        }else if(move1 == 'L'){
            if((move2 == 'P') || (move2 == 'V')){
                return true;
            }else{
                return false;
            }
        }else{
            if((move2 == 'R') || (move2 == 'S')){
                return true;
            }else{
                return false;
            }
        }
    }

    private static char countMost(char[] moves){
        int[] enemyMoveList = {0,0,0,0,0};

        for(int i=0; i<moves.length; i++){
            if(moves[i] == 'R'){
                enemyMoveList[0]++;
            }else if(moves[i] == 'P'){
                enemyMoveList[1]++;
            }else if(moves[i] == 'S'){
                enemyMoveList[2]++;
            }else if(moves[i] == 'L'){
                enemyMoveList[3]++;
            }else if(moves[i] == 'V'){
                enemyMoveList[4]++;
            }
        }

        int max = 0, maxIndex = 0;
        for(int i=0; i<5; i++){
            if(enemyMoveList[i] > max){
                max = enemyMoveList[i];
                maxIndex = i;
            }
        }

        switch (maxIndex){
            case 0: return 'R';
            case 1: return 'P';
            case 2: return 'S';
            case 3: return 'L';
            default: return 'V';
        }
    }

    private static boolean theyreSmarter(char[] myMoves, char[] enemyMoves){
        int loseCounter = 0;

        if(enemyMoves.length >= 40){
            for(int i=0; i<40; i++){
                if(beats(enemyMoves[i],myMoves[i])){
                    loseCounter++;
                }
            }
        }else{
            return false;
        }

        if(loseCounter > 20){
            return true;
        }else{
            return false;
        }
    }
}

4

O jogador - Python 2

import sys
import random

MODE = 1

moves = 'RSLPV'

def element_sums(a, b):
    return [a[i] + b[i] for i in xrange(len(a))]

def move_scores(p):
    def calc(to_beat):
        return ['LDW'.find('DLLWW'[moves.find(m)-moves.find(to_beat)]) for m in moves]

    return dict(zip(moves, element_sums(calc(p[0]), calc(p[1]))))

def move_chooser(my_history, opponent_history):
    predict = sorted(moves, key=opponent_history.count, reverse=MODE)[-2:]
    scores = move_scores(predict)
    return max(scores, key=lambda k:scores[k])

if __name__ == '__main__':
    if len(sys.argv) == 3:
        print move_chooser(*sys.argv[1:])
    elif len(sys.argv) == 1:
        print random.choice(moves)

Ao contrário do nome, a única aleatoriedade usada neste programa é na primeira rodada, quando não há informações. Em vez disso, recebeu o nome da falácia do jogador, a crença de que, se um evento aleatório aconteceu com menos frequência no passado, é mais provável que ocorra no futuro. Por exemplo, se você jogar uma moeda justa 20 vezes e os 15 primeiros forem cara, a falácia do jogador afirma que as chances de os flips restantes serem caudas aumentam. Claro, isso é falso; Independentemente dos flips anteriores, as chances de uma moeda chegar com coroa é sempre de 50%.

Este programa analisa a história do oponente, encontra os 2 movimentos que ele usou menos até agora e assume que o movimento do oponente desta vez será um desses dois. Atribuindo 2 a uma vitória, 1 a um empate e 0 a uma perda, ele encontra o lance com a pontuação máxima contra esses dois lances previstos e o lança.

O irmão do jogador - Python 2

import sys
import random

MODE = 0

moves = 'RSLPV'

def element_sums(a, b):
    return [a[i] + b[i] for i in xrange(len(a))]

def move_scores(p):
    def calc(to_beat):
        return ['LDW'.find('DLLWW'[moves.find(m)-moves.find(to_beat)]) for m in moves]

    return dict(zip(moves, element_sums(calc(p[0]), calc(p[1]))))

def move_chooser(my_history, opponent_history):
    predict = sorted(moves, key=opponent_history.count, reverse=MODE)[-2:]
    scores = move_scores(predict)
    return max(scores, key=lambda k:scores[k])

if __name__ == '__main__':
    if len(sys.argv) == 3:
        print move_chooser(*sys.argv[1:])
    elif len(sys.argv) == 1:
        print random.choice(moves)

Ao mudar o MODE variável para 0, este programa funcionará com base em uma falácia relacionada, também conhecida como falácia do jogador. Ele afirma que, se um evento aleatório tiver ocorrido com mais frequência no passado, é mais provável que ocorra no futuro. Por exemplo, se você jogar uma moeda 20 vezes e os 15 primeiros forem cara, essa falácia indica que os flips restantes são mais propensos a ser cara, já que atualmente há uma raia. No modo 0, este programa opera da mesma maneira, exceto que assume que o oponente fará um dos dois movimentos que ele realiza com mais freqüência até agora.

Então, sim, esses dois programas têm apenas um caractere. :)


Em que condições TheGambler altera MODE?
Dr R Dizzle

@DrRDizzle Não, parece que este é um envio de dois bots em um.
Pa Elo Ebermann 29/07

2
Este programa não seria mais eficaz se o MODE alternasse se você perder mais de uma certa quantidade de vezes seguidas?
Dr R Dizzle

4

Dienstag (Python 2)

Minha primeira entrada Pony parece se sair muito bem com toda a sua segunda adivinhação (tripple adivinhação, ...) e meta raciocínio. Mas isso é mesmo necessário?

Então, aqui está Dienstag, o amiguinho de Pony, com apenas uma das 55 estratégias: prever o próximo passo do oponente e vencê-lo.

A longo prazo, Dienstag vence ou empata com todos os Bots entre os dez primeiros da tabela de classificação atual. Exceto por Pony.

import sys
if len(sys.argv)<2 or len(sys.argv[1])<2: print 'L'; sys.exit()
hist = [map('RPSVL'.index, p) for p in zip(sys.argv[1], sys.argv[2])]
N = len(hist)
cand = range(N-1)
for l in xrange(1,N):
    cand = ([c for c in cand if c>=l and hist[c-l+1]==hist[-l]] or cand[-1:])
print 'RPSVL'[(hist[cand[-1]+1][1]+(1,3)[N%2==0])%5]

Correr como:

python Dienstag.py

Admito que o código esteja um pouco ofuscado. Se alguém quiser saber mais sobre isso, posso acrescentar explicações.

Edit: Aqui está um pequeno exemplo de explicação para explicar a ideia:

  • O programa obtém o histórico próprio e os movimentos do oponente:

    sys.arg[1] = 'LLVLLVL', sys.arg[2] = 'RPSPSSP'

  • O histórico é combinado em uma lista de pares e os movimentos são traduzidos para números (R = 0, ...):

    hist = [[4, 0], [4, 1], [3, 2], [4, 1], [4, 2], [3, 2], [4, 1]]

  • O número de rodadas disputadas até agora é determinado:

    N = 7

  • A idéia básica agora é procurar a cadeia mais longa e ininterrupta, exatamente dos últimos movimentos da história anterior. O programa controla onde essa cadeia termina na lista cand(para 'candidatos'). No começo, sem verificação, todas as posições no histórico, exceto a última, são consideradas:

    cand = [0, 1, 2, 3, 4, 5]

  • Agora o comprimento das cadeias possíveis é aumentado passo a passo. Para o comprimento da corrente l = 1, procura ocorrências anteriores do último par de movimentos [4, 1]. Isso pode ser encontrado na posição do histórico 1e 3. Somente estes são mantidos na candlista:

    cand = [1, 3]

  • Em seguida, l = 2verifica qual dos possíveis candidatos foi precedido pelo penúltimo par de movimentos [3, 2]. Este é apenas o caso da posição 3:

    cand = [3]

  • Para l = 3 mais, não há cadeias anteriores desse comprimento e candestariam vazias. Nesse caso, o último elemento de candé mantido:

    cand = [3]

  • O bot agora assume que a história se repetirá. A última vez que o Caim [3, 2], [4, 1]ocorreu, foi seguido por[4, 2] . Assim, o oponente jogou 2(tesoura) que pode ser derrotado por (2+1)%5 = 3(Spock) ou (2+3)%5 = 0(pedra). O bot responde, com a primeira ou a segunda alternativa, dependendo se Né ímpar ou mesmo apenas para introduzir alguma variação.

  • Aqui mova 3 é escolhido o que é então traduzido de volta:

    print 'V'

Nota: Dienstag tem complexidade de tempo O ( N 2 ) para retornar o próximo movimento após N rodadas. O pônei tem complexidade de tempo O ( N 3 ). Portanto, nesse aspecto, eles provavelmente são muito piores que a maioria das outras entradas.


por favor faça. esta é uma experiência de aprendizado incrível para mim. Eu geralmente moro em terra C # / Java, então toda a loucura lua, rubi, python e haskell é muito interessante para mim.
Eoin Campbell

Também estou tentado a adicionar uma instância extra de Pony aos jogos. Será como ter que lutar contra o seu espelho de auto no 3º para durar níveis combate mortal ;-)
Eoin Campbell

@EoinCampbell :-) Pelo menos a partida direta entre Pony e Pony seria um empate perfeito. Não há nenhum elemento aleatório em ambos os meus bots.
Emil

3

Bash Rocks

O cygwin é pedir demais em tempo de execução?

bashrocks.sh:

#!/bin/bash
HAND=(R P S L V)
RAND=`od -A n -t d -N 1 /dev/urandom | xargs`
echo ${HAND[ $RAND  % 5 ]}

e execute assim:

sh bashrocks.sh

5
Depois de ler o título, estou um pouco decepcionado por você fazer qualquer coisa, menos R. ;)
Martin Ender

@mccannf. tendo alguns problemas com este ... Instalei o cygwin e modifiquei seus scripts com caminhos totalmente qualificados para C: \ Cygwin \ bin para od.exe, xargs.exe e echo.exe. ainda está recebendo o seguinte erro. C: / Cygwin / bin / xargs: echo: Não existe esse arquivo ou diretório% 5 ") erro de sintaxe: operando esperado (o token de erro é"
Eoin Campbell

@EoinCampbell - quando você cria o arquivo no Windows, pode executar dos2unixo arquivo no cygwin antes de executá-lo?
Mccannf

certo. Vou tentar.
Eoin Campbell

Eu acho que o problema pode ser com a declaração / dev / urandom
Eoin Campbell

3

Algoritmo

Um algoritmo para ter um.

Porque sempre é mais seguro fazer alguma coisa, quanto mais complicado, melhor.

Ainda não fizemos matemática séria, portanto esse algoritmo pode não ser tão eficaz.

import random, sys

if __name__ == '__main__':

    # Graph in adjacency matrix here
    graph = {"S":"PL", "P":"VR", "R":"LS", "L":"VP", "V":"SR"}
    try:
        myHistory = sys.argv[1]
        opHistory = sys.argv[2]
        choices = ""

        # Insert some graph stuff here. Newer versions may include advanced Math.
        for v in graph:
            if opHistory[-1] == v:
                for u in graph:
                    if u in graph[v]:
                        choices += graph[u]

        print random.choice(choices + opHistory[-1])

    except:
        print random.choice("RPSLV")

Programa Python 2: python algorithm.py


1
Resumo deste algoritmo: observe o que o oponente jogou pela última vez e, em seguida, toque aleatoriamente um dos dois movimentos que perderiam contra o último movimento do oponente se o jogassem novamente. Portanto, é melhor contra bots que não jogam o mesmo movimento duas vezes seguidas.
Rory O'Kane

Haha Realmente não sei se fiz dessa maneira. Se não estou errado, na verdade é apenas uma maneira complicada de selecionar aleatoriamente qualquer um dos 5 movimentos. ;)
Vetorizado

3

FairBot, Ruby

Vamos começar simples.

puts ['R','P','S','L','V'].sample

Corra como

ruby fairbot.rb

pequeno erro de digitação no último parâmetro 'V'. fixaram-lo em myside se você quer atualizar para a completude
Eoin Campbell

@EoinCampbell obrigado, corrigido!
Martin Ender

1
O interessante é que isso tem chances exatamente iguais de ganhar contra TODAS as estratégias.
Cruncher

3

ViolentBot

Este bot escolhe a opção mais violenta com base na escolha anterior do oponente:

import sys

choice_dict = {"L" : "S", "P" : "S", "R" : "V", "S" : "V", "V" : "L"}

total = len(sys.argv)
if total==1:
    print("L")
    sys.exit()

opponent = sys.argv[2]
opponent_last = opponent[-1]

print(choice_dict[opponent_last])

Correr como

python ViolentBot.py (me) (opp)

quebra sem parâmetros. Traceback (chamada mais recente passada): File "ViolentBot \ ViolentBot.py", linha 9, em <module> oponente = sys.argv [2] IndexError: índice de lista fora de alcance
Eoin Campbell

quebra com params. Traceback (última chamada mais recente): arquivo "ViolentBot \ ViolentBot.py", linha 12, em <module> print (choice_dict [oposent_last]) KeyError: 'S'
Eoin Campbell

@EoinCampbell: adicionei uma cláusula de saída para a primeira execução, você deve poder executá-la agora.
Kyle Kanos

3

Haskell - MonadBot

Não sei se o ghc é considerado "dentro da razão", mas vamos supor que sim. A estratégia deste bot é combater o movimento mais popular de seu oponente.

Compile: ghc monadbot.hs
Run:     ./monadbot [Arg1] [Arg2]

Código:

import System.Environment
import Data.List
import Data.Ord

main :: IO ()
main = do
  args <- getArgs
  let moves = if not (null args) then args !! 1 else ""
      fave = if not (null moves) then head $ maximumBy (comparing length) (group $ sort moves) else 'V'
  putChar $ case fave of 'R' -> 'P'
                         'P' -> 'S'
                         'S' -> 'R'
                         'L' -> 'R'
                         'V' -> 'P'
                         _   -> 'V'
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.