The Ultimate Samurai Showdown


37

Aviso: este desafío del ha completado. Esto significa que la marca de verificación verde, que se ha otorgado a C5H8NNaO4 por su entrada, The Observer no se moverá a ninguna nueva respuesta.

Aún puede enviar nuevas entradas, pero puede haber retrasos en los nuevos torneos que se ejecutan ya que ya no estoy buscando activamente nuevas entradas.

Introducción

En este desafío, estás jugando un juego de arcade titulado The Ultimate Samurai Showdown Ultimate Edition Special Version 2.0 X Alpha Omega Turbo (o simplemente Ultimate Samurai Showdown para abreviar). ¿Tus oponentes? ¡Nada menos que los otros miembros de Programming Puzzles & Code Golf!

Como es de esperar de un juego arcade PPCG, no juegas Ultimate Samurai Showdown directamente, sino que escribes un programa que jugará el juego por ti. Este programa luchará contra los programas enviados por otros usuarios en duelos uno a uno. El programa más hábil será coronado como el último samurai de PPCG, y se le otorgará la marca verde de la leyenda.

Descripción del juego

Esta sección describe la mecánica detrás del juego.

Condición de victoria

Una partida consta de dos samurai que se enfrentan entre sí. Cada samurai comienza cada partida con 20 puntos de golpe y 1 honor . Un samurai gana si su oponente está muerto y todavía está vivo. Hay dos métodos por los cuales un samurai puede morir:

  1. Si los puntos de golpe de un samurai se reducen a 0, morirá.
  2. Si un samurai trae su propio honor por debajo de 0, será derrotado por los dioses por actuar deshonrosamente en un duelo.

Ser derrotado por los dioses tiene mayor prioridad que reducir los puntos de golpe a 0, por lo que en una situación en la que un samurai tiene 0 puntos de vida y el otro tiene -1 honor, el samurai con 0 puntos de vida ganará. En una situación en la que ambos samurai tienen -1 honor, ambos son derrotados por los dioses y el juego es un empate.

Una partida consta de hasta 500 turnos . Si pasan los 500 turnos y la partida no se ha decidido (ninguno de los samuráis ha muerto), los dioses se aburren y derriban a los dos samuráis, lo que resulta en un empate.

Comportamiento

En cada turno, el samurai debe realizar exactamente una de las siguientes acciones:

W

El samurai esperará y no realizará ninguna acción. Esto lo hace ver genial, pero no lo ayuda a derrotar a su oponente. Esta es también la acción predeterminada.

B

El samurai se inclinará ante su oponente de manera honorable. Esto agrada a los dioses y, por lo tanto, el samurai ganará 1 Honor. El honor es vital para el éxito de tu samurai porque el honor es esencialmente el "recurso" para este juego: todos se separan By Wpueden disminuir el honor. Además, si un samurai gana 7 de Honor o más, se le otorga el uso de la Espada de los Dioses . Las implicaciones de esto se describen a continuación.
Sin embargo, inclinarse ante su oponente lo deja abierto si su oponente decide golpearlo con su espada, así que tenga cuidado cuando elija inclinarse.

G

El samurai entrará en una posición defensiva y protegerá contra cualquier golpe de espada. Este movimiento bloqueará con éxito todos los golpes de espada, incluso los realizados con la Espada de los Dioses .
Sin embargo, los dioses fruncen el ceño ante un samurai demasiado defensivo, por lo que este movimiento consumirá 1 Honor si la acción del samurai en el turno inmediatamente anterior también estaba protegiendo. No consume Honor de otra manera.

I

El samurai intentará golpear a su oponente con una rápida extracción de su espada de su vaina. Si el samurai tiene 7 Honor o más, usará la Espada de los Dioses en lugar de su espada normal. Este movimiento consume 1 Honor.
El empate rápido es un golpe rápido que vencerá a los ataques aéreos más lentos, sin embargo, perderá contra las paradas. Si el golpe se conecta con éxito, causará 1 daño o 2 daños con la Espada de los Dioses .

P

El samurai intentará detener cualquier ataque entrante y luego lanzar su propio ataque. Si el samurai tiene 7 Honor o más, usará la Espada de los Dioses en lugar de su espada normal. Este movimiento consume 1 Honor.
La parada es una buena maniobra contra golpes rápidos, pero será dominada por ataques aéreos más lentos. Si el golpe se conecta con éxito, causará 1 daño o 2 daños con la Espada de los Dioses .

