The Ultimate Samurai Showdown


37

Avviso: questa sfida del è stata completata. Ciò significa che il segno di spunta verde, che è stato assegnato a C5H8NNaO4 per la loro iscrizione, The Observer non verrà spostato in nessuna nuova risposta.

Puoi ancora inviare nuove iscrizioni, ma potrebbero esserci ritardi nei nuovi tornei in corso poiché non sto più controllando attivamente le nuove iscrizioni.

introduzione

In questa sfida, stai giocando a un gioco arcade intitolato The Ultimate Samurai Showdown Ultimate Edition versione speciale 2.0 Alpha Alpha Turbo (o solo Ultimate Samurai Showdown in breve). I tuoi avversari? Nient'altro che gli altri membri di Programming Puzzles & Code Golf!

Come ci si potrebbe aspettare da un gioco arcade PPCG, non si gioca a Ultimate Samurai Showdown direttamente a , ma si scrive piuttosto un programma che giocherà il gioco per te. Questo programma combatterà contro i programmi presentati da altri utenti in duelli uno contro uno. Il programma più qualificato sarà incoronato Ultimate Samurai di PPCG e gli verrà concesso il segno di spunta verde della leggenda.

Descrizione del gioco

Questa sezione descrive le meccaniche alla base del gioco.

Condizione di vittoria

Una partita è composta da due samurai che si affrontano uno contro l'altro. Ogni samurai inizia ogni incontro con 20 punti ferita e 1 onore . Un samurai vince se il suo avversario è morto ed è ancora vivo. Esistono due metodi con cui un samurai può morire:

  1. Se i punti ferita di un samurai vengono ridotti a 0, morirà.
  2. Se un samurai porta il proprio onore al di sotto di 0, verrà colpito dagli dei per aver agito in modo disonorevole in un duello.

Essere abbattuti dagli dei ha una priorità maggiore rispetto alla riduzione dei punti ferita a 0, quindi in una situazione in cui un samurai è a 0 punti salute e l'altro a -1 punti onore, il samurai con 0 punti salute vincerà. In una situazione in cui entrambi i samurai sono in onore di -1, entrambi vengono colpiti dagli dei e il gioco è un pareggio.

Una partita è composta da un massimo di 500 turni . Se passano tutti i 500 turni e la partita non è stata decisa (né il samurai è morto), gli dei si annoiano e abbattono entrambi i samurai, provocando così un pareggio.

Azioni

Ad ogni turno, il samurai deve eseguire esattamente una delle seguenti azioni:

W

Il samurai deve attendere e non eseguire alcuna azione. Questo lo rende bello ma non lo aiuta a sconfiggere il suo avversario. Questa è anche l'azione predefinita.

B

Il samurai si inchinerà al suo avversario in modo onorevole. Questo piace agli dei e quindi il samurai otterrà 1 onore. Honor è vitale per il successo del tuo samurai perché Honor è essenzialmente la "risorsa" per questo gioco: tutti si allontanano Be Wpossono diminuire Honor. Inoltre, se un samurai ottiene 7 punti onore o più, gli viene concesso l'uso della Spada degli Dei . Le implicazioni di ciò sono descritte di seguito.
Tuttavia, inchinarsi al tuo avversario ti lascia aperto se il tuo avversario decide di colpirti con la sua spada, quindi fai attenzione quando scegli di inchinarti.

G

Il samurai deve entrare in una posizione difensiva e proteggersi da qualsiasi attacco di spada. Questa mossa bloccherà con successo tutti i colpi di spada, anche quelli fatti con la Spada degli Dei .
Tuttavia, gli dei disapprovano un samurai eccessivamente difensivo, quindi questa mossa consumerà 1 Onore se anche l'azione del samurai nel turno immediatamente precedente era di guardia. Non consuma Honor altrimenti.

I

