Giochiamo a Reaper - Chiuso per Sottomissioni


13

NOTA : il vincitore di questa competizione è Jack !!!. Non saranno più accettate proposte.

Ecco la chat room per questa sfida del . Questo è il mio primo, quindi sono aperto ai suggerimenti!

Reaper è un concetto di gioco sviluppato da Art of Problem Solving che coinvolge pazienza e avidità. Dopo aver modificato il gioco per adattarlo a un concorso in stile KOTH (grazie a @NathanMerrill e @dzaima per i tuoi suggerimenti e miglioramenti), ecco la sfida.

Il gioco funziona come segue: abbiamo un valore noto come Reap che si moltiplica per una data costante per ogni tick. Dopo ogni segno di spunta, ogni bot ha la possibilità di "raccogliere", il che significa aggiungere il valore corrente di Reap al proprio punteggio e ridurre Reap fino a 1.

Tuttavia, c'è un numero fisso di tick che un bot deve attendere tra i "reap" e un numero fisso di punti necessari per vincere la partita.

Abbastanza semplice? Ecco i tuoi input:

I / O

Devi scrivere una funzione in Python 3 che accetta 3 input. Il primo è self, usato per fare riferimento a oggetti di classe (mostrato più avanti). Il secondo è il Reapvalore attuale del Reap che guadagneresti se dovessi "raccogliere". Il terzo è prevReap, un elenco dei bot raccolti durante il tick precedente.

Altri oggetti a cui puoi accedere nella tua funzione:

self.obj: An object for your use to store information between ticks.
self.mult: The multiplier that Reap is multiplied by each tick
self.win: The score you need to win
self.points: Your current set of points
self.waittime: The amount of ticks that you must wait between reaps during the game
self.time: The number of ticks since your last reap
self.lenBots: The number of bots (including you) in the game.
self.getRandom(): Use to produce a random number between 0 and 1.

È NECESSARIO Non modificare tutti i contenuti di questi oggetti, ad eccezione di self.obj.

È necessario 1eseguire l' output per raccogliere e qualsiasi altra cosa (o nulla) per non raccogliere. Nota che se raccogli quando non hai aspettato abbastanza tick, ignorerò il fatto che hai scelto di raccogliere.

Regole

I parametri Userò sono winning_score=10000, multiplier=1.6-(1.2/(1+sqrt(x))), waittime = floor(1.5*x)dove xè il numero di bot nel KOTH.

  • Il gioco termina quando un giocatore (o più) raggiunge il punteggio vincente.
  • Quando più robot chiedono di raccogliere in una sola volta, viene data priorità ai robot che hanno atteso più a lungo (in caso di vincoli, i robot che hanno atteso il tempo massimo a tutti possono raccogliere e guadagnare i punti nel Raccogliere)
  • Il bot non deve durare più di 100 ms in media su 5 tick.
  • Se vuoi importare librerie, chiedi! Proverò ad aggiungere tutte le librerie che posso eseguire sulla mia versione desktop di Python (la matematica è già importata: sentiti libero di usarla)
  • Tutte le scappatoie standard per i KoTH, come i robot duplicati, i robot 1-up, ecc., Sono allo stesso modo vietate.
  • Tutti i robot che usano qualsiasi tipo di casualità devono usare la getRandomfunzione che ho fornito.

Puoi trovare il controller nel link TIO qui sotto. Per usarlo, aggiungi il nome della tua funzione BotListcome stringa, quindi aggiungi la funzione al codice. Modifica multiplierper cambiare ciò che il Reap viene moltiplicato per ogni tick, modifica winning_scoreper cambiare il punteggio necessario per terminare il gioco e modifica waittimeper cambiare il numero di tick da attendere tra i giri.

Per comodità, ecco alcuni esempi (e piuttosto sciocchi) di robot. Non sarà consentito inviare robot simili a questi. Tuttavia, dimostrano come funziona il controller.

def Greedybot(self,Reap, prevReap):
    return 1
def Randombot(self,Reap, prevReap):
    if self.obj == None:
        self.obj=[]
    self.obj.append(prevReap)
    if self.getRandom()>0.5:
        return 1

Per chi è interessato, ecco il controller con le 15 proposte integrate: Provalo online

RISULTATI FINALI

