Робот-рулетка: игра на высоких ставках

56

Итоговые результаты

+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +
| Имя | Оценка | WinRate | TieRate | Вероятность исключения |
+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +
| 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. CauiousGamblerBot2 | 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. Осторожный бот | 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. Снаряженный бот | 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. КамикадзеБот | 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]% |
+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +

Спасибо всем, кто принял участие, и поздравляем @Sarcoma с победой!

Правила:

Каждый начинает с 100 л.с. В каждом раунде 2 игрока выбираются случайным образом из числа участников, которые еще не участвовали в этом раунде. Оба игрока выбирают число от 0 до текущего значения в л.с. и показывают эти цифры одновременно. Игрок, выбравший меньшее число, немедленно умирает. Другой игрок вычитает выбранное количество из оставшихся очков здоровья и переходит к следующему раунду.

Турнир работает так:

Из группы участников 2 выбираются случайным образом. Они сталкиваются, и один или оба из них умирают. Игрок умирает, если:

  1. Они выбирают число меньше номера своего оппонента
  2. Их л.с. падает до или ниже нуля
  3. Они три раза подряд связывают со своим противником

В случае связей оба игрока просто генерируют новые числа, до 3 раз. После вбрасывания оставшийся в живых (если таковой имеется) перемещается в пул для следующего раунда, и процесс повторяется до тех пор, пока мы не исчерпаем текущий пул раундов. Если в пуле есть нечетное число, то нечетное число бесплатно переходит в следующий раунд.

Ваша задача - написать функцию в python2.7, которая будет принимать в качестве входных данных ваш текущий hp, список ставок вашего оппонента historyи целое число, tiesкоторое сообщает вам, сколько раз вы уже связались с вашим текущим оппонентом, и целое число, которое сообщает вам, как многие боты все еще alive(включая вас), и целое число, в котором указано количество ботов на startтурнире. Обратите внимание, что история не включает в себя связи. Функция должна возвращать целое число между 0 и текущим общим количеством hp. Несколько простых примеров, которые игнорируют связи, показаны ниже:

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)

Если ваша функция возвращает число больше, чем ваш hp, оно будет сброшено до 0. Да, можно убить себя. Ваша функция не должна пытаться получить доступ или изменить какой-либо член любого объекта класса RouletteBot. Вам не разрешается предпринимать какие-либо действия, которые однозначно идентифицируют вашего противника, независимо от будущих дополнительных ботов. Проверка стека разрешена, если теоретически возможно, что более чем один отдельный оппонент мог получить информацию, которую вы извлекаете из нее, даже если в настоящее время существует только один бот, который мог бы это сделать. то есть вы не можете просто прочитать стек, чтобы увидеть, какая вражеская функция была вызвана.

По этим правилам возможно, что победителя нет, а два последних участника убивают друг друга. В этом случае оба финалиста получают по пол-очка каждый.

Это моя первая попытка программирования, поэтому критика приветствуется!

Контроллер можно найти здесь .

KBriggs
источник
4
FWIW, я планирую использовать нейронную сеть, обученную на всех других ботах, просто для удовольствия, как только вы настроите контроллер :)
Quintec
2
Проверка типа была в пользу antiantiantiantiupyoursbot. Я найду другой путь
KBriggs
3
@Sarcoma Похоже, это соревнование вызвало серьезную кодовую войну. Этот конкурс еще не закончился, но я уже с нетерпением жду развития этого. Может быть, даже следующий шаг, AI усилил конкуренцию: P
Марков прикован
3
WOOOOOOOOOOOOOO!
саркома
5
Боже ты мой. Преднамеренный троллинг, изменяющий mean_kick, всегда возвращающий ноль, когда он использовался в стольких местах, блестящий.
Магуа

Ответы:

12

BinaryBot

Кто-нибудь сделал это еще? Каждый раунд ставит половину своего здоровья.

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

SarcomaBot

Если в последнем боевом предложении л.с. - 1. Если это первое сражение, то в половину л.с. плюс дополнительная случайная сумма до четверти л.с. Если он может побить прямую ставку оппонента после этой ставки, оппонент hp + 1. Если у него меньше здоровья, чем у оппонента, случайная сумма между 75% и текущим 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

Незначительные изменения пытаются уменьшить расходы на жизнь.

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

Обновление тонкой настройки

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

Финальная заявка

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


