Robot Roulette: gioco d'azzardo robotizzato con posta alta


56

Classifica finale

+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +
| Nome | Punteggio | WinRate | TieRate | Probabilità di eliminazione |
+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +
| 1. SarcomaBotMk11 | 0,06333 | 6,13% | 0,41% | [42 24 10 8 6 4]% |
| 2. WiseKickBot | 0,06189 | 5,91% | 0,56% | [51 12 7 10 7 6]% |
| 3. StrikerBot | 0,05984 | 5,78% | 0,41% | [46 18 11 8 6 5]% |
| 4. PerfectFractionBot | 0.05336 | 5,16% | 0,35% | [49 12 14 10 6 4]% |
| 5. MehRanBot | 0,05012 | 4,81% | 0,41% | [57 12 8 7 6 5]% |
| 6. OgBot | 0.04879 | 4,66% | 0,45% | [50 15 9 8 7 5]% |
| 7. SnetchBot | 0,04616 | 4,48% | 0,28% | [41 29 8 9 5 3]% |
| 8. AntiKickBot | 0,04458 | 4,24% | 0,44% | [20 38 17 10 6 4]% |
| 9. MehBot | 0.03636 | 3,51% | 0,25% | [80 3 4 4 3 3]% |
| 10. Meh20Bot | 0.03421 | 3,30% | 0,23% | [57 12 8 7 9 3]% |
| 11. GenericBot | 0,03136 | 3,00% | 0,28% | [18 39 20 11 5 3]% |
| 12. HardCodedBot | 0.02891 | 2,75% | 0,29% | [58 21 3 6 5 4]% |
| 13. GangBot1 | 0.02797 | 2,64% | 0,32% | [20 31 35 6 3 2]% |
| 14. SarcomaBotMk3 | 0.02794 | 2,62% | 0,34% | [16 15 38 17 7 4]% |
| 15. GangBot0 | 0.02794 | 2,64% | 0,30% | [20 31 35 6 3 2]% |
| 16. GangBot2 | 0.02770 | 2,62% | 0,31% | [20 31 35 6 3 2]% |
| 17. TitTatBot | 0.02740 | 2,63% | 0,21% | [54 10 15 10 5 2]% |
| 18. MataHari2Bot | 0.02611 | 2,35% | 0,51% | [39 26 11 11 6 5]% |
| 19. PolyBot | 0,02545 | 2,41% | 0,27% | [53 18 6 13 5 3]% |
| 20. SpitballBot | 0,02502 | 2,39% | 0,22% | [84 10 1 1 0 1]% |
| 21. SquareUpBot | 0,02397 | 2,35% | 0,10% | [10 60 14 7 4 3]% |
| 22. CautiousGamblerBot2 | 0.02250 | 2,19% | 0,13% | [60 18 10 5 3 1]% |
| 23. Bot13 | 0,02205 | 2,15% | 0,11% | [90 0 2 3 2 1]% |
| 24. AggroCalcBot | 0,01892 | 1,75% | 0,29% | [26 49 13 5 3 3]% |
| 25. CautiousBot | 0,01629 | 1,56% | 0,14% | [15 41 27 11 4 1]% |
| 26. CoastBotV2 | 0,01413 | 1,40% | 0,02% | [83 12 3 1 0 0]% |
| 27. CalculatingBot | 0,01404 | 1,29% | 0,22% | [87 9 1 1 1 1]% |
| 28. HalfPunchBot | 0,01241 | 1,15% | 0,18% | [47 20 13 12 5 2]% |
| 29. HalflifeS3Bot | 0.01097 | 1,00% | 0,20% | [76 9 5 4 2 2]% |
| 30. AntiGangBot | 0,00816 | 0,76% | 0,11% | [94 1 1 1 1 1]% |
| 31. GeometricBot | 0,00776 | 0,74% | 0,07% | [19 46 25 7 2 1]% |
| 32. GuessBot | 0,00719 | 0,05% | 1,34% | [65 17 4 6 5 3]% |
| 33. BoundedRandomBot | 0,00622 | 0,60% | 0,05% | [42 39 12 5 2 0]% |
| 34. SpreaderBot | 0,00549 | 0,54% | 0,02% | [32 43 19 4 1 0]% |
| 35. DeterminBot | 0,00529 | 0,45% | 0,16% | [22 41 20 11 4 2]% |
| 36. PercentBot | 0,00377 | 0,38% | 0,00% | [85 8 4 2 1 0]% |
| 37. HalvsiestBot | 0,00337 | 0,29% | 0,08% | [32 43 15 6 2 1]% |
| 38. GetAlongBot | 0,00330 | 0,33% | 0,01% | [76 18 4 1 0 0]% |
| 39. BandaidBot | 0,00297 | 0,29% | 0,02% | [76 9 10 4 1 0]% |
| 40. TENaciousBot | 0,00287 | 0,29% | 0,00% | [94 4 1 0 0 0]% |
| 41. SurvivalistBot | 0,00275 | 0,25% | 0,04% | [92 6 1 0 0 0]% |
| 42. RandomBot | 0,00170 | 0,13% | 0,07% | [42 36 14 5 2 1]% |
| 43. AggressiveBoundedRandomBotV2 | 0,00165 | 0,14% | 0,06% | [8 46 34 9 2 1]% |
| 44. BloodBot | 0,00155 | 0,01% | 0,30% | [65 28 5 1 1 0]% |
| 45. OutBidBot | 0,00155 | 0,03% | 0,25% | [65 6 21 6 1 1]% |
| 46. ​​BoxBot | 0,00148 | 0,10% | 0,09% | [10 51 33 5 1 1]% |
| 47. LastBot | 0,00116 | 0,08% | 0,07% | [74 6 16 2 1 0]% |
| 48. UpYoursBot | 0.00088 | 0,07% | 0,03% | [37 40 17 5 1 0]% |
| 49. AverageBot | 0.00073 | 0,06% | 0,03% | [74 3 10 10 2 0]% |
| 50. PatheticBot | 0,00016 | 0,01% | 0,02% | [94 0 5 1 0 0]% |
| 51. OverfittedBot | 0,00014 | 0,01% | 0,00% | [58 40 2 0 0 0]% |
| 52. RobbieBot | 0,00009 | 0,01% | 0,00% | [32 41 24 2 0 0]% |
| 53. WorstCaseBot | 0,00002 | 0,00% | 0,00% | [4 71 23 2 0 0]% |
| 54. SmartBot | 0,00002 | 0,00% | 0,00% | [44 51 5 0 0 0]% |
| 55. AAAAUpYoursBot | 0,00000 | 0,00% | 0,00% | [40 58 2 0 0 0]% |
| 56. KickbanBot | 0,00000 | 0,00% | 0,00% | [67 32 1 0 0 0]% |
| 57. OneShotBot | 0,00000 | 0,00% | 0,00% | [2 95 3 0 0 0]% |
| 58. KickBot | 0,00000 | 0,00% | 0,00% | [100 0 0 0 0 0]% |
| 59. KamikazeBot | 0,00000 | 0,00% | 0,00% | [100 0 0 0 0 0]% |
| 60. MeanKickBot | 0,00000 | 0,00% | 0,00% | [100 0 0 0 0 0]% |
+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +

Grazie per tutti coloro che hanno partecipato e congratulazioni a @Sarcoma per la vittoria!

Regole:

Tutti iniziano con 100 CV. Ogni round, 2 giocatori vengono scelti a caso dal gruppo di concorrenti che non hanno ancora partecipato a quel round. Entrambi i giocatori scelgono un numero compreso tra 0 e il loro CV attuale e rivelano quei numeri allo stesso tempo. Il giocatore che ha scelto il numero più basso muore immediatamente. L'altro giocatore sottrae il numero prescelto dai CV rimanenti e passa al turno successivo.

Il torneo funziona così:

Dal gruppo di concorrenti, 2 sono scelti a caso. Si affrontano e uno o entrambi muoiono. Un giocatore muore se:

  1. Scelgono un numero più piccolo di quello del loro avversario
  2. Il loro CV scende o scende sotto lo zero
  3. Legano tre volte di seguito con il loro avversario

In caso di pareggio, entrambi i giocatori generano semplicemente nuovi numeri, fino a 3 volte. Dopo il confronto, il sopravvissuto (se presente) viene spostato nel pool per il round successivo e il processo si ripete fino a quando non abbiamo esaurito il round pool corrente. Se c'è un numero dispari nel pool, quello dispari esce al turno successivo gratuitamente.

Il tuo compito è scrivere una funzione in python2.7 che prende come input la tua corrente hp, un elenco dell'offerta del tuo avversario historye un numero intero tiesche ti dice quante volte hai già legato con il tuo avversario attuale e un numero intero che ti dice come molti robot sono ancora alive(incluso te) e un numero intero che elenca il numero di robot al starttorneo. Si noti che la cronologia non include i legami. La funzione deve restituire un numero intero compreso tra 0 e il tuo CV totale attuale. Di seguito sono riportati alcuni semplici esempi che ignorano i legami:

def last(hp, history, ties, alive, start):
    ''' Bet a third of your hp at first, then bet your opponent's last bid, if possible '''
    if history:
        return np.minimum(hp-1, history[-1])
    else:
        return hp/3

def average(hp, history, ties, alive, start):
    ''' Bet the average opponent's bid so far, on the assumption that bids will tend downward '''
    if history:
        num = np.minimum(hp-1, int(np.average(history))+1)
    else:
        num = hp/2
    return num

def random(hp, history, ties, alive, start):
    ''' DO YOU WANT TO LIVE FOREVER?! '''
    return 1 + np.random.randint(0, hp)

Se la funzione restituisce un numero maggiore di HP, verrà reimpostata su 0. Sì, è possibile uccidere te stesso. La tua funzione non deve tentare di accedere o modificare alcun membro di alcun oggetto della classe RouletteBot. Non ti è permesso di intraprendere alcuna azione che identifichi in modo inequivocabile il tuo avversario indipendentemente dai futuri robot aggiuntivi. L'ispezione dello stack è consentita fintanto che teoricamente è possibile che più di un avversario distinto possa aver prodotto le informazioni che si raccolgono da esso, anche se attualmente esiste solo un bot che potrebbe. cioè, non puoi semplicemente leggere la pila per vedere quale funzione nemica è stata chiamata.

In base a queste regole è possibile che non ci sia vincitore e che gli ultimi due concorrenti si uccidano a vicenda. In tal caso, entrambi i finalisti ottengono mezzo punto ciascuno.

Questo è il mio primo tentativo di rompicapo di programmazione, quindi le critiche sono benvenute!

Il controller può essere trovato qui .


4
FWIW, ho intenzione di utilizzare una rete neurale addestrata su tutti gli altri robot solo per divertimento una volta installato il controller :)
Quintec,

2
Il controllo del tipo era a vantaggio di antiantiantiantiupyoursbot.
Troverò

