Robot Roulette: le jeu robotisé aux enjeux élevés


56

Classement final

+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +
| Nom | Score | WinRate | TieRate | Probabilité d'élimination |
+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +
| 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. pourcentageBot | 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]% |
+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +

Merci à tous ceux qui ont participé et félicitations à @Sarcome pour cette victoire!

Règles:

Tout le monde commence avec 100 ch. À chaque tour, deux joueurs sont choisis au hasard dans le groupe de concurrents qui n’ont pas encore participé à ce tour. Les deux joueurs choisissent un nombre compris entre 0 et leur CV actuel et les révèlent en même temps. Le joueur qui a choisi le nombre inférieur meurt immédiatement. L'autre joueur soustrait le nombre qu'ils ont choisi de la valeur restante et continue au tour suivant.

Le tournoi fonctionne comme ceci:

Parmi les participants, 2 sont choisis au hasard. Ils s'affrontent et l'un ou l'autre meurt. Un joueur meurt si:

  1. Ils choisissent un nombre inférieur à celui de leur adversaire
  2. Leur ch tombe à zéro ou moins
  3. Ils sont à égalité trois fois de suite avec leur adversaire

En cas d'égalité, les deux joueurs génèrent simplement de nouveaux numéros, jusqu'à 3 fois. Après la mise au jeu, le survivant (le cas échéant) est déplacé vers la piscine pour la ronde suivante et le processus se répète jusqu'à ce que nous ayons épuisé la piscine de la ronde actuelle. S'il y a un nombre impair dans la piscine, alors l'intrus passe au tour suivant gratuitement.

Votre tâche consiste à écrire une fonction dans python2.7 qui prend en entrée votre hpoffre actuelle , une liste de l’enchère de votre adversaire historyet un entier tiesvous indiquant le nombre de fois que vous avez déjà lié votre adversaire actuel, ainsi qu’un entier indiquant comment. beaucoup de bots sont encore alive(y compris vous), et un nombre entier qui indique le nombre de bots au starttournoi. Notez que l'historique n'inclut pas les liens. La fonction doit renvoyer un entier compris entre 0 et votre total de CV actuel. Quelques exemples simples, qui ignorent les liens, sont présentés ci-dessous:

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)

Si votre fonction retourne un nombre supérieur à votre HP, il sera remis à 0. Oui, il est possible de se tuer. Votre fonction ne doit pas tenter d'accéder ou de modifier un membre d'un objet de la classe RouletteBot. Vous n'êtes pas autorisé à prendre des mesures qui identifient sans ambiguïté votre adversaire indépendamment de futurs robots supplémentaires. Il est permis d’inspecter la pile tant qu’il est théoriquement possible que plus d’un adversaire distinct ait pu produire les informations que l’on en tire, même s’il n’existe actuellement qu’un seul bot. En d'autres termes, vous ne pouvez pas simplement lire dans la pile pour voir quelle fonction ennemie a été appelée.

Selon ces règles, il est possible qu’il n’y ait pas de vainqueur et que les deux derniers concurrents s’entretuent. Dans ce cas, les deux finalistes obtiennent un demi-point chacun.

Ceci est ma première tentative de programmation, les critiques sont les bienvenues!

Le contrôleur peut être trouvé ici .


4
FWIW, je prévois d’utiliser un réseau de neurones formé sur tous les autres robots juste pour le fun une fois que vous aurez configuré le contrôleur :)
Quintec

2
La vérification de type était au profit de antiantiantiantiupyoursbot. Je trouverai un autre moyen
KBriggs

3
@ Sarcoma On dirait que cette compétition a déclenché une guerre du code sérieuse. Cette compétition n’est pas terminée, mais je suis déjà impatient d’évoluer. Peut-être même que la prochaine étape, la concurrence renforcée par l'IA: P
Chaîne de Markov

3
WOOOOOOOOOOOOOO!
Sarcome

5
Oh mon Dieu. La tentative délibérée de changer le mean_kick pour toujours renvoyer zéro quand il a été utilisé tant de lieux est brillante.
Magua

Réponses:


12

BinaryBot

Est-ce que quelqu'un a déjà fait ça? Mises la moitié de sa santé à chaque tour.

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

SarcomaBot

Si la dernière bataille a offert HP - 1. Si c'est la première fois, une enchère plus un demi-HP plus un montant aléatoire supplémentaire allant jusqu’à un quart de HP. S'il parvient à battre un adversaire enchéri sur une offre après cet enchère, l'adversaire gagne + 1 PV. Si sa santé est inférieure à celle de l'adversaire, le montant au hasard est compris entre 75% et sa valeur actuelle - 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