QUI SONO FINALMENTE QUI! Controlla il link TIO sopra per vedere quale codice ho usato per generare la classifica finale. I risultati non sono tremendamente interessanti. Nel corso delle 1000 corse che ho fatto con diversi semi casuali, i risultati sono stati

1000 wins - Jack
0 wins - everyone else

Congratulazioni al vincitore della taglia Jack! (aka @Renzeee)


Diciamo che due robot si raccolgono contemporaneamente e vince quello con il tempo di attesa più lungo. L'altro robot avrà anche il suo tempo di attesa abilitato nonostante non sia stato in grado di raccogliere effettivamente questo round, praticamente sprecando il suo "raccolto"? E cosa succede quando due robot si raccolgono contemporaneamente, con lo stesso tempo di attesa?
Kevin Cruijssen,

1
È consentito l'uso len(BotList)?
Renzeee,

1
@Renzeee Ooo non ci ha pensato! Farò una rapida modifica.
Don

1
@Renzeee Oh, questo è certamente qualcosa di utile da considerare. Potrebbe creare un secondo bot simile al mio Ogni 50, ma con calcoli effettivi nel bot stesso, invece di quello che ho fatto nella mia descrizione sulla base di 25robot in gioco. Prima aspetterò un po 'troppo per vedere comunque i robot di altre persone. Rushabh Mehta , ci sarà una scadenza / data finale in cui verranno eseguiti tutti i robot e verrà determinato un vincitore?
Kevin Cruijssen,

1
@Rushabh Mehta Gotcha, mi trattengo. Ho appena chiesto a b / c che stavo monitorando in modo indipendente i punteggi di altri robot e le attese per poterli beccare, e sono pigro. :)
Triggernometria

Risposte:


9

Pasticcio di Twitchy indeciso

def mess(self, Reap, prevReap):
    if not hasattr(self.obj, "start"):
            self.obj.start = False
    if self.time < self.waittime:
        return 0
    if self.points + Reap >= self.win:
            return 1
    if Reap >= self.waittime / (self.lenBots + 2):
        self.obj.start = True
    if self.obj.start:
        return 1 if self.getRandom() > 0.2 else 0
    return 1 if self.getRandom() > 0.8 else 0

Questo bot esegue prima i consueti controlli (posso raccogliere, posso vincere?) E quindi cerca un valore target prima che ricompaia. Tuttavia, è indeciso, quindi dopo aver raggiunto l'obiettivo, si chiede per quanto ancora può aspettare e non si raccoglie immediatamente. Inoltre, è nervoso, quindi potrebbe accidentalmente "premere il pulsante" e raccogliere prima del bersaglio.

Curiosità: questo è fondamentalmente il modo in cui gioco il mietitore come essere umano.


Bel robot +1. Lo guarderò più da vicino tra un po '. Unisciti alla chat se non l'hai già fatto
Don Thousand

@RushabhMehta Ora con meno indecisione; p
Quintec,

Aggiungerò le tue modifiche quando posso!
Don Mille

9

Cecchino

Un robot alimentato dal dispetto. Tiene traccia dei tempi di recupero e dei punteggi dell'avversario. Tentativi di impedire ad altri di vincere. Praticamente non vince mai, ma rende il gioco frustrante da giocare per gli altri.

MODIFICARE:

  • Se la raccolta lo farebbe vincere, raccogli.
  • Se nessuno è> = 70% del punteggio vincente:

    • Se tutti gli altri sono in cooldown, attendi fino all'ultimo momento possibile per raccogliere.
    • Se qualcun altro vincesse raccogliendo il valore corrente e ora siano attivi o sarebbero attivi il prossimo turno, mietere.
    • Se almeno la metà degli altri utenti è in cooldown, prova a raccogliere. Questo rende difficile bersagliare specifici avversari, e così è stato rimosso.
    • Altrimenti, raccogli il 25% delle volte (essenzialmente per garantire che questo bot raccolga A volte, nel caso in cui succeda qualcosa di strano, come se tutti stessero aspettando diversi turni).
  • Se qualcuno È> = 70% del punteggio vincente:

    • Se Sniper può vincere un tiebreaker e il prossimo round sarà al di sopra del valore medio raccolto per l'avversario con il punteggio più alto, raccoglierà
    • Se l'avversario con il punteggio più alto lascerà il tempo di recupero il prossimo turno, raccogli.
