O Ultimate Samurai Showdown


37

Aviso: Este desafio do foi concluído. Isso significa que a marca de seleção verde, que foi concedida ao C5H8NNaO4 por sua entrada, The Observer não será movida para nenhuma nova resposta.

Você ainda pode enviar novas entradas, mas pode haver atrasos nos novos torneios, pois eu não estou mais procurando ativamente por novas entradas.

Introdução

Neste desafio, você está jogando um jogo de arcade intitulado The Ultimate Samurai Showdown Versão Especial Edição Especial 2.0 X Alpha Omega Turbo (ou apenas Ultimate Samurai Showdown, abreviado). Seus oponentes? Ninguém menos que os outros membros da Programming Puzzles & Code Golf!

Como você pode esperar de um jogo de arcade PPCG, você não joga Ultimate Samurai Showdown diretamente, mas escreve um programa que jogará o jogo para você. Este programa lutará contra programas enviados por outros usuários em duelos individuais. O programa mais qualificado será coroado o Samurai Supremo do PPCG e receberá o visto verde da lenda.

Descrição do jogo

Esta seção descreve a mecânica por trás do jogo.

Condição da vitória

Uma partida consiste em dois samurais que se enfrentam. Cada samurai começa cada partida com 20 pontos de vida e 1 honra . Um samurai vence se seu oponente estiver morto e ele ainda estiver vivo. Existem dois métodos pelos quais um samurai pode morrer:

  1. Se os pontos de vida de um samurai forem reduzidos a 0, ele morrerá.
  2. Se um samurai traz sua própria honra abaixo de 0, ele será derrubado pelos deuses por agir desonrosamente em um duelo.

Ser abatido pelos deuses tem maior prioridade do que ter pontos de vida reduzidos a 0, portanto, em uma situação em que um samurai está com 0 pontos de vida e o outro com -1 de honra, o samurai com 0 pontos de vida vencerá. Em uma situação em que ambos os samurais estão com -1 de honra, ambos são atingidos pelos deuses e o jogo é um empate.

Uma partida consiste em até 500 turnos . Se todos os 500 turnos passarem e a partida não tiver sido decidida (nenhum samurai morreu), os deuses ficam entediados e atacam os dois samurais, resultando em empate.

Ações

Em cada turno, o samurai deve executar exatamente uma das seguintes ações:

W

O samurai deve esperar e não executar nenhuma ação. Isso o faz parecer legal, mas não o ajuda a derrotar seu oponente. Essa também é a ação padrão.

B

O samurai deve se curvar ao seu oponente de maneira honrosa. Isso agrada aos deuses e, assim, o samurai ganhará 1 honra. A honra é vital para o sucesso do seu samurai, porque a honra é essencialmente o "recurso" para este jogo - todos se afastam Be Wpodem diminuir a honra. Além disso, se um samurai ganha 7 de Honra ou mais, ele recebe o uso da Espada dos Deuses . As implicações disso estão descritas abaixo.
No entanto, curvar-se ao seu oponente o deixa aberto se ele decidir acertá-lo com sua espada, portanto, tenha cuidado ao escolher se curvar.

G

O samurai deve entrar em uma posição defensiva e se proteger contra qualquer golpe de espada. Este movimento irá bloquear com sucesso todos os golpes de espada, mesmo aqueles feitos com a Espada dos Deuses .
No entanto, os deuses franzem a testa para um samurai excessivamente defensivo, então esse movimento consumirá 1 Honra se a ação do samurai no turno imediatamente anterior também estivesse protegendo. Não consome Honor de outra forma.

I

O samurai deve tentar golpear seu oponente com um rápido puxão de sua espada da bainha. Se o samurai tiver 7 de Honra ou mais, ele usará a Espada dos Deuses, em vez de sua espada comum. Este movimento consome 1 Honra.
O empate rápido é um ataque rápido que derrota ataques aéreos mais lentos, no entanto, perde contra desvios. Se o ataque se conectar com sucesso, ele causará 1 ou 2 de dano com a Espada dos Deuses .

P

O samurai deve tentar desviar qualquer ataque recebido e então lançar seu próprio ataque. Se o samurai tiver 7 de Honra ou mais, ele usará a Espada dos Deuses, em vez de sua espada comum. Este movimento consome 1 Honra.
O desvio é uma boa manobra contra ataques rápidos, mas será dominado por ataques aéreos mais lentos. Se o ataque se conectar com sucesso, ele causará 1 ou 2 de dano com a Espada dos Deuses .

O

O samurai deve tentar golpear seu oponente com um ataque aéreo mais lento. Se o samurai tiver 7 de Honra ou mais, ele usará a Espada dos Deuses, em vez de sua espada comum. Este movimento consome 1 honra.
O ataque aéreo pode dominar os desvios, mas perderá contra ataques rápidos. Se o ataque se conectar com sucesso, ele causará 1 ou 2 de dano com a Espada dos Deuses .

Espada dos Deuses

Um samurai com honra de 7 anos ou mais ganha a capacidade de usar a Espada dos Deuses . Se sua Honra for reduzida para menos de 7, a capacidade de usar a Espada dos Deuses será revogada. A Espada dos Deuses causa 2 pontos de dano em vez de 1.

A Espada dos Deuses não permite que um ataque derrote um golpe de espada que normalmente não derrotaria. Por exemplo, um desvio da Espada dos Deuses ainda perderá com um ataque aéreo normal, e um empate rápido da Espada dos Deuses não prevalecerá sobre um empate rápido comum. Na verdade, a chamada espada dos deuses não é tão poderosa - talvez seja uma piada cósmica dos deuses ...

Tabela de interação

O Snippet de pilha abaixo contém uma tabela que lista explicitamente todos os resultados possíveis das diferentes combinações de ações que os dois samurais podem executar. Para visualizá-lo, clique em "Mostrar trecho de código" e clique em "Executar trecho de código".

Comunicação do Programa

Para facilitar a execução do torneio, um programa de controle foi escrito para desempenhar o papel dos "deuses" - ele mantém registros de honra e saúde e ataca os samurais de acordo. Esta seção descreve como o seu programa se comunicará com o programa do controlador.

Descrição da entrada

O programa do controlador chamará seu programa a partir da linha de comando da seguinte maneira:

<command> <history> <enemy_history> <your_health> <enemy_health> <your_honour> <enemy_honour>

Onde:

  • <command>é o comando necessário para executar seu programa. Por exemplo, se o seu programa estiver em um arquivo super_sentai.pl, o comando provavelmente está perl super_sentai.pl.

  • <history>é uma história de movimentos que você fez. Por exemplo, WWBPsignificaria que você esperou duas vezes, fez uma reverência e desviou uma vez.

  • <enemy_history>é uma história de movimentos feitos por seu inimigo. Por exemplo, BBBIsignificaria que seu inimigo se curvou três vezes e realizou um empate rápido.

  • <your_health> é sua saúde atual.

  • <enemy_health> é a saúde atual do inimigo.
  • <your_honour> é a sua honra atual.
  • <enemy_honour> é a honra atual do inimigo.

Pela primeira vez, o historye enemy_historyestará vazio, portanto, seu programa será chamado apenas com os últimos quatro argumentos como este:

<command> <your_health> <enemy_health> <your_honour> <enemy_honour>

Por favor, esteja preparado para isso!

Leitores astutos podem perceber que os quatro argumentos que proporcionam a honra e a saúde de ambos os samurais são, em certa medida, supérfluos; como este é um jogo de informações perfeito, a honra e a saúde do samurai podem ser determinadas usando apenas as histórias.

Esses valores são fornecidos para fins de conveniência, para que você não precise analisar os argumentos do histórico. Isso deve ser útil para implementar estratégias simples, como não atacar quando sua Honra for 0.

Descrição da saída

Para escolher uma ação, seu programa deve saída um dos W, B, G, I, P, ou Opara a saída padrão, dependendo de qual ação você quer fazer. Se o seu programa não produzir nada dentro de 1000ms, ele será encerrado e seu programa será tratado como se tivesse sido produzido W.

Se o seu programa exibir mais de uma letra, somente a primeira letra será considerada - portanto, a saída Parryserá a mesma que a saída P.

Se a saída da primeira letra do seu programa não for uma das opções listadas acima, será o padrão para W.

Formato da submissão

Envie um programa como resposta a esta postagem. Você pode enviar vários programas. Se você estiver enviando vários programas simples, recomendo enviá-los como uma única resposta; se você estiver enviando vários programas complexos, recomendo enviá-los como respostas separadas. Depois de adicionar seus programas ao torneio, farei um commit no repositório git com sua entrada (link abaixo).

Se eu encontrar problemas que impeçam que seu programa seja adicionado ao torneio, deixarei um comentário em sua inscrição, indicando o problema.

Inclua o seguinte no seu envio:

  1. O nome legível por humanos do seu programa, para uso em placares. Espaços são permitidos aqui; vírgulas e caracteres Unicode não são.
  2. O idioma em que seu programa está escrito. Evite escrever em idiomas estranhos e de difícil acesso, como o TinyMUSH.
  3. Uma breve sinopse do seu programa. Essa pode ser uma descrição de como o programa funciona, ou apenas algum texto específico sobre o seu programa (se você quiser ser todo secreto) ou talvez ambos.
  4. Os comandos necessários para executar seu programa. Por exemplo, se você estivesse escrevendo seu envio em Java chamado example.java, você forneceria instruções de compilação e instruções de javac example.javaexecução java example.
  5. O código fonte do programa.

Para ajudar no envio, forneço um modelo de envio que pode ser encontrado aqui . O modelo torna as submissões mais agradáveis. Eu recomendo fortemente usá-lo.

Eu também forneço dois exemplos de entradas. Embora as entradas de exemplo participem do round robin, seu principal objetivo é esclarecer os formatos de envio e entrada / saída do torneio, em vez de serem sérios candidatos ao título de Ultimate Samurai.

Estrutura do torneio

Esta seção descreve como o torneio entre os participantes será realizado.

Programa de Controle

O programa de controle está escrito em Python 2 e pode ser encontrado no repositório Ultimate Samurai Showdown Github . Se você deseja executá-lo, instruções sobre como executá-lo estão incluídas no arquivo README.md no link. No entanto, apenas torneios realizados no meu computador serão oficiais para evitar diferenças de hardware que afetem os resultados do torneio.

O programa de controle será executado em um laptop executando o Arch Linux. Ele possui um processador Intel Core i7 e 8 GB de RAM. Esforçarei-me por obter todas as entradas em execução no meu computador, mas agradeceria imensamente se você evitar idiomas que não possam ser acessados ​​livremente (como em nenhum custo monetário).

Sistema de pontuação