Добавлено обновление защиты UpYoursBot


Добавлено обновление защиты AntiAntiUpYoursBot

Обновление
AntiAnitAntiAntiUpYoursBot Я побежден

саркома
источник
Комментарии не для расширенного обсуждения; этот разговор был перенесен в чат .
Mego
17

UpYours

Опоздав на вход, я провел некоторое время, восхищаясь существующими ботами, потратив некоторое время, усложняя идеи ваших парней, затем не усложняя их. Потом до меня дошло

Хорошие художники копируют, великие художники крадут. - Пабло Пикассо Ме


"Up Yours", потому что я беззастенчиво краду (и иногда ставлю точку или две на ставки ваших ботов, чтобы поднять их).

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

Но по-настоящему, это отличное соревнование, ребята. Я люблю это сообщество в такие дни.

Qfwfq
источник
1
Хахахаха, это прекрасно. Я не знаю, позволю ли мне это, но я позволю этому сейчас играть, поскольку я не думал сказать, что это не разрешено. Вы неправильно указали имена функций в нескольких местах - смотрите контроллер на github.
KBriggs
1
Это очень хорошо, очевидно, но он все еще проигрывает Kick Bot
KBriggs
1
Ха, хорошие усилия!
саркома
1
@ Саркома, я бы не справился без тебя. ;) Мне тоже очень нравится твой бот, приятель.
Qfwfq
1
Защита Sarcomabot Upyoursbot действительно мешает с этим
KBriggs
15

Камикадзе

Зачем беспокоиться о сложной логике, когда мы все умрем ...

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


Один выстрел

Он выживет хотя бы один раунд, если не встретит камикадзе.

 def one_shot(hp, history, ties, alive):
      if hp == 1:
          return 1
      else:
          return hp - 1
DobromirM
источник
11
Welp, это было неизбежно
KBriggs
Я собирался добавить и пацифистского бота, но я не хочу затопить твой вызов роботами с мертвым мозгом
DobromirM
5
Основываясь на некотором быстром тестировании, бот-камикадзе практически не меняется - все, что он делает, это удаляет другого бота из раунда наугад, который при достаточно большом количестве турниров просто усредняется до нуля. Тем не менее, Горячий опрятный. Без этого мой AverageBot, как правило, работает лучше, но если в игре есть несколько OneShots, он отклоняет среднее значение к большим числам и приводит к быстрому отмиранию AverageBot. То же самое для LastBot. Вы можете действительно испортить поведение других роботов, изменяя свои собственные шаблоны ставок. С OneShot в игре побеждает RandomBot. Без этого AverageBot побеждает.
Кбриггс
14

Патетический бот получает очень необходимое обновление:

Жалкая попытка бота, который пытается включить функции других ботов

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

Этот бот включает в себя функции от Survivalist Bot и Geometric Bot для более эффективного удаления ботов.

Pre-Upgrade:

Жалкая попытка бота, который анализирует историю своего противника

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

Если у его противника была предыдущая история, он рассчитывает hp противника. Затем он выполняет одно из следующих действий:

  • Если его противник является последним живым противником, то он сделает ставку на единицу меньше, чем его HP.
  • Если его противник не является последним живым противником, но у противника меньше 16 л. С., То он перевесит его соперника.
  • Если его противник не является последним живым противником и у него есть история связей, то он сделает ставку на свое здоровье, потому что ему надоели связи.
  • В противном случае, он превзойдет своего оппонента.

Если истории нет, то она делает некоторые причудливые вычисления, которые я взломал вместе, и предлагает цену. Если значение превышает 100, то оно автоматически назначает свою цену минус 1.

Я взломал этот код вместе во время работы, и это моя первая подача, так что, вероятно, она не выиграет или что-то в этом роде, и проиграет камикадзе.

РЕДАКТИРОВАТЬ: Из-за некоторых предложений, поведение начала бота было изменено, чтобы предложить цену выше.

РЕДАКТИРОВАТЬ 2: добавлен стартовый параметр, который ничего не делает

РЕДАКТИРОВАТЬ 3: Добавлен новый спин-бот:

[Жалкая попытка бота, который атакует бандитских ботов (а также делает все, что делает вышеупомянутый бот)] УДАЛЕНО

[Этот бот анализирует, является ли его противник бандой или нет, и притворяется таковым, чтобы получить приятные низкие ставки, которые он может легко превзойти.]