Des modifications mineures tentent de réduire les dépenses de la vie.

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

Mettre à jour le réglage fin

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

Entrée 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

Mise à jour de la
protection UpYoursBot ajoutée

Mise à jour de la
protection AntiAntiUpYoursBot ajoutée

Mettre à jour
AntiAnitAntiAntiUpYoursBot Je suis vaincu


Les commentaires ne sont pas pour une discussion prolongée; cette conversation a été déplacée pour discuter .
Mego

17

UpYours

Étant en retard pour entrer, j'ai passé un moment à admirer les robots existants, à compliquer un peu les idées de vos gars, puis à les simplifier. Puis il m'est venu

Les bons artistes copient les grands artistes volent. - Pablo Picasso Me


"Up Yours" parce que je vole sans vergogne (et, parfois, je pointe un ou deux points sur les offres de vos robots pour en augmenter un).

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

Mais pour de vrai, c'est une excellente compétition les gars. J'aime cette communauté des jours comme celui-ci.


1
Hahahaha c'est beau. Je suis indécis si je devais le permettre, mais je le laisserai jouer pour l'instant car je ne pensais pas dire que ce n'était pas permis. Les noms de fonction sont erronés à quelques endroits - voir le contrôleur sur github.
KBriggs

1
C'est très bien, évidemment, mais on perd toujours contre Kick Bot
KBriggs

1
Ha, bon effort!
Sarcome

1
@Sarcome Je n'aurais pas pu le faire sans vous. ;) J'aime beaucoup ton bot aussi, mon pote.
Qfwfq

1
La protection Upyoursbot de Sarcomabot a vraiment foiré avec celle-ci
KBriggs

15

Kamikaze

Pourquoi s'embêter avec une logique compliquée quand on va tous mourir de toute façon ...

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


Un tir

Il va survivre au moins un tour s'il ne rencontre pas le kamikaze.

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

11
Welp, c'était inévitable
KBriggs

J'allais aussi ajouter un bot pacifiste, mais je ne veux pas submerger votre défi avec des robots cérébraux
DobromirM

5
Après quelques tests rapides, le bot kamikaze n’a pas beaucoup changé. Il élimine au hasard un autre bot du tour, ce qui, sur un nombre suffisant de tournois, est en moyenne égal à zéro. Le chaud est soigné, cependant. Sans ce dernier, mon AverageBot a tendance à faire de son mieux - mais s'il y a quelques OneShots en jeu, fait pencher la moyenne vers la moyenne et fait en sorte que les AverageBots meurent rapidement. Même chose pour LastBot. Vous pouvez vraiment jouer avec le comportement des autres robots en modifiant vos habitudes de pari. Avec OneShot en jeu, RandomBot gagne. Sans lui, AverageBot gagne.
KBriggs

14

Pathetic Bot obtient une mise à niveau indispensable:

La tentative pathétique d'un bot qui tente d'intégrer les fonctionnalités des autres robots

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

Ce bot incorpore les fonctionnalités de Survivalist Bot et Geometric Bot pour des traitements plus efficaces.

Pré-mise à niveau:

La tentative pathétique d'un bot qui analyse l'histoire de son adversaire

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

S'il y a des antécédents de son adversaire, il calcule alors la puissance de son adversaire. Ensuite, il effectue l'une des opérations suivantes:

  • Si son adversaire est le dernier adversaire en vie, il en offrira une de moins que sa puissance.
  • Si son adversaire n'est pas le dernier adversaire en vie mais que l'adversaire a moins de 16 ch, il surenchérira alors sur les HP de son adversaire.
  • Si son adversaire n'est pas le dernier adversaire en vie et qu'il y a une histoire de liens, il fera une offre à son ch, car il s'ennuie de liens.
  • Sinon, il surenchérira sur son adversaire.

S'il n'y a pas d'histoire, alors il effectue des calculs sophistiqués que j'ai piratés ensemble et enchérit. Si la valeur est supérieure à 100, il enchérit automatiquement son hp moins 1.

J'ai piraté ce code pendant le travail et c'est ma première soumission, donc il ne gagnera probablement pas ou quoi que ce soit, et il perdra face aux kamikazes.

EDIT: En raison de certaines suggestions, le comportement du bot au début a été modifié pour offrir une valeur plus élevée.

EDIT 2: ajout du paramètre start qui ne fait rien

EDIT 3: Ajout d'un nouveau robot dérivant:

[La tentative pathétique d'un bot qui attaque des Gang Bots (en plus de faire tout ce que le bot ci-dessus fait)] Supprimé

[Ce bot analyse si son adversaire est un gangbot ou non et prétend l'être aussi pour obtenir les offres les plus basses qu'il puisse surpasser facilement.]

Ce bot a été supprimé, veuillez le supprimer des classements.

EDIT 4: Erreurs corrigées, fonction de lien modifiée.


Très bien, merci pour le bot! Je donnerai quelques statistiques quand j'en aurai quelques autres.
KBriggs

Je suis novice chez Python, donc je ne suis pas sûr que la syntaxe soit correcte, n'hésitez pas à me le faire savoir si cela se produit
Yodie

Ça fonctionne, donc pas d'inquiétude
KBriggs

@Yodie En tant que révision de code: Votre corps de fonction doit être mis en retrait par un niveau (nécessité syntaxique); opp_hp +1manque un espace pour être pythonique; vos commentaires commencent par des quantités non équilibrées d'espaces. Enfin, votre fonction manque d'une docstring.
Jonathan Frech

2
Je pense que ce bot réussit assez bien s'il passe le premier tour, mais parce que beaucoup de gens parient gros sur le premier tour, il meurt presque toujours tôt. Vous pouvez améliorer les performances en modifiant le comportement initial en augmentant les enchères lorsqu'il n'y a pas d'historique. Par exemple, si vous triplez votre pari sans historique, ce bot gagne par une marge confortable parmi les concurrents jusqu'à présent.
KBriggs

11

Bot bot

Le choix sonore pour mon adversaire est de miser la moitié de sa vie. Ensuite, nous enchérissons jusqu'à la moitié de sa vie + 1 si nous ne pouvons pas le sortir avec une enchère solide, c'est une offre inférieure à la moitié de notre vie.

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

Le bot bot est évidemment la Némésis du bot bot!

Bot bot moyen

Ce nouveau KickBot est plus doux au premier tour, il sera donc plus fort lors des prochains rounds, c’est méchant!

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

Bot sage bot

Son frère a dû se suicider tous les deux mais WiseKickBot a appris de ceux qui étaient tombés au combat.

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

Agréable. Je vois beaucoup de propositions qui
contredisent

Double retour sur la dernière ligne?
Veskah

Ah, je ne l'avais pas encore fait ou j'aurais compris ça.
KBriggs

Celui-ci a pris une avance confortable!
KBriggs

1
@KBriggs voici une sauvegarde!
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)

Une tentative d’équivalent d’un bot tit-à-tat. Suppose que la plupart des paris sont approximativement les mêmes entre les tours. En utilisant cette hypothèse, il essaie de vaincre le bot ennemi tout en restant assez frugal. Dépense environ 40 points de vie au premier tour.

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

Une solution de contournement pour la protection anti-UpYours de SarcomaBot, reprenant l'essentiel de son code pour mon propre usage! Ou est-ce que je prends le code de UpYoursBot? Une question à méditer pendant que vous lisez mon bot ...

AntiAntiUpYours Bot a évolué pour devenir AntiAntiAntiAntiUpYours Bot! Maintenant, avec plus de singe-patcher.

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) 

Poly bot effectue une régression polynomiale sur l'historique de votre bot et bat légèrement le score prévu.

Bot chic

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)

Classy bot a passé un bon moment, mais a décidé de se coucher tôt. Sommeil serré, bot chic.


Les commentaires ne sont pas pour une discussion prolongée; cette conversation a été déplacée pour discuter .
Mego

8

1/2 Punch Bot, revisité

Je pense que ça va mourir assez vite. Ça vaut le coup. Fonction renommée, j'ai oublié de changer le nom ici.

La version revisitée est en hausse, meilleures chances de gagner (encore plus lors de la ronde finale) et légère protection contre les gang bots

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 a trop été victime d'intimidation et est même devenu un laquais de UpYoursBot, alors son frère aîné, le StrikerBot , est venu l'aider.