O

El samurai intentará golpear a su oponente con un ataque aéreo más lento. Si el samurai tiene 7 de Honor o más, usará la Espada de los Dioses en lugar de su espada normal. Este movimiento consume 1 honor.
El ataque aéreo puede dominar las paradas, pero perderá contra los ataques rápidos. Si el golpe se conecta con éxito, causará 1 daño o 2 daños con la Espada de los Dioses .

Espada de los dioses

Un samurai con Honor de 7 o más gana la habilidad de usar la Espada de los Dioses . Si su Honor se reduce por debajo de 7, se le revocará la habilidad de usar la Espada de los Dioses . La Espada de los Dioses hace 2 daños en lugar de 1.

La Espada de los Dioses no permite que un golpe derrote un golpe de espada que normalmente no vencería. Por ejemplo, una parada de la Espada de los Dioses seguirá perdiendo en un ataque aéreo ordinario, y una extracción rápida de la Espada de los Dioses no dominará una extracción rápida ordinaria. De hecho, la llamada Espada de los Dioses en realidad no es tan poderosa, tal vez es una broma cósmica interpretada por los dioses ...

Tabla de interacciones

El Fragmento de pila a continuación contiene una tabla que enumera explícitamente todos los resultados posibles de las diferentes combinaciones de acciones que los dos samurais pueden tomar. Para verlo, haga clic en "Mostrar fragmento de código", luego haga clic en "Ejecutar fragmento de código".

Comunicación del programa

Para facilitar la ejecución del torneo, se escribió un programa controlador para desempeñar el papel de los "dioses": mantiene registros de honor y salud y golpea al samurai en consecuencia. Esta sección describe cómo se comunicará su programa con el programa controlador.

Descripción de entrada

El programa controlador llamará a su programa desde la línea de comando de esta manera:

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

dónde:

  • <command>es el comando requerido para ejecutar su programa. Por ejemplo, si su programa está en un archivo super_sentai.pl, el comando probablemente lo esté perl super_sentai.pl.

  • <history>es una historia de movimientos que hiciste. Por ejemplo, WWBPsignificaría que esperó dos veces, se inclinó una vez y se paró una vez.

  • <enemy_history>es una historia de movimientos que hizo tu enemigo. Por ejemplo, BBBIsignificaría que tu enemigo se inclinó tres veces y realizó un sorteo rápido.

  • <your_health> es tu salud actual

  • <enemy_health> es la salud actual del enemigo.
  • <your_honour> es tu honor actual
  • <enemy_honour> Es el honor actual del enemigo.

Para el primer turno, el historyy enemy_historyestará vacío, por lo que solo se llamará a su programa con los últimos cuatro argumentos como este:

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

¡Prepárate para esto!

Los lectores astutos pueden notar que los cuatro argumentos que proporcionan el honor y la salud de ambos samurai son, hasta cierto punto, superfluos; Como este es un juego de información perfecto, el honor y la salud del samurai se pueden determinar utilizando solo las historias.

Estos valores se proporcionan para fines de conveniencia para que no tenga que analizar los argumentos del historial. Esto debería resultar útil para implementar estrategias simples, como no atacar cuando su Honor es 0.

Descripción de salida

Para elegir una acción, su programa debe una salida de W, B, G, I, P, o Oen la salida estándar, dependiendo de la acción que desea realizar. Si su programa no genera nada dentro de 1000 ms, se terminará y su programa se tratará como si se emitiera W.

Si su programa genera más de una letra, solo se considerará la primera letra, por lo que la salida Parryserá lo mismo que la salida P.

Si la salida de la primera letra de su programa no es ninguna de las opciones enumeradas anteriormente, se establecerá de manera predeterminada W.

Formato de envío

Envía un programa como respuesta a esta publicación. Puede enviar múltiples programas. Si está enviando múltiples programas simples, le recomiendo enviarlos como una sola respuesta; Si está enviando múltiples programas complejos, le recomiendo enviarlos como respuestas separadas. Una vez que haya agregado con éxito su programa / s al torneo, me comprometeré con el repositorio de git con su entrada (vinculada a continuación).