Il samurai tenterà di colpire il suo avversario con una rapida estrazione della sua spada dal suo fodero. Se il samurai ha 7 punti onore o più, userà la Spada degli dei invece della sua spada normale. Questa mossa consuma 1 onore.
Il sorteggio rapido è un colpo rapido che batterà attacchi aerei più lenti, tuttavia, perderà contro le parate. Se lo sciopero si collega correttamente, infliggerà 1 danno o 2 danni con la Spada degli Dei .

P

Il samurai dovrà tentare di parare qualsiasi attacco in arrivo, quindi lanciare il proprio attacco. Se il samurai ha 7 punti onore o più, userà la Spada degli dei invece della sua spada normale. Questa mossa consuma 1 onore.
La parata è una buona manovra contro i colpi veloci, ma sarà sopraffatta da attacchi aerei più lenti. Se lo sciopero si collega correttamente, infliggerà 1 danno o 2 danni con la Spada degli Dei .

O

Il samurai tenterà di colpire il suo avversario con un attacco aereo più lento. Se il samurai ha 7 punti onore o superiore, userà la spada degli dei invece della sua spada normale. Questa mossa consuma 1 onore.
Il colpo in testa può sopraffare le parate, ma perderà in caso di colpi veloci. Se lo sciopero si collega correttamente, infliggerà 1 danno o 2 danni con la Spada degli Dei .

Spada degli dei

Un samurai con Honor che è 7 o più ottiene la capacità di usare la Spada degli Dei . Se il suo onore viene ridotto al di sotto di 7, la capacità di usare la Spada degli dei verrà revocata da lui. La spada degli dei infligge 2 danni invece di 1.

La Spada degli dei non consente a un colpo di sconfiggere un colpo di spada che normalmente non avrebbe sconfitto. Ad esempio, una parata di Sword of the Gods perderà comunque con un normale colpo in testa e un'estrazione rapida di Sword of the God non prevarrà su un'estrazione rapida ordinaria. Anzi, il cosiddetto Spada degli dei non è in realtà così potente - forse è uno scherzo cosmico interpretato dagli dei ...

Tabella delle interazioni

Il frammento di stack di seguito contiene una tabella che elenca esplicitamente tutti i possibili risultati delle diverse combinazioni di azioni che i due samurai possono eseguire. Per visualizzarlo, fai clic su "Mostra snippet di codice", quindi fai clic su "Esegui snippet di codice".

Comunicazione del programma

Per facilitare lo svolgimento del torneo, è stato scritto un programma di controllo per interpretare il ruolo degli "dei": mantiene registri di onore e salute e colpisce di conseguenza il samurai. Questa sezione descrive come comunicherà il programma con il programma del controller.

Descrizione dell'input

Il programma del controller chiamerà il tuo programma dalla riga di comando in questo modo:

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

dove:

  • <command>è il comando richiesto per eseguire il programma. Ad esempio, se il programma si trova in un file super_sentai.pl, probabilmente è il comando perl super_sentai.pl.

  • <history>è una storia di mosse che hai fatto. Ad esempio, WWBPvorrebbe dire che hai aspettato due volte, inchinato una volta e parato una volta.

  • <enemy_history>è una storia di mosse compiute dal tuo nemico. Ad esempio, BBBIsignificherebbe che il tuo nemico si è inchinato tre volte ed ha eseguito un sorteggio rapido.

  • <your_health> è la tua salute attuale.

  • <enemy_health> è la salute attuale del nemico.
  • <your_honour> è il tuo attuale onore.
  • <enemy_honour> è l'onore attuale del nemico.

Per il primo turno, historye enemy_historysarà vuoto, quindi il tuo programma verrà chiamato con gli ultimi quattro argomenti come questo:

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

Si prega di essere preparati per questo!

I lettori astuti possono notare che i quattro argomenti che forniscono l'onore e la salute di entrambi i samurai sono, in una certa misura, superflui; dato che si tratta di un perfetto gioco di informazioni, l'onore e la salute del samurai possono essere determinati usando solo le storie.