def Sniper(self, Reap, prevReap):
    # initialize opponents array
    if not hasattr(self.obj, "opponents"):
        self.obj.opponents = {}

    # initialize previous Reap value
    if not hasattr(self.obj, "lastReap"):
        self.obj.lastReap = 0

    # increment all stored wait times to see who will be "active" this turn
    for opponent in self.obj.opponents:
        self.obj.opponents[opponent]["time"] += 1

    # update opponents array
    for opponent in prevReap:
        # don't track yourself, since you're not an opponent
        if opponent != "Sniper":
            # initialize opponent
            if opponent not in self.obj.opponents:
                self.obj.opponents[opponent] = {"time": 0, "points": 0, "num_reaps": 0, "avg": 0}
            self.obj.opponents[opponent]["time"] = 0
            self.obj.opponents[opponent]["points"] += self.obj.lastReap
            self.obj.opponents[opponent]["num_reaps"] += 1
            self.obj.opponents[opponent]["avg"] = self.obj.opponents[opponent]["points"] / self.obj.opponents[opponent]["num_reaps"]

    # done "assigning" points for last round, update lastReap
    self.obj.lastReap = Reap

    # get current 1st place(s) (excluding yourself)
    winner = "" if len(self.obj.opponents) == 0 else max(self.obj.opponents, key=lambda opponent:self.obj.opponents[opponent]["points"])

    # you are ready now
    if self.time >= self.waittime:
        # current Reap is sufficient for you to win
        if self.points + Reap >= self.win:
            return 1

        if (
                # a 1st place exists
                winner != ''
                # if current 1st place is close to winning
                and self.obj.opponents[winner]["points"] / self.win >= .7
        ):
            if (
                    # next round's Reap value will be above opponent's average Reap
                    (Reap * self.mult >= self.obj.opponents[winner]["avg"])
                    # we have been waiting at least as long as our opponent (tiebreaker)
                    and self.time >= self.obj.opponents[winner]["time"]
            ):
                return 1

                # current 1st place opponent will be active next round
            if self.obj.opponents[winner]["time"] + 1 >= self.waittime:
                return 1

        else:
            if (
                    # everyone is waiting for their cooldown
                    all(values["time"] < self.waittime for key, values in self.obj.opponents.items())
                    # and we're tracking ALL opponents
                    and len(self.obj.opponents) == self.lenBots - 1
                    # at least one person will be ready next turn
                    and any(values["time"] + 1 >= self.waittime for key, values in self.obj.opponents.items())
            ):
                return 1

            if (
                    # opponent will be active next round
                    any( (values["time"] + 1 >= self.waittime)
                         # current Reap value would allow opponent to win
                         and (values["points"] + Reap >= self.win) for key, values in self.obj.opponents.items())
            ):
                return 1

            if (
                    # a 1st place exists
                    winner != ''
                    # current 1st place opponent will be active next round
                    and (self.obj.opponents[winner]["time"] + 1 >= self.waittime)
                    # next round's Reap value will be above their average Reap
                    and (Reap * self.mult >= self.obj.opponents[winner]["avg"])

            ):
                return 1

            # # at least half of opponents are waiting for their cooldown
            # if sum(values["time"] < self.waittime for key, values in self.obj.opponents.items()) >= (self.lenBots - 1) / 2:
            #     return 1

            # 25% of the time
            if self.getRandom() <= .25:
                return 1

    # default return: do not snipe
    return 0

Annoiato

Solo per divertimento, questo robot è stato portato da un amico e in realtà non vuole essere qui. Tirano un d16 fino a quando non ottengono un numero in 1-9, quindi tentano di raccogliere ogni volta che un numero contiene la cifra scelta. (Andare a cercare un d10 interromperebbe il gioco, che è maleducato, e 0 è semplicemente troppo facile!)