O sistema de pontuação é um round robin. Cada programa jogará oito partidas contra todos os outros programas. Uma vitória concede ao programa 1 ponto, uma perda sem pontos e um empate 0,5 pontos. O programa com a maior pontuação vence o jogo. Se houver empate, disputarei os dois melhores programas para determinar o vencedor.

O número de vezes que cada programa será reproduzido pode diminuir de 8 se houver um número extremamente grande de participantes. Vou adicionar uma nota aqui se isso ocorrer.

Estarei executando o round robin muitas vezes à medida que novos envios forem publicados, mas é apenas o round robin mais recente que contará.

Desqualificações

É possível que seu programa seja desqualificado do torneio. A desqualificação pode ocorrer se:

  • Seu programa não compila ou executa;
  • Seu programa é uma duplicata estratégica de outro programa (ou seja, implementa exatamente a mesma estratégia que outro programa);
  • Seu programa tenta sabotar outros programas modificando o código do controlador, o código de outro programa, etc;
  • Seu programa tenta explorar um bug no código do controlador. Em vez de explorar os bugs, você deve abrir um problema no repositório git, fazer um comentário aqui ou enviar um ping para mim no chat.

Resultados passados

Resultados detalhados de todos os torneios são disponibilizados na página wiki .

O torneio mais recente foi concluído em 17/07/2015 - 07:20. Aqui está um resumo dos resultados:

The Observer: 209.0
Coward: 203.0
Monk: 173.0
Elephant Warrior: 157.0
Iniqy: 157.0
Agent 38: 144.0
Ninja: 138.0
Meiyo Senshi: 138.0
Kakashi: 136.0
Yoshimitsu: 131.0
Hermurai: 121.0
Warrior Princess: 120.0
Gargoyle: 119.5
The Honourable: 119.0
Hebi: 118.5
Predictor: 116.0
Whack-a-mole: 107.0
The Fool: 106.0
The Prophet: 105.0
Copy-san: 97.0
YAGMCSE: 80.0
The Waiter: 66.0
Swordsman: 43.0
Spork Holder: 32.5
Blessed Samurai: 27.5
Attacker: 27.0
The Terminator: 17.0
Master Yi: 16.0

11
O garçom está indo surpreendentemente bem. Deve estar ganhando vitórias contra o Spork Holder quando ficar sem honra.
StephenTG

Este é um grande desafio. Você claramente pensa muito e trabalha nisso, e acho que definitivamente valeu a pena. Excelente trabalho. :) #
Alex A. Alex

11
@ C5H8NNaO4 Sim, vou verificar se há atualizações nos bots antes de executar o próximo torneio.
absinto

11
Aviso: Meu laptop quebrou recentemente. Portanto, não tenho como gerenciar o torneio no futuro próximo. Haverá atrasos na execução do próximo torneio, enquanto tento encontrar um computador que possa usar.
absinto

11
@Levi Yes! O fabricante me enviou um substituto que chegou hoje. Há um torneio acontecendo enquanto falamos.
absinto

Respostas:


8

O Monge (Java)

O monge valoriza a honra e louva as bênçãos dos deuses. Sendo treinado em paciência, ele calmamente envia suas orações para o céu até que se sinta favorecido por Deus.

Curtindo a vida, ele tenta protegê-la. Quando ele está perdendo saúde acima de uma certa taxa, ele se defende da melhor maneira possível.

Esperando pelo apoio de seus deuses, ele envia aleatoriamente ejaculações [1] para o céu, caso contrário ele luta da melhor maneira possível.

Se seu oponente estiver exausto da batalha, ele o derruba usando sua honra restante para lhe conceder uma morte rápida e indolor.

Compilar / Executar

javac Monk.java
java Monk

public class Monk {
    public static void main(String[] args){
        char  r = 'B';
        double  s = Math.random ();
        int n = Math.max (args [0].length ()- 8, 1);
        int p = args.length > 4 ? Integer.parseInt (args [4]):0;
        int l = Integer.parseInt (args [3]);
        int m = Integer.parseInt (args [2]);
        double d = 1 + (20 - m) / n;
        double e = 1 + (20 - l) / n;

        if (((p>8&&s<.7)||l<11||m<2)&&p>0) {
                r=(s<(.14)||d>=2||e/d<.618)?'G':"OPI".charAt((int)(Math.random()*3));
        }

        System.out.print (r);
    }
}

O Ninja (Java)

O Ninja é rápido e ataca ainda mais rápido. Ele ataca imediatamente após uma saudação formal amigável, confundindo ainda mais seu inimigo curvando-se antes e depois de cada ataque.

Ao ser abençoado, o ninja mantém esse comportamento, esperando que seu oponente faça seu primeiro movimento. Usando esta oportunidade, ele desencadeia uma série de explosões, abençoadas pela Deusa ninja até que ele esteja muito cansado da batalha. Usando sua honra restante, ele se esconde sob as folhas embaixo, protegendo-se do próximo ataque. Ele pula e ataca seu inimigo por trás, sendo escondido o mais rápido possível.

Se ele recebe uma ferida fatal, faz de tudo para levar a vida de seu oponente com ele - é claro, mantendo um mínimo de honra.

javac Ninja.java
java Ninja

public class Ninja {
    public static void main(String[] args){
        char  r = 'B';
        int n = args [0].length ();
        int p = args.length > 4 ? Integer.parseInt (args [4]):0;
        int m = Integer.parseInt (args [2]);
        int a = n % 3;
        if (p>7) {
           if (m>17) {
                r = "BBI".charAt (a);
           } else if (m>13) {
                r = "BII".charAt (a); 
           } else {
               r  = "GIG".charAt (a);
           }

        } else if (p>0) {
           if (m > 10) {
                    r = "BBI".charAt (a);
           } else {
                r="IGI".charAt (n%2);
           }
        }
        System.out.print (r);
    }
}

Kakashi, o imitador Ninja (Java)

Kakashi copia os movimentos de seus oponentes escolhendo aleatoriamente entre os dois últimos movimentos que o oponente fez. Se o oponente espera, ele se curva - Ele também mantém sua honra.

javac Kakashi.java
java Kakashi

public class Kakashi {
    public static void main(String[] args){
        char  r;
        String h = args [1];
        if (h=="W" || Integer.parseInt ( args.length > 4?args [4]:"0") < 1){
                 r = 'B';
        } else if (Math.random ()<.1) {
            r = 'I';
        } else {
            r  = h.charAt ((int) (h.length()==1?0: h.length()-Math.random ()*2));
        }

        System.out.print (r);
    }
}


Eu gostaria que Kakashi fosse abençoado com o sharingan. Pensei em ler o cast.txt. Simule todas as rodadas de sua história contra todos os oponentes presentes. Tente descobrir contra qual oponente ele está lutando, comparando a história dos inimigos simulados com a história real dos inimigos. Em seguida, use essas informações para prever o próximo movimento que o oponente faria e escolha o melhor contra-movimento de uma lista predefinida. Mas acho que isso pode demorar um pouco, pois tenho Internet super lenta no momento e quase nenhuma habilidade em Java

O observador (node.js)

O Observador se inclina antes de tentar prever o próximo lance do oponente dos últimos 5 lances, escolhendo a melhor contrapartida para o lance previsto.

Edit: Obrigado ao @apsillers por compartilhar o boilerplate do node.js.!

node observer.js

var argv = process.argv;
var history = argv.length>6?argv[2]:"";
var enemyHistory = argv.length>6?argv[3]:"";
var offset = 8 - argv.length;
var my = { health:+argv[4-offset], honor:+argv[6-offset], history:history };
var enemy = { health:+argv[5-offset], honor:+argv[7-offset], history:enemyHistory };
my.godSword = my.honor >= 7;
enemy.godSword = enemy.honor >= 7;
function decide() {
    process.stdout.write(arguments[Math.floor(arguments.length*Math.random())]);
    process.exit();
}

var m = {
    m:{},
    l:function (a,b) {
        if (!this.m[a]) {
           this.m [a] = [];
        }
        this.m[a].push (b);
    },
    p:function (a) {
       for (var k=0;k<a.length;k++)
       for (var j=1;j<a.length;j++)
       for (var i=-1+k; i<a.length-j; i++)this.l (a.slice (i,i+j),a[i+j]);
    },
    a:function (a) {
      if (!this.m[a])return;
      return this.m[a][0|Math.random () * this.m[a].length-1]
    }
}
var g={
   B:"IPO",
   G:"B",
   I:"PG",
   O:"IG",
   P:"OG",
   W:"I"
}
var c,i=0;
m.p(enemy.history);
while (!c && i++<enemy.history.length) {
   c=m.a (enemy.history.slice (i));
}
decide.apply  (0,my.honor < 7?["B"]:g[c].split (''))

Edit: Eu tinha uma grande falha no observador, na verdade eu não sei o que pensei ontem à noite. Parece que ele apenas olhou para os dois últimos movimentos do inimigo. Ele foi surpreendentemente bem assim.

Sua memória agora é consultada para a parte mais longa (final) da história dos inimigos que ele já viu. Isso contém uma matriz com todos os movimentos que seguiram o histórico dos movimentos. Um é selecionado aleatoriamente. Portanto, se um movimento for seguido com mais frequência, é mais provável que ele seja escolhido. Mais ou menos como cadeias de markov.

O Observador, agora também guarda.


[1]: TIL: a ejaculação tem um significado religioso


Você é # 1 e # 3 agora mesmo! Bots agradáveis! :)
apsillers

Parabéns por ganhar com o The Observer. O carrapato verde agora é seu: D
absinto

7

Meiyo Senshi (Java)

Vindo da área de Haijima, pouco se sabe sobre o Meiyo. Normalmente eles não participam de jogos esportivos, mas enviaram um guerreiro a este para avaliar seus rivais.

Eles são um grupo honrado, no entanto, então você pode ter certeza de que ele fará sua presença conhecida pelos deuses em pouco tempo. Depois de ver o suficiente de seu inimigo para denunciar, ele usará as bênçãos recebidas para derrubar seu oponente.

Para compilar a execução, é a maneira Java padrão:

> javac MeiyoSenshi.java
> java MeiyoSenshi
public class MeiyoSenshi {
    public static void main(String[] args){
        System.out.print(
                Integer.valueOf(args[args.length<5?0:2])>12 ||
                Integer.valueOf(args[args.length<5?2:4])<1  ?
                "B":
                "IPO".charAt((int)(Math.random()*3))
        );
    }
}

7

Porta-Spork (Rubi)

Spork Holder se curva no primeiro turno e depois age aleatoriamente. É uma das duas entradas de exemplo.

Comando: ruby spork-holder.rb

if ARGV.length == 4
    print "B"
else
    print ["W", "B", "G", "I", "P", "O"].sample
end

O Garçom (festança)