Questi valori vengono forniti a scopo di praticità, in modo da non dover analizzare gli argomenti della cronologia. Ciò dovrebbe rivelarsi utile per implementare strategie semplici, come non attaccare quando il tuo Honor è 0.

Descrizione dell'uscita

Per scegliere un'azione, il programma dovrebbe uscita una delle W, B, G, I, P, o Osullo standard output, a seconda di quale azione si vuole fare. Se il tuo programma non emette nulla entro 1000 ms, verrà terminato e il tuo programma verrà trattato come se fosse stato emesso W.

Se il tuo programma genera più di una lettera, verrà presa in considerazione solo la prima, quindi l'output Parrysarà lo stesso dell'output P.

Se l'output della prima lettera del tuo programma non è una delle opzioni sopra elencate, verrà automaticamente impostato su W.

Formato di invio

Invia un programma come risposta a questo post. È possibile inviare più programmi. Se stai inviando più programmi semplici, ti consiglio di inviarli come un'unica risposta; se stai inviando più programmi complessi, ti consiglio di inviarli come risposte separate. Una volta che avrò aggiunto con successo i tuoi programmi al torneo, farò un commit al repository git con la tua iscrizione (linkato sotto).

Se riscontro problemi che impediscono l'aggiunta del tuo programma al torneo, lascerò un commento sulla tua partecipazione indicando il problema.

Si prega di includere quanto segue nell'invio:

  1. Il nome umano leggibile del tuo programma, da utilizzare nei tabelloni. Gli spazi sono ammessi qui; virgole e caratteri Unicode non lo sono.
  2. La lingua in cui è scritto il tuo programma. Evita di scrivere in lingue strane e di difficile accesso come TinyMUSH.
  3. Una breve sinossi del tuo programma. Questa può essere una descrizione di come funziona il programma, o solo un po 'di testo sul tuo programma (se vuoi essere tutto riservato), o forse entrambi.
  4. I comandi richiesti per eseguire il programma. Ad esempio, se scrivessi il tuo invio in Java chiamato example.java, forniresti le istruzioni per la compilazione, javac example.javaquindi esegui le istruzionijava example .
  5. Il codice sorgente per il programma.

Per facilitare l'invio, fornisco un modello di invio che può essere trovato qui . Il modello rende le presentazioni più belle. Incoraggio fortemente ad usarlo.

Fornisco anche due voci di esempio. Sebbene le voci di esempio parteciperanno al round robin, il loro scopo principale è quello di chiarire i formati di presentazione e input / output per il torneo, piuttosto che essere seri contendenti per il titolo di Ultimate Samurai.

Struttura del torneo

Questa sezione descrive come si svolgerà il torneo tra i partecipanti.

Programma di controllo

Il programma di controllo è scritto in Python 2 e può essere trovato sul repository Ultimate Samurai Showdown Github . Se desideri eseguirlo da solo, le istruzioni su come eseguirlo sono incluse nel file README.md nel link. Tuttavia, solo i tornei eseguiti sul mio computer saranno ufficiali per evitare differenze hardware che incidono sui risultati dei tornei.

Il programma di controllo verrà eseguito su un computer portatile con Arch Linux. Ha un processore Intel Core i7 e 8 GB di RAM. Cercherò di far funzionare tutte le voci sul mio computer, ma lo apprezzerei immensamente se eviti le lingue a cui non è possibile accedere liberamente (come in nessun costo monetario).

Sistema di punteggio

Il sistema di punteggio è un round robin. Ogni programma giocherà otto partite contro ogni altro programma. Una vittoria garantisce al programma 1 punto, una perdita nessun punto e un pareggio di 0,5 punti. Il programma con il punteggio più alto vince la partita. Se c'è un pareggio, duello i primi due programmi uno contro l'altro per determinare il vincitore.