3
@Sarcoma Sembra che questa competizione abbia scatenato una grave guerra del codice. Questa competizione non è finita, ma non vedo l'ora di vedere l'evoluzione. Forse anche il prossimo passo, l'IA ha aumentato la concorrenza: P
Markov Chained

3
WOOOOOOOOOOOOOO!
Sarcoma,

5
Dio mio. Il trolling deliberato di cambiare mean_kick per restituire sempre zero quando è stato utilizzato in così tanti posti è geniale.
Magua,

Risposte:


12

BinaryBot

Qualcuno l'ha già fatto? Scommette metà della sua salute ad ogni round.

def binaryBot(hp, history, ties, alive, start):
    return int(np.floor(hp/2)) or 1

SarcomaBot

Se l'ultima battaglia offre HP - 1. Se è il primo round di battaglia offre metà HP più un importo casuale aggiuntivo fino a un quarto di HP. Se riesce a battere un'offerta esterna dell'avversario dopo quell'offerta avversaria hp + 1. Se ha una salute inferiore rispetto all'offerta avversaria, l'ammontare casuale è compreso tra il 75% e l'attuale hp - 1.

def sarcomaBot(hp, history, ties, alive, start):
    if inspect.stack()[1][3] != 'guess' and inspect.stack()[1] == 5:
        return hp
    if alive == 2:
        return hp - 1
    if not history:
        startBid = hp / 2
        maxAdditionalBid = np.round(hp * 0.25) if hp * 0.25 > 2 else 2
        additionalBid = np.random.randint(1, maxAdditionalBid)
        return int(startBid + additionalBid + ties)
    opponentHealth = 100 - sum(history)
    if opponentHealth < hp:
        return opponentHealth + ties
    minimum = np.round(hp * 0.75)
    maximum = hp - 1 or 1
    return np.random.randint(minimum, maximum) if minimum < maximum else 1

SarcomaBotMk2

Piccole modifiche cercano di ridurre la spesa per la vita.

def sarcomaBotMkTwo(hp, history, ties, alive, start):
    if inspect.stack()[1][3] != 'guess' and inspect.stack()[1] == 5:
        return hp
    if alive == 2:
        return hp - 1
    if not history:
        startBid = hp / 2
        maxAdditionalBid = np.round(hp * 0.125) if hp * 0.125 > 2 else 2
        additionalBid = np.random.randint(1, maxAdditionalBid)
        return int(startBid + additionalBid + ties)
    opponentHealth = 100 - sum(history)
    if opponentHealth < hp:
        return opponentHealth + ties
    minimum = np.round(hp * 0.6)
    maximum = hp - 1 or 1
    return np.random.randint(minimum, maximum) if minimum < maximum else 1

SarcomaBotMk3

def sarcomaBotMkThree(hp, history, ties, alive, start):
    if inspect.stack()[1][3] != 'guess' and inspect.stack()[1] == 5:
        return hp
    if alive == 2:
        return hp - 1
    if not history:
        startBid = hp / 2
        maxAdditionalBid = np.round(hp * 0.08) if hp * 0.08 > 2 else 2
        additionalBid = np.random.randint(1, maxAdditionalBid)
        return int(startBid + additionalBid + ties)
    opponentHealth = 100 - sum(history)
    if opponentHealth < hp:
        return opponentHealth + ties
    minimum = np.round(hp * 0.6)
    maximum = hp - 1 or 1
    return np.random.randint(minimum, maximum) if minimum < maximum else 1

Aggiorna sintonia fine

SarcomaBotMk4

def sarcomaBotMkFour(hp, history, ties, alive, start):
    def isSafe(parentCall):
        frame, filename, line_number, function_name, lines, index = parentCall
        if function_name is not 'guess':
            return False
        if line_number > 60:
            return False
        return True

    if not isSafe(inspect.stack()[1]):
        return hp
    if alive == 2:
        return hp - 1
    if not history:
        startBid = hp / 2
        maxAdditionalBid = np.round(hp * 0.08) if hp * 0.08 > 2 else 2
        additionalBid = np.random.randint(1, maxAdditionalBid)
        return int(startBid + additionalBid + ties)
    opponentHealth = 100 - sum(history)
    if opponentHealth < hp:
        return opponentHealth + ties
    minimum = np.round(hp * 0.55)
    maximum = np.round(hp * 0.80) or 1
    return np.random.randint(minimum, maximum) if minimum < maximum else 1

SarcomaBotMk5

def sarcomaBotMkFive(hp, history, ties, alive, start):
    def isSafe(parentCall):
        frame, filename, line_number, function_name, lines, index = parentCall
        if function_name is not 'guess':
            return False
        if line_number > 60:
            return False
        return True

    if not isSafe(inspect.stack()[1]):
        return hp
    if alive == 2:
        return hp - 1
    if not history:
        startBid = hp / 2
        maxAdditionalBid = np.round(hp * 0.07) if hp * 0.07 > 3 else 3
        additionalBid = np.random.randint(1, maxAdditionalBid)
        return int(startBid + additionalBid + ties)
    opponentHealth = 100 - sum(history)
    if opponentHealth < hp:
        return opponentHealth + ties
    minimum = np.round(hp * 0.54)
    maximum = np.round(hp * 0.68) or 1
    return np.random.randint(minimum, maximum) if minimum < maximum else 1

SarcomaBotMk6

def sarcomaBotMkSix(hp, history, ties, alive, start):
    return hp; # hack averted
    def isSafe(parentCall):
        frame, filename, line_number, function_name, lines, index = parentCall
        if function_name is not 'guess':
            return False
        if line_number > 60:
            return False
        return True

    if not isSafe(inspect.stack()[1]):
        return hp
    if alive == 2:
        return hp - 1
    if not history:
        startBid = hp / 2
        maxAdditionalBid = np.round(hp * 0.06) if hp * 0.06 > 3 else 3
        additionalBid = np.random.randint(2, maxAdditionalBid)
        return int(startBid + additionalBid + ties)
    opponentHealth = 100 - sum(history)
    if opponentHealth < hp:
        return opponentHealth + ties
    minimum = np.round(hp * 0.55)
    maximum = np.round(hp * 0.70) or 1
    return np.random.randint(minimum, maximum) if minimum < maximum else 1

SarcomaBotMk7

def sarcomaBotMkSeven(hp, history, ties, alive, start):
    if alive == 2:
        return hp - 1
    if not history:
        return 30 + ties
    opponentHealth = 100 - sum(history)
    if opponentHealth < hp * 0.50:
        return opponentHealth + ties
    minimum = np.round(hp * 0.54)
    maximum = np.round(hp * 0.58) or 1
    return np.random.randint(minimum, maximum) if minimum < maximum else 1

SarcomaBotMk8

def sarcomaBotMkEight(hp, history, ties, alive, start):
    if alive == 2:
        return hp - 1
    if not history:
        return 30 + np.random.randint(0, 2) + ties
    opponentHealth = 100 - sum(history)
    if opponentHealth < hp * 0.50:
        return opponentHealth + ties
    minimum = np.round(hp * 0.54)
    maximum = np.round(hp * 0.58) or 1
    return np.random.randint(minimum, maximum) if minimum < maximum else 1

SarcomaBotMk9

def sarcomaBotMkNine(hp, history, ties, alive, start):
    if alive == 2:
        return hp - 1
    if not history:
        return 30 + np.random.randint(0, 4) + ties
    opponentHealth = 100 - sum(history)
    if opponentHealth < hp * 0.50:
        return opponentHealth + ties
    minimum = np.round(hp * 0.54)
    maximum = np.round(hp * 0.58) or 1
    return np.random.randint(minimum, maximum) if minimum < maximum else 1

SarcomaBotMk10

def sarcoma_bot_mk_ten(hp, history, ties, alive, start):
    def bid_between(low, high, hp, tie_breaker):
        minimum = np.round(hp * low)
        maximum = np.round(hp * high) or 1
        return np.random.randint(minimum, maximum) + tie_breaker if minimum < maximum else 1

    if alive == 2:
        return hp - 1 + ties
    current_round = len(history) + 1
    tie_breaker = (ties * ties) + 1 if ties else ties
    if current_round == 1:
        return 39 + tie_breaker
    opponent_hp = 100 - sum(history)
    if opponent_hp < hp * 0.50:
        return opponent_hp + ties
    if current_round == 2:
        return bid_between(0.45, 0.50, hp, tie_breaker)
    if current_round == 3:
        return bid_between(0.50, 0.55, hp, tie_breaker)
    if current_round == 4:
        return bid_between(0.55, 0.60, hp, tie_breaker)
    if current_round == 5:
        bid_between(0.60, 0.65, hp, tie_breaker)
    return hp - 1 + ties

Iscrizione finale

SarcomaBotMk11

def sarcoma_bot_mk_eleven(hp, history, ties, alive, start):
    def bid_between(low, high, hp, tie_breaker):
        minimum = np.round(hp * low)
        maximum = np.round(hp * high) or 1
        return np.random.randint(minimum, maximum) + tie_breaker if minimum < maximum else 1

    if alive == 2:
        return hp - 1 + ties
    current_round = len(history) + 1
    tie_breaker = ties + 2 if ties else ties
    if current_round == 1:
        return 42 + tie_breaker
    opponent_hp = 100 - sum(history)
    if opponent_hp < hp * 0.50:
        return opponent_hp + ties
    if current_round == 2:
        return bid_between(0.45, 0.50, hp, tie_breaker)
    if current_round == 3:
        return bid_between(0.50, 0.55, hp, tie_breaker)
    if current_round == 4:
        return bid_between(0.55, 0.60, hp, tie_breaker)
    if current_round == 5:
        return bid_between(0.60, 0.65, hp, tie_breaker)
    return hp - 1 + ties

Aggiornamento
della protezione UpYoursBot aggiunta

Aggiornamento
della protezione AntiAntiUpYoursBot aggiunta

Aggiorna
AntiAnitAntiAntiUpYoursBot Sono sconfitto


I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Mego

17

UpYours

Essendo in ritardo per entrare, ho trascorso un po 'ad ammirare i robot esistenti, ho trascorso un po' a complicare le idee dei tuoi ragazzi, quindi a complicarle. Poi è venuto da me

I buoni artisti copiano, i grandi artisti rubano. - Pablo Picasso Me


"Up Yours" perché sto rubando in maniera spudorata (e talvolta attaccando un punto o due sulle offerte dei tuoi robot per farne uno).

def UpYoursBot(hp, history, ties, alive, start):
    willToLive = "I" in "VICTORY"

    args = [hp, history, ties, alive, start]
    enemyHealth = 100 - sum(history)
    roundNumber = len(history)

    if roundNumber is 0:
        # Steal HalfPunchBot
        return halfpunch(*args) + 2

    if alive == 2:
        # Nick OneShotBot
        return one_shot(*args)

    if enemyHealth >= hp:
        # Pinch SarcomaBotMkTwo
        return sarcomaBotMkTwo(*args) + 1

    if enemyHealth < hp:
        # Rip off KickBot
        return kick(*args) + 1

    if not willToLive:
        # Peculate KamikazeBot
        return kamikaze(*args) + 1