O garçom espera apenas a cada turno. É uma das duas entradas de exemplo.

Comando: echo W

Não há código fonte necessário.


7

Covarde (Node.js)

Eu sou um covarde / É um milagre que ouso respirar
Sobrecarregado / Pela brisa mais suave do verão

  • Verifica se há BXBXBX/ BBBpadrões de curvar (ou bater em você) quando você está se curvando.
  • Verifica se os GXGXGXpadrões estão curvados quando você está protegendo.
  • Se sua jogada de bravura exceder seu limite de medo nessa rodada, ele tentará um golpe.
    • Ter uma espada dos deuses o torna mais corajoso.
    • Um oponente com uma espada dos deuses o torna mais temeroso.
    • Um oponente que lidera com pelo menos 5 pontos de vida ou mais também o deixa um pouco assustado.
  • Caso contrário, ele se revezará em guardar e se curvar.

Se você deseja escrever um envio para o Node.js. , sinta-se à vontade para usar meu código padrão; tudo, incluindo uma decidefunção, é totalmente geral e gratuito.


node coward.js

var argv = process.argv;
var history = argv.length>6?argv[2]:"";
var enemyHistory = argv.length>6?argv[3]:"";
var offset = 8 - argv.length;
var my = { health:+argv[4-offset], honor:+argv[6-offset], history:history };
var enemy = { health:+argv[5-offset], honor:+argv[7-offset], history:enemyHistory };
my.godSword = my.honor >= 7;
enemy.godSword = enemy.honor >= 7;
function decide() {
    process.stdout.write(arguments[Math.floor(arguments.length*Math.random())]);
    process.exit();
}

var enemyGuards = !!enemy.history.match(/G.G.G.$/);
var enemyBows = !!enemy.history.match(/(B.B.B.$)|(BBB$)/);

// open with a bow
if(!my.history) { decide("B"); }

// enemy will likely bow? Hit them with your super sword! (or bow)
if((!enemy.honor || enemyBows)) {
    if(my.godSword) { decide("P","I","O"); }
    else { decide("B"); }
}

// no point in hitting them if they're going to guard
if(enemyGuards) { decide("B"); }

// calculate bravery level
var braveryLevel = 0.3;
braveryLevel += (my.godSword * 0.2) - (enemy.godSword * 0.2);
braveryLevel -= (enemy.health - my.health > 5) * 0.1;

// if we're feeling brave, hit them
if(Math.random() < braveryLevel && my.honor) { decide("P","I","O"); }

// if we didn't just guard, and we're not feeling brave, cower in fear
if(!my.history.match(/G$/)) {
    decide("G");
}

// if we did just guard, and we're feeling cowardly,
//   if we don't have sword of the gods, bow
//   otherwise, do anything except guard
if(!my.godSword) {
    decide("B");
} else {
    decide("B","P","I","O");
}

11
Esse é um robô difícil. Boilerplate impressionante; Vou usá-lo imediatamente. Obrigado por compartilhar :)
C5H8NNaO4 26/06

6

Whack-a-mole (T)

Ataca quando é provável que o inimigo se curve, mais os guardas.

args <- commandArgs(TRUE)
L <- length(args)
my_health <- as.integer(args[L-3])
enemy_health <- as.integer(args[L-2])
my_honour <- as.integer(args[L-1])
enemy_honour <- as.integer(args[L])
if(L>4){enemy_history <- args[L-4]}else{enemy_history <- ""}
if(my_honour<1){
    out <- "B"
}else if (enemy_honour<=1 | grepl("BB$",enemy_history)){
    out <- sample(c("I","O"),1)
}else{
    out <- "G"
}
cat(out)

Corra usando Rscript Whack-a-mole.R.


11
Bom trabalho, mais eu amo o nome.
Alex A.

3

Guerreiro do elefante (Java)

O Elephant Warrior é de uma época mais antiga e natural. Ele viu muito e se lembra de tudo. Ele recebe favor dos deuses enquanto examina seu oponente e, depois que ele os leva ao coração, ele os separa.

Compilar: javac ElephantWarrior.java
Comando:java ElephantWarrior

import java.util.LinkedList;

//Elephants never forget
class ElephantWarrior
{


  static LinkedList<Choice> analysis = new LinkedList<Choice>();

  public static void main(String[] args){
      if(args.length < 6){ respond("B");}   
      String myhis = args[0];
      String enHis = args[1];
      int health = Integer.parseInt(args[2]);
      int enHealth = Integer.parseInt(args[3]);
      int honour = Integer.parseInt(args[4]);
      int enHonour = Integer.parseInt(args[5]);

        //Bow a few times until I know how he operates
        if(enHis.length() <= 5){
            respond("B");
        }

        //Special cases
        //If I'm at 0 honor, better bow
        else if(honour <= 0){
            respond("B");

        }
        else{
          analyze(enHis);

          //Narrow it down to applicable choices
          char hisLast = enHis.toCharArray()[enHis.toCharArray().length - 1];
          LinkedList<Choice> hisOptions = new LinkedList<Choice>();
          for(Choice c: analysis){
              if(c.pattern.toCharArray()[0] == hisLast){
                  hisOptions.add(c);
              }
          }

           //Default to assuming they bow
          char hisNext = 'B';
          int mostLikely = 0;

          //What will they do next?
          for(Choice c : hisOptions){
              if(c != null && c.probability > mostLikely){
                  //System.out.println("Option = " + c.pattern);
                  //System.out.println("Prob = " + c.probability);
                  mostLikely = c.probability;
                  hisNext = c.pattern.toCharArray()[1]; }
          }

          //Now go through potential case
          switch(hisNext){
              case 'W':
                  respond("I");
                  break;
              case 'B': 
                  respond("O");
                  break;
              case 'G':
                  respond("B");
                  break;
              case 'I':
                  if(enHonour  > 0){
                      respond("P");
                  }
                  else{
                      respond("B");
                  }
                  break;
              case 'P':
                  respond("O");
                  break;
              case 'O':
                  respond("I");
                  break;
              default:
                  respond("G");
          }
        }
    }





      static void analyze(String his){

        //Keep track of his previous moves
        char[] shortString = his.substring(1,his.length() - 1).toCharArray();
        char[] longString = his.toCharArray();
        for( int i = 0; i < shortString.length; i++) {
          String pattern = "" + longString[i] + shortString[i];
          boolean exists = false;
          for(Choice c : analysis){
              if(c.pattern.equals(pattern)){
                  exists = true;
                  c.probability++;
              }
          }
          if(!exists){
              analysis.add(new Choice(pattern, 1));
          }
        }
      }

      private static void respond(String s){
            System.out.println(s);
            System.exit(0);
        }

    }

class Choice{
        String pattern;
        int probability;

       Choice(String p, int i){
            pattern = p;
            probability = i;
       }
}

2
Eu não testei isso, mas parece que vai sair dos limites no primeiro turno, onde há apenas quatro args.
Geobits

Certo, não sabia que eles não seriam incluídos. Eu acho que obviamente uma string em branco não pode ser passada, obrigado!
Cain

@katya Está consertado agora, btw, deve ser incluído no torneio.
Caim

3

Princesa Guerreira (Julia)

Este é o primeiro desafio do King of the Hill em que participei. Vamos ver como isso acontece.

A princesa guerreira prioriza o ataque e a honra e recorre à autopreservação quando necessário. Ela é bastante ansiosa e nunca espera. Em um esforço para permanecer ágil, ela também não usa um ataque aéreo.


Salve como warrior-princess.jle execute na linha de comando da seguinte maneira:

julia warrior-princess.jl <arguments>

Se você não possui Julia, pode fazer o download aqui . Para evitar problemas, é recomendada a versão estável mais recente (ou seja, não a versão de desenvolvimento).


type Samurai
    history::String
    health::Int
    honor::Int
end

A = length(ARGS) < 5 ? ["", "", ARGS] : ARGS

me = Samurai(A[1], int(A[3]), int(A[5]))
opponent = Samurai(A[2], int(A[4]), int(A[6]))


if length(me.history) == 0

    # Always begin the match with an honorable bow
    action = "B"

elseif (!ismatch(r"[OIP]", opponent.history) && me.history[end] != 'G') ||
       (me.health < 2 && me.honor > 0)

    # Guard if the enemy has not yet attacked and I did not previously
    # guard, or if my health is low and my honor is sufficient
    action = "G"

elseif me.honor < 2

    # Bow if I'm low on honor
    action = "B"

elseif opponent.honor >= 7 && opponent.history[end]['B', 'W']

    # Assume the enemy will attack with the Sword of the Gods if they
    # most recently bowed or waited
    action = "I"

else
    action = "P"
end

println(action)

11
Sua primeira entrada no KotH e a primeira entrada na Julia KotH, se não me engano: parabéns!
plannapus

@plannapus Thanks! : D Talvez eu crie um hábito.
Alex A.

3

Gárgula (Java)

Tenta usar o ataque defensivo sem consumir honra.

Como é uma entrada java:

> javac Gargoyle.java
> java Gargoyle
public class Gargoyle { 
    public static void main(String args[]) {
        if (args.length < 5 || Integer.valueOf(args[4]) > 0) {
            System.out.println("IPO".charAt((int)(Math.random()*3)));
        } else if (args[0].charAt(args[0].length()-1) != 'G') {
            System.out.println('G');
        } else {
            System.out.println('B');
        }
    }
}

3

Espadachim (C / Java)

O espadachim se curva no primeiro turno e sempre que está com pouca honra. Ele então verifica se o oponente não havia se curvado, defendido ou esperado no turno anterior. Se o oponente não o fez, existe uma grande probabilidade de que ele faça um deles no turno atual e o espadachim atinja aleatoriamente o oponente. Se isso não for verdade, ele defende se não defendeu o turno anterior. Se ele tivesse, ele se curvou para ganhar honra.

Versão C:

#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void print_and_exit(char* str)
{
    puts(str);
    exit(0);
}

int main(int argc, char** argv){

    srand(time(NULL));
    char* attack_moves[]={"I", "P", "O"};
    int random_num = rand() % 3;

    if(argc == 5 || atoi(argv[5]) == 0)
        print_and_exit("B");
    else if(argv[2][strlen(argv[2])-1] != 'B' && argv[2][strlen(argv[2])-1] != 'G' && argv[2][strlen(argv[2])-1] != 'W')
        print_and_exit(attack_moves[random_num]);
    else if(argv[1][strlen(argv[1])-1] != 'G')
        print_and_exit("G");

     print_and_exit("B");
}

Instale o GCC (compilador) e salve o código em um arquivo chamado " Swordsman.c " para compilar:

gcc Swordsman.c -o Swordsman

O executável chamado " Swordsman " será criado. Executar usando

Swordsman

Versão Java:

public class Swordsman {

    public static void print_and_exit(String str)
    {
        System.out.println(str);
        System.exit(0);
    }
    public static void main(String[] argv) {

        String attack_moves[]={"I", "P", "O"};
        int random_num = (int)(Math.random()*3);

        if(argv.length == 4 || Integer.valueOf(argv[5]) == 0)
            print_and_exit("B");
        else if(argv[2].charAt(argv[2].length()-1) != 'B' && argv[2].charAt(argv[2].length()-1) != 'G' && argv[2].charAt(argv[2].length()-1) != 'W')
            print_and_exit(attack_moves[random_num]);
        else if(argv[1].charAt(argv[1].length()-1) != 'G')
            print_and_exit("G");

         print_and_exit("B");
    }

}

Instale o javac (compilador) e salve o código em um arquivo chamado " Swordsman.java " para compilar:

javac Swordsman.java

Arquivo de classe chamado " Swordsman.class " será criado. Executar usando

java Swordsman



Atacante (Java)

O atacante não se importa com nada, exceto que ele quer o seu oponente morto. Ele golpeia aleatoriamente um dos movimentos de ataque e, se tiver pouca honra, faz uma reverência.

public class Attacker {

    static int position = -1;

    public static void print_and_exit(String str)
    {
        System.out.println(str);
        System.exit(0);
    }
    public static void main(String[] argv) {

        String attack_moves[]={"I", "P", "O"};
        position = (position + 1) % 3;

        if(argv.length != 5 && Integer.valueOf(argv[5]) == 0)
            print_and_exit("B");
        else 
            print_and_exit(attack_moves[position]);
    }

}

Instale o javac (compilador) e salve o código em um arquivo chamado " Attacker.java " para compilar:

javac Attacker.java

O arquivo de classe chamado " Attacker.class " será criado. Executar usando

java Attacker


Preditor (C / Java)

Predictor prevê os movimentos dos inimigos. No primeiro turno, ele usa um movimento aleatório. Curva se sua honra é baixa, ataca se a honra do inimigo é baixa ou se curvou no turno anterior. Se o preditor não tiver guardado o turno anterior, proteja o turno atual. Senão, faz o mesmo movimento que o inimigo fez no turno anterior, desde que não seja 'W'nesse caso, o Predictor faz uma reverência.

Versão C:

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>

void print_and_exit(char* str)
{
    puts(str);
    exit(0);
}

int main(int argc, char** argv){

    srand(time(NULL));
    int random = rand() % 5;
    char* moves[] = {"B", "G", "I", "P", "O"};

    if(argc == 5)
        print_and_exit(moves[random]);

    if(atoi(argv[5]) <= 0)
        print_and_exit(moves[0]);
    if(atoi(argv[6]) <= 0)
        print_and_exit(moves[4]);
    if(argv[2][strlen(argv[2])-1] == 'G')
        print_and_exit(moves[4]);
    if(argv[1][strlen(argv[1])-1] != 'G')
        print_and_exit(moves[1]);

    if(argv[2][strlen(argv[2])-1] != 'W'){
        char buf[2]={0};
        *buf = argv[2][strlen(argv[2])-1];
        print_and_exit(buf);
    }

    print_and_exit(moves[0]);

}

Instale o GCC (compilador) e salve o código em um arquivo chamado comando " Predictor.c " para compilar:

gcc Predictor.c -o Predictor

O executável chamado " Predictor " será criado. Executar usando

Predictor

Versão Java:

public class Predicator{

    public static void print_and_exit(String str)
    {
        System.out.println(str);
        System.exit(0);
    }

    public static void main(String[] argv){

        int random = (int)(Math.random() * 5);
        String moves[] = {"B", "G", "I", "P", "O"};

        if(argv.length == 4)
            print_and_exit(moves[random]);
        else if(Integer.valueOf(argv[5]) <= 0)
            print_and_exit(moves[0]);
        else if(Integer.valueOf(argv[6]) <= 0)
            print_and_exit(moves[4]);
        else if(argv[2].charAt((argv[2].length())-1) == 'G')
            print_and_exit(moves[4]);
        else if(argv[1].charAt((argv[1].length())-1) != 'G')
            print_and_exit(moves[1]);
        else if(argv[2].charAt((argv[1].length())-1) != 'W'){
                    print_and_exit(""+argv[2].charAt((argv[2].length())-1));
        }
        else
            print_and_exit(moves[0]);
    }
}

Instale o javac (compilador) e salve o código em um arquivo chamado " Predicator.java " para compilar:

javac Predicator.java

O arquivo de classe chamado " Predicator.class " será criado. Executar usando

java Predicator


Não tenho certeza da eficácia desses bots, pois não tenho o interpretador python2 para testá-lo.


11
Eu não testei isso (Atacante), mas parece que ele sairá dos limites no primeiro turno, onde há apenas quatro argumentos.
Geobits

O atacante parece estar dando um ArrayIndexOutOfBoundsExceptionno primeiro turno, fazendo com que espere no primeiro turno. Além disso, está funcionando.
absinto

@Katya e Geobits, corrigidos. Obrigado por detectá-lo.
Spikatrix

Ao executar o preditor, recebo uma segmentation fault (core dumped)rodada após 24
C5H8NNaO4

@ C5H8NNaO4 Corrigido o problema. Código atualizado para todos os três bots. Deve funcionar bem agora. Obrigado por apontar isso! :-D
Spikatrix

2

Mestre Yi (Python)

O mestre assassino ganha muito favor no início do jogo, construindo-o até ser invencível. Tenta atacar quando menos espera.

import sys, random

class MasterYi(object):
    def __init__(self):
        self.attack = lambda: random.choice(['I','P','O'])
        self.bow   = "B"
        self.guard = "G"
        self.wait  = "W"
        if len(sys.argv)>6:
            self.hist = sys.argv[1]; self.ohist = sys.argv[2]
            self.hp   = sys.argv[3]; self.ohp   = sys.argv[4]
            self.hon  = sys.argv[5]; self.ohon  = sys.argv[6]
        else:
            self.hist = [];          self.ohist = []
            self.hp   = sys.argv[1]; self.ohp   = sys.argv[2]
            self.hon  = sys.argv[3]; self.ohon  = sys.argv[4]
        self.last  = self.hist  and self.hist[-1]  or "W"
        self.olast = self.ohist and self.ohist[-1] or "W"
        self.oGuarder = len(self.ohist)>4 and self.ohist[-4]==self.ohist[-2]=="G"

    def move(self):
        if self.hon < 1: return self.bow
        if self.olast == "G": return self.attack
        if self.hon > 6:
            if self.oGuarder: return self.bow
            if self.ohon > 6: return self.guard
            if self.ohon < 7: return self.attack
            return self.attack
        if self.ohon > 6: return self.guard
        return self.bow

Yi = MasterYi()
print(Yi.move())

Para executar: Salvar como MasterYi.py

python MasterYi.py <args>

2

Cópia-san (C)

Copia todos os movimentos do seu oponente. Tenho certeza que ele está garantido a perder. Compilar:gcc copy-san.c

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    if (argc == 5) {
        putchar('B');
    } else {
        char *enemy_hist = argv[2];
        size_t len = strlen(enemy_hist);
        putchar(enemy_hist[len - 1]);
    }
    putchar('\n');
    return 0;
}

2

Hebi (Java)

Hebi segue o Caminho da Serpente.

A serpente não precisa da bênção dos deuses.

A serpente desliza seus ataques; como ondas na praia, o que aparece retrocede como veio.

A cobra nunca espera.

O Snake não tem senso de aptidão, caso contrário, teria sido escrito em Python.

Instruções de execução:

> javac hebi.java
> java hebi

Corpo do código:

public class hebi{

    public static void main(String args[]){

        if( (args.length < 5) || (args[0].length() % 18 == 0) ) System.out.println( "IPO".charAt((int)(Math.random()*3)) );
        else{

            int hist_size = args[0].length();

            if      (hist_size % 3 == 1) System.out.println("G");
            else if (hist_size % 3 == 2) System.out.println("B");
            else{

                if     (hist_size % 18 ==  9) System.out.println(args[0].charAt(hist_size -  3));
                else if(hist_size % 18 == 12) System.out.println(args[0].charAt(hist_size -  9));
                else if(hist_size % 18 == 15) System.out.println(args[0].charAt(hist_size - 15));
                else{

                    char move_head = args[0].charAt( (hist_size / 18) * 18 );
                    char move_mid;
                    if( hist_size % 18 == 3 ){
                        if     ( move_head == 'I' ) move_mid = "PO".charAt((int)(Math.random()*2));
                        else if( move_head == 'O' ) move_mid = "IP".charAt((int)(Math.random()*2));
                        else                        move_mid = "OI".charAt((int)(Math.random()*2));
                        System.out.println(move_mid);
                    }
                    else{
                        move_mid = args[0].charAt( ((hist_size / 18) * 18) + 3 );
                        char move_tail;

                        if( move_head == 'I' ){
                            if( move_mid == 'P' ) move_tail = 'O';
                            else                  move_tail = 'P';
                        }else if( move_head == 'P' ){
                            if( move_mid == 'O' ) move_tail = 'I';
                            else                  move_tail = 'O';
                        }else{
                            if( move_mid == 'I' ) move_tail = 'P';
                            else                  move_tail = 'I';
                        }

                        System.out.println( move_tail );

                    }

                }

            }

        }

    }

}

2

O honorável (Java)

Os valores honoráveis ​​honram acima de tudo. Ou seja, sua honra acima de todos os outros. Se o samurai inimigo tem maior ou igual honra, ele se curva. Ninguém será mais honrado que ele. Caso contrário, ele faz um movimento aleatório. Ele nunca guarda duas vezes seguidas - isso seria desonroso!

compilar:

> javac TheHonourable.java
> java TheHonourable

Fonte:

public class TheHonourable {
    public static void main(String[] args) {
        char move;

        if (args.length < 5) {
            move = 'B';
        } else if (Integer.valueOf(args[5]) >= Integer.valueOf(args[4])){
            move = 'B';
        } else {
            move =  (args[0].endsWith("G")) ?
                    "IPO".charAt((int)(Math.random()*3)) :
                    "GIPO".charAt((int)(Math.random()*4));
        }

        System.out.print(move);
    }
}

1

Samurai Abençoado (Pitão)

Este samurai tenta manter o favor dos deuses o maior tempo possível. Ele corre para pegar a espada sagrada, depois alterna entre Guardar e Atacar com um dos ataques, reabastecendo honra quando necessário. Se parece que ele ou seu oponente podem cair em breve, ele corre para matar. Ele cairá facilmente em um oponente que pode rastrear seu padrão, mas sua estratégia de sempre atacar com dois danos deve ser bastante eficaz.