Il numero di volte in cui ciascun programma si giocherà a vicenda può essere ridotto da 8 se vi è un numero estremamente elevato di partecipanti. Aggiungerò una nota qui se questo si verifica.

Eseguirò il round robin molte volte man mano che vengono pubblicati nuovi invii, ma è solo il round robin più recente che conterà.

squalifiche

È possibile che il tuo programma venga squalificato dal torneo. La squalifica può verificarsi se:

  • Il tuo programma non viene compilato o eseguito;
  • Il tuo programma è un duplicato strategico di un altro programma (ovvero implementa esattamente la stessa strategia di un altro programma);
  • Il tuo programma tenta di sabotare altri programmi modificando il codice del controller, il codice di altri programmi, ecc .;
  • Il tuo programma tenta di sfruttare un bug nel codice del controller. Invece di sfruttare i bug, dovresti invece aprire un problema nel repository git, fare un commento qui o pingarmi in chat.

Risultati passati

I risultati dettagliati di tutti i tornei sono disponibili sulla pagina wiki .

Il torneo più recente è stato completato il 17/07/2015 alle 07:20. Ecco un riepilogo dei risultati:

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
Il cameriere sta sorprendentemente bene. Deve accumulare vittorie contro Spork Holder quando si esaurisce l'onore.
StephenTG,

Questa è una bella sfida. Chiaramente hai riflettuto molto e hai lavorato su questo, e penso che sia stato sicuramente ripagato. Lavoro eccellente. :)
Alex A.

1
@ C5H8NNaO4 Sì, controllerò gli aggiornamenti dei robot prima di iniziare il prossimo torneo.
assenzio

1
Avviso: il mio laptop si è rotto di recente. Pertanto, non ho modo di organizzare il torneo nel prossimo futuro. Ci saranno ritardi nello svolgimento del prossimo torneo mentre provo a trovare un computer che posso usare.
assenzio

1
@Levi Sì! Il produttore mi ha spedito un sostituto arrivato oggi. C'è un torneo in corso mentre parliamo.
assenzio

Risposte:


8

The Monk (Java)

Il monaco apprezza l'onore e loda le benedizioni degli dei. Essendo addestrato alla pazienza, invia con calma le sue preghiere in cielo fino a quando non si sente favorito da Dio.

Godendosi la vita, cerca di proteggerla. Quando sta perdendo la salute oltre un certo tasso, si difende il meglio che può.

Sperando nel sostegno dei suoi dei, manda casualmente eiaculazioni [1] in paradiso, altrimenti combatte il meglio che può.

Se il suo avversario è sfinito dalla battaglia, lo finisce usando il suo onore rimanente per garantirgli una morte veloce e indolore.

Compile / Run

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

The Ninja (Java)

Il Ninja è veloce e attacca ancora più velocemente. Attacca subito dopo un amichevole saluto formale, confondendo ulteriormente il suo nemico inchinandosi prima e dopo ogni attacco.

Dopo essere stato benedetto, il ninja mantiene questo comportamento, aspettando che il suo avversario faccia le sue prime mosse. Usando questa opportunità, scatena una serie di esplosioni, benedette dalla dea ninja fino a quando non è troppo sfinito dalla battaglia. Usando il suo onore rimanente si nasconde sotto le foglie sottostanti, proteggendosi dal prossimo attacco. Salta fuori e attacca il nemico da dietro, nascondendosi di nuovo velocemente.

Se riceve una ferita mortale, fa di tutto per portare in vita l'avversario con lui - ovviamente, mantenendo un minimo d'onore.

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, The Copycat Ninja (Java)

Kakashi copia le mosse dei suoi avversari scegliendo casualmente tra le ultime due mosse effettuate dall'avversario. Se l'avversario aspetta, si inchina - Anche lui mantiene il suo onore.

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