def Bored(self, Reap, prevReap):
    # if this is the first round, determine your fav number
    if not hasattr(self.obj, "fav_int"):
        r = 0

        while r == 0:
            # 4 bits are required to code 1-9 (0b1001)
            for i in range(0, 4):
                # flip a coin. Puts a 1 in this bit place 50% of the time
                if self.getRandom() >= .50:
                    r += 2**i
            # if your random bit assigning has produced a number outside the range 1-9, try again
            if not (0 < r < 10):
                r = 0

        self.obj.fav_int = r

    # you are ready now
    if self.time >= self.waittime:
        # current Reap is sufficient for you to win
        if self.points + Reap >= self.win:
            return 1
        # do you like this value?
        if str(self.obj.fav_int) in str(Reap):
            return 1
        # do you like your wait time?
        if self.time % int(self.obj.fav_int) == 0:
            return 1

    # default return: do not reap
    return 0

Bel robot! +1. Sarà interessante vedere come funziona.
Don

1
Penso che dovresti usare self.obj.opponents[opponent]["time"] += 1nel primo for-loop e self.obj.lastReapalla fine del secondo for-loop. Oltre a ciò, belle idee. Sono curioso di sapere come funzionerebbe con molti altri robot. Quando sto usando molti robot avidi e casuali, mi limiterò a raccogliere appena perché la maggior parte delle volte la metà dei robot non riesce a raccogliere. Ma ovviamente quelli non sono concorrenti realistici.
Renzeee,

@Triggernometry Dovresti unirti alla chat. Inoltre, controlla le modifiche che ho pubblicato. Assicurati che le modifiche che ho apportato al tuo bot siano corrette.
Don mille,

7

Jack

Questo è un semplice bot con 4 regole:

  • Non mietere quando non fa nulla
  • Raccogli sempre quando raccogli ci permette di vincere
  • Raccogli anche quando non è stato raccolto per 3 tick
  • Altrimenti non fare nulla

Ho ottimizzato i 3 tick rispetto agli attuali robot esistenti (Sniper, grim_reaper, Every50, pasticcio, BetterRandom, Averager, alcuni altri).

def Jack(self, Reap, prevReap):
    if self.time < self.waittime:
        return 0
    if self.win - self.points < Reap:
        return 1
    if self.mult ** 3 <= Reap:
        return 1
    return 0

Ho cercato di rimanere con la mia vecchia soluzione (5 tick) ma mietevo anche se non avete raccolto più di X tick, e poi mietere dopo che sono stati passati meno tick durante il non-raccolto (cioè 5, se aspettato più a lungo di sé .waittime + 5, anche raccogliere se non è stato raccolto per 4 tick). Ma questo non è migliorato solo raccogliendo sempre dopo 4 tick anziché 5.


5

Ogni 50

Questo bot raccoglieranno ogni volta che l' Reapimporto è superiore a 50.

Perché 50

Se presumo ci saranno 25 robot in gioco, significa che multiplier = 1.6-(1.2/(1+sqrt(25))) = 1.4e waittime = floor(1.5*25) = 37. Dall'inizio Reapalle 1, salirà in questo modo:

Round: 1  2    3     4      5      6      7      8       9       10      11      12      13      14      15       16       17       18       19       20       etc.
Reap:  1  1.4  1.96  2.744  ~3.84  ~5.39  ~7.53  ~10.54  ~14.76  ~20.66  ~28.92  ~40.50  ~56.69  ~79.37  ~111.12  ~155.57  ~217.79  ~304.91  ~426.88  ~597.63  etc.

Come puoi vedere, supera i 50 dopo 13 tick. Poiché il Reapazzererà di 1 ogni volta che un bot miete, e waittimeper un bot che miete è 37, la probabilità di un bot miete prima che poi è piuttosto alto, soprattutto con i bot simili all'esempio GreedyBotche raccoglieranno appena i loro waittimeIS disponibile di nuovo. All'inizio volevo fare 200, che è il 17esimo tick, un po 'nel mezzo dei 37 tick del tempo di attesa, ma con l'ipotesi che ci siano 25 robot in gioco c'è una possibilità piuttosto alta che qualcun altro Reapmi afferri davanti. Quindi l'ho abbassato a 50. È ancora un bel numero arrotondato, ma soprattutto perché è il tredicesimo tick (con 25 bot), e anche 13 e "mietere" si adattano un po 'allo stesso genere "malvagio".

Codice:

Il codice è ridicolo banale ..

def Every50(self, Reap, prevReap):
  return int(Reap > 50)

Appunti:

Questo bot è piuttosto male con una bassa quantità di robot in gioco. Per ora lo lascerò e potrei creare un bot migliore calcolando il momento migliore per Reap. Con una quantità estremamente bassa di robot in gioco, waittimeè anche molto più basso, quindi GreedyBotpotrebbe anche vincere abbastanza facilmente da questo bot se waittimeè abbastanza basso.

Spero che più persone aggiungano molti più robot. ; p


def Every49(self, Reap, prevReap): return Reap > 49 La tua mossa.
Quintec

@Quintec Hehe. Con 25 robot in gioco significherebbe che è ancora il 13esimo tick e entrambi vinciamo il Reap, quindi non mi dispiace condividere la vittoria con te, lol. ; p
Kevin Cruijssen,

Potresti voler ovviare intalla disuguaglianza, dato che 1 è il vero comando
Don Mille

@Quintec sono consapevole che stai scherzando, ma non permetterò robot 1-up o duplicati
Don Thousand

@RushabhMehta Non programma molto spesso in Python, quindi avevo già dubbi sul fatto che avrei dovuto aggiungere il cast per rendere Trueesplicito 1. Ho pensato che il True == 1controllo sarebbe comunque tornato Trueper il mio bot aggiungendolo agli elenchi della Reaperstua nextfunzione, ma ho comunque aggiunto il cast a int come hai suggerito.
Kevin Cruijssen,

5

Averager

def Averager(self,Reap,prevReap):
    returner = 0
    if not hasattr(self.obj,"last"):
        self.obj.last = Reap
        self.obj.total = 0
        self.obj.count = 0
        returner = 1
    else:
        if len(prevReap) > 0:
            self.obj.total += self.obj.last
            self.obj.count += 1
        self.obj.last = Reap
    if self.obj.count > 0 and Reap > self.obj.total / self.obj.count:
        returner = 1
    return returner

Questo bot tenta di raccogliere ogni volta che il valore Reap corrente è superiore al valore medio raccolto.


Bot molto bello! +1
Don Mille

Sono entrambi estremamente infastidito e impressionato dal fatto che un algoritmo così semplice batte tutti così facilmente. Ottimo lavoro!
Triggernometria

3

Triste Mietitore

Questo bot mantiene una media corrente dei valori di tutti i precedenti reap e del tempo di attesa di ciascun bot. Si raccoglie quando ha atteso più di 3/4 degli altri bot e il raccolto è almeno 3/4 della dimensione del raccolto medio visto finora. L'obiettivo è quello di afferrare molti raccoglitori di dimensioni ragionevoli, a basso rischio.

def grim_reaper(self, Reap, prevReap):
    if self.obj == None:
        self.obj = {}
        self.obj["reaps"] = []
        self.obj["prev"] = 1
        self.obj["players"] = {i:0 for i in range(math.ceil(self.waittime / 1.5))}
    if Reap == 1 and len(prevReap) > 0:
        self.obj["reaps"].append(self.obj["prev"])
        for player in prevReap:
            self.obj["players"][player] = 0

    retvalue = 0
    if (len(self.obj["reaps"]) > 0 
         and Reap > sum(self.obj["reaps"]) / len(self.obj["reaps"]) * 3. / 4.
         and sum([self.time >= i for i in self.obj["players"].values()]) >= len(self.obj["players"].values()) * 3 / 4):
        retvalue = 1

    for player in self.obj["players"]:
        self.obj["players"][player] += 1
    self.obj["prev"] = Reap
    return retvalue

Modifica: risolti alcuni errori di sintassi imbarazzanti.

Provalo online


1
Dovresti usare self.obj.reapsinvece di self.reapse self.objinvece di self.objecte prevReapinvece di prevLeape aggiungi () dopo self.obj.players.valuesdue volte. E penso self.obj.reaps = []che non funzionerà se non self.objè un oggetto. Non sono completamente sicuro che tutto funzioni ancora come previsto e se tutto ciò che ho detto è vero, ma dopo queste modifiche e l'utilizzo di un oggetto fittizio per self.objquando non esiste ancora, il tuo codice viene compilato per me.
Renzeee,

@ZacharyColton Non è necessario importare la matematica. È già importato
Don Mille

@RushabhMehta Ho aggiunto class Object(object):[newline] passin cima e usato self.obj = Object()nel if not hasattr(..)(se ricordo bene).
Renzeee,

@Renzeee aha ic
Don Thousand

@ZacharyCotton Devi unirti alla chat.
Don Mille

