Robot Roulette: hazard z wysokimi stawkami

56

Klasyfikacja końcowa

+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +
| Imię | Wynik | WinRate | TieRate | Prawdopodobieństwo eliminacji |
+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +
| 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]% |
+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +

Dziękujemy wszystkim, którzy wzięli udział i gratulujemy @Sarcoma wygranej!

Zasady:

Każdy zaczyna od 100 KM. W każdej rundzie 2 graczy wybiera się losowo z puli zawodników, którzy jeszcze nie brali udziału w tej rundzie. Obaj gracze wybierają liczbę od 0 do ich aktualnego HP i ujawniają te liczby jednocześnie. Gracz, który wybrał niższą liczbę, natychmiast umiera. Drugi gracz odejmuje wybraną liczbę od pozostałego HP i przechodzi do następnej rundy.

Turniej działa w następujący sposób:

Z grupy zawodników wybiera się 2 losowo. Stają twarzą w twarz i jedno lub oba z nich giną. Gracz umiera, jeśli:

  1. Wybierają liczbę mniejszą niż liczba przeciwnika
  2. Ich HP spada do lub poniżej zera
  3. Wiążą się trzy razy z rzędu z przeciwnikiem

W przypadku remisów obaj gracze po prostu generują nowe liczby, nawet 3 razy. Po starciu, który przeżył (jeśli w ogóle), zostaje przeniesiony do puli na następną rundę, a proces ten powtarza się, aż wyczerpiemy obecną pulę rund. Jeśli w puli znajduje się nieparzysta liczba, nieparzysta przechodzi do następnej rundy za darmo.

Twoim zadaniem jest napisanie funkcji w python2.7, która przyjmuje jako dane wejściowe twój prąd hp, listę licytacji przeciwnika historyoraz liczbę całkowitą, tiesktóra mówi ci, ile razy już łączyłeś się z twoim obecnym przeciwnikiem, oraz liczbę całkowitą, która mówi ci jak wiele botów jest nadal alive(w tym ty), oraz liczba całkowita, która podaje liczbę botów w startturnieju. Pamiętaj, że historia nie obejmuje powiązań. Funkcja musi zwracać liczbę całkowitą między 0 a bieżącym całkowitym hp. Kilka prostych przykładów, które ignorują powiązania, pokazano poniżej:

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)

Jeśli twoja funkcja zwróci liczbę większą niż twoje hp, zostanie zresetowana do 0. Tak, możesz się zabić. Twoja funkcja nie może próbować uzyskiwać dostępu ani modyfikować żadnego elementu dowolnego obiektu klasy RouletteBot. Nie wolno podejmować żadnych działań, które jednoznacznie identyfikują przeciwnika, niezależnie od przyszłych dodatkowych botów. Sprawdzanie stosu jest dozwolone, o ile teoretycznie jest możliwe, że więcej niż jeden wyraźny przeciwnik mógł wygenerować informacje, które z niego czerpiesz, nawet jeśli obecnie istnieje tylko jeden bot, który mógłby. tzn. nie możesz po prostu przeczytać stosu, aby zobaczyć, która funkcja wroga została wywołana.

Zgodnie z tymi zasadami możliwe jest, że nie ma zwycięzcy, a dwóch ostatnich zawodników zabija się nawzajem. W takim przypadku obaj finaliści otrzymują po pół punktu.

To moja pierwsza próba układania puzzli, więc krytyka jest mile widziana!

Kontroler można znaleźć tutaj .

KBriggs
źródło
4
FWIW, planuję użyć sieci neuronowej wyszkolonej na wszystkich innych
botach
2
Kontrola typu miała na celu zastosowanie antyantiantiantiupyoursbot. Znajdę inny sposób
KBriggs
3
@ Sarcoma Wygląda na to, że ta konkurencja wywołała poważną wojnę kodową. Konkurs się nie zakończył, ale już nie mogę się doczekać jego ewolucji. Może nawet następny krok, wzmocniona konkurencja AI: P
Markov przykuty
3
WOOOOOOOOOOOOOOOO!
Mięsak
5
O mój Boże. Umyślne trollowanie zmieniającego mean_kick, aby zawsze zwracał zero, gdy było używane w tak wielu miejscach, jest genialne.
Magua

Odpowiedzi:

12

BinaryBot

Czy ktoś już to zrobił? Obstawia połowę swojego zdrowia w każdej rundzie.

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

SarcomaBot

Jeśli ostatnia bitwa oferuje hp - 1. Jeśli jest to pierwsza runda bitwy, licytuj pół HP plus dodatkową losową kwotę do jednej czwartej hp Jeśli uda mu się pokonać bezpośrednią ofertę przeciwnika po tym, licytuje przeciwnika o HP + 1. Jeśli ma mniej zdrowia niż przeciwnik, licytuje losowo między 75% a jego obecnym 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

Drobne poprawki poprawiają wydatki na życie.

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

Zaktualizuj dostrojenie

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

Ostateczne wejście

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


Dodano aktualizację UpYoursBot


Dodano aktualizację ochrony AntiAntiUpYoursBot