Vorrei che Kakashi potesse essere benedetto con lo sharean .. Ho pensato di leggere il cast.txt. Simula ogni round della sua storia contro ogni avversario lì dentro. Prova a scoprire contro quale avversario sta combattendo confrontando la storia dei nemici simulati con la storia dei nemici reali. Quindi usa quelle informazioni per prevedere la mossa successiva che l'avversario farebbe e scegliere il miglior contromossa da un elenco predefinito. Ma penso che questo potrebbe richiedere un po 'perché al momento ho Internet super slow e non ho abilità Java

The Observer, (node.js)

L'Osservatore si inchina prima di provare a prevedere la prossima mossa dell'avversario tra le sue 5 mosse precedenti, scegliendo la controparte migliore per la mossa prevista.

Modifica: grazie a @apsillers per la condivisione del boiler.ate 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 (''))

Modifica: ho avuto un grosso difetto nell'osservatore, in realtà non so cosa pensassi ieri sera. Sembra che abbia solo guardato le ultime due mosse del nemico. Ha fatto sorprendentemente bene così.

La sua memoria ora viene interrogata per la parte più lunga (fine) della storia dei nemici che ha già visto. Questo contiene un array con tutte le mosse che hanno seguito la storia delle mosse. Uno è selezionato in modo casuale. Quindi, se una mossa è seguita più spesso, è anche più probabile che venga scelta. Un po 'come catene markov.

The Observer, ora anche guardie.


[1]: TIL: l'eiaculazione ha un significato religioso


Sei il numero 1 e il numero 3 in questo momento! Simpatici robot! :)
apsillers

Congratulazioni per aver vinto con The Observer. Il segno di spunta verde è ora tuo: D
assenzio

7

Meiyo Senshi (Java)

Provenienti dalla zona di Haijima, non si sa molto del Meiyo. Normalmente non partecipano a giochi sportivi, ma hanno inviato un guerriero a questo per valutare i loro avversari.

Sono un gruppo onorevole, tuttavia, quindi puoi essere certo che farà conoscere la sua presenza agli dei in breve tempo. Una volta che ha visto abbastanza del suo nemico da riferire, userà le benedizioni ricevute per abbattere il suo avversario.

Per compilare l'esecuzione, è il modo Java standard:

> 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 si inchina al primo turno, quindi agisce in modo casuale dopo. È una delle due voci di esempio.

Comando: ruby spork-holder.rb

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

The Waiter (bash)

Il cameriere aspetta solo ad ogni turno. È una delle due voci di esempio.

Comando: echo W

Non è richiesto alcun codice sorgente.


7

Coward (Node.js)

Sono un codardo / È un miracolo che oso respirare
Sopraffatto / Dalla più leggera brezza estiva

  • Verifica BXBXBX/BBB modelli per inchinarsi (o colpirti) quando ti inchini.
  • Controlla per GXGXGX motivi per inchinarsi quando si fa la guardia.
  • Se il suo tiro per il coraggio casuale supera la soglia di paura per quel round, proverà a colpire.
    • Avere una Spada degli dei lo rende più coraggioso.
    • Un avversario con Sword of the Gods lo rende più spaventoso.
    • Un avversario che conduce per almeno 5 punti salute o più lo rende anche un po 'spaventato.
  • Altrimenti, a turno, fa la guardia e si inchina.

Se si desidera scrivere un invio Node.js , non esitate a utilizzare il mio codice boilerplate; tutto fino a includere la decidefunzione è completamente generale e libero di prendere.


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
È un robot difficile. Magnifico boilerplate; Lo userò subito. Grazie per aver condiviso :)
C5H8NNaO4,

6

Whack-a-mole (R)

Colpisce quando è probabile che il nemico si inchini, altre guardie.

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)

Esegui utilizzando Rscript Whack-a-mole.R.


1
Bel lavoro, in più adoro il nome.
Alex A.

3

Elephant Warrior (Java)

Elephant Warrior è di un tempo più antico e più naturale. Ha visto molto e ricorda tutto. Curry favorisce gli dei mentre esamina il suo avversario, e poi, una volta che li prende nel suo cuore, li separa.