import sys
import random
class BlessedSamurai(object):
    def __init__(self):
        if len(sys.argv) < 7:
            print("B")
        else:
            self.attack = ['O', 'I', 'P']
            self.hp = sys.argv[3]
            self.ohp = sys.argv[4]
            self.hon = sys.argv[5]
            self.last = sys.argv[1][-1]
            print(self.move())

    def move(self):
        #check if I have low health or should rush the kill
        if (self.hp < 5 or self.ohp < 5) and self.hon > 0:
            return(random.choice(self.attack))
        # charge honour to get SOTG
        elif self.hon < 7:
            return 'B'
        #Alternate guarding and attacking
        else:
            if self.last == 'G':
                return(random.choice(self.attack))
            return 'G'
Sam = BlessedSamurai()

Para executar:
Salvar como BlessedSamurai.py

python BlessedSamurai.py <args>

4
Seu programa precisa imprimir sua mudança.
mbomb007

3
Eu não testei isso, mas parece que ele sairá dos limites no primeiro turno, onde há apenas quatro argumentos.
Geobits

Eu usei um formato semelhante ao que ele fez. @ Stranjyr, dê uma olhada no que eu fiz para obter os argumentos.
mbomb007

Obrigado a todos vocês! No momento, não tenho acesso a um intérprete python, mas acho que corrigi os problemas. De alguma forma, perdi completamente que o primeiro conjunto de instruções não tivesse um histórico.
Stranjyr

Olá, você teve um pequeno bug no seu programa "o nome global 'last' não está definido". Como é um pequeno bug, mudei lastpara o self.lastque parece corrigir o problema.
absinthe

1

Hermurai (C ++)

Admira seu oponente e é um pouco paranóico. Quer saber se ele pode fazer o que outros samurais podem, porque ele ainda não consegue acreditar que é um samurai. Seu sonho sem fim se tornou realidade antes que ele percebesse. O que poderia custar sua cabeça ...

#include <stdio.h>
#include <string>
#include <sstream>

using namespace std;

char getLastAttack(string enemy_history)
{
    size_t found = enemy_history.find_last_of("IPO");
    if(found == string::npos)
    {
        return 'I';
    }

    return enemy_history[found];
}

int main(int argc, const char * argv[])
{
    if(argc != 7){
        printf("B");
        return 0;
    }

    string enemy_history(argv[2]);

    int ho;
    string honour(argv[5]);
    stringstream(honour) >> ho;

    if(ho > 20){
        char atk = getLastAttack(enemy_history);
        printf("%c", atk);
        return 0;
    }

    char lastMove = enemy_history[enemy_history.length()-1];
    if(lastMove == 'W' || lastMove == 'G')
        lastMove = 'B';
    printf("%c", lastMove);
    return 0;
}

Iniqy (C ++)

Golpeia o mais forte possível. Entra no modo de ataque imparável quando ele está em perigo.

#include <stdio.h>
#include <string>
#include <sstream>

using namespace std;

char getLastAttack(string enemy_history)
{
    size_t found = enemy_history.find_last_of("IPO");
    if(found == string::npos)
    {
        return 'I';
    }

    return enemy_history[found];
}

int main(int argc, const char * argv[])
{
    if(argc != 7){
        printf("B");
        return 0;
    }

    string history(argv[1]);
    string enemy_history(argv[2]);
    string health(argv[3]);
    string enemy_health(argv[4]);
    string honour(argv[5]);
    string enemy_honour(argv[6]);

    int he, enemy_he, ho, enemy_ho;
    stringstream(health) >> he;
    stringstream(enemy_health) >> enemy_he;
    stringstream(honour) >> ho;
    stringstream(enemy_honour) >> enemy_ho;

    if(ho > 6 || ((he < 6 || enemy_he < 6) && ho > 0))
    {
        char atk = getLastAttack(enemy_history);
        printf("%c", atk);
        return 0;
    }


    printf("B");
    return 0;
}

Ambos são escritos em C ++. Compilar:

g++ iniqy.cpp -o iniqy

Para executar no Linux: ./iniqy

Para executar no Windows: iniqy.exe


1

O Exterminador do Futuro (ruby)

O Terminator não presta atenção à sua própria saúde. O Terminator não tem noção de honra. O Terminator é enviado do futuro e simplesmente determinado a finalizar seu oponente. Faz isso observando os movimentos de seus oponentes e nada mais. Ele mostra os movimentos e calcula a resposta apropriada de maneira tão complexa que nenhuma tecnologia atual pode prever as ações do Terminator. De fato, para quem vive em 2015, o Terminator pode parecer um tanto aleatório ...

responses = {
  ?W => %w(B I),
  ?B => %w(I O),
  ?G => %w(B B),
  ?I => %w(G P),
  ?P => %w(B O),
  ?O => %w(G I)
}

if ARGV.size > 4
  pool = ARGV[1].chars.map{ |c| responses[c] }.flatten
  puts pool.sample
else
  puts %w(O I P B).sample
end

1

Agente 38 [1] (C)

Como um produto de uma extensa manipulação genética, agente 38 tem o físico e acuidade mental de um super [2] -samurai, e é definitivamente superior a toda a sua impotente [carece de fontes?] Falho [carece de fontes?] Concorrentes.


//Agent 38
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#ifdef _WIN32
#include <Windows.h>
unsigned int tick_count(){
    return GetTickCount();
}
#else
#include <sys/time.h>
unsigned int tick_count(){
    struct timeval t;
    gettimeofday(&t, NULL);
    return 1000 * t.tv_sec + t.tv_usec / 1000;
}
#endif