Si encuentro problemas que impiden que su programa se agregue al torneo, dejaré un comentario en su entrada indicando el problema.

Incluya lo siguiente en su envío:

  1. El nombre legible por humanos de su programa, para usar en marcadores. Los espacios están permitidos aquí; las comas y los caracteres Unicode no lo son.
  2. El idioma en el que está escrito su programa. Evite escribir en idiomas extraños y de difícil acceso como TinyMUSH.
  3. Una breve sinopsis de su programa. Esto puede ser una descripción de cómo funciona el programa, o simplemente un poco de texto de sabor sobre su programa (si quiere ser todo secreto), o tal vez ambos.
  4. Los comandos requeridos para ejecutar su programa. Por ejemplo, si estaba escribiendo su envío en Java llamado example.java, proporcionaría instrucciones de compilación y javac example.javaluego instrucciones de ejecución java example.
  5. El código fuente del programa.

Para ayudar en el envío, proporciono una plantilla de envío que se puede encontrar aquí . La plantilla hace que las presentaciones se vean mejor. Recomiendo encarecidamente su uso.

También proporciono dos entradas de ejemplo. Aunque las entradas de ejemplo participarán en el round robin, su propósito principal es aclarar los formatos de presentación y entrada / salida para el torneo, en lugar de ser competidores serios por el título de Ultimate Samurai.

Estructura de torneo

Esta sección describe cómo se realizará el torneo entre los participantes.

Programa de control

El programa de control está escrito en Python 2 y se puede encontrar en el repositorio Ultimate Samurai Showdown Github . Si desea ejecutarlo usted mismo, las instrucciones sobre cómo ejecutarlo se incluyen en el archivo README.md en el enlace. Sin embargo, solo los torneos que se ejecuten en mi computadora serán oficiales para evitar diferencias de hardware que afecten los resultados del torneo.

El programa de control se ejecutará en una computadora portátil con Arch Linux. Tiene un procesador Intel Core i7 y 8GB de RAM. Me esforzaré para que todas las entradas se ejecuten en mi computadora, pero lo agradecería enormemente si evita los idiomas a los que no se puede acceder libremente (como sin costo monetario).

Sistema de puntuación

El sistema de puntuación es un round robin. Cada programa jugará ocho partidos contra cualquier otro programa. Una victoria le otorga al programa 1 punto, una pérdida sin puntos y un empate 0.5 puntos. El programa con la puntuación más alta gana el juego. Si hay un empate, competiré entre los dos mejores programas para determinar el ganador.

El número de veces que cada programa se reproducirá entre sí puede reducirse de 8 si hay un número extremadamente grande de participantes. Agregaré una nota aquí si esto ocurre.

Ejecutaré el round robin muchas veces a medida que se publiquen nuevos envíos, pero solo contará el round robin más reciente.

Descalificaciones

Es posible que su programa sea descalificado del torneo. La descalificación puede ocurrir si:

  • Su programa no se compila ni se ejecuta;
  • Su programa es un duplicado estratégico de otro programa (es decir, implementa exactamente la misma estrategia que otro programa);
  • Su programa intenta sabotear otros programas modificando el código del controlador, el código de otro programa, etc.
  • Su programa intenta explotar un error en el código del controlador. En lugar de explotar errores, debería abrir un problema en el repositorio de git, hacer un comentario aquí o hacerme ping en el chat.

Resultados pasados

Los resultados detallados de todos los torneos están disponibles en la página wiki .

El torneo más reciente se completó el 2015-07-17 07:20. Aquí hay un resumen de los 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

1
El camarero lo está haciendo sorprendentemente bien. Debe estar acumulando victorias contra Spork Holder cuando se queda sin honor.
StephenTG

Este es un gran desafío. Claramente pensaste mucho y trabajaste en esto, y creo que definitivamente valió la pena. Excelente trabajo. :)
Alex A.

1
@ C5H8NNaO4 Sí, buscaré actualizaciones para los bots antes de ejecutar el próximo torneo.
absenta

1
Aviso: mi computadora portátil se descompuso recientemente. Por lo tanto, no tengo una forma actual de ejecutar el torneo en un futuro próximo. Habrá demoras en la ejecución del próximo torneo mientras trato de encontrar una computadora que pueda usar.
ajenjo