Compila: 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
Non l'ho provato, ma sembra che andrà oltre i limiti nel primo turno in cui ce ne sono solo quattro args.
Geobits il

Giusto, non avevo capito che quelli non sarebbero stati inclusi affatto. Immagino che ovviamente una stringa vuota non possa essere passata, grazie!
Caino il

@katya Ora è stato risolto, tra l'altro, dovrebbe essere incluso nel torneo.
Caino,

3

Principessa guerriera (Julia)

Questa è la prima sfida di King of the Hill a cui ho partecipato. Vediamo come va.

La Principessa Guerriera privilegia l'attacco e l'onore e ricorre all'autoconservazione quando necessario. È piuttosto desiderosa e non aspetta mai. Nel tentativo di rimanere agile, anche lei non usa un attacco aereo.


Salva come warrior-princess.jled esegui dalla riga di comando in questo modo:

julia warrior-princess.jl <arguments>

Se non hai Julia, puoi scaricarlo qui . Per evitare problemi, si consiglia l'ultima versione stabile (ovvero non la versione di sviluppo).


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
La tua prima voce KotH e la prima voce Julia KotH di sempre se non sbaglio: congratulazioni!
plannapus,

@plannapus Grazie! : D Forse ne prenderò l'abitudine.
Alex A.

3

Gargoyle (Java)

Cerca di usare la mossa difensiva senza consumare onore.

Dal momento che è una voce 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

Spadaccino (C / Java)

Swordsman si inchina al primo turno e ogni volta che si sta esaurendo in onore. Quindi controlla se l'avversario non si è inchinato, difeso o atteso nel turno precedente. Se l'avversario non ha avuto, c'è una grande probabilità che faccia uno di questi nel turno in corso e lo spadaccino quindi colpisce casualmente l'avversario. Se questo non è vero, difende se non ha difeso il turno precedente. Se lo avesse fatto, si inchina per ottenere onore.

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

Installa GCC (compilatore) e salva il codice in un file chiamato " Swordsman.c " comando per la compilazione:

gcc Swordsman.c -o Swordsman

Verrà creato il file eseguibile " Swordsman ". Esegui utilizzando

Swordsman

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

}

Installa javac (compilatore) e salva il codice in un file chiamato " Swordsman.java " comando per la compilazione:

javac Swordsman.java

Verrà creato il file di classe denominato " Swordsman.class ". Esegui utilizzando

java Swordsman



aggressore (Java)

All'attaccante non importa nulla se non che vuole che il suo avversario sia morto. Colpisce in modo casuale una delle mosse di attacco e se ha un basso onore, si inchina.

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

}

Installa javac (compilatore) e salva il codice in un file chiamato " Attacker.java " comando per la compilazione:

javac Attacker.java

Verrà creato il file di classe denominato " Attacker.class ". Esegui utilizzando

java Attacker


Predictor (C / Java)

Il predittore prevede le mosse dei nemici. Nel primo turno, usa una mossa casuale. Si inchina se il suo onore è basso, colpisce se l'onore dei nemici è basso o si è inchinato nel turno precedente. Se il predittore non ha sorvegliato il turno precedente, le guardie nel turno corrente. Altrimenti, fa la stessa mossa che il nemico ha fatto nel turno precedente, a condizione che non sia 'W'in questo caso, Predictor si inchina.

Versione 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]);

}

Installa GCC (compilatore) e salva il codice in un file chiamato " Predictor.c " comando per la compilazione:

gcc Predictor.c -o Predictor

Eseguibile chiamato " PredictorVerrà creato il file ". Esegui utilizzando

Predictor

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

Installa javac (compilatore) e salva il codice in un file chiamato " Predicator.java " per la compilazione:

javac Predicator.java

File di classe denominato " Predicator.classVerrà creato il ". Esegui utilizzando