float program[5][4][4][4][4]={
    {{{{-1.192779,0.693321,-1.472931,-0.054087},{0.958562,0.557915,0.883166,-0.631304},{-0.333221,1.410731,0.496346,0.087134},{0.459846,0.629780,-0.479042,-0.025909}},{{0.547976,1.059051,-0.748062,-0.675350},{-0.607591,-0.152156,-0.400350,-0.685337},{1.686450,0.628706,0.312865,0.324119},{1.652558,0.403733,-0.456481,-0.081492}},{{0.371629,-0.036948,-0.982682,0.065115},{1.360809,0.681294,0.505074,0.782737},{-0.545192,0.954937,-0.727853,0.273542},{-0.575777,1.615253,-0.064885,-0.516893}},{{0.577015,-0.112664,0.456595,-0.007560},{-0.660930,-0.738453,0.668093,1.716388},{1.972322,0.108558,0.535114,-0.337916},{0.640208,-0.019680,-0.769389,0.873087}}},{{{-0.021140,-0.095956,-0.098309,-0.280295},{-0.926284,1.724028,0.278855,0.678060},{0.153006,-1.860947,-0.577699,-1.931683},{-0.187152,0.529719,-1.164157,0.125499}},{{0.582208,-0.835029,-0.329857,0.088176},{-0.030797,0.389396,0.584636,-0.025866},{-0.736538,1.624658,0.690493,0.387515},{0.973253,-0.530825,1.934379,-0.872921}},{{0.812884,0.138399,-1.452478,-1.504340},{-0.119595,0.986078,-0.993806,1.102894},{0.848321,-0.268764,0.876110,0.782469},{0.948619,-0.557342,0.749764,-0.712915}},{{-1.195538,0.783784,-1.973428,-0.873207},{0.085426,-0.241360,-0.534561,-0.372105},{0.029696,-0.906821,0.932227,-0.834607},{0.764903,-0.276117,-1.346102,-0.093012}}},{{{0.168113,0.855724,1.817381,-0.547482},{0.468312,0.923739,-0.723461,0.798782},{-0.875978,-0.942505,-0.684104,-0.046389},{0.893797,-0.071382,0.283264,0.811233}},{{0.391760,0.309392,-0.045396,-0.977564},{0.085694,0.257926,-0.775461,0.060361},{0.486737,-0.175236,0.806258,-0.196521},{0.691731,-0.070052,0.636548,0.464838}},{{0.532747,-1.436236,-0.900262,-0.697533},{0.566295,0.650852,0.871414,-0.566183},{-0.075736,-0.886402,0.245348,-0.438080},{-0.811976,0.022233,-0.685647,0.323351}},{{-1.864578,1.141054,1.636157,-0.455965},{0.592333,0.890900,-0.259255,0.702826},{0.404528,0.905776,0.917764,0.051214},{0.761990,0.766907,-0.595618,-0.558207}}},{{{0.209262,-1.126957,-0.517694,-0.875215},{0.264791,0.338225,0.551586,0.505277},{0.183185,0.782227,0.888956,0.687343},{0.271838,0.125254,1.071891,-0.849511}},{{0.261293,-0.445399,0.170976,-0.401571},{0.801811,0.045041,-0.990778,-0.013705},{-0.343000,-0.913162,0.840992,0.551525},{-0.526818,-0.231089,0.085968,0.861459}},{{0.540677,-0.844281,-0.888770,0.438555},{0.802355,-0.825937,0.472974,-0.719263},{-0.648519,1.281454,0.470129,-0.538160},{-0.851015,0.985721,-0.993719,0.558735}},{{1.164560,-0.302101,0.953803,0.277318},{0.886169,0.623929,1.274299,-0.559466},{-0.948670,0.807814,-1.586962,-0.502652},{-0.069760,1.387864,-0.423140,0.285045}}}},
    {{{{0.747424,-0.044005,0.402212,-0.027484},{0.785297,0.169685,0.734339,-0.984272},{-0.656865,-1.397558,0.935961,-0.490159},{-0.099856,-0.293917,0.129296,-0.920536}},{{0.546529,-0.488280,-0.516120,-1.112775},{0.155881,-0.103160,0.187689,0.485805},{0.918357,0.829929,0.619437,0.877277},{0.389621,0.360045,0.434281,0.456462}},{{-0.803458,-0.525248,-0.467349,0.714159},{-0.648302,-0.005998,-0.812863,0.205664},{0.591453,0.653762,-0.227193,-0.946375},{0.080461,0.311794,0.802115,-1.115836}},{{-0.495051,-0.869153,-0.179932,0.925227},{-1.950445,1.908723,-0.378323,-0.472620},{-0.688403,-1.470251,1.991375,-1.698926},{-0.955808,-0.260230,0.319449,-1.368107}}},{{{-0.029073,-0.622921,-1.095426,-0.764465},{-0.362713,-0.123863,0.234856,-0.772613},{0.697097,0.103340,0.831709,0.529785},{0.103735,-0.526333,-0.084778,0.696831}},{{-0.670775,0.289993,-0.082204,-1.489529},{0.336070,0.322759,0.613241,0.743160},{0.298744,-1.193191,0.848769,-0.736213},{0.472611,-0.830342,0.437290,-0.467557}},{{-0.529196,-0.245683,0.809606,-0.956047},{-1.725613,0.187572,0.528054,-0.996271},{-0.330207,0.206237,0.218373,0.187079},{0.243388,0.625787,-0.388859,0.439888}},{{-0.802928,-0.811282,0.788538,0.948829},{0.966371,1.316717,0.004928,0.832735},{-0.226313,0.364653,0.724902,-0.579910},{-0.544782,-0.143865,0.069256,-0.020610}}},{{{-0.393249,0.671239,-0.481891,0.861149},{-0.662027,-0.693554,-0.564079,-0.477654},{0.070920,-0.052125,-0.059709,0.473953},{-0.280146,-0.418355,0.703337,0.981932}},{{-0.676855,0.102765,-0.832902,-0.590961},{1.717802,0.516057,-0.625379,-0.743204},{-0.170791,-0.813844,-0.269250,0.707447},{0.057623,0.472053,-0.211435,0.147894}},{{-0.298217,0.577550,1.845773,0.876933},{0.617987,0.502801,0.951405,0.122180},{0.924724,-0.166798,0.632685,-0.466165},{-0.834315,-0.864180,-0.274019,0.568493}},{{0.669850,-0.961671,0.790462,0.738113},{-0.534215,-0.556158,0.653896,0.031419},{0.065819,0.220394,0.153365,-0.373006},{0.886610,-0.742343,1.282099,0.198137}}},{{{0.092579,-0.026559,-1.121547,0.143613},{-0.289030,0.265226,-0.350741,-0.897469},{-0.918046,0.038521,-1.515900,0.488701},{-0.759326,-1.782885,-1.787784,0.249131}},{{-0.849816,-0.857074,-0.843467,-0.153686},{0.998653,0.356216,0.926775,0.300663},{-0.749890,-0.003425,-0.607109,0.317334},{-0.561644,0.446478,-0.898901,0.711265}},{{0.232020,-0.445016,0.618918,0.162098},{0.381030,-0.036170,0.084177,0.766972},{0.493139,0.189652,-0.511946,-0.273525},{0.863772,-0.586968,0.829531,-0.075552}},{{0.191787,-0.627198,0.975013,-0.448483},{-0.197885,0.151927,-0.558646,-1.308541},{-0.582967,1.207841,0.746132,0.245631},{0.314827,-0.702463,-0.301494,0.787569}}}},
    {{{{0.670028,-1.825749,-0.739187,0.482428},{0.175521,-0.020120,-0.154805,0.187004},{0.971728,-0.160181,-0.164031,-0.868147},{-0.954732,-0.175713,0.791116,0.294173}},{{-0.958337,-0.843157,-0.472882,0.273517},{-0.999058,0.824762,-0.223130,-0.150628},{0.393747,-0.301297,0.095572,-0.798950},{-0.119787,0.746673,0.955094,0.259353}},{{0.951590,0.225539,0.503282,0.668746},{-0.384898,-0.979592,-0.005485,-0.191883},{-0.692369,-0.642401,-0.825598,0.171933},{-0.321919,-0.498635,0.449704,0.780842}},{{-0.387902,0.522435,0.565608,0.166193},{-0.799671,-0.295871,-0.702573,-0.151006},{0.040550,-0.468503,0.651076,0.636352},{-0.839299,-0.090651,0.428761,0.187043}}},{{{-0.369823,0.377011,0.422936,0.284752},{-0.181514,-0.701449,0.748768,0.540533},{0.734381,0.149410,-0.867043,-0.397142},{-0.770904,-0.581897,-1.578306,-0.402638}},{{0.859015,-0.540358,0.202715,-0.975354},{-0.773629,-0.382342,-0.022498,-0.129286},{-0.901210,-0.641866,1.219216,0.731525},{0.740457,0.858546,-0.408661,-0.364897}},{{-0.830865,-1.370657,-1.226303,-0.392147},{-0.810554,-0.975232,-0.717845,-0.825379},{-0.150096,-0.664533,0.347084,0.243443},{-0.447383,0.842164,1.491342,0.380295}},{{-0.383958,0.811219,0.160459,0.841601},{1.631515,0.371637,0.110000,0.467783},{-0.689356,-0.004289,-0.081057,-0.317243},{0.092451,-0.181268,-0.575747,-0.580061}}},{{{0.908549,-0.013975,-0.880165,-0.938937},{-0.225713,0.449478,0.372569,-0.229889},{0.255711,-0.264752,0.307982,0.260505},{0.314966,-0.540905,0.743032,-0.078475}},{{-0.307472,-1.268296,0.020383,1.798401},{-0.150954,0.909716,-0.407903,0.379046},{0.621853,-0.003629,-0.582697,0.614618},{-0.122843,-0.627133,-0.217968,0.608322}},{{0.071923,0.807315,0.538905,-0.630660},{0.495641,0.240202,-0.920822,-0.258533},{-1.760363,-0.448525,-0.351553,-0.551666},{0.152720,0.900531,0.061966,-0.544377}},{{0.648923,0.450945,-1.530020,1.570190},{0.536210,0.078454,0.577168,0.464872},{-0.888258,-0.950748,0.781474,0.958593},{0.463631,0.319614,-0.248374,-0.413144}}},{{{0.293463,0.236284,1.721511,0.107408},{-0.790508,-0.072027,-0.559467,-0.955839},{-0.777662,-0.169876,0.896220,0.776105},{0.003944,-0.745496,-0.236446,-0.824604}},{{-1.770746,-0.051266,-0.174258,0.003074},{-0.339553,-0.868807,-0.032754,-0.494847},{-0.896712,0.957339,-0.003444,-1.582125},{-0.699883,0.626691,0.799635,-0.542343}},{{-0.635123,-0.755960,0.576373,-0.899530},{-0.393745,0.718900,0.312400,0.511415},{-0.647565,0.368431,0.214726,0.892693},{-0.511960,-0.513262,0.885908,-0.536478}},{{-0.590074,0.623328,0.268674,-0.401391},{0.308868,-0.869862,0.233132,0.243337},{-0.242908,-0.557192,-0.728454,0.867029},{0.156435,-0.805308,-0.815392,-1.437798}}}},
    {{{{0.613484,1.454566,-0.363858,0.634053},{0.535096,-0.641079,-0.607553,0.852559},{0.959100,-0.398621,0.375819,0.385756},{-0.601982,0.494128,0.809699,0.608804}},{{-1.390871,-0.943062,1.556671,0.966501},{-0.013242,0.152716,-0.089592,0.230793},{0.933785,0.119358,0.057387,0.502033},{-0.332925,0.537509,-0.081436,-0.701995}},{{-0.435117,0.996885,0.646630,-0.092342},{0.004343,-0.737514,-0.716187,-0.946819},{0.814258,-0.766971,-0.488162,-0.531619},{-0.923069,0.683915,-0.023809,-1.242992}},{{-0.909155,-0.166488,-0.159273,-0.908121},{-0.783871,-0.522598,0.691845,-0.164065},{1.255966,0.051373,-0.566025,0.820081},{0.186583,0.266032,-0.793747,-0.510092}}},{{{0.890639,0.970042,-0.507885,-0.029557},{-0.771142,-0.875802,0.400070,-1.264247},{-0.881146,0.570950,-0.051624,0.347612},{0.312110,-0.374885,0.600112,0.388460}},{{-0.417107,-0.309284,-0.128477,0.689671},{-0.695866,1.254585,-0.381883,-0.313415},{0.433565,0.919626,0.159180,-0.657310},{-1.396139,0.346053,0.108768,0.061238}},{{-0.776695,0.084491,0.045357,0.312823},{-0.379268,1.217006,-0.014838,-1.032272},{-1.251344,-0.366283,-0.124786,0.729754},{0.979936,0.669519,-0.900018,-0.596954}},{{-0.998834,0.593942,0.375639,-0.627459},{0.297281,0.400240,0.839707,0.960262},{-0.872143,0.574040,-0.559580,-1.965570},{-0.559218,-0.778780,-0.955526,-0.253380}}},{{{-1.919625,-1.911049,0.025035,0.754917},{-0.110993,0.535933,-0.572788,-0.856476},{-0.810836,-0.496261,1.128368,1.758826},{-0.564368,-1.849772,-0.251560,0.635528}},{{0.768196,-0.934122,0.207228,0.884610},{-0.356145,0.265792,-0.835582,0.377675},{-0.410745,0.613212,0.245560,-0.873826},{1.725191,-0.263344,-0.077167,-0.976379}},{{-0.736299,-0.109476,0.044512,-0.004005},{0.692230,0.316670,0.267247,-1.076821},{-0.903184,0.189762,-0.674111,0.219113},{0.639162,1.347521,0.428823,-0.765664}},{{-0.509165,0.458806,-0.851011,0.455027},{-0.218564,-0.063492,0.889320,-0.762062},{0.145950,0.985037,-0.489372,-0.879851},{0.352346,-0.127275,0.896496,-0.596037}}},{{{0.402678,1.479855,0.089187,0.967153},{-0.431225,0.402980,0.883584,-0.900324},{0.262233,-0.647278,0.637005,0.142678},{-0.003253,-0.671924,0.969458,-0.316752}},{{0.345185,-0.477503,-0.326822,-0.106251},{0.239521,1.617125,0.632651,0.969976},{-1.015183,-0.676629,0.955842,0.134925},{-0.319063,-0.493157,-0.488088,0.713008}},{{-0.468621,1.301292,-1.826501,1.138666},{0.170247,-0.661171,0.895204,-0.400700},{-0.077645,-0.978179,-0.245724,0.245282},{-0.258300,0.287261,-0.006274,0.549716}},{{-0.932247,-0.274950,0.920451,0.016237},{0.888865,-0.845248,1.661716,-0.108960},{0.712357,0.586609,-0.867356,0.355058},{-0.540912,0.892622,0.302627,0.247194}}}},
    {{{{0.817578,0.719047,0.438903,0.637398},{0.750466,-0.911799,-0.609606,0.358541},{-1.782979,-0.851717,-0.802122,0.735913},{0.490604,-0.417822,-0.332074,0.836756}},{{-0.650232,-0.442026,0.874916,0.705671},{0.217602,-0.755841,0.573944,0.279365},{-0.713729,0.358880,-0.308992,0.778297},{0.832099,-0.916695,-0.887834,1.041483}},{{1.019467,1.099488,-0.130674,-0.241995},{0.792572,0.756977,0.518186,0.070411},{-0.815779,-0.790757,-1.027439,-0.163698},{0.721461,-0.403364,0.656609,-0.367364}},{{-0.279333,-0.742041,0.515832,-0.408114},{0.834577,0.736056,0.900594,0.276357},{0.726000,0.464991,-0.569281,0.098139},{-0.582324,0.875666,-0.681556,-0.903009}}},{{{1.300969,-0.798351,0.107230,1.611284},{0.239211,0.418231,-0.795764,-0.398818},{-0.939666,1.768175,-0.297023,-0.064087},{-0.239119,-0.365132,0.864138,0.595560}},{{1.898313,-0.343816,1.066256,0.876655},{-0.053636,0.544756,-0.937927,0.189233},{0.445371,-0.656790,-0.675091,0.753163},{-0.293330,-0.002717,0.341173,0.095493}},{{0.951658,0.513912,-0.678347,-0.981140},{-0.020791,0.571138,-0.890648,0.881789},{-1.783345,0.909598,-0.393155,0.240630},{-0.057908,-0.237435,-0.124993,-0.754091}},{{-0.014153,0.127172,0.097134,0.538952},{0.167943,0.786395,0.946153,-0.762513},{-0.562758,0.675657,-0.226395,0.979761},{0.850214,0.818309,0.397074,-0.372059}}},{{{0.803316,-0.659538,-1.987864,-0.186366},{-0.259213,0.315848,-0.427898,0.326521},{-0.168181,-0.620898,0.562309,0.722064},{-1.949690,0.307720,-0.147760,0.603492}},{{0.898339,0.986228,0.724530,0.105193},{0.066046,0.037689,-0.553543,0.597864},{0.296553,0.165199,0.500125,-0.395978},{0.790120,-1.873361,0.354841,-0.187812}},{{-0.559746,0.357012,0.373903,-0.113564},{-0.671918,-0.919720,0.258328,-0.283453},{0.008365,0.597272,0.355827,0.391287},{0.355297,-0.631888,0.221383,1.448221}},{{0.259199,-0.491776,0.721151,0.391427},{0.494000,0.652814,-0.153306,-0.615687},{0.142167,-0.601161,0.281702,0.563390},{0.904019,1.284241,0.901663,0.244620}}},{{{-0.664638,-0.564596,0.839897,0.153358},{-0.506883,0.822337,-0.974957,-0.098112},{-0.962870,-0.274566,0.418039,-0.020525},{-0.965969,0.954587,-0.250493,-0.031592}},{{-0.966475,0.455338,0.868491,0.723032},{-0.002141,0.021922,-0.131429,-0.601106},{-1.240003,1.483318,1.612920,-0.653210},{-0.505979,0.005588,-0.087506,-0.705789}},{{-0.203137,0.765652,-0.132974,-0.900534},{0.731132,0.133467,-1.086363,0.600763},{1.795911,-0.411613,-1.990494,0.405937},{0.729332,-0.119175,-0.979213,0.362346}},{{-0.049014,0.228577,-1.728796,-0.898348},{-0.540969,1.245881,-0.820859,0.285859},{0.430751,-0.373652,0.034535,0.434466},{0.365354,0.243261,0.910114,1.497873}}}}
};
float eval_polynomial(float variables[4],int program_index,int variable_index,int indices[4]){
    if(variable_index==4)return program[program_index][indices[0]][indices[1]][indices[2]][indices[3]];
    float result=0,base=1;
    for(int power=0;power<4;++power){
        indices[variable_index]=power;
        result+=base*eval_polynomial(variables,program_index,variable_index+1,indices);
        base*=variables[variable_index];
    }
    return result;
}
int main(int argc,char *argv[]){
    srand(tick_count());
    rand();
    float variables[4],probability[5],total=0;
    int i,indices[4],temp;
    for(i=0;i<4;++i){
        sscanf(argv[i-4+argc],"%d",&temp);
        variables[i]=temp;
    }
    temp=variables[1];
    variables[1]=variables[2];
    variables[2]=temp;
    if(variables[1]==0){ //bow if our honour is 0
        putchar('B');
        return 0;
    }

    variables[0]/=20;variables[2]/=20;
    variables[1]=1/(variables[1]+1);variables[3]=1/(variables[3]+1);
    for(i=0;i<5;++i){
        probability[i]=eval_polynomial(variables,i,0,indices);
        if(probability[i]<0)probability[i]=0;
        total+=probability[i];
        probability[i]=total;
    }
    total*=(float)rand()/RAND_MAX;
    for(i=0;i<5;++i)if(total<probability[i]){
        putchar("BGIPO"[i]);
        return 0;
    }
    putchar('B');
    return 0;
}