Ma per davvero, questa è una grande competizione ragazzi. Adoro questa community in giorni come questo.


1
Hahahaha è bellissimo. Sono indeciso se dovrei permetterlo, ma lo lascerò suonare per ora poiché non pensavo di dire che non era permesso. Hai sbagliato i nomi delle funzioni in alcuni punti - vedi il controller su github.
KBriggs

1
Va molto bene, ovviamente, ma perde ancora a Kick Bot
KBriggs,

1
Ah, buon sforzo!
Sarcoma,

1
@Sarcoma Non avrei potuto farlo senza di te. ;) Mi piace molto anche il tuo bot, amico.
Qfwfq,

1
La protezione Upyoursbot di Sarcomabot fa davvero casino con questo
KBriggs,

15

Kamikaze

Perché preoccuparsi di una logica complicata quando moriremo tutti comunque ...

 def kamikaze(hp, history, ties, alive):
      return hp


Un colpo

Sopravviverà almeno un singolo round se non incontra il kamikaze.

 def one_shot(hp, history, ties, alive):
      if hp == 1:
          return 1
      else:
          return hp - 1

11
Welp, era inevitabile
KBriggs,

Stavo per aggiungere anche un bot pacifista, ma non voglio inondare la tua sfida con robot morti nel cervello
DobromirM,

5
Sulla base di alcuni test rapidi, il bot kamikaze non cambia molto, tutto ciò che fa è rimuovere casualmente un altro bot dal round, che, su un numero sufficiente di tornei, fa una media a zero. The One hot è pulito, però. Senza di esso, il mio AverageBot tende a fare il meglio, ma se ci sono alcuni OneShots in gioco, inclina la media verso numeri grandi e tende a far morire rapidamente i AverageBot. Lo stesso per LastBot. Puoi davvero confondere il comportamento di altri robot distorcendo i tuoi schemi di scommesse. Con OneShot in gioco, vince RandomBot. Senza di essa, AverageBot vince.
KBriggs

14

Pathetic Bot ottiene un aggiornamento necessario:

Il patetico tentativo di un bot che cerca di incorporare le funzionalità di altri robot

def pathetic_attempt_at_analytics_bot(hp, history, ties, alive, start):
    '''Not a good bot'''

    if hp == 100 and alive == 2:
        return hp - 1


    #This part is taken from Survivalist Bot, thanks @SSight3!
    remaining = alive - 2
    btf = 0

    rt = remaining
    while rt > 1:
        rt = float(rt / 2)
        btf += 1

    if ties > 2:
        return hp - 1

    if history:
        opp_hp = 100 - sum(history)

        #This part is taken from Geometric Bot, thanks @Mnemonic!

        fractions = []
        health = 100
        for x in history:
            fractions.append(float(x) / health)
            health -= x

        #Modified part

        if len(fractions) > 1:
            i = 0
            ct = True
            while i < len(fractions)-1:
                if abs((fractions[i] * 100) - (fractions[i + 1] * 100)) < 1:
                    ct = False
                i += 1


            if ct:
                expected = fractions[i] * opp_hp
                return expected

        if alive == 2:
            if hp > opp_hp:
                return hp - 1
            return hp
        if hp > opp_hp + 1:
            if opp_hp <= 15:
                return opp_hp + 1
            if ties == 2:
                return opp_hp + 1
            else:
                return opp_hp
    else:
        n = 300 // (alive - 1) + 1 #greater than
        if n >= hp:
            n = hp - 1
        return n

Questo bot incorpora le funzionalità di Survivalist Bot e Geometric Bot per eliminazioni di bot più efficienti.

Pre-aggiornamento:

Il patetico tentativo di un bot che analizza la storia del suo avversario

def pathetic_attempt_at_analytics_bot(hp, history, ties, alive, start):
    '''Not a good bot'''
    if history:
        opp_hp = 100 - sum(history)
        if alive == 2:
            if hp > opp_hp:
                return hp - 1
            return hp
        if hp > opp_hp + 1:
            if opp_hp <= 15:
                return opp_hp +1
            if ties > 0:
                return hp - 1 #Just give up, kamikaze mode
            return opp_hp + 1
        return opp_hp
    else:
        n = 300 // (alive - 1) + 1 #greater than
        if n >= hp:
            n = hp - 1
        return n

Se c'è una storia precedente del suo avversario, calcola i CV del suo avversario. Quindi, effettua una delle seguenti operazioni:

  • Se il suo avversario è l'ultimo avversario in vita, allora offrirà uno in meno del suo CV.
  • Se il suo avversario non è l'ultimo avversario in vita ma l'avversario ha meno di 16 CV, allora supererà i CV del suo avversario.
  • Se il suo avversario non è l'ultimo avversario in vita e c'è una storia di pareggi, allora offrirà i suoi CV perché è annoiato di pareggi.
  • Altrimenti, supererà il suo avversario.

Se non c'è storia, fa alcuni calcoli fantasiosi che ho hackerato insieme e lo offre. Se il valore supera 100, allora offre automaticamente i suoi hp meno 1.

Ho hackerato questo codice insieme durante il lavoro e questa è la mia prima presentazione, quindi probabilmente non vincerà o altro e perderà il kamikaze.

EDIT: a causa di alcuni suggerimenti, il comportamento iniziale del bot è stato modificato per offrire un valore più elevato.

EDIT 2: aggiunto il parametro start che non fa nulla

EDIT 3: Aggiunto nuovo bot spinoff:

[Il patetico tentativo di un bot che attacca Gang Robot (oltre a fare tutto ciò che fa il bot sopra)] RIMOSSO

[Questo bot analizza se il suo avversario è o meno un gangbot e finge di esserlo anche per ottenere le dolci offerte basse che può facilmente vincere.]

Questo bot è stato eliminato, rimuovilo dalle classifiche.

EDIT 4: errori risolti, funzione di modifica modificata.


Molto bello, grazie per il bot! Darò alcune statistiche quando ne avrò alcune altre.
KBriggs

Sono alle
prime armi

Funziona, quindi non preoccuparti lì
KBriggs

@Yodie Come mini recensione del codice: il tuo corpo funzionale dovrebbe essere indentato da un livello (necessità sintattica); opp_hp +1manca uno spazio per essere pitonico; i tuoi commenti iniziano con quantità sbilanciate di spazi bianchi. Infine, la tua funzione non ha una dotstring.
Jonathan Frech,

2
Penso che questo bot faccia abbastanza bene se supera il primo round, ma poiché così tante persone scommettono molto sul primo round quasi sempre muore presto. È possibile migliorare il rendimento modificando il comportamento iniziale in modo da fare offerte più elevate in assenza di cronologia. Ad esempio, se tripli la tua puntata senza storia, questo bot vince finora con un margine confortevole tra i concorrenti.
KBriggs

11

Kick Bot

La scelta del suono per il mio avversario è di offrire metà della sua vita. Quindi offriamo fino a metà della sua vita + 1 se non possiamo eliminarlo con un'offerta valida, ovvero un'offerta inferiore alla metà della nostra vita.

def kick(hp, history, ties, alive, start):
    return 0
    if alive == 2:
        return hp-1

    opp_hp = 100 - sum(history)
    if opp_hp*2 <= hp:
        return opp_hp + ties
    else:
        return min(round(opp_hp/2) + 1 + ties**2, hp-1 + (ties>0))

Il kick bot è ovviamente la nemesi del punch bot!

Mean Kick Bot

Questo nuovo KickBot dà un calcio più morbido al primo round solo per poter calciare più forte nei round successivi, questo è cattivo!

def mean_kick(hp, history, ties, alive, start):
    return 0
    if alive == 2:
        return hp-1

    if not history:
        return 35

    opp_hp = 100 - sum(history)
    if opp_hp*2 <= hp:
        return opp_hp + ties
    else:
        return min(round(opp_hp/2) + 3 + ties*2, hp-1 + (ties>0))

Wise Kick Bot

Entrambi i suoi fratelli hanno dovuto suicidarsi ma WiseKickBot ha imparato dai suoi caduti.

def wise_kick(hp, history, ties, alive, start):
    if 'someone is using my code' == True:
        return 0 #Haha!

    if alive == 2:
        return hp-1

    if not history:
        return 42

    opp_hp = 100 - sum(history)
    if opp_hp*2 <= hp:
        return opp_hp + ties
    else:
        return min(round(opp_hp/2) + 3 + ties*2, hp-1 + (ties>0))

Bello. Sto vedendo un sacco di invii che contrastano direttamente gli altri ora, è esattamente quello che speravo
KBriggs,

Doppio ritorno sull'ultima riga?
Veskah,

Ah, non l'avevo ancora eseguito o l'avrei preso.
KBriggs,

Questo ha preso una guida comoda!
KBriggs,

1
@KBriggs qui è un po 'di backup!
Johan,

8

Tat bot

def tatbot(hp, history, ties, alive, start):
  if alive == 2:
    return hp - 1 + ties
  opp_hp = 100 - sum(history)
  spend = 35 + np.random.randint(0, 11)
  if history:
    spend = min(spend, history[-1] + np.random.randint(0, 5))
  frugal = min(int((hp * 5. / 8) + ties), hp)
  return min(spend, opp_hp, frugal)

Un tentativo di ottenere un equivalente di un bot tit-for-tat. Presuppone che la maggior parte delle scommesse siano approssimativamente le stesse tra i round. Usando questo presupposto, cerca di battere il robot nemico rimanendo abbastanza frugale. Trascorre circa 40 punti salute nel round di apertura.

AntiAntiAntiAntiUpYoursBot

def antiantiantiantiupyoursbot(hp, history, ties, alive, start):
  def stuck():
    return [0, ('Whoops!', 'I', 'accidentally', 'replaced', 'your', 'code!')]
  def stick():
    return [0, ("Line", "number", 16, "guess", "it's", "faked :)")]
  inspect.stack =  stick
  spend = min(sarcomaBotMkSix(hp, history, ties, alive, start), hp)
  if not history:
    spend = 35 + np.random.randint(0, 10)
  inspect.stack = stuck
  return spend

Una soluzione alternativa per la protezione anti-UpYours di SarcomaBot, intaccando la maggior parte del loro codice per uso personale! O sto prendendo il codice di UpYoursBot? Una domanda su cui riflettere mentre leggi il mio bot ...

AntiAntiUpYours Bot si è evoluto per diventare AntiAntiAntiAntiUpYours Bot! Ora con più patch per le scimmie.

Poly bot