java Predicator


Non sono sicuro di quanto saranno efficaci questi robot poiché non ho l'interprete python2 per testarlo.


1
Non l'ho provato (Attaccante), ma sembra che andrà oltre i limiti nel primo turno in cui ci sono solo quattro argomenti.
Geobits il

L'attaccante sembra dare un ArrayIndexOutOfBoundsExceptionprimo turno, facendolo attendere nel primo turno. A parte questo, funziona.
assenzio il

@ Katya e Geobits, fissi. Grazie per averlo individuato.
Spikatrix,

Quando segmentation fault (core dumped)
eseguo

@ C5H8NNaO4 Risolto il problema. Codice aggiornato per tutti e tre i robot. Dovrebbe funzionare bene ora. Grazie per segnalarlo! :-D
Spikatrix

2

Master Yi (Python)

Il maestro assassino guadagna molto favore all'inizio del gioco, costruendolo fino a quando non è invincibile. Prova ad attaccare quando meno se lo aspettano.

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())

Per eseguire: Salva con nome MasterYi.py

python MasterYi.py <args>

2

Copy-san (C)

Copia ogni mossa del suo avversario. Abbastanza sicuro che abbia la garanzia di perdere. Compilare: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 The Way Of The Snake.

Il serpente non ha bisogno della benedizione degli dei.

Il serpente striscia i suoi colpi; come onde sulla spiaggia, ciò che entra si allontana da come è venuta.

Il serpente non aspetta mai.

The Snake non ha senso di attitudine, altrimenti sarebbe stato scritto in Python.

Istruzioni per l'esecuzione:

> javac hebi.java
> java hebi

Corpo del codice:

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

The Honorable (Java)

Gli onorevoli valori onorano soprattutto. Cioè, il suo onore sopra tutti gli altri. Se il samurai nemico ha un onore maggiore o uguale, si inchina. Nessuno sarà più onorevole di lui. Altrimenti, fa una mossa casuale. Non fa mai la guardia due volte di seguito: sarebbe disonorevole!

compilare:

> 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

Beato Samurai (Python)

Questo samurai cerca di mantenere il favore degli dei il più a lungo possibile. Si precipita a prendere la spada sacra, quindi si alterna tra Guardia e Attacco con uno dei colpi, rifornendo l'onore quando necessario. Se sembra che lui o il suo avversario possano presto cadere, si precipita a uccidere. Cadrà facilmente in un oppositore in grado di seguire il suo schema, ma la sua strategia di attaccare sempre a due danni dovrebbe essere piuttosto efficace.

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()

Per eseguire:
Salva come BlessedSamurai.py

python BlessedSamurai.py <args>

4
Il tuo programma deve stampare la sua mossa.
mbomb007,

3
Non l'ho provato, ma sembra che andrà oltre i limiti nel primo turno in cui ci sono solo quattro argomenti.
Geobits il

Ho usato un formato simile a quello che ha fatto. @Stranjyr, dai un'occhiata a quello che ho fatto per ottenere le discussioni.
mbomb007,

Grazie a tutti e due! Non ho accesso a un interprete Python in questo momento, ma penso di aver risolto i problemi. In qualche modo mi mancava completamente che la prima serie di istruzioni non avesse una storia.
Stranjyr,

Ciao, hai avuto un piccolo bug nel tuo programma "il nome globale 'last' non è definito". Dal momento che si tratta di un piccolo bug che ho cambiato lasta self.lastche sembra risolvere il problema.
assenzio il

1

Hermurai (C ++)

Ammira il suo avversario ed è un po 'paranoico. Vuole sapere se può fare ciò che gli altri samurai possono fare, perché non riesce ancora a credere di essere un samurai. Il suo sogno senza sbiadire divenne realtà prima che lui lo sapesse. Che potrebbe costargli la testa ...

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

Colpisce il più forte possibile. Entra in modalità di attacco inarrestabile quando è in pericolo.

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