Этот бот был удален, пожалуйста, удалите его из списка лидеров.

РЕДАКТИРОВАТЬ 4: Исправлены ошибки, изменена функция связи.

Yodie
источник
Очень приятно, спасибо за бот! Я дам немного статистики, когда получу еще несколько.
Кбриггс
Я новичок в Python, поэтому я не уверен, что синтаксис правильный, не стесняйтесь, дайте мне знать, если это произойдет
Yodie
Он работает, так что не беспокойтесь там
KBriggs
@Yodie Как небольшой обзор кода: тело вашей функции должно иметь отступ по уровню (синтаксическая необходимость); opp_hp +1не хватает места, чтобы быть питоническим; Ваши комментарии начинаются с несбалансированного количества пробелов. Наконец, вашей функции не хватает строки документации.
Джонатан Фрех
2
Я думаю, что этот бот неплохо справляется, если он проходит первый раунд, но поскольку многие люди делают большие ставки, он в первом раунде почти всегда умирает рано. Вы можете улучшить производительность, изменив начальное поведение, чтобы повысить ставку, когда нет истории. Например, если вы утроите свою ставку без истории, этот бот пока выигрывает с удобством среди участников.
KBriggs
11

Kick Bot

Правильный выбор для моего оппонента - сделать ставку на половину своей жизни. Затем мы ставим до половины его жизни + 1, если мы не можем взять его с разумной ставкой, то есть ставкой меньше, чем половина нашей жизни.

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

Кик-бот, очевидно, является заклятым врагом пунта-бота!

Mean Kick Bot

Этот новый KickBot мягче пинает в первом раунде, чтобы он мог пнуть сильнее в следующих раундах, это значит!

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

Оба его брата должны были покончить жизнь самоубийством, но WiseKickBot учился у своих павших.

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
источник
Приятно. Я вижу много представлений, которые прямо противоречат другим сейчас, это именно то, на что я надеялся
KBriggs
Двойной возврат на последней строке?
Веска
Ах, я еще не запускал это, иначе я бы это поймал.
KBriggs
Этот взял удобное лидерство!
KBriggs
1
@KBriggs вот какая-то резервная копия!
Йохан
8

Тат бот

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)

Попытка эквивалента бота «синица за тату». Предполагается, что большинство ставок примерно одинаковы между раундами. Используя это предположение, он пытается победить вражеского бота, оставаясь при этом довольно скромным. Тратит около 40 здоровья на первый раунд.

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

Обходной путь для защиты SarcomaBot от UpYours, для которой я использую большую часть кода! Или я принимаю код UpYoursBot? Вопрос для размышления, пока вы читаете мой бот ...

Бот AntiAntiUpYours превратился в бот AntiAntiAntiUpYours! Теперь с большим количеством исправлений обезьян.

Поли бот

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) 

Поли-бот выполняет полиномиальную регрессию в истории вашего бота и немного превосходит прогнозируемый показатель.

Классный бот

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)

Классный бот хорошо провел время, но решил рано лечь спать. Спи спокойно, классный бот.

персона
источник
Комментарии не для расширенного обсуждения; этот разговор был перенесен в чат .
Mego
8

1/2 Punch Bot, Revisited

Я думаю, что он умрет довольно быстро. Стоило того. Переименовал функцию, забыл поменять там имя.

Пересмотренная версия вышла, лучшие шансы на победу (тем более в финальном раунде) и небольшая защита от бандитских ботов

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

Нападающий бот

1/2 Punch Bot слишком много издевались и даже стали лакеем UpYoursBot, поэтому на помощь пришел его старший брат StrikerBot .