Ce n'est pas si différent du 1/2 Punch optimisé, mais il est un peu plus intelligent et a bien réussi dans les manches que j'ai faites (10k et 35k, bien qu'il pourrait perdre contre KickbanBot)

La dernière version est terminée, le temps est écoulé. À moins que des surprises ne se manifestent, il devrait assurer la deuxième place, sinon le premier but (il y a une mince chance de battre 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

Vous devrez le renommer, il existe déjà un bot kamikaze ^ _ ^
KBriggs

Jusqu'à présent, celui-ci est le gagnant
KBriggs

Votre fonction ceilsemble ne pas être définie.
Jonathan Frech

J'ai changé pour np.ceil () pour l'exécuter
KBriggs

édité, merci pour le heads-up
Belhenix

7

Gang Bot

L'idée était que potentiellement deux ou plus du bot pourraient être utilisés dans la même simulation. Le bot tente de donner des "gains faciles" aux autres robots du gang, en vérifiant si son historique est un multiple de 7 offres. Bien sûr, cela pourrait aussi être facilement manipulé par d'autres robots. Ensuite, je calcule une estimation des offres des bots ne faisant pas partie de gangs sur la base du ratio de mon état de santé sur le leur et de leur état de santé précédent sur leur enchère précédente, en ajoutant 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

Très cool. Combien sont nécessaires? Je vais probablement devoir
limiter

Votre bloc de code semble manquer la première ligne de votre source.
Jonathan Frech

Je ne sais pas combien de temps il faudrait dans une simulation, mais si l'un des robots se voyait, il devrait augmenter les chances de gagner. J'imagine que 10% de la population constituée de gang bots devrait suffire à faire une différence significative. De plus, le bloc de code manque la première ligne -> c'est mon premier post ici, je ne sais pas pourquoi le formatage l'a fait mais oui, c'est juste la déclaration de la méthode.
Jim Hat

Vous avez un bug: le bot identifiera toute personne ayant len ​​(historique)> 1 en tant que membre d'un gang
KBriggs

Mon mauvais, devrait être corrigé maintenant.
Jim Hat

6

Pire cas

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

Bot simple. Dans la hp - hp / (start - alive + 4)plupart des cas, les retours et, en cas d'égalité, l'augmentent de 2 (il en faut un!) Pour chaque égalité, en veillant à ne pas renvoyer de numéro par dessus hp.


Cela échoue avec une division par zéro si alive==8. Je peux modifier manuellement le nombre total de bot, mais cela élargit les règles car ce n'est pas une entrée pour votre fonction - vous savez si combien d'adversaires il vous reste à un moment donné, pas combien vous avez démarré.
KBriggs

J'ai mis à jour le concours en fonction de votre demande
KBriggs

@KBriggs Thanks :)
Quintec

Vous devez également ajouter 1 à start-alive, car il s'agit de 0 pour le premier tour
KBriggs

@KBriggs corrigé, devrait en fait +2 pour qu'il ne retourne pas 0, lol
Quintec

6

Surenchère

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 tentera de faire une offre supérieure à celle de son adversaire, dans la mesure du possible.


Il y a une condition where np.random.randint(hp/5, hp/2)peut échouer si hp/5 == hp/2, c'est-à-dire si hp==0ouhp==1
KBriggs

3
Si HP est égal à 0, je ne devrais pas être appelé. : P Vous avez raison à propos de HP 1 cependant.
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

Elle juge quelle quantité de santé elle devrait sacrifier en fonction du nombre de robots restants. S'il ne reste plus que deux robots, il enchérira hp-1, mais s'il en reste trois, la moitié, quatre, un troisième, etc.

Cependant, dans un très gros concours, je pense que je devrai miser plus de 3 ou 4 ch pour éviter de mourir au premier tour. J'ai donc fixé la limite inférieure à 10. Bien sûr, je ne miserai toujours pas plus que hp-1.

Il ajoute également 1,5 cv pour les cravates, car je vois plusieurs bots "ajouter 1 cv pour les cravates". Je ne sais pas si cela compte pour la triche. Si c'est le cas, je le changerai.

Excellente idée, au fait!

Spitball Bot 2.0

Quoi de neuf?

  • Passage à la division par le nombre de tours restants au lieu du nombre de robots restants (Merci à @Heiteira!). En fait, je divise maintenant par ce nombre élevé de puissance .8, afin de charger un peu plus mes offres.

  • Augmentation de l'enchère minimum de 10 à 20 (Merci @KBriggs!)

  • Insertion vérifie si l'enchère de spitball est au-dessus du PV actuel de l'adversaire, et l'abaissez si c'est le cas.

(SO ne rendra pas le code ci-dessous en tant que code, sauf si je mets du texte ici, alors 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
Votre enchère doit être un entier. Par conséquent, tant que vous fixez ou plafonnez votre valeur de base pour vous débarrasser de la virgule décimale, c'est bien
KBriggs

Oui, je le répare juste après avoir fait tous les calculs. Merci pour la réponse rapide!
MegaWidget

2
Vous pourrez peut-être optimiser cela si vous ne divisez pas votre CV par le nombre de concurrents restants, mais par le nombre de rounds restants (qui devrait être math.ceil (math.log (alive, 2))
Black Owl Kai

1
Sur la base d'autres robots, la plupart d'entre eux semblent avoir une offre en amont, cela pourrait donc s'améliorer si vous augmentez l'enchère du premier tour au-dessus de 10
KBriggs

Ce sont deux bonnes idées! Je n'avais pas réalisé que le nombre de bot n'était pas le même que le nombre de tours restants (j'ai mal interprété le règlement du concours au début). Je vais essayer de les implémenter demain. Merci!
MegaWidget

5

Géométrique

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ème place du premier essai, pas mal du tout
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

Essayez de maximiser les gains avec le moins d’effort:

  • si nous pouvons gagner, il suffit de le faire
  • si c'est le dernier tour, ne meurs pas en essayant
  • sinon, ne vous embêtez pas

Pourquoi?

Essayez de tirer parti de la probabilité: gagner le premier tour en jouant le plus bas est la meilleure façon de commencer le tournoi. 13 semble être le bon choix: le deuxième tour est une victoire assurée, et le reste est un Spaziergang dans le parc.


Vous avez pris les devants, très gentil! Faites attention, vous voudrez peut-être ajouter une protection contre les parasites, car les bots qui prennent les devants deviennent des cibles pour des choses comme UpYoursBot. Consultez SarcomaBots pour des idées de protection si vous en avez besoin.
KBriggs

5

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

Première publication ici. Cela semblait très amusant, alors je soumets ma terrible tentative et je devine ce que les autres robots parieront.

Edit 1: Ajout d'un autre 1 au premier pari, simplement pour réduire le risque d'égalité avec d'autres personnes qui parient 51.

Edit 2: Stole Le coup d'envoi du Sarcoma bot puisqu'il avait de bonnes chances de ne pas être éliminé en premier.

Edit 3: Bot survit très bien au premier tour, mais il est facilement détruit à un stade ultérieur. Changement de la façon dont le robot pense au deuxième tour maintenant que les demi-parieurs sont morts dans l'eau.

Edit 4: Maintenant que le premier tour est bon, j'ai changé la façon dont il gère le second tour. Mourir beaucoup au second tour donc je dois survivre.

Sang bot

Fait un bot assoiffé à la recherche d'une tuerie. L'idée est d'essayer de gagner contre les bots à faible pari et qu'après le bain de sang du premier tour, il devrait être impossible de l'arrêter, car il devrait avoir des quantités énormes de HP pour surenchérir sur ses ennemis.

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
Je pense que len (histoire) * len (histoire) pourrait être changé en len (histoire) ** 2 si ma connaissance de python est correcte.
Yodie

Vous avez une division par zéro pour quand len (historique) == 0
KBriggs

Le code a été mis à jour. Ne trouvant aucune histoire, il passe à la première option
Markov Chained,

oi .............
Sarcome

2
@Sarcome c'est un monde de bot acéré!
Markov enchaîné

5

meh_bot

Juste enchérir un peu plus de la moitié de ses 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

Il existe de nombreux robots qui tirent exactement parti de ce comportement. Vous aurez donc peut-être du mal à vous en sortir!
KBriggs

@KBriggs Fait une mise à jour, je ne m'attendais pas à ce que la première version soit aussi performante, espérons-le, cette mise à jour lui donnera une chance de se battre plus
meh Man

Wow, cela a fait une grande différence, je pense que vous êtes en premier. La mise à jour sera publiée dans quelques minutes. Vous devrez peut-être doter votre bot d'un système immunitaire (voir SarcomaBot) si vous continuez à le faire correctement.
KBriggs

@KBriggs Je ne m'attendais pas à bien faire cela, je pensais qu'au mieux ce serait le top 10. Quoi qu'il en soit, j'en ai ajouté un autre juste pour voir l'effet du premier tour hp. Pouvez-vous les exécuter tous les deux afin que je puisse voir le résultat des deux? Merci
meh Man

@KBriggs S'il vous plaît, faites-le également, 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

Ce bot effectue une analyse simple de l'historique du bot ennemi ou offre la moitié de ses points de vie restants, sinon


4

Enchérissez plus le moins de concurrence que vous avez. Merci aux commentateurs d’avoir suggéré des améliorations.

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
Bonne idée, mais je vois deux problèmes. L’un est la plupart des autres robots gros au premier tour, alors celui-ci mourra probablement tôt la plupart du temps. La seconde est que dans la finale, la plupart des robots misent sur hp-1, donc celui-ci les perdra sauf si vous avez le double de leur hp. Mais pour les rondes intermédiaires, j'aime bien l'idée. Si vous abordez les deux cas particuliers, vous pourrez probablement améliorer les performances.
KBriggs

4

SurvivalistBot et HalvsiesBot

Merci d'avoir répondu à mes questions. Le résultat final est un bot plus complexe.

HalvsiesBot est un robot fantaisiste qui «passe juste la moitié» avec une chance sur 50/50 de gagner. Je suppose.

SurvivalistBot prend une série de décisions d'arborescence binaire if-else basées sur l'ensemble de données, y compris une dérogation sur une égalité (si elle atteint 2 liaisons, les kamikazes évitent la mort par triple liaison).

Mon python est un peu rouillé, le code peut donc être un peu buggé, alors n'hésitez pas à le corriger ou le mettre à jour.

Il a été conçu pour essayer de manipuler des données afin de déduire des informations telles que le nombre de HP restants, le nombre minimum de robots qu’il est susceptible de combattre, le nombre minimum de HP à quitter, les enchères moyennes. Il exploite également la randomisation dans des situations ambiguës, telles que des jeux d'ouverture ou des enchères optimales.

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. Cette ligne doit gérer le cas d’historique 0 longueur.
KBriggs

Merci, je vais le corriger.
SSight3

Fixé. Faites-moi savoir s'il y a d'autres erreurs.
SSight3

1
Couple d'erreurs de syntaxe: manquant: `après else, math.[func] -> np.[func]et à un moment donné que vous utilisez Lowestoù vous voulez dire LowestBid. Tous corrigés dans le contrôleur sur github et les scores mis à jour sous peu.
KBriggs

Merci. Correction de toutes les erreurs susmentionnées dans l'article.
SSight3

4

Calcul Bot

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 calculateur agressif

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

Si nous pouvons prédire les actions de l'adversaire, nous pouvons faire les paris optimaux! Si nous ne pouvons pas jouer (pas assez de données ou d’opposants, c’est trop aléatoire), nous pouvons au moins faire ce qui maximiserait notre potentiel de gain. Théoriquement, au moins la moitié des robots vivants mourront à chaque tour. Je peux donc m'attendre à ce qu'il y ait au plus log2 (en vie) rounds. Idéalement, nous répartirions notre CV uniformément entre tous les tours. Cependant, nous savons que certains robots seront stupides et se suicideront / mourront tôt, nous devrions donc miser un peu plus lors des tours précédents.

Agressif Calculating Le code de calcul de Bot modifié pour tenter de rester en vie en étant plus agressif, au détriment de la santé à long terme. Seules les simulations diront si le tempo ou la valeur l'emporte.

Anti Kick Bot devrait toujours battre le leader actuel KickBot: P

EDIT: Remplacé Déterministic Bot par Anti Kick Bot, un bot plus intelligent avec presque exactement les mêmes valeurs de retour. Également empêché de voter plus que les opposants HP


Mignonne. Je pense que celui-ci fera mieux avec un très grand pool de bot.
KBriggs

Je reçois une erreur parfois avec celui - ci: return np.max(theoreticalBet, hp - 1): AxisError: axis 23 is out of bounds for array of dimension 0. J'ai posté un lien vers le contrôleur afin que vous puissiez le tester.
KBriggs

@KBriggs Mis à jour le code pour le réparer.
Bob Cratchit

1
confirmé, mise à jour du score entrant. Vous êtes dans le top 10 à coup sûr.
KBriggs

@KBriggs J'ai ajouté quelques autres robots à essayer :)
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))

Il est vraiment tard ... je suis fatigué ... je ne trouve pas de nom ... et le format de ce bot est vraiment similaire aux autres, avec un algorithme légèrement différent étant donné l'historique. Il essaie d'obtenir le taux actuel de l'adversaire vers le jeu ... ou quelque chose comme ça ... zzz


vous devez utiliser np.maximumau lieu de np.max, idem pourmin
KBriggs

@KBriggs Merci :) Hmm, il semble que les bots génériques dominent ce jeu
Quintec

On dirait qu'ils seraient des cibles assez faciles, je suis surpris que personne n'ait encore fait de parasite
KBriggs

@KBriggs Oui, je suis surpris. Il est temps d'ajouter des protections ...
Quintec

Vous envisagez toujours de faire 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 [À la retraite]

Je vais essayer de surmonter la concurrence en divisant équitablement sa puissance entre les rondes. Soumettra tout HP restant au premier tour pour se donner une meilleure chance de se qualifier pour les tours "côtes".

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

Comme j'aime tellement ce défi, je devais créer un autre bot. Cette version sacrifie une partie de ses derniers chevaux en utilisant plus de chevaux dans les deux premiers tours.

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

Pourcentage Bot

Essaie de calculer le pourcentage moyen de dépenses que l'adversaire dépense en HP, et offre en conséquence.

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)