Zaktualizuj
AntiAnitAntiAntiUpYoursBot Jestem pokonany

Mięsak
źródło
Komentarze nie są przeznaczone do rozszerzonej dyskusji; ta rozmowa została przeniesiona do czatu .
Mego
17

UpYours

Spóźniając się na wejście, spędziłem trochę czasu podziwiając istniejące boty, spędziłem trochę czasu na komplikowaniu pomysłów twoich facetów, a następnie na ich komplikowaniu. Potem przyszło mi do głowy

Dobrzy artyści kopiują, świetni artyści kradną. - Pablo Picasso Me


„Up Your Yours”, ponieważ bezwstydnie kradnę (i czasami przypinam punkt lub dwa do stawek twoich botów, aby je podnieść).

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

Ale tak naprawdę to świetna konkurencja. Uwielbiam tę społeczność w takie dni.

Qfwfq
źródło
1
Hahahaha, to jest piękne. Nie jestem zdecydowany, czy powinienem na to pozwolić, ale na razie pozwolę mu grać, ponieważ nie pomyślałem, że to niedozwolone. W kilku miejscach masz błędne nazwy funkcji - zobacz kontroler na github.
KBriggs
1
Oczywiście robi to bardzo dobrze, ale wciąż przegrywa z Kick
Botem
1
Ha, dobry wysiłek!
Sarcoma
1
@ Sarcoma Nie zrobiłbym tego bez ciebie. ;) Naprawdę lubię też twojego bota, kolego.
Qfwfq,
1
Ochrona Upyoursbot Sarcomabota naprawdę zadziera z tym
KBriggs
15

Kamikadze

Po co zawracać sobie głowę skomplikowaną logiką, skoro i tak wszyscy umrzemy ...

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


Jeden strzał

Przetrwa przynajmniej jedną rundę, jeśli nie napotka kamikadze.

 def one_shot(hp, history, ties, alive):
      if hp == 1:
          return 1
      else:
          return hp - 1
DobromirM
źródło
11
Welp, to było nieuniknione
KBriggs
Zamierzałem także dodać pacyfistycznego bota, ale nie chcę zalać twojego wyzwania botami martwymi
DobromirM,
5
Opierając się na szybkich testach, bot kamikaze nie zmienił wiele - wystarczy, że losowo usunie innego bota z rundy, co w wystarczającej liczbie turniejów po prostu uśrednia do zera. Jednak jeden gorący jest schludny. Bez tego mój AverageBot zwykle robi najlepiej, ale jeśli w grze jest kilka OneShotów, zmienia średnią w kierunku dużych liczb i powoduje, że AverageBoty szybko umierają. To samo dla LastBot. Możesz naprawdę zadzierać z zachowaniem innych robotów, wypaczając własne wzorce obstawiania. Z OneShot w grze, RandomBot wygrywa. Bez niego AverageBot wygrywa.
KBriggs,
14

Żałosny bot otrzymuje bardzo potrzebne ulepszenie:

Żałosna próba bota, który próbuje wykorzystać cechy innych botów

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

Ten bot zawiera funkcje Survivalist Bot i Geometric Bot w celu skuteczniejszej eliminacji botów.

Przed aktualizacją:

Żałosna próba bota, który analizuje historię przeciwnika

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

Jeśli istnieje wcześniejsza historia przeciwnika, wówczas oblicza jego HP. Następnie wykonuje jedną z następujących czynności:

  • Jeśli jego przeciwnik jest ostatnim żyjącym przeciwnikiem, wówczas licytuje o jeden mniej niż HP.
  • Jeśli jego przeciwnik nie jest ostatnim żyjącym przeciwnikiem, ale ma mniej niż 16 KM, wtedy przebije jego HP.
  • Jeśli jego przeciwnik nie jest ostatnim żyjącym przeciwnikiem i istnieje historia remisów, wtedy licytuje on swoje HP, ponieważ znudzi się remisami.
  • W przeciwnym razie przebije przeciwnika.

Jeśli nie ma historii, wykonuje kilka fantazyjnych obliczeń, które razem zhakowałem i licytuje to. Jeśli wartość przekracza 100, to automatycznie licytuje swoje hp minus 1.

Zhakowałem ten kod razem podczas pracy i jest to moje pierwsze zgłoszenie, więc prawdopodobnie nie wygra ani nic, a przegra z kamikadze.

EDYCJA: Z powodu niektórych sugestii początkowe zachowanie bota zostało zmienione, aby zaoferować wyższą wartość.

EDYCJA 2: dodano parametr początkowy, który nic nie robi

EDYCJA 3: Dodano nowego bota spinoff:

[Żałosna próba bota atakującego Gang Boty (a także robienie wszystkiego, co robi powyższy bot)] USUNIĘTO

[Ten bot analizuje, czy jego przeciwnikiem jest gangbot, czy nie, i udaje, że jest jednym z nich, aby uzyskać słodkie niskie stawki, które może łatwo pokonać.]

Ten bot został złomowany, usuń go z tabel wyników.

EDYCJA 4: Naprawiono błędy, zmieniono funkcję remisu.