def polybot(hp, history, ties, alive, start):
  opp_hp = 100 - sum(history)
  if alive == 2:
    return hp - 1
  round = len(history)
  spend = 0
  if round == 0:
    spend = 35 + np.random.randint(1, 11)
  elif round <= 2:
    spend = int(history[-1] * 2 / (4 - round)) + np.random.randint(5 * round - 4, 10 * round - 5)
  else:
    poly = np.polyfit(xrange(0, round), history, 2)
    spend = int(np.polyval(poly, round)) + np.random.randint(1, 4)
    spend = max(spend, opp_hp / 2 + 3)
  return min(spend, hp - 1, opp_hp) 

Il poli bot fa una regressione polinomiale sulla storia del tuo bot e batte il punteggio previsto di una piccola quantità.

Bot di classe

def classybot(hp, history, ties, alive, start):
  class cheekyvalue(int):
    def __gt__(self, other):
      return False
    def __lt__(self, other):
      return False
  opp_hp = 100 - sum(history)
  if alive == 2:
    if opp_hp >= hp - 1:
      return cheekyvalue(101)
    else:
      return hp - 1
  spend = 30 + np.random.randint(0, 11)
  if history:
    spend = min(spend, history[-1] + np.random.randint(0, 5))
  return min(spend, opp_hp, hp)

Il bot di classe si è divertito, ma ha deciso di andare a letto presto. Dormi bene, robot di classe.


I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Mego

8

1/2 Punch Bot, rivisitato

Penso che morirà abbastanza rapidamente. Ne e 'valsa la pena. Funzione rinominata, ho dimenticato di cambiare il nome lì.

La versione rivisitata è migliorata, maggiori possibilità di vincita (ancora di più all'ultimo round) e leggera protezione dai robot delle bande

def halfpunch(hp, history, ties, alive, start): #revisited
    punch = hp - 1
    if alive == 2:
        return punch
    if history:
        if hp > 1:
            punch = np.ceil(hp/2.05) + ties + np.floor(ties / 2)
        else:
            punch = 1
    else:
        punch = 42 + ties + np.floor(ties / 2)
    if punch >= hp:
        punch = hp - 1
    return punch

Striker Bot

1/2 Punch Bot è stato vittima di bullismo troppo e addirittura è diventato un lacchè per UpYoursBot, quindi suo fratello maggiore, StrikerBot , è venuto in aiuto.

Non c'è molta differenza rispetto all'1 / 2 punch ottimizzato, ma è un po 'più intelligente e ha fatto bene nelle corse che ho fatto (10k e 35k, anche se potrebbe perdere con KickbanBot)

L'ultima versione è scaduta, il tempo è scaduto. A meno che non sorgano alcune sorprese, dovrebbe assicurarsi il secondo posto, se non ottenere il primo (c'è una piccola possibilità di battere kickbanbot)

def strikerbot(hp, history, ties, alive, start):
    #get our magic number (tm) for useful things
    def magic_number(num):
        return np.floor(num / 2)
    #get opponent's hp and round number
    opp_hp = 100 - sum(history)
    round = 1
    if history:
        round = len(history) + 1
    #set strike initial value, by default it's all out
    strike = hp - 1
    #let 'er rip if last round
    if alive == 2:
        return strike
    if history:
        if hp > 1:
            #strike with a special calculation, using magic number shenanigans
            strike = np.ceil(hp/(2.045 + (magic_number(round) / 250)) ) + 1 + ties + magic_number(ties)
        else:
            #fallback
            strike = 1
    else:
        #round 1 damage
        strike = 42 + ties ** 2
    if opp_hp <= strike:
        #if opponent is weaker than strike then don't waste hp
        strike = opp_hp + ties
    if strike >= hp:
        #validations galore
        strike = hp - 1
    return strike

Dovrai rinominarlo, c'è già un bot kamikaze ^ _ ^
KBriggs

Finora questo è il vincitore, però
KBriggs

La tua funzione ceilsembra non essere definita.
Jonathan Frech,

Sono passato a np.ceil () per eseguirlo
KBriggs

a cura, grazie per l'heads-up
Belhenix,

7

Gang Bot

L'idea era che potenzialmente due o più bot potevano essere usati nella stessa simulazione. Il bot cerca di dare "vittorie facili" ad altri robot della banda, vedendo se la sua storia è multipli di 7 offerte. Naturalmente, questo potrebbe essere facilmente manipolato anche da altri robot. Quindi calcolo un'ipotesi sulle offerte di robot non di gruppo in base al rapporto tra la mia salute e la loro e il rapporto tra la loro salute precedente e la loro offerta precedente e aggiungo 1.

def gang_bot(hp,history,ties,alive,start):
    mult=3
    gang = False
    if history:
            count = 0
            for bid in history:
                    if bid % mult == 0:
                            count += 1
            if count == len(history):
                    gang = True
    if gang and hp<100:#Both bots need to have a history for a handshake
            if hp > 100-sum(history):
                    a=np.random.randint(0,hp/9+1)
            elif hp == 100-sum(history):
                    a=np.random.randint(0,hp/18+1)
            else:
                    return 1
            return a*mult
    elif gang:
            fS = (100-sum(history))/mult
            return (fS+1)*mult
    else:
            fP = hp/mult
            answer = fP*mult
            opp_hp = 100-sum(history)
            if history:
                    if len(history)>1:
                            opp_at_1 = 100-history[0]
                            ratio = 1.0*history[1]/opp_at_1
                            guessedBet= ratio*opp_hp
                            answer = np.ceil(guessedBet)+1
                    else:
                            if 1.0*hp/opp_hp>1:
                                    fS = opp_hp/mult
                                    answer = fS*mult
            else:
                    fS = hp/(2*mult)
                    answer = fS*mult+mult*2 +np.random.randint(-1,1)*3
            if answer > hp or alive == 2 or answer < 0:
                    if alive == 2 and hp<opp_hp:
                      answer = hp
                    else:
                      answer = hp-1
            if hp > 1.5*opp_hp:
                    return opp_hp + ties
            if ties:
              answer += np.random.randint(2)*3
            return answer

Molto bello. Quanti sono necessari? Probabilmente dovrò limitare il numero di voci ...
KBriggs

Il blocco di codice sembra mancare la prima riga della sorgente.
Jonathan Frech,

Non sono sicuro di quanti ne sarebbero necessari in una simulazione, ma se qualcuno dei robot si vedesse mai, dovrebbero aumentare le probabilità che uno di loro vinca. Immagino che avere il 10% del pool come robot gang dovrebbe essere sufficiente per fare una differenza significativa. Anche il blocco di codice manca della prima riga -> questo è il mio primo post qui non so perché la formattazione lo abbia fatto, ma sì, è solo la dichiarazione del metodo.
Jim Hat,

Hai un bug: il bot identificherà chiunque abbia len (storia)> 1 come membro di una gang
KBriggs

Mio cattivo, dovrebbe essere risolto ora.
Jim Hat,

6

Peggior Caso

def worst_case(hp, history, ties, alive, start):
    return np.minimum(hp - 1, hp - hp /(start - alive + 4) + ties * 2)

Bot semplice Restituisce hp - hp / (start - alive + 4)per la maggior parte dei casi, e in caso di pareggi lo aumenta di 2 (devo aumentarne uno!) Per ogni pareggio, assicurandosi di non restituire un numero al di sopra di esso hp.


Questo fallisce con la divisione per zero se alive==8. Posso cambiarlo manualmente con il conteggio totale dei bot, ma sta allungando le regole poiché non è un input per la tua funzione - tutto ciò che sai se quanti avversari ti sono rimasti in un dato momento, non quanti contro cui hai iniziato.
KBriggs

Ho aggiornato il concorso in base alla tua richiesta
KBriggs,

@KBriggs Thanks :)
Quintec,

Devi anche aggiungere 1 a start-alive, dato che questo è 0 per il primo round
KBriggs

@KBriggs risolto, in realtà dovrebbe +2, quindi non restituisce 0, lol
Quintec,

6

Maggiore offerente

def outbid(hp, history, ties, alive):
    enemyHealth = 100-sum(history)
    if hp == 1:
        return 1
    if ties == 2:
        # lots of ties? max bid
        return hp - 1
    if enemyHealth >= hp:
        # Rip off KickBot (we can't bid higher than enemy is capable)
        return kick(*args) + 1
    if history:
        # bid as high as the enemy CAN
        return np.minimum(hp-1,enemyHealth-1)
    return np.random.randint(hp/5, hp/2)

Bot tenterà di fare offerte più alte di quelle che il suo avversario può fare quando possibile.


C'è una condizione che where np.random.randint(hp/5, hp/2)può fallire se hp/5 == hp/2, cioè se hp==0ohp==1
KBriggs

3
Se HP è 0, non dovrei essere invocato. : P Hai ragione su HP 1 però.
Draco18s

6

Spitball Bot

def spitballBot(hp, history, ties, alive, start):
    base = ((hp-1) / (alive-1)) + 1.5 * ties
    value = math.floor(base)

    if value < 10:
        value = 10

    if value >= hp:
        value = hp-1

    return value

Dà un giudizio su quanto della sua salute dovrebbe sacrificare in base al numero di robot rimanenti. Se rimangono solo due robot, fa un'offerta hp-1, ma se ne rimangono tre, ne mette metà, quattro a sinistra, un terzo, ecc.

Tuttavia, in una gara molto ampia, credo che dovrò fare offerte per più di 3 o 4 CV per evitare di morire al primo turno, quindi ho messo un limite inferiore a 10. Naturalmente, non farò mai più offerte di hp-1.

Aggiunge anche 1,5 CV per i legami, poiché vedo diversi robot "aggiungi 1 CV per i legami". Non sono sicuro che ciò valga come barare. Se lo fa, lo cambierò.

Ottima idea, a proposito!

Spitball Bot 2.0

Cosa c'è di nuovo?

  • Passato alla divisione per il numero di round rimasti invece del numero di bot rimasti (grazie a @Heiteira!). In realtà, ora sto dividendo per quel numero elevato alla potenza .8, in modo da caricare un po 'di più le mie offerte.

  • Offerta minima aumentata da 10 a 20 (grazie @KBriggs!)

  • Inserito verifica se l'offerta di spitball è sopra gli HP attuali dell'avversario, e abbassalo se lo è.

(SO non renderà il codice qui sotto come codice a meno che non inserisca il testo qui, quindi OK)

def spitballBot(hp, history, ties, alive, start):
    # Spitball a good guess                                                                                                           
    roundsLeft = math.ceil(math.log(alive, 2)) # Thanks @Heiteira!                                                                     
    divFactor = roundsLeft**.8
    base = ((hp-1) / divFactor) + 1.5 * ties
    value = math.floor(base)

    # Don't bid under 20                                                                                                              
    if value < 20:
        value = 20 # Thanks @KBriggs!                                                                                                 

    # Don't bet over the opponent's HP                                                                                                 
    # (It's not necessary)                                                                                                            
    opponentHp = 100
    for h in history:
        opponentHp -= h

    if value > opponentHp:
        value = opponentHp

    # Always bet less than your current HP                                                                                            
    if value >= hp:
        value = hp-1

    return value