Idée assez cool. Sacking le premier tour est une nouvelle tendance chez les bots, et il semble fonctionner assez bien.
KBriggs

@KBriggs J'ai mis à jour cette réponse afin qu'elle contienne ma deuxième tentative. En vous mentionnant selon les nouvelles règles. Grand puzzle d'ailleurs!
Wazz

Voulez-vous que j'entre les deux, ou juste la dernière version? En ce moment, c'est juste V2
KBriggs

@KBriggs J'aimerais que les deux soient entrés si ça vous va, s'il vous plaît. Ce serait bien de voir comment ils se comparent.
Wazz

Performance assez similaire dans l'ensemble
KBriggs

4

ConsistentBot

Mises le même montant à chaque tour. Il n’est pas très probable que les premiers tours survivent, mais s’il a la chance d’arriver au bout, il lui restera encore une quantité raisonnable de PV.

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, il est trop tard pour régler le problème, mais mon bot a utilisé suffisamment de HP pour pouvoir combattre jusqu'à la fin de chaque adversaire et non pour se rendre au dernier round. C'est mon mauvais: P
Kevin - Réintégrer Monica

4

Kickban Bot

Ce bot essaie simplement de contrer le leader actuel, Mean Kickbot, en le battant au premier tour et en jouant plus agressivement par la suite s’il le reconnaît.

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
Je pense que votre indentation est un peu en retrait.
Jonathan Frech