Jodie
źródło
Bardzo fajnie, dzięki za bota! Dam kilka statystyk, kiedy otrzymam jeszcze kilka.
KBriggs,
Jestem nowicjuszem w Pythonie, więc nie jestem pewien, czy składnia jest poprawna, daj mi znać, jeśli tak się stanie
Yodie
Działa, więc nie martw się
KBriggs
@Yodie Jako przegląd mini kodu: ciało funkcji powinno być wcięte poziomem (konieczność składniowa); opp_hp +1brakuje spacji, aby być pytonicznym; Twoje komentarze zaczynają się od niezrównoważonych ilości białych znaków. Wreszcie, w twojej funkcji brakuje dokumentacji.
Jonathan Frech,
2
Myślę, że ten bot radzi sobie całkiem nieźle, jeśli przejdzie przez pierwszą rundę, ale ponieważ tak wielu ludzi stawia duże zakłady, pierwsza runda prawie zawsze umiera wcześnie. Możesz poprawić wydajność, zmieniając początkowe zachowanie, aby licytować wyżej, gdy nie ma historii. Na przykład, jeśli potroisz swój zakład bez historii, ten bot wygrywa o wygodną przewagę wśród dotychczasowych zawodników.
KBriggs,
11

Kick Bot

Dobrym wyborem dla mojego przeciwnika jest licytacja połowy jego życia. Następnie licytujemy do połowy jego życia + 1, jeśli nie możemy go wyliczyć z dźwiękiem, czyli mniej niż połowa naszego życia.

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

Bot-bot jest oczywiście nemezis bota-bota!

Mean Kick Bot

Ten nowy KickBot kopie bardziej miękko w pierwszej rundzie, aby mógł mocniej kopać w następnych rundach, to znaczy!

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

Obaj jego brat musiał popełnić samobójstwo, ale WiseKickBot nauczył się od swoich poległych.

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))
Johan
źródło
Miły. Widzę teraz wiele zgłoszeń, które bezpośrednio przeciwstawiają się innym, właśnie na to
liczyłem
Podwójny powrót do ostatniej linii?
Veskah
Ach, jeszcze go nie uruchomiłem, inaczej bym to złapał.
KBriggs
Ten zajął wygodną pozycję!
KBriggs
1
@KBriggs tutaj jest trochę kopii zapasowej!
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)

Próba stworzenia odpowiednika bota tit-for-tat. Zakłada, że ​​większość zakładów jest w przybliżeniu taka sama między rundami. Przyjmując to założenie, próbuje pokonać wroga bota, pozostając dość oszczędny. Wydaje około 40 zdrowia w rundzie otwarcia.

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

Obejście dla ochrony anty-UpYours SarcomaBot, wykasowanie większości ich kodu na własny użytek! A może pobieram kod UpYoursBot? Pytanie do przemyślenia podczas czytania mojego bota ...

AntiAntiUpYours Bot ewoluował i stał się AntiAntiAntiAntiUpYours Bot! Teraz z większą łatką małp.

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 dokonuje regresji wielomianowej w historii twojego bota i nieznacznie przewyższa przewidywany wynik.

Classy bot

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)

Z klasą bot dobrze się bawił, ale postanowił wcześnie położyć się spać. Śpij spokojnie, elegancki robot.

Osoba
źródło
Komentarze nie są przeznaczone do rozszerzonej dyskusji; ta rozmowa została przeniesiona do czatu .
Mego
8

1/2 Poncz Bot, ponownie odwiedzony

Myślę, że umrze dość szybko. Warto było. Zmieniono nazwę funkcji, zapomniałem zmienić tam nazwę.

Nowa wersja jest gotowa, większe szanse na wygraną (tym bardziej w ostatniej rundzie) i niewielka ochrona przed botami gangów

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 został zbyt mocno prześladowany, a nawet stał się lokajem UpYoursBot, więc jego starszy brat, StrikerBot , przyszedł mu z pomocą.

Nie ma dużej różnicy od zoptymalizowanego 1/2 Puncha, ale jest nieco mądrzejszy i dobrze sobie radził w biegach, które zrobiłem (10k i 35k, choć może przegrać z KickbanBotem)

Ostatnia wersja minęła, czas się skończył. O ile nie pojawią się jakieś niespodzianki, powinno zapewnić sobie drugie miejsce, jeśli nie zdobycie pierwszego (istnieje niewielka szansa na pokonanie kickbanbota)

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
Belhenix
źródło
Musisz go zmienić, jest już bot kamikaze ^ _ ^
KBriggs
Jak dotąd ten jest zwycięzcą
KBriggs
Twoja funkcja ceilwydaje się nie być zdefiniowana.
Jonathan Frech
Zmieniłem na np.ceil (), aby go uruchomić
KBriggs
edytowane, dzięki za heads-up
Belhenix
7

Gang Bot