1
@Levi ¡Sí! El fabricante me envió un reemplazo que llegó hoy. Hay un torneo corriendo mientras hablamos.
ajenjo

Respuestas:


8

El monje (Java)

El monje valora el honor y alaba las bendiciones de los dioses. Siendo entrenado en paciencia, calmadamente envía sus oraciones al cielo hasta que se siente favorecido por Dios.

Disfrutando de su vida, trata de protegerla. Cuando pierde salud por encima de cierto ritmo, se defiende lo mejor que puede.

Esperando el apoyo de sus dioses, envía al azar eyaculaciones [1] al cielo, de lo contrario, lucha lo mejor que puede.

Si su oponente está agotado de la batalla, lo termina usando su honor restante para otorgarle una muerte rápida e indolora.

Compilar / Ejecutar

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);
    }
}

El ninja (Java)

El Ninja es rápido y ataca aún más rápido. Ataca inmediatamente después de un saludo formal amistoso, confundiendo aún más a su enemigo al inclinarse antes y después de cada ataque.

Al ser bendecido, el ninja mantiene este comportamiento, esperando que su oponente haga su primer movimiento (s). Aprovechando esta oportunidad, desata una serie de explosiones, bendecidas por la Diosa ninja hasta que esté demasiado cansado de la batalla. Usando su honor restante, se esconde debajo de las hojas debajo, protegiéndose del próximo ataque. Salta y ataca a su enemigo desde atrás, ocultándose lo más rápido de nuevo.

Si recibe una herida fatal, se esfuerza por llevarse la vida de su oponente con él, por supuesto, manteniendo un mínimo de honor.

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, el ninja imitador (Java)

Kakashi copia los movimientos de sus oponentes eligiendo aleatoriamente entre los dos últimos movimientos realizados por el oponente. Si el oponente espera, se inclina: también mantiene su honor.

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);
    }
}


Desearía que Kakashi pudiera ser bendecido con el Sharingan ... Pensé en leer el cast.txt. Simula cada ronda de su historia contra todos los oponentes allí. Intenta averiguar contra qué oponente está luchando comparando la historia de enemigos simulados con la historia de enemigos reales. Luego usa esa información para predecir el próximo movimiento que haría el oponente y elige el mejor contramovimiento de una lista predefinida. Pero siento que esto podría tomar un poco ya que tengo Internet súper lento en este momento y casi no tengo habilidades Java

El observador, (node.js)

El Observador se inclina antes de intentar predecir el próximo movimiento del oponente de sus últimos 5 movimientos, eligiendo la mejor contraparte para el movimiento predicho.

Editar: ¡Gracias a @apsillers por compartir el boilerplate de 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 (''))

Editar: Tuve una falla importante en el observador, en realidad no sé lo que pensé ayer por la noche. Parece que solo miró los dos últimos movimientos del enemigo. Lo hizo sorprendentemente bien así.

Su memoria ahora es consultada por la parte más larga (final) de la historia de los enemigos que ya ha visto. Contiene una matriz con todos los movimientos que siguieron el historial de movimientos. Uno es seleccionado al azar. Entonces, si un movimiento se sigue con más frecuencia, también es más probable que se elija. Algo así como cadenas de markov.

The Observer, ahora también guardias.


[1]: TIL: la eyaculación tiene un significado religioso


¡Eres el número 1 y el número 3 en este momento! Buenos bots! :)
apsillers 01 de

Felicitaciones por ganar con The Observer. La marca verde ahora es tuya: D
ajenjo

7

Meiyo Senshi (Java)

Proveniente del área de Haijima, no se sabe mucho sobre el Meiyo. Normalmente no participan en juegos deportivos, pero han enviado un guerrero a este para evaluar a sus rivales.

Sin embargo, son un grupo honorable, por lo que puede estar seguro de que hará que su presencia sea conocida por los dioses en poco tiempo. Una vez que haya visto a su enemigo lo suficiente como para informar, usará las bendiciones recibidas para golpear a su oponente.

Para compilar run, es la forma estándar de Java:

> 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

Spork Holder (Ruby)

Spork Holder se inclina en el primer turno, luego actúa al azar después. Es una de las dos entradas de ejemplo.