Не так уж много различий с оптимизированным 1/2 Punch, но он немного умнее и преуспел в бегах, которые я сделал (10k и 35k, хотя он может проиграть 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
Belhenix
источник
Вам придется переименовать его, там уже есть бот-камикадзе ^ _ ^
KBriggs
Пока что этот победитель
KBriggs
Ваша функция ceilне определена.
Джонатан Фрех
Я переключился на np.ceil (), чтобы запустить его
KBriggs
Отредактировано, спасибо за хедз-ап
Belhenix
7

Gang Bot

Идея заключалась в том, что потенциально два или более бота могут быть использованы в одной симуляции. Бот пытается дать "легкий выигрыш" другим ботам в банде, посмотрев, кратна ли его история 7 ставкам. Конечно, этим могут легко манипулировать и другие боты. Затем я рассчитываю предположение о ставках ботов, не являющихся бандами, на основе отношения моего здоровья к их и отношения их предыдущего здоровья к их предыдущей ставке и добавляю 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
Джим Хэт
источник
Очень круто. Сколько нужно? Мне, вероятно, придется ограничить количество записей ...
KBriggs
Ваш кодовый блок пропускает первую строку вашего источника.
Джонатан Фрех,
Я не уверен, сколько будет нужно в симуляции, но если какой-либо из ботов когда-либо увидит друг друга, он должен увеличить шанс на победу одного из них. Я предполагаю, что наличие 10% пула, являющегося бандой ботов, должно быть достаточно, чтобы иметь существенное значение. Также в блоке кода отсутствует первая строчка -> это мой первый пост, я не знаю, почему форматирование так и сделало, но да, это просто объявление метода.
Джим Хэт
У вас есть ошибка: бот идентифицирует любого с len (history)> 1 в качестве члена банды
KBriggs
Мой плохой, должен быть исправлен сейчас.
Джим Хэт
6

Худший случай

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

Простой бот. Возвращает hp - hp / (start - alive + 4)в большинстве случаев, а в случае связей увеличивает его на 2 (надо поднять!) Для каждого связывания, стараясь не возвращать число над его hp.

Quintec
источник
Это не с делением на ноль, если alive==8. Я могу вручную изменить его на общее количество ботов, но это растягивает правила, поскольку это не влияет на вашу функцию - все, что вы знаете, сколько противников у вас осталось в данный момент времени, а не сколько вы начали против.
Кбриггс
Я обновил конкурс на основе вашего запроса
KBriggs,
@KBriggs Спасибо :)
Quintec
Вам также нужно добавить 1 к старт-живому, так как это 0 для первого раунда
KBriggs
@KBriggs исправлено, на самом деле должно +2, поэтому он не возвращает 0, лол
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 попытается сделать ставку выше , чем его противник может предложить цену , где это возможно.

Draco18s
источник
Есть условие, которое where np.random.randint(hp/5, hp/2)может не сработать, если hp/5 == hp/2, т.е. если hp==0илиhp==1
KBriggs
3
Если HP равен 0, то меня не следует вызывать. : P Вы правы насчет 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

Принимает решение о том, сколько здоровья он должен пожертвовать, основываясь на количестве оставшихся ботов. Если осталось только два бота, он делает ставку hp-1, но если осталось три, он бит вдвое меньше, четыре слева, третий и т. Д.

Тем не менее, в очень большом конкурсе, я считаю, мне нужно будет делать ставку более чем на 3 или 4 л.с., чтобы не умереть в первом раунде, поэтому я поставил нижнюю границу на 10. Конечно, я все равно никогда не буду делать ставки больше. чем hp-1.

Он также добавляет 1,5 л.с. для галстуков, так как я вижу несколько ботов "добавить 1 л.с. для галстуков". Я не уверен, что это считается обманом. Если это произойдет, я изменю это.

Отличная идея, кстати!

Spitball Bot 2.0

Что нового?

  • Переключен на деление на количество оставшихся раундов вместо количества оставшихся ботов (Спасибо @Heiteira!). На самом деле, теперь я делю это число на степень .8, чтобы немного увеличить фронтальные ставки.

  • Увеличена минимальная ставка с 10 до 20 (Спасибо @KBriggs!)

  • Добавлена ​​проверка того, превышает ли ставка на спитбол текущее значение HP противника, и понизьте ее, если она есть.