3

BetterRandom

def BetterRandom(self,reap,prevReap):
    return self.getRandom()>(reap/self.mult**self.waittime)**-0.810192835

Il bot si basa sul presupposto che la possibilità di raccogliere dovrebbe essere proporzionale alla dimensione del raccolto perché un punto è un punto, indipendentemente da quando è ottenuto. C'è sempre una possibilità molto piccola di raccogliere, questo mantiene il comportamento sfruttabile. In primo luogo ho pensato che sarebbe stato direttamente proporzionale e ho assunto la costante di proporzionalità attorno alla1/mult^waittime (il massimo raccolto supponendo che almeno un bot sia avido) dopo aver eseguito alcune simulazioni ho scoperto che questa era davvero la costante ottimale. Ma il bot era ancora sovraperformato da Random, quindi ho concluso che la relazione non era direttamente proporzionale e ho aggiunto una costante per calcolare quale fosse la relazione. Dopo alcune simulazioni ho scoperto che contro il mio set di bot di test -1.5era ottimale. Questo in realtà corrisponde a una relazione inversamente proporzionale tra la possibilità di raccolta ereap*sqrt(reap)che è sorprendente. Quindi sospetto che questo dipenda fortemente dai bot specifici, quindi sarebbe meglio una versione di questo bot che calcola k durante il gioco. (Ma non so se ti è permesso usare i dati dei round precedenti).

EDIT: ho creato un programma per trovare automaticamente il tipo di proporzionalità. Sul set di test ["myBot("+str(k)+")","Randombot","Greedybot","Every50","Jack","grim_reaper","Averager","mess"]ho trovato il nuovo valore.


aggiungerò presto alcune nuove statistiche usando il tuo bot
Don Thousand

1
Sembra (reap/self.mult**self.waittime)**-0.810192835sempre superiore a 1, ovvero self.getRandom () non è mai superiore.
Renzeee,

@fejfo puoi anche usare i dati dei round precedenti. Questo è ciò che self.objserve. Per vedere alcuni esempi su come usarlo, guarda alcuni altri robot che lo stanno usando.
Don

3

Bersaglio

def target(self,Reap,prevReap):
    if not hasattr(self.obj, "target_time"):
        self.obj.target_time = -1
        self.obj.targeting = False
        self.obj.target = None
    if self.obj.target_time >= 0:
        self.obj.target_time += 1

    if self.time < self.waittime:
            return 0
    if self.points + Reap >= self.win:
        return 1
    if len(prevReap) > 0:
        if not self.obj.targeting:
            self.obj.target_time = 0
            self.obj.target = prevReap[int(self.getRandom() * len(prevReap))]
            self.obj.targeting = True
    if self.waittime <= self.obj.target_time + 1:
        self.obj.targeting = False
        self.obj.target = None
        self.obj.target_time = -1
        return 1
    return 0

Le mie possibilità di vincere con il pasticcio non sono quasi adesso, quindi è il momento di rovinare tutti gli altri robot in tutti i modi possibili! :)

Questo bot funziona in modo simile al cecchino. Ogni volta che qualcuno raccoglie, prende un bersaglio casuale da chiunque abbia raccolto. Quindi, aspetta semplicemente che quel bersaglio quasi riesca a raccogliere di nuovo e lo taglia. Tuttavia, non cambia focus: una volta che sei stato scelto e bloccato, non puoi scappare :)


2

EveryN

Immagino sia giunto il momento per il mio secondo bot proprio prima della scadenza.

Questo bot:

  • Salta quando è ancora in attesa per l'ultimo Reap
  • Raccogli quando può vincere
  • Raccogli quando nessuno ha raccolto per almeno nround, dove nviene calcolaton = 3 + ceil(self.waittime / self.lenBots)

Codice:

def every_n(self, Reap, prevReap):
    # Initialize obj fields
    if not hasattr(self.obj, "roundsWithoutReaps"):
        self.obj.roundsWithoutReaps = 0

    # Increase the roundsWithoutReaps if no bots reaped last round
    if len(prevReap) < 1:
        self.obj.roundsWithoutReaps += 1
    else
        self.obj.roundsWithoutReaps = 0

    # Skip if you're still in your waiting time
    if self.time < self.waittime:
        return 0
    # Reap if you can win
    if self.win - self.points < Reap:
        return 1

    # i.e. 25 bots: 3 + ceil(37 / 25) = 5
    n = 3 + math.ceil(self.waittime / self.lenBots)

    # Only reap when no bots have reaped for at least `n` rounds
    if self.obj.roundsWithoutReaps >= n:
        self.obj.roundsWithoutReaps = 0
        return 1

    return 0