Mando: ruby spork-holder.rb

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

El camarero (bash)

El camarero solo espera en cada turno. Es una de las dos entradas de ejemplo.

Mando: echo W

No se requiere código fuente.


7

Cobarde (Node.js)

Soy un cobarde / Es un milagro Me atrevo a respirar
Dominado / Por la suave brisa de verano

  • Comprueba BXBXBX/ BBBpatrones para inclinarse (o golpearte) cuando te inclinas.
  • Comprueba si hay GXGXGXpatrones para inclinarse cuando estás vigilando.
  • Si su lanzamiento de valentía al azar supera su umbral de miedo para esa ronda, intentará un golpe.
    • Tener una espada de los dioses lo hace más valiente.
    • Un oponente con una Espada de los Dioses lo hace más temeroso.
    • Un oponente que lidera con al menos 5 puntos de vida o más también lo asusta un poco.
  • De lo contrario, se turna para protegerse e inclinarse.

Si desea escribir un envío de Node.js , no dude en usar mi código repetitivo; todo hasta una decidefunción incluida es totalmente general y 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");
}

1
Ese es un robot difícil. Impresionante repetitivo; Lo usaré de inmediato. Gracias por compartir :)
C5H8NNaO4

6

Whack-a-mole (R)

Ataca cuando es probable que el enemigo se doble, de lo contrario los guardias

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)

Ejecutar usando Rscript Whack-a-mole.R.


1
Buen trabajo, además me encanta el nombre.
Alex A.

3

Guerrero Elefante (Java)

El Elephant Warrior es de una época más antigua y natural. Ha visto mucho y recuerda todo. Él se gana el favor de los dioses mientras examina a su oponente, y luego, una vez que los toma en su corazón, los 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
No he probado esto, pero parece que se saldrá de los límites en el primer turno donde solo hay cuatro args.
Geobits

Correcto, no me di cuenta de que no se incluirían en absoluto. Supongo que obviamente no se puede pasar una cadena en blanco, ¡gracias!
Caín

@katya Ahora está arreglado, por cierto, debería incluirse en el torneo.
Caín

3

Princesa Guerrera (Julia)

Este es el primer desafío de King of the Hill en el que he competido. Veamos cómo va esto.

La Princesa Guerrera prioriza el ataque y el honor, y recurre a la autoconservación cuando es necesario. Ella está bastante ansiosa y nunca espera. En un esfuerzo por mantenerse ágil, ella tampoco usa un ataque aéreo.


Guardar como warrior-princess.jly ejecutar desde la línea de comandos de esta manera:

julia warrior-princess.jl <arguments>

Si no tienes a Julia, puedes descargarla aquí . Para evitar problemas, se recomienda la última versión estable (es decir, no la versión de desarrollo).


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)

1
Su primera entrada de KotH y la primera entrada de Julia KotH si no me equivoco: ¡felicidades!
plannapus

@plannapus ¡Gracias! : D Quizás haga un hábito con eso.
Alex A.

3

Gárgola (Java)

Intenta usar el movimiento defensivo sin consumir honor.

Como es una entrada de 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

Espadachín (C / Java)

El espadachín se inclina en el primer turno y cada vez que se está quedando sin honor. Luego verifica si el oponente no se había inclinado, defendido o esperado en el turno anterior. Si el oponente no lo hubiera hecho, existe una gran probabilidad de que haga uno de estos en el turno actual y, por lo tanto, el espadachín golpea al oponente al azar. Si esto no es cierto, defiende si no ha defendido el turno anterior. Si lo hubiera hecho, se inclina para ganar honor.

Versión 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 GCC (compilador) y guarde el código en un archivo llamado comando " Swordsman.c " para compilar:

gcc Swordsman.c -o Swordsman

Se creará un ejecutable llamado " Swordsman ". Ejecutar usando

Swordsman

Versión de 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 javac (compilador) y guarde el código en un archivo llamado comando " Swordsman.java " para compilar:

javac Swordsman.java

Archivo de clase llamado "Se creará un Swordsman.class ". Ejecutar usando

java Swordsman



Atacante (Java)

Al atacante no le importa nada, excepto que quiere que su oponente esté muerto. Al azar golpea uno de los movimientos de ataque y si tiene poco honor, se inclina.

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 javac (compilador) y guarde el código en un archivo llamado " comando Attacker.java " para compilar:

javac Attacker.java

Se creará un archivo de clase llamado " Attacker.class ". Ejecutar usando

java Attacker


Vaticinador (C / Java)

Predictor predice los movimientos de los enemigos. En el primer turno, usa un movimiento aleatorio. Se inclina si su honor es bajo, ataca si el honor de los enemigos es bajo o se ha inclinado en el turno anterior. Si el predictor no ha protegido el turno anterior, los guardias en el turno actual. De lo contrario, realiza el mismo movimiento que el enemigo en el turno anterior, siempre que no sea'W' así, Predictor se inclina.

Versión 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 GCC (compilador) y guarde el código en un archivo llamado comando " Predictor.c " para compilar:

gcc Predictor.c -o Predictor

Se creará el ejecutable llamado " Predictor ". Ejecutar usando

Predictor

Versión de 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 javac (compilador) y guarde el código en un archivo llamado comando " Predicator.java " para compilar:

javac Predicator.java

Se creará un archivo de clase llamado " Predicator.class ". Ejecutar usando

java Predicator


No estoy seguro de cuán efectivos serán estos bots, ya que no tengo el intérprete de python2 para probarlo.


1
No he probado esto (atacante), pero parece que se saldrá de los límites en el primer turno donde solo hay cuatro args.
Geobits

El atacante parece estar dando un ArrayIndexOutOfBoundsExceptionprimer turno, haciendo que espere en el primer turno. Aparte de eso está funcionando.
absenta

@Katya y Geobits, fijo. Gracias por verlo.
Spikatrix

Cuando segmentation fault (core dumped)
ejecuto

@ C5H8NNaO4 Se solucionó el problema. Código actualizado para los tres bots. Debería funcionar bien ahora. ¡Gracias por mencionarlo! :-D
Spikatrix

2

Maestro Yi (Python)

El maestro asesino gana mucho favor al principio del juego, construyéndolo hasta que sea invencible. Intenta atacar cuando menos lo esperan.

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 ejecutar: Guardar como MasterYi.py

python MasterYi.py <args>

2

Copy-san (C)

Copia cada movimiento de su oponente. Estoy bastante seguro de que está garantizado para 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 sigue el camino de la serpiente.

La serpiente no necesita la bendición de los dioses.

La serpiente desliza sus golpes; Como las olas en la playa, lo que entra retrocede por donde vino.

La serpiente nunca espera.

La serpiente no tiene sentido de aptitud, de lo contrario, habría sido escrita en Python.

Instrucciones de ejecución:

> javac hebi.java
> java hebi

Cuerpo del 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

El Honorable (Java)

Los honorables valores honran sobre todo. Es decir, su honor por encima de todos los demás. Si el samurai enemigo tiene mayor o igual honor, se inclina. Ninguno será más honorable que él. De lo contrario, hace un movimiento aleatorio. Nunca guarda dos veces seguidas, ¡eso sería deshonroso!

compilar:

> javac TheHonourable.java
> java TheHonourable

Fuente:

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

Bendito Samurai (Python)

Este Samurai trata de mantener el favor de los dioses por el mayor tiempo posible. Se apresura a obtener la espada sagrada, luego alterna entre Guardia y Ataque con uno de los golpes, reabasteciendo el honor cuando sea necesario. Si parece que él o su oponente pueden caer pronto, se apresura a matar. Fácilmente caerá ante un oponente que puede seguir su patrón, pero su estrategia de atacar siempre con dos daños debería ser bastante efectiva.

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 ejecutar:
Guardar como BlessedSamurai.py

python BlessedSamurai.py <args>

44
Su programa necesita imprimir su movimiento.
mbomb007

3
No he probado esto, pero parece que se saldrá de los límites en el primer turno donde solo hay cuatro args.
Geobits

Usé un formato similar a lo que hizo. @Stranjyr, mira lo que hice para obtener los argumentos.
mbomb007

Gracias a los dos! No tengo acceso a un intérprete de Python en este momento, pero creo que he solucionado los problemas. De alguna manera, me perdí por completo que el primer conjunto de instrucciones no tendría un historial.
Stranjyr