oups, merci, étrange éditeur de code décoiffé avec la première ligne
HRSE

une leçon précieuse dans le code de confiance que vous ne contrôlez pas
OganM

4

Trois-quart Bot

Il ne va pas battre MehBot ou SarcomaBot (s), mais je pense qu'il s'en sort plutôt bien. Quand j’ai vu le défi pour la première fois, c’était la première chose qui me vint à l’esprit: pariez toujours les trois quarts de votre santé à moins d’y avoir aucune raison de le faire.

* après le début du premier tour.

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

Quatre Sept Sept

Après le succès modéré de 3/4 bot, il y a une nouvelle fraction en ville, ce n'est que rationnel.

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 fraction parfaite

Je suis entier

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

Sur la base de ces probabilités d'élimination, vous pourrez probablement vous en tirer avec des offres plus petites au tour 2 également. Celui-ci fait bien, mais quelques ajustements mineurs peuvent le rendre beaucoup mieux.
KBriggs

@KBriggs Ajout d'un nouveau bot avec de nouvelles cotes améliorées;)
Joshua Webb

Vous voulez les deux là-bas, ou juste 1?
KBriggs

@KBriggs Je ne sais pas si j'ai raté la date limite, mais j'ai ajouté un dernier bot. Si je l'ai fait à temps, vous pouvez supprimer les deux autres bots de fraction
Joshua Webb