[1] Número totalmente irrelevante. [2] Garantido como verdadeiro 1% do tempo.


YAGMCSE

Os métodos de Monte Carlo parecem exibir um jogo decente, então aqui está mais uma entrada genérica de simulação de Monte Carlo!

Diferentemente da maioria das outras entradas deste concurso, essa entrada usa um grande número de simulações de jogos aleatórios e, portanto, requer o uso do sinalizador -O3 para obter o desempenho ideal.

Compile o programa com o comando: gcc monte.c -o monte -O3 -std = c99

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef _WIN32
#include <Windows.h>
unsigned int tick_count(){
    return GetTickCount();
}
#else
#include <sys/time.h>
unsigned int tick_count(){
    struct timeval t;
    gettimeofday(&t, NULL);
    return 1000 * t.tv_sec + t.tv_usec / 1000;
}
#endif

const int turn_limit=500;
enum Move{
    WAIT,BOW,GUARD,QUICK,PARRY,OVERHEAD
};
struct Player{
    int health,honour;
    enum Move lastMove;
};
typedef struct Player Player;
//<command> <history> <enemy_history> <your_health> <enemy_health> <your_honour> <enemy_honour>
//<command> <your_health> <enemy_health> <your_honour> <enemy_honour>
int damage_table[6][6][2]={
    {{0,0},{0,0},{0,0},{1,0},{1,0},{1,0}}, //P1 is waiting
    {{0,0},{0,0},{0,0},{1,0},{1,0},{1,0}}, //P1 is bowing
    {{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}}, //P1 is guarding
    {{0,1},{0,1},{0,0},{0,0},{1,0},{0,1}}, //P1 is using quick draw
    {{0,1},{0,1},{0,0},{0,1},{0,0},{1,0}}, //P1 is parrying
    {{0,1},{0,1},{0,0},{1,0},{0,1},{0,0}} //P1 is using overhead attack
};
enum Move decode_move(char x){
    switch(x){
        case 'W': return WAIT; break;
        case 'B': return BOW; break;
        case 'G': return GUARD; break;
        case 'I': return QUICK; break;
        case 'P': return PARRY; break;
        case 'O': return OVERHEAD; break;
    }
    return WAIT;
}
struct SimulationStat{
    enum Move first_me_move;
    int win,draw,lose,compound;
};
int stat_compare(const void*a,const void*b){
    return ((struct SimulationStat*)b)->compound-((struct SimulationStat*)a)->compound;
}
struct SimulationStat monte_carlo(int num_iters,enum Move first_me_move,Player original_me,Player original_opponent){
    struct SimulationStat simulation_result={first_me_move,0,0,0};

    for(int iter=0;iter<num_iters;++iter){
    Player me=original_me,opponent=original_opponent;
        int turn,game_result;
        for(turn=0;turn<turn_limit;++turn){
            enum Move me_move,opponent_move=rand()%(OVERHEAD-BOW+1)+BOW;
            if(turn==0)me_move=first_me_move;
            else me_move=rand()%(OVERHEAD-BOW+1)+BOW;

            //update honour for guarding
            if(me.lastMove==GUARD&&me_move==GUARD)--me.honour;
            if(opponent.lastMove==GUARD&&opponent_move==GUARD)--opponent.honour;

            int me_attacking=me_move==QUICK||me_move==PARRY||me_move==OVERHEAD,opponent_attacking=opponent_move==QUICK||opponent_move==PARRY||opponent_move==OVERHEAD;

            //update health of players
            me.health-=damage_table[me_move][opponent_move][0]*(1+(opponent.honour>=7));
            opponent.health-=damage_table[me_move][opponent_move][1]*(1+(me.honour>=7));

            //update honour for attacking (Sword of the Gods is revoked after the player attacks with an original honour value of 7)
            if(me_attacking)--me.honour;
            if(opponent_attacking)--opponent.honour;

            //printf("%d %d\n",me.health,me.honour);
            //printf("%d %d\n",opponent.health,opponent.honour);

            //check if any of the terminating conditions are met
            //c. both players fall off the graces of the gods (me.honour<0&&opponent.honour<0)
            if(me.honour<0&&opponent.honour<0){
                game_result=0; //draw
                break;
            }
            //a. player 1 falls off the graces of the gods (me.honour<0)
            else if(me.honour<0){
                game_result=-1; //loss
                break;
            }
            //b. player 2 falls off the graces of the gods (opponent.honour<0)
            else if(opponent.honour<0){
                game_result=1; //win
                break;
            }
            //d. both players are dead (me.health<0&&opponent.health<0)
            else if(me.health<0&&opponent.health<0){
                game_result=0; //draw
                break;
            }
            //e. player 1 is dead (me.health<0)
            else if(me.health<0){
                game_result=-1; //loss
                break;
            }
            //f. player 2 is dead (opponent.health<0)
            else if(opponent.health<0){
                game_result=1; //win
                break;
            }
        }
        //both players get struck down by the guards for being boring
        if(turn==turn_limit)game_result=0; //draw

        if(game_result==1)++simulation_result.win;
        else if(game_result==0)++simulation_result.draw;
        else ++simulation_result.lose;
    }
    return simulation_result;
}
int main(int argc,char*argv[]){
    //const int num_iters=200000,num_shortlist_iters=1000000;
    const int num_iters=20000,num_shortlist_iters=55000;

    srand(tick_count());
    Player me,opponent;
    if(argc==5){
        sscanf(argv[1],"%d",&me.health);
        sscanf(argv[2],"%d",&opponent.health);
        sscanf(argv[3],"%d",&me.honour);
        sscanf(argv[4],"%d",&opponent.honour);
        me.lastMove=WAIT;
        opponent.lastMove=WAIT;
    }else{
        sscanf(argv[3],"%d",&me.health);
        sscanf(argv[4],"%d",&opponent.health);
        sscanf(argv[5],"%d",&me.honour);
        sscanf(argv[6],"%d",&opponent.honour);
        me.lastMove=decode_move(argv[1][strlen(argv[1])-1]);
        opponent.lastMove=decode_move(argv[2][strlen(argv[2])-1]);
    }

    struct SimulationStat results[6];
    results[0].first_me_move=WAIT;
    results[0].win=0;
    results[0].draw=0;
    results[0].lose=num_iters;
    results[0].compound=-num_iters*2-1000; //waiting is worse than any other action

    for(enum Move first_me_move=BOW;first_me_move<=OVERHEAD;++first_me_move){
        results[first_me_move]=monte_carlo(num_iters,first_me_move,me,opponent);
        struct SimulationStat *cur=&results[first_me_move];
        cur->compound=cur->win*4+cur->draw*1-cur->lose*2;
    }
    qsort(results,OVERHEAD-WAIT+1,sizeof(*results),stat_compare);

    for(int i=0;i<OVERHEAD-BOW+1;++i){
        struct SimulationStat *cur=&results[i];
//        fprintf(stderr,"%c: %f%% win, %f%% draw, %f%% lose => %d\n","WBGIPO"[cur->first_me_move],(double)cur->win/num_iters*100.,(double)cur->draw/num_iters*100.,(double)cur->lose/num_iters*100.,cur->compound);
    }

    for(int i=0;i<2;++i){
        results[i]=monte_carlo(num_shortlist_iters,results[i].first_me_move,me,opponent);
        struct SimulationStat *cur=&results[i];
        cur->compound=cur->win*2+cur->draw*1;
    }
    qsort(results,2,sizeof(*results),stat_compare); 

    for(int i=0;i<2;++i){
        struct SimulationStat *cur=&results[i];
//        fprintf(stderr,"%c: %f%% win, %f%% draw, %f%% lose => %d\n","WBGIPO"[cur->first_me_move],(double)cur->win/num_shortlist_iters*100.,(double)cur->draw/num_shortlist_iters*100.,(double)cur->lose/num_shortlist_iters*100.,cur->compound);
    }
    putchar("WBGIPO"[results[0].first_me_move]);
    return 0;
}