Pomysł polegał na tym, że potencjalnie dwa lub więcej botów może być wykorzystanych w tej samej symulacji. Bot próbuje „łatwo wygrywać” innym botom w gangu, sprawdzając, czy jego historia to wielokrotność 7 ofert. Oczywiście mogą to łatwo manipulować także inne boty. Następnie obliczam liczbę trafień botów nie gangowych na podstawie stosunku mojego zdrowia do ich i stosunku ich wcześniejszego zdrowia do poprzedniej oferty i dodam 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
Jim Hat
źródło
Bardzo fajny. Ile potrzeba? Prawdopodobnie będę musiał ograniczyć liczbę wpisów ...
KBriggs
Wygląda na to, że w bloku kodu brakuje pierwszego wiersza źródła.
Jonathan Frech
Nie jestem pewien, ile będzie potrzebnych w symulacji, ale jeśli któryś z botów kiedykolwiek się zobaczy, powinien zwiększyć szansę na wygraną jednego z nich. Domyślam się, że 10% puli to boty gangów, które powinny wystarczyć, aby zrobić znaczącą różnicę. Także w bloku kodu brakuje pierwszego wiersza -> to jest mój pierwszy post tutaj Nie wiem, dlaczego formatowanie to zrobiło, ale tak, to tylko deklaracja metody.
Jim Hat
Masz błąd: bot zidentyfikuje każdego z len (historia)> 1 jako członka gangu
KBriggs
Mój zły, powinien być teraz naprawiony.
Jim Hat
6

Najgorszy przypadek

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

Prosty bot. Zwraca hp - hp / (start - alive + 4)w większości przypadków, a w przypadku remisów zwiększa go o 2 (muszę jeden do góry!) Za każdy remis, upewniając się, że nie zwróci liczby nad nim hp.

Quintec
źródło
Nie powiedzie się to, jeśli dzielimy przez zero alive==8. Mogę ręcznie zmienić go na całkowitą liczbę botów, ale to rozciąga reguły, ponieważ nie jest to wkład w twoją funkcję - wszystko, co wiesz, jeśli ilu przeciwników opuściłeś w danym momencie, a nie przeciwko ilu zacząłeś.
KBriggs,
Zaktualizowałem konkurs na podstawie Twojej prośby
KBriggs
@KBriggs Thanks :)
Quintec
Musisz również dodać 1, aby rozpocząć życie, ponieważ jest to 0 dla pierwszej rundy
KBriggs
@KBriggs naprawione, faktycznie powinno +2, więc nie zwraca 0, lol
Quintec
6

Outbidder

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 będzie próbował licytować wyżej, niż jego przeciwnik może licytować tam, gdzie to możliwe.

Draco18s
źródło
Istnieje warunek, który where np.random.randint(hp/5, hp/2)może się nie powieść, jeśli hp/5 == hp/2, tj. Jeśli hp==0lubhp==1
KBriggs
3
Jeśli HP wynosi 0, nie powinienem się wzywać. : P Masz jednak rację co do HP 1.
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

Ocenia, ile zdrowia powinien poświęcić na podstawie liczby pozostałych botów. Jeśli pozostały tylko dwa boty, licytuje hp-1, ale jeśli pozostały trzy, to bity w połowie, cztery w lewo, trzeci itd.

Jednak w bardzo dużym konkursie uważam, że będę musiał licytować więcej niż 3 lub 4 KM, aby uniknąć śmierci w pierwszej rundzie, więc ustawiłem dolną granicę na 10. Oczywiście, nigdy nie będę licytować więcej niż hp-1.

Dodaje również 1,5 KM dla remisów, ponieważ widzę kilka botów „dodaj 1 hp dla remisów”. Nie jestem pewien, czy liczy się to jako oszustwo. Jeśli tak, zmienię to.

Nawiasem mówiąc, świetny pomysł!

Spitball Bot 2.0

Co nowego?

  • Przełączono na dzielenie przez liczbę pozostałych rund zamiast liczby botów (dzięki @Heiteira!). Właściwie dzielę teraz przez liczbę podniesioną do potęgi .8, aby trochę bardziej załadować moje oferty.

  • Zwiększono minimalną ofertę z 10 do 20 (Dzięki @KBriggs!)

  • Wstawiono sprawdzanie, czy stawka spitball jest wyższa od aktualnego HP przeciwnika, i obniża go, jeśli tak jest.