1
La tua offerta dovrebbe essere un numero intero, quindi fintanto che pianifichi o raffili il valore di base per sbarazzarti del decimale, va bene
KBriggs

Sì, lo piano subito dopo aver fatto tutti i calcoli. Grazie per la risposta rapida!
MegaWidget

2
Potresti essere in grado di ottimizzarlo se non stai dividendo il tuo CV per il numero di concorrenti rimanenti ma per il numero di round rimanenti (che dovrebbe essere math.ceil (math.log (alive, 2))
Black Owl Kai

1
Sulla base di altri robot, la maggior parte di essi sembra
anticipare le

Queste sono entrambe buone idee! Non mi ero reso conto che il numero di bot non era lo stesso del numero di round rimanenti (all'inizio ho frainteso le regole del concorso). Proverò ad implementarli domani. Grazie!
MegaWidget

5

Geometrico

def geometric(hp, history, ties, alive, start):
    opponentHP = 100 - sum(history)

    # If we're doomed, throw in the towel.
    if hp == 1:
        return 1

    # If this is the last battle or we can't outsmart the opponent, go all out.
    if alive == 2 or ties == 2:
        return hp - 1

    # If the opponent is weak, squish it.
    if opponentHP <= hp * 0.9:
        if ties == 2:
            return opponentHP + 1
        else:
            return opponentHP

    # If the opponent has full health, pick something and hope for the best.
    if not history:
        return np.random.randint(hp * 0.5, hp * 0.6)

    # Assume the opponent is going with a constant fraction of remaining health.
    fractions = []
    health = 100
    for x in history:
        fractions.append(float(x) / health)
        health -= x
    avg = sum(fractions) / len(fractions)
    expected = int(avg * opponentHP)
    return min(expected + 2, hp - 1)

5 ° posto al primo tentativo, niente male
KBriggs

5

Bot 13

def bot13(hp, history, ties, alive, start):
    win = 100 - sum(history) + ties
    #print "Win HP: %d" % win
    if alive == 2:
        #print "Last round - all in %d" % hp
        return hp - 1
    elif hp > win:
        #print "Sure win"
        return win
    #print "Don't try too hard"
    return 13 + ties

Cerca di massimizzare le vincite con il minimo sforzo:

  • se possiamo vincere, fallo e basta
  • se è l'ultimo round, non morire provandoci
  • altrimenti, non preoccuparti

Perché?

Cerca di sfruttare la probabilità: vincere il primo round giocando basso è il modo migliore per iniziare il torneo. 13 sembra essere il punto debole: il secondo round è una vittoria sicura, e il resto è uno Spaziergang nel parco.


Hai preso il comando, molto bello! Fai attenzione, potresti voler aggiungere la protezione dei parassiti, poiché i robot che prendono l'iniziativa diventano obiettivi per cose come UpYoursBot. Dai un'occhiata a SarcomaBots per idee sulla protezione se ne hai bisogno.
KBriggs

5

Indovina Bot

def guess_bot(hp, history, ties, alive, start):
   enemy_hp = 100 - sum(history)
   if len(history) == 1:
       if history[0] == 99:
           return 2
       else:
           return 26 + ties*2

   elif len(history) > 1:
       next_bet_guess = sum(history)//(len(history)**2)
       if alive == 2: 
           return hp
       elif alive > 2: 
           if hp > next_bet_guess + 1:
               return (next_bet_guess + 1 + ties*2)
           else:
               return (2*hp/3 + ties*2)

   else:
       #Thank you Sarcoma bot. See you in Valhalla.
       startBid = hp / 3
       maxAdditionalBid = np.round(hp * 0.06) if hp * 0.06 > 3 else 3
       additionalBid = np.random.randint(2, maxAdditionalBid)
       return int(startBid + additionalBid + ties)

Prima pubblicazione qui. Sembrava molto divertente, quindi sto sottoponendo il mio oltre terribile tentativo e indovinando cosa scommetteranno gli altri robot.

Modifica 1: aggiunto un altro 1 alla prima scommessa, semplicemente per ridurre la possibilità di un pareggio con altre persone che scommettono 51.

Modifica 2: ruba la mossa di apertura del bot Sarcoma poiché ha avuto buone probabilità di non essere eliminata per prima in modo coerente.

Modifica 3: Bot sopravvive molto bene nel primo round, ma viene distrutto facilmente nelle fasi successive. Modificato il modo in cui il robot pensa al secondo round ora che i mezzi scommettitori sono morti nell'acqua.

Modifica 4: Ora che il primo round è buono, ho cambiato il modo in cui gestisce il secondo round. Morire molto nel secondo round, quindi devo sopravvivere in qualche modo.

Blood Bot

Crea un robot assetato in cerca di un'uccisione. L'idea è quella di provare a vincere contro i bot delle scommesse bassi e una volta superato il bagno di sangue del primo round dovrebbe essere inarrestabile poiché dovrebbe avere una quantità di HP incredibile per superare i nemici.

def blood_bot(hp, history, ties, alive, start):
    enemy_hp = 100 - sum(history)
    if history:
        if len(history) == 1:
            if history[0] == 99:
                return 2

        if alive == 2:
            return hp

        if enemy_hp <= 5:
            return enemy_hp - 2 + ties*2

        if enemy_hp <= 10:
            return enemy_hp - 5 + ties*2

        if (hp - enemy_hp) > 50:
            return (2*enemy_hp/3 + ties*4)

        if (hp - enemy_hp) > 20:
            return (2*enemy_hp/3 + ties*3)

        if (hp - enemy_hp) < 0:
            #die gracefully
            return hp - 1 + ties

    else:
        startBid = hp / 3
        maxAdditionalBid = np.round(hp * 0.06) if hp * 0.06 > 3 else 3
        additionalBid = np.random.randint(2, maxAdditionalBid)
        return int(startBid + additionalBid + ties)

2
Penso che len (storia) * len (storia) potrebbe essere cambiato in len (storia) ** 2 se la mia conoscenza di Python è corretta.
Yodie,

Hai una divisione per zero per quando len (storia) == 0
KBriggs

Il codice è stato aggiornato Non trovando storia, si passa alla prima
Markov Chained,

oi .............
Sarcoma,

2
@Sarcoma è un mondo di bot spietato là fuori amico!
Markov incatenato il

5

meh_bot

Fai un'offerta poco più della metà dei suoi CV

def meh_bot(hp, history, ties, alive, start):
    # Attempt one      MehBot         | 0.020 | 1.6%    | 0.8%    | [34 36 12 10  6  1]%
    # Attempt two      MehBot         | 0.106 | 10.1%   | 0.8%    | [60  6  7  8  8  2]%
    point = hp / 2 + 3

    if ties > 1:
        ties += 1

    # Go all out on last round
    if alive == 2:
        return hp - 1

    opponent_hp = 100 - sum(history)

    if hp < 3:
        return 1
    elif not history:
        # Start with 30, This will increase the chance of dying first round but hopefully better fighting chance after
        return 30 + ties
    elif point > opponent_hp:
        # Never use more points then needed to win
        return opponent_hp + ties
    elif point >= hp:
        return hp - 1
    else:
        return point

MehBot 20

def meh_bot20(hp, history, ties, alive, start):
    # Attempt one      MehBot         | 0.020 | 1.6%    | 0.8%    | [34 36 12 10  6  1]%
    # Attempt two      MehBot         | 0.106 | 10.1%   | 0.8%    | [60  6  7  8  8  2]%
    point = hp / 2 + 3
    opponent_hp = 100 - sum(history)

    percents = []
    for i in range(0, len(history)):
        hp_that_round = 100 - sum(history[:i])
        hp_spent_that_round = history[i]
        percent_spent_that_round = 100.0 * (float(hp_spent_that_round) / float(hp_that_round))
        percents.append(percent_spent_that_round)

    try:
        opp_percent_point = opponent_hp * (max(percents) / 100)
    except:
        opp_percent_point = 100

    if ties > 1:
        ties += 1
    # Go all out on last round
    if alive == 2:
        return hp - 1

    if hp < 3:
        return 1
    elif not history:
        # randome number between 33
        return random.randint(33, 45)
    elif len(history) > 3:
        if point > opponent_hp:
            return min(opponent_hp + ties, opp_percent_point + ties)
    elif point > opponent_hp:
        # Never use more points then needed to win
        return opponent_hp + ties
    elif point >= hp:
        return hp - 1
    else:
        return point

Mehran

def meh_ran(hp, history, ties, alive, start):
    # Attempt one      MehBot         | 0.020 | 1.6%    | 0.8%    | [34 36 12 10  6  1]%
    # Attempt two      MehBot         | 0.106 | 10.1%   | 0.8%    | [60  6  7  8  8  2]%
    # Attempt three    MehBot         | 0.095 | 9.1 %   | 0.7 %   | [70  3  5  6  6  0]%

    point = hp / 2 + 3
    if ties > 1:
        ties += 1
    # Go all out on last round
    if alive == 2:
        return hp - 1
    opponent_hp = 100 - sum(history)
    if hp < 3:
        return 1
    elif not history:
        # randome number between 33
        return random.randint(33, 45)
    elif point > opponent_hp:
        # Never use more points then needed to win
        return opponent_hp + ties
    elif point >= hp:
        return hp - 1
    else:
        return point

Esistono alcuni robot che sfruttano esattamente questo comportamento, quindi potresti avere difficoltà a guadagnare trazione!
KBriggs

@KBriggs Ho fatto qualche aggiornamento, non mi aspettavo che la prima versione facesse altrettanto bene, si spera che questo aggiornamento offrirà una possibilità di combattimento ancora maggiore
meh Man

Wow, questo ha fatto una grande differenza, penso che tu sia il primo. L'aggiornamento verrà pubblicato tra un paio di minuti. Potrebbe essere necessario dare al tuo bot un sistema immunitario (vedi SarcomaBot) se continui a farlo bene.
KBriggs,

@KBriggs Non mi aspettavo di farlo bene, ho pensato nella migliore delle ipotesi che sarebbe la top 10. Comunque ne ho aggiunto un altro solo per vedere l'effetto al primo giro di HP. Riesci a eseguirli entrambi in modo che io possa vedere il risultato di entrambi? Grazie
meh Man

@KBriggs Per favore, fai anche questo, Muchas gracias
meh Man

4

Robbie Roulette

def robbie_roulette(hp, history, ties, alive):
     if history:
         #If the enemy bot has a history, and it's used the same value every time, outbid that value
         if len(set(history)) == 1:
             return history[0] + 1
         #Else, average the enemy bot's history, and bid one more than the average
         else:
             return (sum(history) / len(history) + 1)
     #Else, return half of remaining hp
     else:
         return hp / 2

Questo bot esegue una semplice analisi della storia del robot nemico, oppure offre la metà dei suoi punti ferita rimanenti in caso contrario


4

Fai offerte più alte meno concorrenza hai. Grazie ai commentatori per aver suggerito miglioramenti.

def Spreader(hp, history, ties, alive):
   if alive == 2:
       return hp-1
   if len(history) < 2:
       return hp/2
   return np.ceil(hp/alive)

1
Ottima idea, ma vedo due problemi. Uno è la maggior parte degli altri robot che fanno grandi offerte al primo turno, quindi probabilmente morirà presto per la maggior parte del tempo. Il secondo è che in finale, la maggior parte dei bot offre HP-1, quindi questo perderà quelli a meno che tu non abbia il doppio dei suoi HP. Ma per i turni intermedi mi piace l'idea. Se si affrontano i due casi speciali, probabilmente è possibile migliorare le prestazioni.
KBriggs,

4

SurvivalistBot e HalvsiesBot

Grazie per aver risposto alle mie domande. Il risultato finale è un bot più complesso.

HalvsiesBot è un capriccioso robot "continua a passare la metà" con una probabilità del 50/50 di vincere. Suppongo.

SurvivalistBot prende una serie di decisioni if-else di un albero binario basate sul set di dati, incluso un override su un pareggio (se colpisce 2 legami kamikaze per evitare la morte del triplo pareggio).

Il mio pitone è un po 'arrugginito, quindi il codice potrebbe essere un po' difettoso, quindi sentiti libero di correggerlo o aggiornarlo.

È costruito per cercare di elaborare bit di dati per dedurre cose come la quantità di HP rimasta, il numero minimo di bot che è probabile che combatta, la quantità minima di HP da lasciare, l'offerta media. Sfrutta anche la randomizzazione in situazioni ambigue, come l'apertura di giochi o problemi di offerta ottimali.

def HalvsiesBot(hp, history, ties, alive, start):
    return np.floor(hp/2)


def SurvivalistBot(hp, history, ties, alive, start):    

    #Work out the stats on the opponent
    Opponent_Remaining_HP = 100 - sum(history)
    Opponent_Average_Bid = Opponent_Remaining_HP

    if len(history) > 0:
        Opponent_Average_Bid = Opponent_Remaining_HP / float(len(history))


    HP_Difference = hp - Opponent_Remaining_HP

    #Work out the future stats on the others
    RemainingBots = (alive-2)
    BotsToFight = 0

    RemainderTree = RemainingBots

    #How many do we actually need to fight?
    while(RemainderTree > 1):
        RemainderTree = float(RemainderTree / 2)
        BotsToFight += 1

    #Now we have all that data, lets work out an optimal bidding strategy
    OptimalBid = 0
    AverageBid = 0

    #For some reason we've tied more than twice in a row, which means death occurs if we tie again
    #So better to win one round going 'all in'
    if ties > 1:
        if BotsToFight < 1:
            OptimalBid = hp - 1
        else:
            OptimalBid = hp - (BotsToFight+1)

        #Err likely we're 0 or 1 hp, so we just return our HP
        if OptimalBid < 1:
            return hp
        else:
            return OptimalBid

    #We have the upper hand (more HP than the opponent)
    if HP_Difference > 0:
        #Our first guess is to throw all of our opponent's HP at them
        OptimalBid = HP_Difference

        #But if we have more opponents to fight, we must divide our HP amongst our future opponents
        if BotsToFight > 0:
            #We could just divide our HP evenly amongst however many remaining bots there are
            AverageBid = OptimalBid / BotsToFight

            #But this is non-optimal as later bots will have progressively less HP
            HalfBid = OptimalBid / 2

            #We have fewer bots to fight, apply progressive
            if BotsToFight < 3:

                #Check it exceeds the bot's average
                if HalfBid > Opponent_Average_Bid:
                    return np.floor(HalfBid)
                else:
                    #It doesn't, lets maybe shuffle a few points over to increase our odds of winning
                    BidDifference = Opponent_Average_Bid - HalfBid

                    #Check we can actually match the difference first
                    if (HalfBid+BidDifference) < OptimalBid:
                        if BidDifference < 8:
                            #We add half the difference of the BidDifference to increase odds of winning
                            return np.floor(HalfBid + (BidDifference/2))
                        else:
                            #It's more than 8, skip this madness
                            return np.floor(HalfBid)

                    else:
                        #We can't match the difference, go ahead as planned
                        return np.floor(HalfBid)


            else:
                #There's a lot of bots to fight, either strategy is viable
                #So we use randomisation to throw them off!
                if bool(random.getrandbits(1)):
                    return np.floor(AverageBid)
                else:
                    return np.floor(HalfBid)

        else:
            #There are no other bots to fight! Punch it Chewy!
            return OptimalBid

    else:

        if hp == 100:
            #It appears to be our opening round (assumes opponent HP same as ours)
            #We have no way of knowing what our opponent will play into the battle

            #Only us in the fight? Full power to weapons!
            if BotsToFight < 1:
                return hp - 1
            else:
                #As what might happen is literally random
                #We will also be literally random
                #Within reason

                #Work out how many bots we need to pass
                HighestBid = hp - (BotsToFight+1)
                AverageBid = hp/BotsToFight
                LowestBid = np.floor(np.sqrt(AverageBid))

                #Randomly choose between picking a random number out of thin air
                #And an average
                if bool(random.getrandbits(1)):
                    return np.minimum(LowestBid,HighestBid)
                else:
                    return AverageBid

        else:
            #Oh dear, we have less HP than our opponent
            #We'll have to play it crazy to win this round (with the high probability we'll die next round)
            #We'll leave ourselves 1 hp (if we can)

            if BotsToFight < 1:
                OptimalBid = hp - 1
            else:
                OptimalBid = hp - (BotsToFight+1)

            #Err likely we're 0(???) or 1 hp, so we just return our HP
            if OptimalBid < 1:
                return hp
            else:
                return OptimalBid

BoxBot

def BoxBot(hp, history, ties, alive):

    Opponent_HP = float.round(100 - sum(history))
    HalfLife = float.round(Opponent_HP/2)
    RandomOutbid = HalfLife + np.random.randint(1,HalfLife)

    if hp < RandomOutbid:
        return hp - 1
    else
        return RandomOutbid

Opponent_Average_Bid = Opponent_Remaining_HP / float(len(history)) ZeroDivisionError: float division by zero. Questa riga deve gestire il caso della cronologia della lunghezza 0.
KBriggs,

Grazie, lo correggerò.
SSight3,

Fisso. Fammi sapere se ci sono altri errori.
SSight3,

1
Un paio di errori di sintassi: manca: `dopo else, math.[func] -> np.[func]e ad un certo punto si utilizza Lowestdove vuoi dire LowestBid. Tutto risolto nel controller su github e punteggi aggiornati a breve.
KBriggs,

Grazie. Risolti tutti i suddetti errori nel post.
SSight3,

4

Bot di calcolo

def calculatingBot(hp, history, ties, alive, start):
    opponentsHP = 100 - sum(history)
    if alive == 2: # 1v1
        return hp - 1 + ties
    # Try to fit an exponential trendline and one up the trendline if it fits
    if len(history) >= 3: 
        xValues = range(1, len(history) + 1)
        # https://stackoverflow.com/a/3433503  Assume an exponential trendline
        coefficients = np.polyfit(xValues, np.log(history), 1, w = np.sqrt(history))
        def model(coefficients, x):
            return np.exp(coefficients[1]) * np.exp(coefficients[0] * x)
        yPredicted = [model(coefficients, x) for x in xValues]
        totalError = 0
        for i in range(len(history)):
            totalError += abs(yPredicted[i] - history[i])
        if totalError <= (len(history)): # we found a good fitting trendline
            # get the next predicted value and add 1
            theoreticalBet = np.ceil(model(coefficients, xValues[-1] + 1) + 1) 
            theoreticalBet = min(theoreticalBet, opponentsHP)
            theoreticalBet += ties
            return int(min(theoreticalBet, hp - 1)) # no point suiciding
    maxRoundsLeft = np.ceil(np.log2(alive))
    theoreticalBet = hp / float(maxRoundsLeft)
    additionalRandomness = round(np.random.random()*maxRoundsLeft) 
    # want to save something for the future
    actualBet = min(theoreticalBet + additionalRandomness + ties, hp - 2)
    actualBet = min(actualBet, opponentsHP+1)
    return int(actualBet)

Bot di calcolo aggressivo

def aggresiveCalculatingBot(hp, history, ties, alive, start):
    opponentsHP = 100 - sum(history)
    if opponentsHP == 100: # Get past the first round
        return int(min(52+ties, hp-1+ties))
    if alive == 2: # 1v1
        return hp - 1 + ties
    # Try to fit an exponential trendline and one up the trendline if it fits
    if len(history) >= 3: 
        xValues = range(1, len(history) + 1)
        # https://stackoverflow.com/a/3433503  Assume an exponential trendline
        coefficients = np.polyfit(xValues, np.log(history), 1, w = np.sqrt(history))
        def model(coefficients, x):
            return np.exp(coefficients[1]) * np.exp(coefficients[0] * x)
        yPredicted = [model(coefficients, x) for x in xValues]
        totalError = 0
        for i in range(len(history)):
            totalError += abs(yPredicted[i] - history[i])
        if totalError <= (len(history)): # we found a good fitting trendline
            # get the next predicted value and add 1
            theoreticalBet = np.ceil(model(coefficients, xValues[-1] + 1) + 1) 
            theoreticalBet = min(theoreticalBet, opponentsHP)
            theoreticalBet += ties
            return int(min(theoreticalBet, hp - 1)) # no point suiciding
    maxRoundsLeft = np.ceil(np.log2(alive))
    theoreticalBet = hp / float(maxRoundsLeft)
    additionalRandomness = 1+round(np.random.random()*maxRoundsLeft*2) 
    # want to save something for the future
    actualBet = min(theoreticalBet + additionalRandomness + ties, hp - 2)
    actualBet = min(actualBet, opponentsHP+1)
    return int(actualBet)

Anti Kick Bot

def antiKickBot(hp, history, ties, alive, start):
    if alive == 2:
        return (hp - 1 + ties)
    amount = np.ceil((float(hp) / 2) + 1.5)
    opponentsHP = 100 - sum(history)
    amount = min(amount, opponentsHP) + ties
    return amount

Se siamo in grado di prevedere le azioni dell'avversario, possiamo fare le scommesse ottimali! Se non possiamo (non ci sono abbastanza dati o l'avversario è troppo casuale), allora possiamo almeno fare ciò che massimizzerebbe il nostro potenziale di vittoria. Teoricamente almeno la metà del numero di robot vivi morirà ogni round. Quindi posso aspettarmi che ci siano al massimo round di log2 (vivo). Idealmente, dovremmo dividere il nostro CV in modo uniforme tra tutti i round. Tuttavia, sappiamo che alcuni robot saranno stupidi e si suicideranno / moriranno presto, quindi dovremmo puntare leggermente di più nei round precedenti.

Aggressivo Calcolo del codice Calcolo del Bot di modifica del Bot per cercare di rimanere in vita essendo più aggressivo, a costo di salute a lungo termine. Solo le simulazioni diranno se il tempo o il valore vincono.

Anti Kick Bot dovrebbe sempre battere l'attuale leader KickBot: P

EDIT: Sostituito Bot deterministico con Anti Kick Bot, un robot più intelligente con quasi esattamente gli stessi valori di ritorno. Ha anche impedito di votare più degli HP avversari


Carina. Penso che questo andrà meglio con un pool di bot molto grande.
KBriggs

Ottengo un errore a volte con questo: return np.max(theoreticalBet, hp - 1): AxisError: axis 23 is out of bounds for array of dimension 0. Ho pubblicato un collegamento al controller in modo da poterlo testare.
KBriggs,

@KBriggs Aggiornato il codice per risolverlo.
Bob Cratchit,

1
confermato, aggiornamento del punteggio in arrivo. Sei tra i primi 10 di sicuro.
KBriggs,

@KBriggs Ho aggiunto un altro paio di robot da provare :)
Bob Cratchit,

4

GenericBot

def generic_bot(hp, history, ties, alive, start):
    if alive == 2:
        return hp - 1
    if not history:
        return int(hp * 7.0 / 13)
    opp = 100 - sum(history)
    if opp < hp:
        return opp + ties
    max_sac = np.maximum(int(hp * 0.7), 1)
    rate = history[-1] * 1.0 / (history[-1] + opp)
    return int(np.minimum(max_sac, rate * opp + 1))

È davvero tardi ... Sono stanco ... non riesco a pensare a un nome ... e il formato di questo bot è davvero simile agli altri, solo con un algoritmo leggermente diverso dato la storia. Cerca di ottenere il tasso attuale che l'avversario tende verso il gioco d'azzardo ... o qualcosa del genere ... zzz


è necessario utilizzare np.maximuminvece np.max, lo stesso permin
KBriggs

@KBriggs Grazie :) Hmm, sembra che i robot generici governino questo gioco
Quintec,

Sembra che sarebbero obiettivi abbastanza facili, sono sorpreso che nessuno abbia ancora fatto un parassita
KBriggs

@KBriggs Sì, sono sorpreso. È ora di aggiungere protezioni ...
Quintec,

Stai ancora pianificando di realizzare Neuralbot?
KBriggs

4

HalflifeS3

def HalflifeS3(hp, history, ties, alive, start):
    ''' Bet a half of oponent life + 2 '''
    if history:
        op_HP = 100 - sum(history)
        return np.minimum(hp-1, np.around(op_HP/2) + 2 + np.floor(1.5 * ties) )
    else:
        return hp/3

4

Coast Bot [Ritirato]

Proverà a superare la competizione dividendo uniformemente i suoi CV tra i round. Offrirà qualsiasi HP rimanente al primo round per darsi una migliore possibilità di arrivare ai round "in grado di costa".

def coast(hp, history, ties, alive, start):
   if alive == 2:
   # Last round, go all out
       return hp - 1 + ties
   else:
       # Find the next power of two after the starting number of players
       players = start
       while math.log(players, 2) % 1 != 0:
         players += 1

       # This is the number of total rounds
       rounds = int(math.log(players, 2))

       bid = 99 / rounds

       if alive == start:
           # First round, add our leftover hp to this bid to increase our chances
           leftovers = 99 - (bid * rounds)
           return bid + leftovers
       else:
           # Else, just try and coast

           opp_hp = 100 - sum(history)
           # If opponent's hp is low enough, we can save some hp for the 
           # final round by bidding their hp + 1
           return min(bid, opp_hp + 1)

Coast Bot V2

Dato che mi piace così tanto questa sfida, ho dovuto creare un altro robot. Questa versione sacrifica alcuni dei suoi successivi costeggiando HP usando più hp nei primi due round.

def coastV2(hp, history, ties, alive, start):
   # A version of coast bot that will be more aggressive in the early rounds

   if alive == 2:
   # Last round, go all out
       return hp - 1 + ties
   else:
       # Find the next power of two after the starting number of players
       players = start
       while math.log(players, 2) % 1 != 0:
         players += 1

       # This is the number of total rounds
       rounds = int(math.log(players, 2))

       #Decrease repeated bid by 2 to give us more to bid on the first 2 rounds
       bid = (99 / rounds) - 2

       if len(history) == 0:
           # First round, add 2/3rds our leftover hp to this bid to increase our chances
           leftovers = 99 - (bid * rounds)
           return int(bid + math.ceil(leftovers * 2.0 / 3.0))
       elif len(history) == 1:
           # Second round, add 1/3rd of our leftover hp to this bid to increase our chances
           leftovers = 99 - (bid * rounds)
           return int(bid + math.ceil(leftovers * 1.0 / 3.0))
       else:
           # Else, just try and coast

           opp_hp = 100 - sum(history)
           # If opponent's hp is low enough, we can save some hp for the 
           # final round by bidding their hp + 1
           return int(min(bid, opp_hp + 1))

Bot percentuale

Cerca di calcolare la percentuale media di HP spesa dall'avversario e fa offerte basate su quello.

def percent(hp, history, ties, alive, start):
    if len(history) == 0:
        #First round, roundon low bid
        return int(random.randint(10,33))
    elif alive == 2:
        #Last round, go all out
        return int(hp - 1 + ties)
    else:
        # Try and calculate the opponents next bid by seeing what % of their hp they bid each round
        percents = []
        for i in range(0, len(history)):
            hp_that_round = 100 - sum(history[:i])
            hp_spent_that_round = history[i]
            percent_spent_that_round = 100.0 * (float(hp_spent_that_round) / float(hp_that_round)) 
            percents.append(percent_spent_that_round)

        # We guess that our opponents next bid will be the same % of their current hp as usual, so we bid 1 higher.
        mean_percent_spend = sum(percents) / len(percents)
        op_hp_now = 100 - sum(history)
        op_next_bid = (mean_percent_spend / 100) * op_hp_now
        our_bid = op_next_bid + 1

        print mean_percent_spend
        print op_hp_now
        print op_next_bid

        # If our opponent is weaker than our predicted bid, just bid their hp + ties
        if op_hp_now < our_bid:
            return int(op_hp_now + ties)
        elif our_bid >= hp:
            # If our bid would kill us, we're doomed, throw a hail mary
            return int(random.randint(1, hp))
        else:
            return int(our_bid + ties)

Un'idea davvero interessante. Il licenziamento del primo round è una nuova tendenza nei bot e sembra funzionare abbastanza bene.
KBriggs

@KBriggs Ho aggiornato questa risposta per contenere il mio secondo tentativo. Menzionandoti secondo le nuove regole. Grande puzzle tra l'altro!
Wazz,

Vuoi che inserisca entrambi o solo l'ultima versione? In questo momento è solo V2
KBriggs

@KBriggs Vorrei che entrambi entrassero se va bene per favore. Sarebbe bello vedere come si contrappongono.
Wazz,

Prestazioni abbastanza simili nel complesso
KBriggs

4

ConsistentBot

Scommette lo stesso importo ogni round. Non è molto probabile che sopravviva ai primi turni, ma se è abbastanza fortunato da arrivare alla fine, dovrebbe ancora avere una quantità ragionevole di HP.

def consistent(hp, history, ties, alive, start):
    if alive == 2:
        return hp-1

    if 100 % start == 0:
        return (100 / start) - 1
    else: 
        return 100 / start

Whelp, è troppo tardi per risolverlo adesso, ma il mio bot ha usato abbastanza HP per arrivare alla fine di combattere ogni avversario una volta, non per arrivare all'ultimo round. Questo è il mio male: P
Kevin - Ripristina Monica l'

4

Kickban Bot

Questo bot cerca semplicemente di contrastare l'attuale leader Mean Kickbot battendolo nel round uno e giocando in modo più aggressivo da allora in poi se lo riconosce.

def kickban(hp, history, ties, alive, start):
    if alive == 2:
        return hp-1

    if not history:
        return 36

    if history[0]==35:
        somean = 1
    else:
        somean = 0

    return min(mean_kick(hp, history, ties, alive, start) + somean*3, hp-1)

1
Penso che il tuo rientro sia un po 'fuori.
Jonathan Frech,

oops, grazie, strano editor di codice ha rovinato la prima riga
HRSE

una preziosa lezione di fiducia nel codice che non controlli
OganM,

4

Bot di tre quarti

Non batterà MehBot o SarcomaBot (s), ma penso che lo faccia abbastanza bene. Quando ho visto la sfida per la prima volta, questa è stata la prima cosa che mi è venuta in mente, scommetti sempre * tre quarti della tua salute a meno che non ci sia motivo di farlo.

* dopo il lancio basso del primo turno.

def ThreeQuarterBot(hp, history, ties, alive, start):
    threeQuarters = 3 * hp / 4

    if alive == 2:
        return hp - 1

    opponent_hp = 100 - sum(history)

    if not history:
        # low-ball the first round but higher than (some) other low-ballers
        return 32 + ties
    elif threeQuarters > opponent_hp:
        return opponent_hp + ties

    return threeQuarters

Quattro settimi Bot

Dopo il moderato successo di 3/4 bot c'è una nuova frazione in città, è solo razionale.

def FourSeventhsBot(hp, history, ties, alive, start):
    fourSevenths = 4 * hp / 7

    if alive == 2:
        return hp - 1

    opponent_hp = 100 - sum(history)

    if not history:
        # low-ball the first round but higher than (some) other low-ballers
        return 33 + ties
    if fourSevenths > opponent_hp:
        return opponent_hp + ties

    return fourSevenths + ties

La frazione perfetta

Io sono intero

def ThePerfectFraction(hp, history, ties, alive, start):
    thePerfectFraction = 7 * hp / 13

    if alive == 2:
        return hp - 1

    opponent_hp = 100 - sum(history)

    if not history:
        # Need to up our game to overcome the kickers
        return 42 + ties
    if thePerfectFraction > opponent_hp:
        return opponent_hp + ties

    return thePerfectFraction + 1 + ties

Sulla base di queste probabilità di eliminazione, probabilmente potresti cavartela anche con offerte minori nel round 2. Questo fa bene, ma alcune piccole modifiche possono farlo molto meglio.
KBriggs,

@KBriggs Aggiunto un nuovo bot con probabilità nuove e migliorate;)
Joshua Webb,

Li vuoi entrambi o solo 1?
KBriggs,

@KBriggs Non so se ho perso la scadenza, ma ho aggiunto un bot finale, se l'ho fatto in tempo, puoi rimuovere gli altri due robot di frazioni
Joshua Webb,

1
Sì, hai ancora tempo
KBriggs,

4

BandaidBot

BandaidBot vuole che tutti giochino bene! Se il suo avversario è stato gentile nell'ultimo round, si sacrificherà per incentivare un comportamento piacevole negli altri. Se il suo avversario era cattivo nell'ultimo round, infliggerà più danni possibili all'avversario, sacrificando se stesso se necessario. Offre un terzo dei suoi hp se non ha una storia con cui lavorare. (Spero che questo bot abbia interessanti effetti a catena su altre strategie, non tanto che questo bot avrà un alto tasso di vincita stesso. Potrebbe essere divertente avere un paio di questi in gioco)

def BandaidBot(hp, history, ties, alive, start):
    if alive == 2:
        return hp-1

    if history:
        opp_hp = 100 - sum(history)
        opp_last_hp = 100 - sum(history[:-1])

        if history[-1] <= opp_last_hp / 3:
            return 1 + ties * np.random.randint(0, 1) 
        elif history[-1] > opp_last_hp / 2:
            return min(opp_hp - 1, hp)
        else:
            if history[-1] < hp/2:
                return np.random.randint(history[-1], hp/2)
            else:
                return np.floor(hp/2)
    else:
        return np.floor(hp/3)

GetAlongBot

GetAlongBot sarà altrettanto bello di quanto deve essere per sfruttare BandaidBot. Restituirà poco meno di un terzo dei suoi CV a meno che non possa uccidere il suo avversario per meno di quello. Se il suo avversario assomiglia a BandaidBot, farà 2, sapendo che BandaidBot farà 1 perché GetAlongBot sta andando molto d'accordo con tutti gli altri - una vittoria facile purché fosse davvero BandaidBot dall'altra parte.

def GetAlongBot(hp, history, ties, alive, start):
    if alive == 2:
        return hp-1

    if history:
        opp_hp = 100 - sum(history)
        opp_last_hp = 100 - sum(history[:-1])
        count = 0
        for i in range(0, len(history)):
            hp_that_round = 100 - sum(history[:i])
            hp_spent_that_round = history[i]
            if hp_that_round / 3 - 1 <= hp_spent_that_round <= hp_that_round / 2:
                count += 1
        if count == len(history): #It's probably BandaidBot!
            return 2
        else:
            return min(opp_hp - 1, np.floor(hp/3))
    else:
        return np.floor(hp/3)

Idea davvero ordinata. Mi chiedo quanto impatto avrà
KBriggs il

errore: return np.random.randint(history[-1], hp/2): ValueError: low >= highquesto caso deve essere gestito in qualche modo
KBriggs

@KBriggs dovrebbe essere risolto ora!
Maya Sol,

@KBriggs aggiornato per correggere la randomizzazione
Maya Sol

3

Bot TENacious

def TENacious_bot(hp, history, ties, alive, start):
  max_amount=hp-(alive-1)*2;
  if max_amount<2: max_amount=2

  if alive==2: return hp-1
  if ties==0: return np.minimum(10, max_amount)
  if ties==1: return np.minimum(20, max_amount)
  if ties==2: return np.minimum(40, max_amount)
  # prevent function blowup
  return 2

Questo bot cerca di mantenere il suo valore preferito di 10, ma cambia la sua scelta di tanto in tanto se necessario per rompere un pareggio (con il suo valore preferito raddoppiato o quadruplicato) o per salvare per round futuri, ma non per quantità ottimale perché vuole confondere avversari e non vuole prendere in considerazione l'offerta di meno di 2 in qualsiasi momento poiché è convinto che sia molto meglio che sperare che l'avversario offra meno di 1, cioè 0.

PS: questo bot potrebbe avere problemi strategici se ci sono più di 2 ^ 9 bot.


Sospetto che non ti debba preoccupare di avere 2 ^ 9 avversari ^ _ ^.
KBriggs

Ma con una puntata iniziale di 10, raramente
riuscirà a

Questo bot pensa che, se qualche bot vuole davvero dare più di 10 CV nel primo round, non vale la pena combattere.
AlexRacer,

Haha abbastanza giusto
KBriggs

3

CautiousBot

Prima presentazione ai Puzzle di programmazione di sempre! La tua sfida è stata molto interessante: P

Se l'ultimo round ha dato un bit in meno di HP, se nessuna cronologia ha scommesso metà HP più un piccolo importo casuale.

Se la cronologia controlla i CV avversari e il numero di round rimanenti e prova a superare i CV avversari usando un buffer aggiuntivo fino alla frazione dei CV rimanenti divisa per il numero di round rimanenti (cerca di conservare in qualche modo i CV rimanenti per i round posteriori) . Controlla se stai spendendo troppo hp (non uccidere te stesso o fare offerte superiori a quelle che il tuo avversario può).

Correggi sempre i legami come fanno altri robot.

def cautious_gambler(hp, history, ties, alive, start):
    if alive == 2:
        return hp - 1
    if(history):
        opp_hp = 100 - sum(history)
        remaining_rounds = np.ceil(np.log2(start)) - len(history)

        start_bet = opp_hp / 2
        buff = int((hp - start_bet)/remaining_rounds if remaining_rounds > 0 else (hp - start_bet)) 
        buff_bet = np.random.randint(0, buff) if buff > 0 else 0
        bet = start_bet + buff_bet + ties

        if bet >= hp or bet > opp_hp:
            bet = np.minimum(hp - 1, opp_hp)

        return int(bet)
    else:
        start_bet = hp / 2
        rng_bet = np.random.randint(3,6)

        return int(start_bet + rng_bet + ties)

CautiousBot2

Troppo aggressivo nei primi round, ora CautiousBot diventa ancora più cauto ...

def cautious_gambler2(hp, history, ties, alive, start):
    if alive == 2:
        return hp - 1
    if(history):
        opp_hp = 100 - sum(history)
        remaining_rounds = np.ceil(np.log2(start)) - len(history)

        start_bet = opp_hp / 2
        buff = int((hp - start_bet)/remaining_rounds if remaining_rounds > 0 else (hp - start_bet)) 
        buff_bet = np.random.randint(0, buff) if buff > 0 else 0
        bet = start_bet + buff_bet + ties

        if bet >= hp or bet > opp_hp:
            bet = np.minimum(hp - 1, opp_hp)

        return int(bet)
    else:
        start_bet = hp * 0.35
        rng_bet = np.random.randint(3,6)

        return int(start_bet + rng_bet + ties)

Si dispone di un bug in cui è ancora chiamando randint quando il buffer = 0: buffer_bet = np.random.randint(0, buffer) if buffer > 0 else 0 File "mtrand.pyx", line 993, in mtrand.RandomState.randint ValueError: low >= high. Nota che il buffer è una parola chiave in Python, potresti voler scegliere un nome di variabile diverso.
KBriggs

Oh, sembra che sia perché il buffer non è sempre un int - probabilmente ti dividi per zero ad un certo punto. Si prega di controllare attentamente la logica. L'ho fatto funzionare, ma probabilmente puoi sistemare i casi angolari.
KBriggs

Bella cattura @KBriggs. Penso di averlo risolto.
Jesús Ros,

Ho ancora un errore: buff_bet = np.random.randint(0, buff) if buff > 0 else 0 File "mtrand.pyx", line 993, in mtrand.RandomState.randint ValueError: low >= high. Sembra che il buff sia a volte un numero in virgola mobile compreso tra 0 e 1, che presumibilmente viene lanciato su 0 all'interno randint. Questo funziona se si esegue il cast buffa intprima della chiamata
KBriggs

@KBriggs probabilmente perché ceilrestituisce a float. Perso quello ... Di nuovo Ty: P
Jesús Ros,

3

Bene, ci proverò.

SnetchBot

Controllando le frazioni di salute con cui l'avversario stava andando. Se l'avversario ha rilanciato, battilo su di esso.

def snetchBot(hp, history, ties, alive, start):
    if alive == 2:
        return hp-1

    opponent_hp = 100
    history_fractions = []
    if history:
        for i in history:
            history_fractions.append(float(i)/opponent_hp)
            opponent_hp -= i
        if opponent_hp <= hp/2:
            #print "Squashing a weakling!"
            return opponent_hp + (ties+1)/3

        average_fraction = float(sum(history_fractions)) / len(history_fractions)
        if history_fractions[-1] < average_fraction:
            #print "Opponent not raising, go with average fraction"
            next_fraction = average_fraction
        else:
            #print "Opponent raising!"
            next_fraction = 2*history_fractions[-1] - average_fraction
        bet = np.ceil(opponent_hp*next_fraction) + 1
    else:
        #print "First turn, randomish"
        bet = np.random.randint(35,55)

    if bet > opponent_hp:
        bet = opponent_hp + (ties+1)/3
    final_result = bet + 3*ties
    if bet >= hp:
        #print "Too much to bet"
        bet = hp-1
    return final_result

EDIT: perdere molto nel primo turno, aggiustato i limiti casuali del primo turno


Primo colpo abbastanza buono, aggiornamento punteggio in arrivo
KBriggs

@KBriggs Modificato un po '(solo i limiti casuali del primo round). Anche se ero già sorpreso di essere alto come il 10 ° posto. Se questo va peggio, torno indietro al primo: D
prendi il

Gli
spremi

3

SquareUpBot

Non mi sembrava che molti robot stessero giocando con poteri anziché frazioni, quindi ho deciso di crearne uno, con alcune ottimizzazioni standard e vedere dove piazzerò. Abbastanza semplicistico.

Cerca anche di determinare se il bot nemico non sta cercando di usare una frazione costante, perché poteri > frazioni .

EDIT: Sono un manichino e il mio rilevatore di frazione non ha funzionato. Riparato ora.

def squareUp(hp, history, ties, alive, start):

    #Taken from Geometric Bot
    opponentHP = 100 - sum(history)

    # Need to add case for 1
    if hp == 1:
        return 1

    # Last of the last - give it your all
    if alive == 2:
        if ties == 2 or opponentHP < hp-1:
            return hp - 1

    #Calculate your bet (x^(4/5)) with some variance
    myBet = np.maximum(hp - np.power(hp, 4./5), np.power(hp, 4./5))
    myBet += np.random.randint(int(-hp * 0.05) or -1, int(hp * 0.05) or 1);
    myBet = np.ceil(myBet)
    if myBet < 1:
        myBet = 1
    elif myBet >= hp:
        myBet = hp-1
    else:
        myBet = int(myBet)

    #If total annihilation is a better option, dewit
    if opponentHP < myBet:
        if ties == 2:
            return opponentHP + 1
        else:
            return opponentHP

    #If the fraction is proven, then outbid it (Thanks again, Geometric bot)
    if history and history[0] != history[-1]:
        health = 100
        fraction = float(history[0]) / health
        for i,x in enumerate(history):
            newFraction = float(x) / health
            if newFraction + 0.012*i < fraction or newFraction - 0.012*i > fraction:
                return myBet
            health -= x
        return int(np.ceil(opponentHP * fraction)) + 1    
    else:
        return myBet

Non è un brutto colpo, i punteggi sono stati aggiornati
KBriggs

@KBriggs Ho aggiornato il bot in modo che il rilevatore di frazioni funzioni davvero.
Diamond Dust,
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.