11
Ele apenas parece se curvar por qualquer motivo. Você pode querer dar uma olhada
C5H8NNaO4

@ C5H8NNaO4 Obrigado por me notificar sobre esse bug sério. Minha edição deve corrigir o erro.
Potatomato

YAGMCSE parece fazer apenas o quer GBWWWWW...ouBWWWW
C5H8NNaO4

@ C5H8NNaO4 Isso é estranho. Não consigo replicar os resultados que você mencionou. O oponente do YAGMCSE estava sempre se curvando / vigiando / esperando?
Potatomato 01/07/2015

Sim, ele estava se curvando nas primeiras 7 rodadas. Aqui está um pastebin #
C5H8NNaO4

1

Após minha tentativa fracassada de entrar no Target Dummy, apresento a você meu próximo bot ...

ScroogeBot - Python 2

Esse bot vai se curvar se ele tiver uma honra. Caso contrário, ele jogará uma moeda.

Se cair na cabeça, ele realizará um ataque aleatório. Se cair nas caudas, ele irá se curvar ou guardar.

Comando: python scroogebot.py

import random, sys
# If he has more than one honor...
if int(sys.argv[5]) > 1:
    #Flip a coin.
    coin = random.choice(['heads','tails'])
    #If the coin lands on heads...
    if coin == 'heads':
        #Attack!
        print random.choice(['I','O','P'])
    #If the coin lands on tails...
    else:
        #Don't attack!
        print random.choice(['G','B'])
#If he has 1 honor...
else:
    #Bow!
    print "B"

Yay, uma nova entrada! Apenas um alerta rápido - pode demorar um pouco até que eu possa montar um novo torneio, desde que eu reimaginei meu sistema operacional ontem. No entanto, eu deveria ter um novo torneio finalizado com seus resultados até o final da semana.
absinthe

0

Yoshimitsu (JS)

Tentar não ser vigiado verificando os dois últimos movimentos, obterá bravura com maior honra. com base nos apsillers modelo feitos

var attacks = ['I','P','O'];
var pasive = ['B','W'];
var argv = process.argv;
var playerHistory = argv.length>6?argv[2].split(''):[];
var enemyHistory = argv.length>6?argv[3].split(''):[];
var offset = 8 - argv.length;
var my = { health:+argv[4-offset], honor:+argv[6-offset], history:playerHistory };
var enemy = { health:+argv[5-offset], honor:+argv[7-offset], history:enemyHistory };
my.godSword = my.honor >= 7;
enemy.godSword = enemy.honor >= 7;

enemy.lastMove = enemyHistory.pop();
enemy.secondToLast = enemyHistory.pop();

enemy.didAttack = !!attacks.indexOf(enemy.lastMove);

my.lastMove = playerHistory.pop();

function decide() {
    process.stdout.write(arguments[Math.floor(arguments.length*Math.random())]);
    process.exit();
}

chooseAnAttack = function(){ decide.apply(this,attacks); };

if( ( pasive.indexOf( enemy.lastMove ) && my.honor < 15 ) || (my.honor < 7 && enemy.health > 10) || my.honor === 1 ){
    if( Math.random * 15 < my.honor ){
        chooseAnAttack();
    } else {
        decide('B');
    }
} else if( enemy.honor < 2 ){
    chooseAnAttack();
} else if( enemy.didAttack ){

    if( attacks.indexOf( enemy.secondToLast ) ){
        decide('G');
    } else if( pasive.indexOf( enemy.secondToLast ) ){
        chooseAnAttack();
    } else if( enemy.secondToLast == 'G' ){
        decide('B');
    }

} else if( enemy.lastMove = 'G' ) {
    chooseAnAttack();
} else if( enemy.lastMove === 'W' ){
    if( attacks.indexOf( enemy.secondToLast ) ){
        decide('G');
    } else if( pasive.indexOf( enemy.secondToLast ) ){
        chooseAnAttack();
    } else if( enemy.secondToLast == 'G' ){
        decide('B');
    }
}

0

O Louco (C)

O Louco implora uma estratégia bastante errática, nunca repetindo o mesmo movimento duas vezes, a menos que seja forçado a passar por falta de honra. Seus movimentos são amplamente baseados na aleatoriedade, dificultando a previsão de suas ações. Seu bem-estar é a última coisa em sua mente, pois seus pensamentos se concentram apenas no derramamento de sangue e na vitória final

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

const char commands[] =
{
    'W', 'B', 'G', 'I', 'P', 'O'
};

char select_candidate(const char c[])
{
    unsigned i = 0;
    int n_candidates = 0;
    char candidates[sizeof(commands)];

    for (; i < sizeof(commands); i++)
        if (c[i])
            candidates[n_candidates++] = c[i];

    /* There are no candidates for actions, so the fool blindly attacks his opponent, hoping for the best */
    return n_candidates == 0 ? 'I' : candidates[rand() % n_candidates];
}

int main(int argc, char *argv[])
{
    unsigned i = 0;
    int honour;
    char candidates[sizeof(commands)];
    char last_action;

    srand(time(NULL));

    memcpy(candidates, commands, sizeof(commands));

    /* It's the first round, the fool selects a random action except for waiting */
    if (argc != 7)
    {
        candidates[0] = 0;
        putchar(select_candidate(candidates));
        return 0;
    }

    last_action = argv[1][strlen(argv[1]) - 1];
    honour = atoi(argv[5]);

    if (honour == 0)
    {
        /* The fool realises he will meet his doom if he performs any of the following moves */
        /* and removes them from his list of possible actions */
        candidates[3] = 0;
        candidates[4] = 0;
        candidates[5] = 0;

        /* Only omit the blocking action if the last action was blocking */
        if (last_action == 'G')
            candidates[2] = 0;
    } else if (honour >= 7) {

        /* If the fool has the opportunity to abuse power, he will */
        candidates[0] = 0;
        candidates[1] = 0;
    }

    /* However unintellegent, the fool decides never to repeat the same move twice */
    for (; i < sizeof(commands); i++)
    {
        if (candidates[i] == last_action)
        candidates[i] = 0;
    }

    /* The fool randomly selects a possible action and hopes for the best */
    putchar(select_candidate(candidates));

    return 0;
}


O Profeta (C)

O Profeta usa o conhecimento dos 2 movimentos anteriores de seu oponente para prever seu próximo movimento e fornecer um contra-ataque rápido e mortal. Além disso, ele faz astrologia e outras coisas.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main(int argc, char* argv[])
{
    char* hist;
    char* enemy_hist;
    int hist_len;
    int enemy_hist_len;
    int health;
    int enemy_health;
    int honour;
    int enemy_honour;

    if (argc != 7)
    {
        /* Always start with guarding */
        putchar('G');
        return 0;
    }

    srand(time(NULL));

    /* Grab the command-line values */
    hist         = argv[1];
    enemy_hist   = argv[2];
    health       = atoi(argv[3]);
    enemy_health = atoi(argv[4]);
    honour       = atoi(argv[5]);
    enemy_honour = atoi(argv[6]);

    hist_len = strlen(hist);
    enemy_hist_len = strlen(enemy_hist);

    /* Looks like the enemy is starving for honour. */
    /* This means that they have to bow, so attack them,  */
    /* But only if we have the honour to do so. */
    if (enemy_honour == 0 && honour > 0)
    {
        putchar('O');
        return 0;
    } else if (honour == 0) {
        /* We have to bow */
        putchar('B');
        return 0;
    } else if (honour <= 3) {
        /* We have low honour, attack if the enemy has no honour, otherwise bow to restore some of our honour */
        putchar(enemy_honour == 0 ? ((rand() % 2) ? 'I' : 'O') : 'B');
        return 0;
    }

    switch (enemy_hist[enemy_hist_len - 1])
    {
        /* The enemy has previously performed a passive action, so they will likely attack this round */
        case 'W':
        case 'B':
        case 'G':
            putchar(hist[hist_len - 1] == 'G' ? 'P' : 'G'); /* Protect ourselves, using `guard` if we did not use it last turn */
            return 0;

        default:
            if (enemy_hist_len >= 2)
            {
                switch (enemy_hist[enemy_hist_len - 2])
                {
                    case 'I':
                    case 'P':
                    case 'O':
                        /* The enemy has attacked for the last 2 turns, they will likely rest now */
                        putchar((rand() % 2) ? 'I' : 'O');
                        return 0;

                    default:
                        /* Low health, block an incoming attack */
                        if (health <= 5)
                        {
                            putchar(hist[hist_len - 1] == 'G' ? 'P' : 'G');
                            return 0;
                        } else {
                            /* Choose randomly to bow or attack */
                            int decision = rand() % 3;
                            putchar(decision == 2 ? 'B' : decision == 1 ? 'I' : 'O');
                            return 0;
                        }
                }
            } else {
                /* Attack! */
                putchar((rand() % 2) ? 'I' : 'O');
                return 0;
            }
    }

    /* If somehow we get to this point, parry */
    putchar('P');
    return 0;
}


Compilação

Ambos os programas são escritos em C e podem ser compilados com gcc:

gcc fool.c -o fool
gcc prophet.c -o prophet


Corrida

* nix

./fool <args>
./prophet <args>

janelas

fool.exe <args>
prophet.exe <args>
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.