(SO nie wyświetli poniższego kodu jako kodu, chyba że wstawię tutaj tekst, więc 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
MegaWidget
źródło
1
Twoja oferta powinna być liczbą całkowitą, więc tak długo, jak doliczasz lub podnosisz swoją wartość bazową, aby pozbyć się dziesiętnego, jest OK
KBriggs
Tak, układam podłogę zaraz po wykonaniu wszystkich obliczeń. Dziękuję za szybką odpowiedź!
MegaWidget
2
Być może uda Ci się to zoptymalizować, jeśli nie dzielisz swojego hp przez liczbę pozostałych uczestników, ale przez liczbę pozostałych rund (które powinny być matematycznie (mat.log (żywy, 2))
Black Owl Kai
1
W oparciu o inne boty większość z nich wydaje się ładować z przodu, więc może się to poprawić, jeśli podniesiesz stawkę w pierwszej rundzie powyżej 10
KBriggs
To są dobre pomysły! Nie zdawałem sobie sprawy, że liczba botów nie jest taka sama jak liczba pozostałych rund (na początku źle zinterpretowałem zasady konkursu). Spróbuję je wdrożyć jutro. Dzięki!
MegaWidget
5

Geometryczny

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)
Mnemoniczny
źródło
5 miejsce przy pierwszej próbie, wcale nie takie złe
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

Spróbuj zmaksymalizować wygrane przy najmniejszym wysiłku:

  • jeśli możemy wygrać, po prostu zrób to
  • jeśli to ostatnia runda, nie umieraj próbując
  • w przeciwnym razie nie zawracaj sobie głowy

Dlaczego?

Spróbuj wykorzystać prawdopodobieństwo: najlepszym sposobem na rozpoczęcie turnieju jest wygranie pierwszej rundy, grając na niskim poziomie. 13 wydaje się być ulubionym miejscem: druga runda jest pewną wygraną, a reszta to Spaziergang w parku.

GB
źródło
Przejęłeś inicjatywę, bardzo dobrze! Bądź ostrożny, możesz dodać ochronę przed pasożytami, ponieważ boty, które przejmują prowadzenie, stają się celem takich rzeczy jak UpYoursBot. Sprawdź SarcomaBots, aby znaleźć pomysły na ochronę, jeśli ich potrzebujesz.
KBriggs,
5

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

Pierwszy post tutaj. Wyglądało to na dobrą zabawę, więc poddaję się mojej strasznej próbie i zgaduję, co postawią inne boty.

Edycja 1: Dodano kolejną 1 do pierwszego zakładu, po prostu w celu zmniejszenia szansy na remis z innymi zakładami 51.

Edycja 2: Ruch otwierający bota Sarcoma, ponieważ miał dużą szansę, że nie zostanie wyeliminowany jako pierwszy konsekwentnie.

Edycja 3: Bot przeżywa bardzo dobrze w pierwszej rundzie, ale na późniejszych etapach jest łatwo niszczony. Zmieniono sposób, w jaki robot myśli o drugiej rundzie, gdy połowa graczy jest martwa w wodzie.

Edycja 4: Teraz, gdy pierwsza runda jest dobra, zmieniłem sposób, w jaki obsługuje drugą rundę. Dużo umiera w drugiej rundzie, więc muszę jakoś przetrwać.

Blood Bot

Zrobił spragnionego bota szukającego zabójstwa. Chodzi o to, aby spróbować wygrać z botami o niskich stawkach, a kiedy minie krwawa pierwsza runda, powinna być nie do powstrzymania, ponieważ powinna mieć ogromne ilości HP, aby prześcignąć wrogów.

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)
Łańcuch Markowa
źródło
2
Myślę, że len (historia) * len (historia) można zmienić na len (historia) ** 2, jeśli moja znajomość języka Python jest poprawna.
Yodie
Dzielisz
Kod został zaktualizowany. Nie znajdując historii, przechodzi do pierwszej
Markov Chained
oi .............
Mięsak
2
@ Sarcoma, to jest porywczy świat botów, człowieku!
Markov przykuty
5

meh_bot

Postaw tylko nieco ponad połowę jego HP

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
meh Man
źródło
Istnieje wiele botów, które wykorzystują dokładnie to zachowanie, więc możesz mieć trudności z uzyskaniem przyczepności!
KBriggs,
@KBriggs Dokonałem jakiejś aktualizacji, nie spodziewałem się, że pierwsza wersja wypadnie tak dobrze, jak miała, mam nadzieję, że ta aktualizacja da jej większą szansę na walkę
meh Man,
Wow, to zrobiło dużą różnicę, myślę, że jesteś pierwszy. Aktualizacja zostanie opublikowana za kilka minut. Być może będziesz musiał podać swojemu botowi układ odpornościowy (patrz SarcomaBot), jeśli chcesz to dobrze wykonać.
KBriggs,
@KBriggs Nie spodziewałem się, że zrobię to dobrze, pomyślałem, że w najlepszym razie będzie w pierwszej dziesiątce. W każdym razie dodałem kolejną, aby zobaczyć efekt HP w pierwszej rundzie. Czy potrafisz uruchomić oba, żeby zobaczyć wynik obu? Dziękuję
meh Man
@KBriggs Zrób to też, 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

Ten robot wykonuje prostą analizę historii wrogiego bota lub w przeciwnym razie licytuje połowę jego pozostałych punktów wytrzymałości

Belgabad
źródło
4

Licytuj wyżej, tym mniej masz konkurencji. Dzięki komentującym za sugestie ulepszeń.

def Spreader(hp, history, ties, alive):
   if alive == 2:
       return hp-1
   if len(history) < 2:
       return hp/2
   return np.ceil(hp/alive)
Gus314
źródło
1
Świetny pomysł, ale widzę dwa problemy. Jednym z nich jest większość innych botów licytujących w pierwszej rundzie, więc ten prawdopodobnie umrze wcześnie przez większość czasu. Po drugie, w końcowej fazie większość botów licytuje hp-1, więc ten straci je, chyba że podwoisz ich hp. Ale dla rund pośrednich podoba mi się ten pomysł. Jeśli rozwiążesz dwa wyjątkowe przypadki, prawdopodobnie poprawisz wydajność.
KBriggs
4