1
Oui, vous avez encore le temps
KBriggs

4

BandaidBot

BandaidBot veut que tout le monde joue bien! Si son adversaire était gentil au dernier tour, il se sacrifiera pour inciter un comportement gentil chez les autres. Si son adversaire était méchant au dernier tour, il fera autant de dégâts que possible à son adversaire, en se sacrifiant si nécessaire. Il offre un tiers de ses CV s'il n'a pas d'historique à travailler. (J'espère que ce bot aura des effets d'entraînement intéressants sur d'autres stratégies, pas tellement que ce bot aura un taux de victoire élevé. Il pourrait être amusant d'avoir deux de ces stratégies en jeu)

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 sera aussi agréable que nécessaire pour profiter de BandaidBot. Il retournera un peu moins du tiers de sa puissance à moins de pouvoir tuer son adversaire pour moins que cela. Si son adversaire ressemble à BandaidBot, il enchérira 2, sachant que BandaidBot enchérira 1 car GetAlongBot s'entend si bien avec tout le monde - une victoire facile tant que BandaidBot se trouve à l'autre bout.

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)

Vraiment belle idée. Je me demande quel impact cela aura
KBriggs

erreur: return np.random.randint(history[-1], hp/2): ValueError: low >= highcette affaire doit être traitée d'une manière ou d'une autre
KBriggs