Hola, tuviste un pequeño error en tu programa "el nombre global 'apellido' no está definido". Puesto que es un pequeño fallo que he cambiado lasta self.lastlo que parece solucionar el problema.
absenta

1

Hermurai (C ++)

Admira a su oponente y es un poco paranoico. Quiere saber si puede hacer lo que otros samurais pueden hacer, porque todavía no puede creer que sea un samurai. Su sueño incesante se hizo realidad antes de que él lo supiera. Lo que podría costarle la cabeza ...

#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 ++)

Golpea lo más fuerte posible. Entra en modo de ataque imparable cuando está en peligro.

#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 están escritos en C ++. Compilar:

g++ iniqy.cpp -o iniqy

Para ejecutar en Linux: ./iniqy

Para ejecutar en Windows: iniqy.exe


1

El terminador (rubí)

El Terminator no presta atención a su propia salud. El Terminator no tiene noción de honor. El Terminator se envía desde el futuro y simplemente está decidido a terminar con su oponente. Lo hace observando los movimientos de sus oponentes, y nada más. Muestra los movimientos y calcula la respuesta apropiada de una manera tan compleja que ninguna tecnología actual puede predecir las acciones de Terminator. De hecho, para cualquiera que viva en 2015, Terminator puede parecer algo aleatorio ...

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 producto de una extensa manipulación genética, el Agente 38 tiene el físico y la agudeza mental de un super [2] -samurai, y es definitivamente superior a todo su desamparo. [necesitaba citación] viciado [cita requerida] competidores.


//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 completamente irrelevante [2] Garantizado para ser verdad el 1% del tiempo


YAGMCSE

Los métodos de Monte Carlo parecen exhibir un juego decente, así que aquí hay otra entrada de simulación genérica de Monte Carlo.

A diferencia de la mayoría de las otras entradas en este concurso, esta entrada usa una gran cantidad de simulaciones de juegos aleatorios, y por lo tanto requiere el uso de la bandera -O3 para un rendimiento óptimo.

Compile el programa con el 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;
}

1
Él solo parece inclinarse por cualquier razón. Es posible que desee echar un vistazo
C5H8NNaO4

@ C5H8NNaO4 Gracias por notificarme sobre este error grave. Mi edición debería corregir el error.
Potatomato

YAGMCSE parece hacer solo una GBWWWWW...oBWWWW
C5H8NNaO4 01 de

@ C5H8NNaO4 Eso es extraño. No puedo replicar los resultados que ha mencionado. ¿Estaba el oponente de YAGMCSE inclinándose perpetuamente / protegiendo / esperando?
Potatomato

Sí, estaba inclinando las primeras 7 rondas. Aquí hay un pastebin
C5H8NNaO4

1

Después de mi intento fallido de ingresar a Target Dummy, te presento mi próximo bot ...

ScroogeBot - Python 2

Este bot se inclinará si tiene un honor. De lo contrario, lanzará una moneda.

Si cae en la cabeza, realizará un ataque aleatorio. Si cae sobre las colas, se inclinará o protegerá.

Mando: 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, una nueva entrada! Solo un aviso rápido: podría pasar un tiempo antes de que pueda configurar un nuevo torneo, ya que ayer reescribí mi sistema operativo. Sin embargo, debería haber hecho un nuevo torneo con tus resultados para el final de la semana.
ajenjo

0

Yoshimitsu (JS)

Los intentos de no protegerse al verificar los dos últimos movimientos, obtendrán valentía con mayor honor. basado en la plantilla de los apsillers realizados

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

El tonto (C)

El tonto implora una estrategia bastante errática, nunca repite el mismo movimiento dos veces a menos que sea forzado por falta de honor. Sus movimientos se basan en gran medida en la aleatoriedad, lo que dificulta predecir sus acciones. Su bienestar es lo último en lo que piensa, ya que sus pensamientos se centran solo en el derramamiento de sangre y la victoria 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;
}


El profeta (C)

El Profeta usa el conocimiento de los 2 movimientos anteriores de su oponente para predecir su próximo movimiento y proporciona un contraataque rápido y mortal. Además, hace astrología y otras cosas.

#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;
}


Compilacion

Ambos programas están escritos en C y se pueden compilar con gcc:

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


Corriendo

*nada

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

Ventanas

fool.exe <args>
prophet.exe <args>
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.