(SO не будет отображать код ниже как код, если я не помещу текст здесь, так что хорошо)

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
источник
1
Ваша ставка должна быть целым числом, поэтому до тех пор, пока вы указали минимальное или базовое значение, чтобы избавиться от десятичной дроби, все в порядке
KBriggs
Да, я полагаю это сразу после выполнения всех вычислений. Спасибо за быстрый ответ!
MegaWidget
2
Вы могли бы оптимизировать это, если не делите свой hp на количество оставшихся участников, а на количество оставшихся раундов (которое должно быть math.ceil (math.log (alive, 2))
Black Owl Kai
1
Основываясь на других ботах, большинство из них, похоже, имеют фронтальную загрузку, поэтому это может улучшиться, если вы увеличите ставку в первом раунде выше 10
KBriggs
Это обе хорошие идеи! Я не осознавал, что количество ботов не совпадает с количеством оставшихся раундов (сначала я неверно истолковал правила конкурса). Я попробую реализовать их завтра. Спасибо!
MegaWidget
5

геометрический

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-е место с первой попытки, совсем неплохо
KBriggs
5

Бот 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

Попробуйте максимизировать выигрыши с наименьшими усилиями:

  • если мы можем победить, просто сделай это
  • если это последний раунд, не умирай, пытаясь
  • в противном случае не беспокойтесь

Почему?

Попытайтесь воспользоваться вероятностью: выиграть первый раунд, играя на низком уровне, - лучший способ начать турнир. 13, кажется, сладкое пятно: второй раунд - уверенная победа, а остальные - Spaziergang в парке.

гигабайт
источник
Вы взяли на себя инициативу, очень приятно! Будьте осторожны, вы можете добавить защиту от паразитов, так как боты, которые идут впереди, становятся мишенями для таких вещей, как UpYoursBot. Проверьте SarcomaBots для идей защиты, если они вам нужны.
Кбриггс
5

Угадай Бот

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)

Первое размещение здесь. Это выглядело очень весело, поэтому я отправляю свою невероятную попытку и угадываю, на что будут делать ставки другие боты.

Изменить 1: Добавил еще 1 к первой ставке, просто чтобы уменьшить вероятность ничьей с другими людьми, ставками 51.

Редактировать 2: Украл первый ход бота саркомы, так как у него были хорошие шансы на то, что он не будет последовательно устранен.

Редактировать 3: Бот выживает очень хорошо в первом раунде, но он легко уничтожается на более поздних этапах. Изменилось то, как робот думает о втором раунде, теперь, когда половина игроков мертва в воде.

Изменить 4: Теперь, когда первый раунд хорош, я изменил способ обработки второго раунда. Много умираю во втором раунде, поэтому мне нужно как-то выжить.

Кровавый бот

Сделал жаждущий бот в поисках убийства. Идея состоит в том, чтобы попытаться выиграть у ботов с низкими ставками, и после того, как они закончат кровопролитие в первом раунде, их нельзя остановить, поскольку у них должно быть огромное количество HP, чтобы превзойти врагов.

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
Я думаю, что len (история) * len (история) может быть изменена на len (история) ** 2, если мои знания Python верны.
Йоди
У вас есть деление на ноль, когда len (history) == 0
KBriggs
Код был обновлен. Не найдя истории, он переходит к первому
Маркову, прикованному
ой .............
саркома
2
@ Саркома, это беспощадный бот-мир, чувак!
Марков прикован
5

meh_bot

Просто поставьте чуть больше половины своего л.с.

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
Мех Ман
источник
Существует довольно много ботов, которые могут воспользоваться именно этим поведением, поэтому вам может быть трудно набрать обороты!
Кбриггс
@KBriggs Сделал какое-то обновление, я не ожидал, что первая версия заработает так же хорошо, как и, надеюсь, это обновление даст ему больше шансов на сражение
Мех Ман
Вау, это имело большое значение, я думаю, ты первый. Обновление будет опубликовано через пару минут. Возможно, вам придется дать вашему боту иммунную систему (см. SarcomaBot), если вы продолжите делать это хорошо.
KBriggs
@KBriggs Я не ожидал, что сделаю это хорошо, я думал, что в лучшем случае это будет топ-10. В любом случае, я добавил еще один, чтобы увидеть эффект первого раунда hp. Можете ли вы запустить их обоих, чтобы я мог увидеть результат обоих? Спасибо
Мех Ман
@KBriggs Пожалуйста, сделайте это также, Muchas gracias
Мех Ман
4

Робби рулетка

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

Этот бот делает простой анализ истории вражеского бота, в противном случае получает половину оставшихся очков жизни.

Belgabad
источник
4

Ставка выше, чем меньше у вас конкуренции. Спасибо комментаторам за предложения по улучшению.

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
источник
1
Идеальная идея, но я вижу две проблемы. Одним из них является то, что большинство других ботов делают большие ставки в первом раунде, так что этот, вероятно, большую часть времени умрет рано. Во-вторых, в финале большинство ботов предлагают ставку hp-1, поэтому этот игрок проиграет, если вы не удвоите его HP. Но для промежуточных раундов мне нравится идея. Если вы решите два особых случая, вы, вероятно, сможете улучшить производительность.
Кбриггс
4