Entrambi sono scritti in C ++. Compilare:

g++ iniqy.cpp -o iniqy

Per eseguire su Linux: ./iniqy

Per funzionare su Windows: iniqy.exe


1

The Terminator (ruby)

Terminator non presta attenzione alla propria salute. Il Terminator non ha alcuna nozione d'onore. Il Terminator viene inviato dal futuro e semplicemente determinato a terminare il suo avversario. Lo fa guardando le mosse dei suoi avversari e nient'altro. Campiona le mosse e calcola la risposta appropriata in modo così intricato che nessuna tecnologia odierna può prevedere le azioni del Terminator. In effetti, a chiunque viva nel 2015 il Terminator può sembrare in qualche modo casuale ...

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)

Come prodotto di una vasta manipolazione genetica, l'Agente 38 ha il fisico e l'acuità mentale di un super [2] -samurai ed è decisamente superiore a tutti i suoi concorrenti impotenti [citazione necessaria] imperfetti [citazione necessaria] .


//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] Numero completamente irrilevante [2] Garantito per essere vero l'1% delle volte


YAGMCSE

I metodi Monte Carlo sembrano esibire un gioco decente, quindi ecco ancora un'altra voce di simulazione Monte Carlo generica!

A differenza della maggior parte delle altre voci in questo concorso, questa voce utilizza un gran numero di simulazioni di giochi casuali e quindi richiede l'uso del flag -O3 per prestazioni ottimali.

Compilare il programma con il 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
Sembra inchinarsi solo per qualsiasi motivo. Potresti dare un'occhiata
C5H8NNaO4,

@ C5H8NNaO4 Grazie per avermi informato di questo grave bug. La mia modifica dovrebbe correggere il bug.
Potatomato,

YAGMCSE sembra fare solo uno dei due GBWWWWW...oBWWWW
C5H8NNaO4

@ C5H8NNaO4 È strano. Non sono in grado di replicare i risultati che hai citato. L'avversario di YAGMCSE si stava inchinando / custodendo / aspettando perennemente?
Potatomato

Sì, stava inchinando i primi 7 round. Ecco un pastebin
C5H8NNaO4

1

Dopo il mio tentativo fallito di inserire Target Dummy, vi presento il mio prossimo bot ...

ScroogeBot - Python 2

Questo robot si inchinerà se ha un solo onore. Altrimenti lancerà una moneta.

Se finisce in testa, eseguirà un attacco casuale. Se atterra su croce, si inchinerà o proteggerà.

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, una nuova voce! Solo un rapido testa a testa - potrebbe passare un po 'di tempo prima che io possa creare un nuovo torneo, dal momento che ho reinventato il mio sistema operativo ieri. Dovrei comunque concludere un nuovo torneo con i tuoi risultati entro la fine della settimana.
assenzio

0

Yoshimitsu (JS)

Cerca di non essere sorvegliato controllando le ultime due mosse, otterrà il coraggio con maggiore onore. basato sul modello realizzato apsillers

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

The Fool (C)

Il Matto implora una strategia piuttosto irregolare, non ripetendo mai la stessa mossa due volte a meno che non sia costretto a farlo per mancanza di onore. I suoi movimenti sono in gran parte basati sulla casualità, il che rende difficile prevedere le sue azioni. Il suo benessere è l'ultima cosa che ha in mente, poiché i suoi pensieri si basano solo sullo spargimento di sangue e sulla vittoria finale

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


Il profeta (C)

Il Profeta usa la conoscenza delle precedenti 2 mosse del suo avversario per fare una previsione della sua prossima mossa e fornisce un rapido e mortale contropiede. Inoltre, fa astrologia e cose del genere.

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


Compilazione

Entrambi i programmi sono scritti in C e possono essere compilati con gcc:

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


In esecuzione

* nix

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

finestre

fool.exe <args>
prophet.exe <args>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.