@KBriggs devrait être corrigé maintenant!
Maya Sol

@KBriggs mis à jour pour corriger la randomisation
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

Ce bot tente de conserver sa valeur favorite de 10, mais il change parfois de choix s'il le faut pour briser l'égalité (avec sa valeur favorite doublée ou quadruplée) ou pour épargner en vue des prochains rounds, mais pas de manière optimale car il veut confondre et ne veut pas envisager d’enchérir à moins de 2 à tout moment, persuadé que c’est bien mieux que d’espérer que son adversaire enchérisse moins de 1, c’est-à-dire 0.

PS: ce bot peut avoir des problèmes stratégiques s’il ya plus de 2 ^ 9 robots.


Je suppose que vous n'avez pas à craindre d'avoir 2 ^ 9 adversaires ^ _ ^.
KBriggs

Mais avec un pari d'ouverture de 10, il va rarement passer le premier tour
KBriggs

Ce bot pense que si un bot veut vraiment donner plus de 10 CV au premier tour, il ne vaut pas la peine de se battre.
AlexRacer

Haha assez juste
KBriggs

3

CautiousBot

Première soumission à la programmation Puzzles jamais! Vous avez trouvé votre défi assez intéressant: P

Si le dernier tour est un peu inférieur à HP, si aucun historique ne parie, un demi-HP plus une petite quantité aléatoire.

Si l'historique vérifie la puissance de l'adversaire et le nombre de rounds restants et tente de surenchérir sur l'adversaire hp / 2 en utilisant un tampon supplémentaire pouvant aller jusqu'à la fraction de hp restante divisé par le nombre de rounds restants (il essaie de conserver le hp restant d'une manière ou d'une autre pour les rounds postérieurs). . Vérifiez si vous dépensez trop de CV (ne vous tuez pas et ne faites pas plus que votre adversaire).

Corrigez toujours pour les liens comme les autres robots.

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

Trop agressif lors des premiers tours, CautiousBot devient de plus en plus prudent ...

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)

Vous avez un bug où il appelle encore randint lorsque le tampon = 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. Notez que tampon est un mot clé en python, vous pouvez choisir un nom de variable différent.
KBriggs

Oh, on dirait que c'est parce que le tampon n'est pas toujours un int - vous divisez probablement par zéro à un moment donné. S'il vous plaît vérifier la logique attentivement. Je l'ai fait fonctionner, mais vous pouvez probablement résoudre les problèmes de coin.
KBriggs

Belle prise @KBriggs. Je pense que j'ai résolu le problème.
Jesús Ros

Je reçois encore une erreur: buff_bet = np.random.randint(0, buff) if buff > 0 else 0 File "mtrand.pyx", line 993, in mtrand.RandomState.randint ValueError: low >= high. Il semble que buff soit parfois un nombre à virgule flottante compris entre 0 et 1, qui est probablement attribué à 0 à l'intérieur randint. Cela fonctionne si vous lancez buffà intavant l'appel
KBriggs

@KBriggs probablement parce que ceilretourne un float. A raté celui-là ... Ty encore: P
Jesús Ros

3

Bon, je vais essayer ma main à ceci.

SnetchBot

Vérifier les fractions de santé avec lesquelles l'adversaire s'est rendu. Si l'adversaire a été relancé, battez-le.

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: perdre beaucoup au premier tour, ajusté les limites aléatoires du premier tour


Très bon premier coup, mise à jour du score entrant
KBriggs

@KBriggs Edité un peu (seulement les limites aléatoires du premier tour). Bien que j'étais déjà surpris d'être aussi haut que la 10ème place. Si celui-ci fait pire, je vais revenir au premier: D
snetch

Tu lui
sers

3

SquareUpBot

Il ne semblait pas que beaucoup de robots jouaient avec des pouvoirs au lieu de fractions, alors j'ai décidé d'en créer un, avec quelques optimisations standard et de voir où je placerais. Assez simpliste.

Essaie également de déterminer si le bot ennemi n'essaie pas d'utiliser une fraction constante, car puissances > fractions .

EDIT: Je suis un mannequin et mon détecteur de fraction ne pourrait pas fonctionner. Réparé maintenant.

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

Pas mal comme premier coup, les scores ont été mis à jour
KBriggs

@KBriggs J'ai mis à jour le bot pour que le détecteur de fraction fonctionne réellement.
Diamond Dust
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.