SurvivalistBot i HalvsiesBot

Dziękuję za odpowiedź na moje pytania. Efektem końcowym jest bardziej złożony bot.

HalvsiesBot to kapryśny bot „tylko mijaj pół” z szansą na wygraną 50/50. Zgaduję.

SurvivalistBot podejmuje serię decyzji binarnych dotyczących drzewa binarnego w oparciu o zestaw danych, w tym nadpisanie remisu (jeśli trafi 2 remisy, kamikadze unikają potrójnej śmierci remisu).

Mój python jest trochę zardzewiały, więc kod może być nieco wadliwy, więc możesz go poprawić lub zaktualizować.

Został zbudowany, aby próbować wypracować bity danych, aby wywnioskować, na przykład, ile HP pozostało, minimalną liczbę botów, z którymi prawdopodobnie będzie walczył, minimalną ilość HP do opuszczenia, średnią licytację. Wykorzystuje także randomizację w niejednoznacznych sytuacjach, takich jak gra początkowa lub optymalne problemy z licytacją.

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
SSight3
źródło
Opponent_Average_Bid = Opponent_Remaining_HP / float(len(history)) ZeroDivisionError: float division by zero. Ta linia musi obsłużyć przypadek historii o długości 0.
KBriggs
Dzięki, poprawię to.
SSight3
Naprawiony. Daj mi znać, jeśli wystąpią inne błędy.
SSight3
1
Kilka błędów składniowych: brakuje: `po else, math.[func] -> np.[func]i w pewnym momencie użyć Lowestgdzie masz na myśli LowestBid. Wszystko naprawione w kontrolerze na githubie i wyniki aktualizowane wkrótce.
KBriggs
Dzięki. Naprawiono wszystkie wyżej wymienione błędy w poście.
SSight3
4

Calculating 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 agresywny obliczeniowy

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

Jeśli potrafimy przewidzieć działania przeciwnika, możemy postawić optymalne zakłady! Jeśli nie możemy (za mało danych lub przeciwnik jest zbyt losowy), możemy przynajmniej zrobić to, co zmaksymalizuje nasz potencjał wygranej. Teoretycznie co najmniej połowa żywych botów umiera w każdej rundzie. Dlatego mogę się spodziewać, że będzie co najwyżej log2 (żywych) rund. Idealnie podzielilibyśmy nasze hp równomiernie na wszystkie rundy. Wiemy jednak, że niektóre boty będą głupie, a samobójstwa / zginą wcześnie, dlatego powinniśmy stawiać nieco więcej we wcześniejszych rundach.

Agresywne obliczanie kodu modyfikacji Bota Obliczanie kodu Bota, aby starać się pozostać przy życiu, będąc bardziej agresywnym, kosztem długoterminowego zdrowia. Tylko symulacje pokażą, czy wygra tempo lub wartość.

Anti Kick Bot powinien zawsze pokonać aktualnego lidera KickBota: P

EDYCJA: Zastąpił Deterministycznego Bota Botem Anti Kick, inteligentniejszym botem o prawie dokładnie takich samych wartościach zwrotnych. Uniemożliwił także głosowanie więcej niż HP przeciwników

Bob Cratchit
źródło
Uroczy. Myślę, że ten poradzi sobie lepiej z bardzo dużą pulą botów.
KBriggs
I pojawia się błąd czasami z tego: return np.max(theoreticalBet, hp - 1): AxisError: axis 23 is out of bounds for array of dimension 0. Wysłałem link do kontrolera, abyś mógł go przetestować.
KBriggs
@KBriggs Zaktualizowano kod, aby go naprawić.
Bob Cratchit
1
potwierdzone, aktualizacja wyniku nadchodzi. Na pewno jesteś w pierwszej dziesiątce.
KBriggs
@KBriggs Dodałem jeszcze kilka botów do wypróbowania :)
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))

Jest naprawdę późno ... Jestem zmęczony ... nie mogę wymyślić nazwy ... a format tego bota jest bardzo podobny do innych, tylko z nieco innym algorytmem podanym w historii. Stara się uzyskać bieżącą stawkę, którą przeciwnik dąży do hazardu ... lub coś w tym rodzaju ... zzz

Quintec
źródło
musisz użyć np.maximumzamiast np.max, to samo dlamin
KBriggs
@KBriggs Dzięki :) Hmm, wygląda na to, że ogólne boty rządzą tą grą
Quintec
Wydaje się, że byłyby to dość łatwe cele, jestem zaskoczony, że nikt jeszcze nie stworzył pasożyta
KBriggs
@KBriggs Tak, jestem zaskoczony. Czas dodać zabezpieczenia ...
Quintec,
Nadal planujesz zrobić Neuralbota?
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
Roo4data
źródło
4

Coast Bot [Koniec kariery]

Spróbuje wyprzedzić konkurencję, równo dzieląc swoje HP między rundami. Licytuje wszystkie pozostałe HP w pierwszej rundzie, aby mieć większą szansę na awans do rund „nadających się”.

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

Ponieważ tak bardzo lubię to wyzwanie, po prostu musiałem stworzyć kolejnego bota. Ta wersja poświęca część swojego późniejszego wybiegu hp, wykorzystując więcej hp w pierwszych dwóch rundach.

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

Percent Bot

Próbuje obliczyć średni procent hp wydawany przez przeciwnika i na tej podstawie licytuje.

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)
Wazz
źródło
Całkiem fajny pomysł. Zwolnienie z pierwszej rundy jest nowym trendem w botach i wydaje się, że działa całkiem dobrze.
KBriggs,
@KBriggs Zaktualizowałem tę odpowiedź, aby zawierała moją drugą próbę. Wspominając o tobie zgodnie z nowymi zasadami. Świetne puzzle btw!
Wazz
Chcesz, żebym wprowadził obie lub tylko najnowszą wersję? W tej chwili jest to tylko V2
KBriggs
@KBriggs Chciałbym, aby oba zostały wprowadzone, jeśli to w porządku, proszę. Dobrze byłoby zobaczyć, jak porównują się ze sobą.
Wazz
Całkiem podobna ogólna wydajność
KBriggs,
4

ConsistentBot

Obstawia taką samą kwotę w każdej rundzie. Nie jest zbyt prawdopodobne, aby przetrwał pierwsze rundy, ale jeśli ma szczęście, aby dojść do końca, powinien pozostać rozsądną ilość 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
Kevin - Przywróć Monikę
źródło
Cóż, jest już za późno, aby to naprawić, ale mój bot wykorzystał wystarczającą ilość HP, aby do końca walki z każdym przeciwnikiem jeden raz, nie przejść do ostatniej rundy. To moje złe: P
Kevin - Przywróć Monikę
4

Kickban Bot

Ten bot po prostu próbuje skontrować obecnego lidera Mean Kickbota, pokonując go w pierwszej rundzie i grając bardziej agresywnie, jeśli go rozpozna.

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)
HRSE
źródło
1
Myślę, że twoje wcięcie jest trochę niepotrzebne.
Jonathan Frech,
Ups, dzięki, dziwny edytor kodu pomieszany z pierwszym wierszem
HRSE
cenna lekcja zaufania do kodu, którego nie kontrolujesz
OganM,
4

Three Quarter Bot

Nie pokona MehBota ani SarcomaBota, ale myślę, że radzi sobie całkiem nieźle. Kiedy po raz pierwszy zobaczyłem wyzwanie, była to pierwsza rzecz, która przyszła mi do głowy, zawsze * stawiaj trzy czwarte swojego zdrowia, chyba że nie ma powodu.

* po niskim balowaniu w pierwszej rundzie.

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

Four Sevenths Bot

Po umiarkowanym sukcesie bota 3/4 pojawiła się nowa frakcja w mieście, to tylko racjonalne.

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

Idealna frakcja

Jestem cały

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
Joshua Webb
źródło
Opierając się na tych prawdopodobieństwach eliminacji, prawdopodobnie możesz również uzyskać mniejsze oferty w rundzie 2. Ten robi dobrze, ale niektóre drobne poprawki mogą sprawić, że będzie o wiele lepszy.
KBriggs,
@KBriggs Dodano nowego bota z nowymi i ulepszonymi szansami;)
Joshua Webb
Chcesz ich obu tam, czy tylko 1?
KBriggs,
@KBriggs Nie wiem, czy nie dotrzymałem terminu, ale dodałem jednego końcowego bota, jeśli zdążę na czas, możesz usunąć pozostałe dwa boty frakcyjne
Joshua Webb
1
Tak, wciąż masz czas
KBriggs
4

BandaidBot

BandaidBot chce, aby wszyscy grali dobrze! Jeśli jego przeciwnik był miły w ostatniej rundzie, poświęci się, aby zachęcić innych do miłego zachowania. Jeśli jego przeciwnik miał na myśli ostatnią rundę, zada mu jak najwięcej obrażeń, poświęcając się w razie potrzeby. Licytuje jedną trzecią HP, jeśli nie ma historii do pracy. (Mam nadzieję, że ten bot będzie miał ciekawe efekty falowania w innych strategiach, nie tyle, że sam bot będzie miał wysoki wskaźnik wygranych. Fajnie byłoby mieć kilka takich w grze)

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 będzie równie przyjemny, jak trzeba, aby skorzystać z BandaidBot. Zwróci nieco mniej niż jedną trzecią HP, chyba że zabije przeciwnika za mniej. Jeśli jego przeciwnik wygląda jak BandaidBot, licytuje 2, wiedząc, że BandaidBot licytuje 1, ponieważ GetAlongBot radzi sobie tak dobrze ze wszystkimi innymi - łatwa wygrana, o ile naprawdę był to BandaidBot z drugiej strony.

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)
Maya Sol
źródło
Naprawdę fajny pomysł. Zastanawiam się, jaki będzie to miało wpływ
KBriggs
błąd: return np.random.randint(history[-1], hp/2): ValueError: low >= highTa sprawa musi być jakoś załatwiona
KBriggs
@KBriggs powinno zostać naprawione teraz!
Maya Sol
@KBriggs zaktualizowano, aby naprawić losowość
Maya Sol,
3

TENacious bot

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

Ten bot próbuje utrzymać swoją ulubioną wartość 10, ale od czasu do czasu zmienia swój wybór, aby przerwać remis (z podwojoną lub czterokrotną ulubioną wartością) lub zaoszczędzić na przyszłe rundy, ale nie o optymalną ilość, ponieważ chce pomylić przeciwników i nie chce rozważać licytacji mniejszej niż 2, ponieważ jest przekonany, że znacznie lepiej niż mieć nadzieję, że przeciwnik licytuje mniej niż 1, to znaczy 0.

PS: ten bot może mieć problemy strategiczne, jeśli jest więcej niż 2 ^ 9 botów.

AlexRacer
źródło
Podejrzewam, że nie musisz się martwić o 2 ^ 9 przeciwników ^ _ ^.
KBriggs,
Ale z zakładem otwierającym wynoszącym 10, rzadko
zdoła przejść
Ten bot uważa, że ​​jeśli jakiś bot naprawdę chce dać więcej niż 10 KM w pierwszej rundzie, nie warto walczyć.
AlexRacer
Haha wystarczy
KBriggs
3

CautiousBot

Pierwsze zgłoszenie do Programowania Puzzle kiedykolwiek! Znalazłeś swoje wyzwanie całkiem interesujące: P

Jeśli ostatnia runda była o jeden mniejsza niż HP, jeśli żadna historia nie stawiła połowy HP plus mała losowa kwota.

Jeśli historia sprawdzi HP przeciwnika i liczbę pozostałych rund i spróbuje przelicytować HP przeciwnika / 2 za pomocą dodatkowego bufora do ułamka pozostałego HP podzielonego przez liczbę pozostałych rund (stara się jakoś zachować pozostałe HP dla rund późniejszych) . Sprawdź, czy wydajesz za dużo HP (nie zabijaj się i nie licytuj więcej niż twój przeciwnik może).

Zawsze poprawiaj więzy, tak jak robią to inne boty.

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

Zbyt agresywny w pierwszych rundach, teraz CautiousBot staje się jeszcze bardziej ostrożny ...

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)
Jesús Ros
źródło
Masz błąd, gdzie wciąż jest wzywającą randint gdy bufor = 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. Zauważ, że bufor jest słowem kluczowym w pythonie, możesz chcieć wybrać inną nazwę zmiennej.
KBriggs,
Och, wygląda na to, że bufor nie zawsze jest liczbą całkowitą - prawdopodobnie w pewnym momencie dzielisz przez zero. Sprawdź dokładnie logikę. Sprawiłem, że działa, ale prawdopodobnie możesz naprawić narożne skrzynki.
KBriggs,
Niezły chwyt @KBriggs. Myślę, że to naprawiłem.
Jesús Ros
Wciąż pojawia się błąd: buff_bet = np.random.randint(0, buff) if buff > 0 else 0 File "mtrand.pyx", line 993, in mtrand.RandomState.randint ValueError: low >= high. Wygląda na to, że buff jest czasem liczbą zmiennoprzecinkową między 0 a 1, która przypuszczalnie zmienia się na 0 w środku randint. To działa, jeśli oddasz buffsię intprzed wywołaniem
KBriggs
@KBriggs prawdopodobnie dlatego, że ceilzwraca a float. Brakowało tego ... Ty znowu: P
Jesús Ros
3

W porządku, spróbuję w tym spróbować.

SnetchBot

Sprawdzanie frakcji zdrowia, z którymi zmierzał przeciwnik. Jeśli przeciwnik przebijał, pokonaj go.

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

EDYCJA: dużo przegrywając w pierwszej rundzie, dostosowałem losowe limity pierwszej tury

porwać
źródło
Całkiem niezły pierwszy strzał, aktualizacja wyników nadchodzi
KBriggs
@KBriggs Trochę edytowano (tylko losowe granice pierwszej rundy). Chociaż byłem już zaskoczony, że byłem na 10 miejscu. Jeśli to się pogorszy,
cofnę
Wyciskasz
3

SquareUpBot

Nie wyglądało na to, że wiele botów bawi się mocami zamiast frakcjami, więc postanowiłem zrobić jeden, z pewnymi standardowymi optymalizacjami i zobaczyć, gdzie umieszczę. Całkiem uproszczone.

Próbuje również ustalić, czy bot wroga nie próbuje użyć jakiejś stałej frakcji, ponieważ moce > frakcje .

EDYCJA: Jestem manekinem i mój detektor frakcji nie mógł działać. Naprawiony teraz.

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
Pył diamentowy
źródło
Niezły pierwszy strzał, wyniki zostały zaktualizowane
KBriggs
@KBriggs Zaktualizowałem bota, więc detektor frakcji faktycznie działa.
Diamond Dust