SurvivalistBot и HalvsiesBot

Спасибо, что ответили на мои вопросы. Конечный результат - более сложный бот.

HalvsiesBot - это причудливый бот «просто держи половину» с вероятностью 50/50 на победу. Я полагаю.

SurvivalistBot принимает серию решений if-else бинарного дерева, основываясь на наборе данных, включая переопределение связи (если он достигнет 2 связей, то это камикадзе, чтобы избежать смерти тройной связи).

Мой питон немного ржавый, поэтому код может быть немного глючным, поэтому не стесняйтесь исправлять или обновлять его.

Он создан для того, чтобы попытаться обработать биты данных, чтобы сделать вывод о том, сколько HP осталось, минимальное количество ботов, с которыми он может сражаться, минимальное количество HP, которое нужно оставить, средняя ставка. Он также использует рандомизацию в неоднозначных ситуациях, таких как открытие игры или вопросы оптимальных ставок.

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
источник
Opponent_Average_Bid = Opponent_Remaining_HP / float(len(history)) ZeroDivisionError: float division by zero, Эта строка должна обрабатывать случай истории 0 длины.
KBriggs
Спасибо, я исправлю это.
SSight3
Исправлена. Дайте мне знать, если есть какие-либо другие ошибки.
SSight3
1
Пара синтаксических ошибок: отсутствует: `после того, как else, math.[func] -> np.[func]и в какой -то момент вы используете , Lowestгде вы имеете в виду LowestBid. Все исправлено в контроллере на github и оценки обновляются в ближайшее время.
KBriggs
Благодарю. Исправлены все вышеперечисленные ошибки в посте.
SSight3
4

Расчет бот

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)

Агрессивный расчетливый бот

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

Если мы можем предсказать действия противника, мы можем сделать оптимальные ставки! Если мы не можем (недостаточно данных или оппонент слишком случайный), то мы можем, по крайней мере, сделать то, что максимизирует наш потенциал выигрыша. Теоретически, по крайней мере, половина числа живых ботов умрет в каждом раунде. Таким образом, я могу ожидать, что будет не более log2 (живых) раундов. В идеале мы бы равномерно распределяли наши лс между всеми раундами. Тем не менее, мы знаем, что некоторые боты будут глупыми и самоубийцами / умрут рано, поэтому мы должны ставить чуть больше в ранних раундах.

Код вычисляющего бота для Агрессивного вычисляющего бота модифицирует его, чтобы попытаться остаться в живых, будучи более агрессивным, за счет долговременного здоровья. Только симуляции покажут, победит ли темп или значение.

Anti Kick Bot всегда должен побеждать нынешнего лидера KickBot: P

РЕДАКТИРОВАТЬ: Заменили детерминированного бота на Anti Kick Bot, более умного бота с почти такими же возвращаемыми значениями. Также мешало голосовать больше, чем противникам HP

Боб Кратчит
источник
Милый. Я думаю, что этот будет лучше с очень большим пулом ботов.
KBriggs,
Я получаю ошибку иногда с этим: return np.max(theoreticalBet, hp - 1): AxisError: axis 23 is out of bounds for array of dimension 0. Я разместил ссылку на контроллер, чтобы вы могли проверить это.
KBriggs
@KBriggs Обновил код, чтобы исправить это.
Боб Кратчит
1
подтверждено, оценка обновляется. Вы в топ-10 наверняка.
KBriggs
@KBriggs Я добавил еще пару ботов, чтобы попробовать :)
Боб 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))

Уже поздно ... Я устал ... не могу придумать имени ... и формат этого бота действительно похож на другие, только с немного другим алгоритмом, заданным историей. Он пытается получить текущую ставку противника на азартные игры ... или что-то в этом роде ... zzz

Quintec
источник
вам нужно использовать np.maximumвместо np.max, то же самое дляmin
KBriggs
@KBriggs Спасибо :) Хм, похоже, что боты управляют этой игрой
Quintec
Кажется, что они будут довольно легкими целями, я удивлен, что никто еще не сделал паразита
KBriggs
@KBriggs Да, я удивлен. Время добавлять защиту ...
Quintec
Все еще планируете сделать нейронобота?
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
источник
4

Берег бот [пенсионер]

Постараюсь пройти путь через соревнование, равномерно разделив его hp между раундами. Поставит цену любому оставшемуся л.с. в первом раунде, чтобы дать себе больше шансов попасть в раунды "на побережье".

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

Поскольку мне очень нравится этот вызов, мне просто нужно было создать еще одного бота. Эта версия жертвует некоторыми из своих более поздних хп, используя больше хп в первых двух раундах.

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

Процент бот

Пытается рассчитать средний процент л.с., который тратит противник, и ставки, основанные на этом.

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
источник
Довольно классная идея. Увольнение в первом раунде - это новая тенденция для ботов, и, похоже, это работает достаточно хорошо.
KBriggs
@KBriggs Я обновил этот ответ, чтобы содержать мою вторую попытку. Упоминание о вас согласно новым правилам. Отличная головоломка, кстати!
Wazz
Хотите, чтобы я ввел оба или только последнюю версию? Прямо сейчас это просто V2
KBriggs
@KBriggs Я хотел бы, чтобы оба вошли, если все в порядке, пожалуйста. Было бы хорошо видеть, как они весят друг против друга.
Wazz
Довольно похожая производительность в целом
KBriggs
4

ConsistentBot

Ставки одинаковые в каждом раунде. Вероятность того, что он выживет в первых раундах, невелика, но если ему посчастливится дойти до конца, у него все равно должно остаться достаточное количество 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
Кевин - Восстановить Монику
источник
Дракончик, уже слишком поздно, чтобы исправить это, но мой бот использовал достаточно HP, чтобы дойти до конца, сражаясь с каждым противником, а не до последнего раунда. Это мое плохо: P
Кевин - Восстановить Монику
4

Кикбан Бот

Этот бот просто пытается противостоять нынешнему лидеру Mean Kickbot, обыгрывая его в первом раунде и после этого играя более агрессивно, если узнает его.

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
источник
1
Я думаю, что ваши отступы немного сбиты.
Джонатан Фрех
Ой, спасибо, странный редактор кода перепутался с первой строкой
HRSE
ценный урок в доверительном коде, который вы не контролируете
OganM
4

Три четверти бот

Он не собирается бить MehBot или SarcomaBot (s), но я думаю, что он делает это довольно хорошо. Когда я впервые увидел вызов, это было первое, что пришло мне на ум: всегда ставить три четверти своего здоровья, если нет причин для этого.

* после первого раунда.

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

Четыре Седьмых Бот

После умеренного успеха бота 3/4 в городе появилась новая фракция, это только рационально.

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

Идеальная фракция

Я целая

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
Джошуа Уэбб
источник
Основываясь на вероятностях исключения, вы, вероятно, могли бы уйти с меньшими ставками и во втором раунде. Это хорошо, но некоторые незначительные изменения могут сделать его намного лучше.
KBriggs
@KBriggs Добавлен новый бот с новыми и улучшенными коэффициентами;)
Джошуа Уэбб
Хотите их обоих там или только 1?
Кбриггс
@KBriggs Я не знаю, пропустил ли я крайний срок, но я добавил одного финального бота, если я успел сделать это вовремя, вы можете удалить двух других фракционных ботов
Джошуа Уэбб
1
Да, у вас еще есть время
KBriggs
4

BandaidBot

BandaidBot хочет, чтобы все хорошо играли! Если его противник был хорошим в последнем раунде, он жертвует собой, чтобы стимулировать хорошее поведение в других. Если его противник в последнем раунде был злым, он нанесет как можно больше урона своему противнику, пожертвовав собой в случае необходимости. Он назначает треть своего л.с., если у него нет истории для работы. (Я надеюсь, что этот бот будет иметь интересные волновые эффекты на других стратегиях, не настолько, чтобы у этого бота был высокий коэффициент выигрыша. Было бы забавно иметь пару таких в игре)

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 будет так же хорош, как и должен использовать BandaidBot. Он вернет чуть менее трети своего здоровья, если не сможет убить своего противника за меньшее время. Если его оппонент выглядит как BandaidBot, он будет делать ставку 2, зная, что BandaidBot будет делать ставку 1, потому что GetAlongBot так хорошо ладил со всеми остальными - легкая победа, если это действительно был BandaidBot на другом конце.

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)
Майя Сол
источник
Действительно аккуратная идея. Интересно, какое влияние это окажет
KBriggs
ошибка: return np.random.randint(history[-1], hp/2): ValueError: low >= highэтот случай должен быть как-то обработан
KBriggs
@KBriggs должен быть исправлен сейчас!
Майя Сол
@KBriggs обновлен, чтобы исправить рандомизацию
Maya Sol
3

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

Этот бот пытается удержать свое любимое значение 10, но он иногда меняет свой выбор, если необходимо разорвать ничью (с его любимым значением, удвоенным или увеличенным в четыре раза) или сохранить для будущих раундов, но не оптимальной суммой, потому что он хочет запутать оппонентам, и он не хочет рассматривать ставку менее 2 в любое время, так как убежден, что это гораздо лучше, чем надеяться, что оппонент сделает ставку менее 1, то есть 0.

PS: у этого бота могут быть стратегические проблемы, если ботов больше чем 2 ^ 9.

AlexRacer
источник
Я подозреваю, что вам не нужно беспокоиться о наличии 2 ^ 9 противников ^ _ ^.
KBriggs,
Но со стартовой ставкой в ​​10 он редко собирается пройти первый раунд
KBriggs
Этот бот думает, что если какой-то бот действительно хочет дать больше 10 л.с. в первом раунде, это не стоит борьбы.
AlexRacer
Хаха, достаточно честно
KBriggs
3

CautiousBot

Первая в истории Пазлы для программирования! Нашел свой вызов довольно интересным: P

Если в последнем раунде бит на единицу меньше, чем лс, если история не ставит половину лс плюс небольшую случайную сумму

Если история проверяет hp противника и количество оставшихся раундов и пытается превзойти hp / 2 противника, используя дополнительный буфер до доли оставшегося hp, деленной на количество оставшихся раундов (он пытается каким-то образом сохранить оставшийся hp для последующих раундов) , Проверьте, не тратите ли вы слишком много здоровья (не убивайте себя и не ставьте больше, чем ваш противник).

Всегда поправляйте галстуки, как это делают другие боты.

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

Слишком агрессивен в первых раундах, теперь CautimsBot становится еще более осторожным ...

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)
Хесус Рос
источник
У вас есть ошибка , где она по - прежнему вызывая randint когда буфер = 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. Обратите внимание, что буфер - это ключевое слово в Python, вы можете выбрать другое имя переменной.
KBriggs
О, похоже, это потому, что буфер не всегда является целым числом - вы, вероятно, делите на ноль в какой-то момент. Пожалуйста, проверьте логику внимательно. Я сделал это, но вы, вероятно, можете исправить угловые случаи.
KBriggs
Хороший улов @KBriggs. Думаю, я это исправил.
Хесус Рос
Я все еще получаю ошибку: buff_bet = np.random.randint(0, buff) if buff > 0 else 0 File "mtrand.pyx", line 993, in mtrand.RandomState.randint ValueError: low >= high. Кажется, что бафф иногда представляет собой число с плавающей запятой между 0 и 1, которое предположительно получает внутри 0 randint. Это работает , если вы накладываете buffна intперед вызовом
KBriggs
@KBriggs, вероятно, потому что ceilвозвращает float. Пропустил тот ... Ты снова: P
Хесус Рос
3

Хорошо, я попробую свои силы в этом.

SnetchBot

Проверка доли здоровья, с которым шел оппонент. Если противник делал рейз, побейте его этим.

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

РЕДАКТИРОВАТЬ: потерять много в первом раунде, скорректированы случайные пределы первого хода

snetch
источник
Довольно хороший первый выстрел, обновление
счета поступило
@KBriggs Отредактировано немного (только первый раунд случайных границ). Хотя я уже удивился, поднявшись на 10-е место. Если этот будет хуже, я просто вернусь к первому: D
snetch
Вы выдавливаете немного больше сока из него
KBriggs
3

SquareUpBot

Не похоже, чтобы многие боты играли с силами вместо фракций, поэтому я решил сделать один с некоторыми стандартными оптимизациями и посмотреть, где я буду размещать. Довольно упрощенно.

Также пытается определить, не пытается ли вражеский бот использовать некоторую постоянную дробь, потому что полномочия > дроби .

РЕДАКТИРОВАТЬ: я дурак, и мой детектор фракций не может работать. Ремонт сейчас.

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
Бриллиантовая пыль
источник
Неплохой первый выстрел, результаты были обновлены
KBriggs
@KBriggs Я обновил бота, так что детектор фракций действительно работает.
Алмазная пыль