Non programma molto spesso in Python, quindi se vedi qualche errore fammelo sapere.


Nome variabile lungo santo. (Inoltre, PEP: python.org/dev/peps/pep-0008 )
Quintec,

@Quintec Modificato il rientro di 2 spazi in 4; abbreviato il subsequentRoundsWithoutReapsa roundsWithoutReaps; usato minuscolo con caratteri di sottolineatura per il nome del metodo; e rimosso la parentesi nelle istruzioni if. Grazie.
Kevin Cruijssen,

Nessun problema! (Tecnicamente dovrebbe essere rounds_without_reaps, ma non è un problema dato che questa sfida utilizza anche mixedCamelCase, quindi non ha importanza)
Quintec,

@Quintec Ah ok. Ho guardato il prevReape lenBotse tali e assunte le variabili sono camelCase come in Java. ;) Ah bene, qualunque sia il caso che utilizziamo, dovrebbe funzionare comunque. I 2 spazi invece di 4 rientrati probabilmente avrebbero causato alcuni problemi, quindi grazie in entrambi i casi.
Kevin Cruijssen,

2

In corso: il mio progetto di estendere T4T a tutti i KOTH aperti.

Tit per Tat

def t4t(self, r, p):
    if(not hasattr(self.obj,"last")): self.obj.last = self.win
    if(p):
        self.obj.last = r
        return 0

    # The usual checks
    if self.time < self.waittime:
        return 0
    if self.points + r >= self.win:
        return 1

    if(r >= self.obj.last):
        return 1

Tit per n Tats

def t4nt(self, r, p):
    n = 5 # Subject to change
    if(not hasattr(self.obj,"last")): self.obj.last = [self.win]*n

    if(p):
        self.obj.last.append(r)
        self.obj.last.pop(0)
        return 0

    # The usual checks
    if(self.time < self.waittime):
        return 0
    if(self.points + r >= self.win):
        return 1

    if(r >= self.obj.last[0]):
        return 1

Kevin

Solo per tenerti in punta di piedi.

def kevin(just, a, joke):
    return 0

Assicurati di ricordare, self.lastnon è una cosa, ma puoi fare self.obj.lastuna cosa !. Ad ogni modo, aggiungerò tutti e tre i tuoi robot per i meme +1
Don Thousand

Sì, sono un idiota. Fisso.
SIGSTACKFAULT,

@RushabhMehta Sono appena passato e li ha fatti funzionare davvero. per favore modifica.
SIGSTACKFAULT,

suona bene! Unisciti al GC, posterò alcuni risultati parziali lì
Don Thousand

1

Joe medio

Mi sono ispirato ad Averager e ho creato un bot che calcola in media il numero di turni necessari prima che qualcuno si ricompili e cerchi di raccogliere un turno prima di quello.

def average_joe(self, Reap, prevReap):

    if not hasattr(self.obj, "average_turns"):
        self.obj.turns_since_reap = 1
        self.obj.total_turns = 0
        self.obj.total_reaps = 0
        return 1

    if len(prevReap) > 0:
        self.obj.total_turns = self.obj.total_turns + self.obj.turns_since_reap
        self.obj.total_reaps += 1
        self.obj.turns_since_reap = 0
    else:
        self.obj.turns_since_reap += 1

    # Don't reap if you are in cooldown
    if self.time < self.waittime:
        return 0

    # Reap if you are going to win
    if self.win - self.points < Reap:
        return 1

    # Reap if it is one turn before average
    average_turns = self.obj.total_turns / self.obj.total_reaps

    if average_turns - 1 >= self.obj.turns_since_reap:
        return 1
    else:
        return 0

Lo aggiungerò domani.
Don

1

hardcoded

Sì.

def HardCo(self,reap,prevReap):
    return reap > 2

Invece di fare la media sui reap precedenti, usa una media pre-calcolata su una corsa tipica. Non migliorerà comunque col tempo.

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.