Roleta Robótica: Jogo de robôs de apostas altas

56

Classificação Final

+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +
| Nome Pontuação | WinRate | TieRate | Probabilidade de eliminação |
+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +
| 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]% |
+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +

Obrigado a todos que participaram e parabéns a @Sarcoma pela vitória!

Regras:

Todo mundo começa com 100 hp. A cada rodada, dois jogadores são escolhidos aleatoriamente dentre os competidores que ainda não competiram nessa rodada. Ambos os jogadores escolhem um número entre 0 e seu hp atual e revelam esses números ao mesmo tempo. O jogador que escolheu o número mais baixo morre imediatamente. O outro jogador subtrai o número escolhido do hp restante e passa para a próxima rodada.

O torneio funciona assim:

Entre os concorrentes, 2 são escolhidos aleatoriamente. Eles se enfrentam e um ou os dois morrem. Um jogador morre se:

  1. Eles escolhem um número menor que o do oponente
  2. O hp deles cai para ou abaixo de zero
  3. Eles empatam três vezes seguidas com seu oponente

No caso de empate, ambos os jogadores simplesmente geram novos números, até 3 vezes. Após o confronto, o sobrevivente (se houver) é movido para a piscina para a próxima rodada, e o processo se repete até esgotarmos a piscina da rodada atual. Se houver um número ímpar na piscina, o número ímpar passa para a próxima rodada de graça.

Sua tarefa é escrever uma função no python2.7 que tenha como entrada a sua corrente hp, uma lista da oferta do seu oponente historye um número inteiro tiesque informa quantas vezes você já empatou com o seu oponente atual e um número inteiro que informa como muitos bots ainda estão alive(incluindo você) e um número inteiro que lista o número de bots no starttorneio. Observe que o histórico não inclui laços. A função deve retornar um número inteiro entre 0 e seu hp total atual. Alguns exemplos simples, que ignoram os vínculos, são mostrados abaixo:

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

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

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

Se sua função retornar um número maior que seu hp, ela será redefinida para 0. Sim, é possível se matar. Sua função não deve tentar acessar ou modificar qualquer membro de qualquer objeto da classe RouletteBot. Você não tem permissão para executar nenhuma ação que identifique inequivocamente seu oponente, independentemente de futuros bots adicionais. A inspeção da pilha é permitida desde que seja teoricamente possível que mais de um oponente distinto possa ter produzido as informações que você extrai dela, mesmo que apenas um bot exista atualmente. ou seja, você não pode simplesmente ler a pilha para ver qual função inimiga foi chamada.

Sob essas regras, é possível que não haja vencedor, e os dois últimos competidores se matam. Nesse caso, os dois finalistas ganham meio ponto cada.

Esta é minha primeira tentativa de quebra-cabeça de programação, então críticas são bem-vindas!

O controlador pode ser encontrado aqui .

KBriggs
fonte
4
FWIW, eu pretendo usar uma rede neural treinada em todos os outros bots apenas por diversão uma vez que você configurar o controlador :)
Quintec
2
A verificação de tipo foi feita em benefício do antiantiantiantiupyoursbot. Eu vou encontrar uma outra maneira
KBriggs
3
@ Sarcoma Parece que essa competição provocou uma séria guerra de códigos. Esta competição não terminou, mas já estou ansioso para a evolução disso. Talvez até o próximo passo, a IA aprimorou a concorrência: P
Markov acorrentado
3
WOOOOOOOOOOOOOO!
Sarcoma
5
Meu Deus. O troll deliberado de alterar o mean_kick para sempre retornar zero quando usado em tantos lugares é brilhante.
Magua

Respostas:

12

BinaryBot

Alguém já fez isto? Aposta metade da sua saúde a cada rodada.

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

SarcomaBot

Se a última batalha licitar hp - 1. Se for a primeira rodada de batalha, ofereça meio HP mais um valor aleatório adicional de até um quarto de HP. Se ele puder vencer um lance definitivo do oponente após esse lance, o oponente hp + 1. Se tiver menos pontos de vida do que o lance oponente, o valor aleatório será entre 75% e o atual 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

Pequenos ajustes tentam reduzir o gasto de vida.

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

Atualizar ajuste fino

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

Entrada Final

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

Atualização da
proteção UpYoursBot adicionada

Atualização da
proteção AntiAntiUpYoursBot adicionada

Atualizar
AntiAnitAntiAntiUpYoursBot Estou derrotado

Sarcoma
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Mego
17

UpYours

Chegando atrasado para entrar, passei um tempo admirando os bots existentes, passei um tempo complicando demais as idéias de seus colegas e depois descomplicando-as. Então, veio para mim

Bons artistas copiam, grandes artistas roubam. - Pablo Picasso Me


"Up Yours" porque estou roubando descaradamente (e às vezes colocando um ou dois pontos nos lances dos seus bots para aumentar um deles).

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

Mas, na verdade, essa é uma grande competição, pessoal. Eu amo essa comunidade em dias como esse.

Qfwfq
fonte
11
Hahahaha isso é lindo. Estou indeciso se devo permitir, mas deixarei tocar por enquanto, pois não pensei em dizer que não era permitido. Você errou os nomes das funções em alguns lugares - veja o controlador no github.
21418 KBriggs #
11
Ele faz muito bem, obviamente, mas ainda perde para Bot pontapé
KBriggs
11
Ha, bom esforço!
Sarcoma
11
@ Sarcoma Eu não poderia ter feito isso sem você. ;) Eu também gosto muito do seu bot, amigo.
Qfwfq 03/10/1918
11
Proteção Upyoursbot de Sarcomabot realmente messes com este
KBriggs
15

Kamikaze

Por que se preocupar com lógica complicada quando todos nós vamos morrer de qualquer maneira ...

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


Um disparo

Vai sobreviver pelo menos uma rodada, se não encontrar o kamikaze.

 def one_shot(hp, history, ties, alive):
      if hp == 1:
          return 1
      else:
          return hp - 1
DobromirM
fonte
11
Welp, que era inevitável
KBriggs
Eu estava indo para adicionar um bot pacifista também, mas eu não quero inundar o seu desafio com bots morte cerebral
DobromirM
5
Com base em alguns testes rápidos, o bot do kamikaze não muda muito - tudo o que faz é remover outro bot da rodada aleatoriamente, que, em um número grande de torneios, simplesmente calcula a média de zero. O quente é limpo, no entanto. Sem ele, meu AverageBot tende a fazer o melhor - mas se houver alguns OneShots em jogo, ele inclina a média para números grandes e tende a fazer com que o AverageBots morra rapidamente. O mesmo para LastBot. Você pode realmente mexer com o comportamento de outros robôs distorcendo seus próprios padrões de apostas. Com o OneShot em jogo, o RandomBot vence. Sem ele, o AverageBot vence.
KBriggs
14

O Patetic Bot recebe uma atualização muito necessária:

A tentativa patética de um bot que tenta incorporar os recursos de outros bots

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

Este bot incorpora recursos do Survivalist Bot e Geometric Bot para quedas de bot mais eficientes.

Pré-atualização:

A tentativa patética de um bot que analisa a história de seu oponente

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

Se houver histórico anterior de seu oponente, ele calculará o HP do oponente. Em seguida, siga um destes procedimentos:

  • Se o seu oponente for o último oponente vivo, ele oferecerá um a menos que o seu HP.
  • Se o seu oponente não for o último oponente vivo, mas o oponente tiver menos de 16 hp, ele irá superar o HP do oponente.
  • Se o seu oponente não é o último oponente vivo e há um histórico de empates, ele oferecerá seu HP por estar entediado.
  • Caso contrário, será melhor que seu oponente.

Se não há histórico, ele faz alguns cálculos sofisticados que eu hackeei e lancei. Se o valor exceder 100, então ele lance automaticamente seu hp menos 1.

Eu hackeei esse código juntos durante o trabalho e esta é minha primeira submissão, então provavelmente não vai ganhar nem nada, e vai perder para o kamikaze.

EDIT: Devido a algumas sugestões, o comportamento inicial do bot foi alterado para oferecer um valor mais alto.

EDIT 2: adicionado parâmetro inicial que não faz nada

EDIT 3: Adicionado novo bot de spinoff:

[A tentativa patética de um bot que ataca Gang Bots (além de fazer tudo o que o bot acima faz)] REMOVIDO

[Esse bot analisa se seu oponente é um gangbot ou não e finge ser um também para obter os lances doces e baixos que ele pode superar facilmente.]

Este bot foi descartado. Remova-o das tabelas de classificação.

EDIT 4: Correção de erros, alteração do recurso de empate.

Yodie
fonte
Muito bom, obrigado pelo bot! Vou dar algumas estatísticas quando conseguir mais algumas.
KBriggs
Eu sou um novato em python, então eu não tenho certeza se a sintaxe está correta, não hesite em deixar-me saber se isso acontecer
Yodie
Ele roda, então não se preocupe lá #
KBriggs #
@ Yodie Como uma mini revisão de código: Seu corpo de função deve ser recuado por um nível (necessidade sintática); opp_hp +1falta um espaço para ser pitônico; seus comentários começam com quantidades desequilibradas de espaço em branco. Finalmente, sua função está sem uma sequência de caracteres.
Jonathan Frech
2
Eu acho que esse bot se sai muito bem se passar da primeira rodada, mas como muitas pessoas apostam muito na primeira rodada, ele quase sempre morre mais cedo. Você pode melhorar o desempenho alterando o comportamento inicial para fazer lances mais altos quando não houver histórico. Por exemplo, se você triplicar sua aposta sem histórico, esse bot ganha uma margem confortável entre os concorrentes até agora.
KBriggs
11

Kick Bot

A melhor escolha para o meu oponente é oferecer metade da vida dele. Em seguida, oferecemos lances para metade da vida dele + 1, se não pudermos eliminá-lo com um lance sensato, ou seja, um lance menor que a metade da nossa vida.

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

O chute bot é obviamente o inimigo do soco bot!

Mean Kick Bot

Este novo KickBot chuta mais suave na primeira rodada, apenas para que ele possa chutar mais forte nas próximas rodadas, isso é mau!

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

O irmão dele teve que cometer suicídio, mas o WiseKickBot aprendeu com os que haviam caído.

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
fonte
Agradável. Eu estou vendo um monte de apresentações que diretamente contra outros agora, isso é exatamente o que eu estava esperando
KBriggs
Retorno duplo na última linha?
Veskah
Ah, eu ainda não tinha rodado ou teria percebido isso.
KBriggs
Este assumiu uma liderança confortável!
22418 KBRiggs #
11
@KBriggs aqui está algum backup!
Johan
8

Tat bot

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

Uma tentativa de um equivalente a um bot tit-for-tat. Supõe que a maioria das apostas seja aproximadamente a mesma entre as rodadas. Usando essa suposição, ele tenta derrotar o bot inimigo enquanto permanece bastante econômico. Gasta cerca de 40 pontos de vida na rodada de abertura.

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

Uma solução alternativa para a proteção anti-UpYours do SarcomaBot, cortando a maior parte do código para meu próprio uso! Ou estou usando o código do UpYoursBot? Uma pergunta para refletir enquanto você lê meu bot ...

O AntiAntiUpYours Bot evoluiu para se tornar AntiAntiAntiAntiUpYours Bot! Agora com mais remendos de macacos.

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) 

O bot poli faz uma regressão polinomial no histórico do bot e supera a pontuação prevista em uma pequena quantidade.

Bot elegante

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)

Bot elegante tem se divertido, mas decidiu ir para a cama cedo. Durma bem, bot elegante.

Persona
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Mego
8

1/2 Punch Bot, revisitado

Eu acho que vai morrer muito rapidamente. Vale a pena. Função renomeada, esqueci de mudar o nome lá.

Versão revisitada, melhores chances de ganhar (ainda mais na rodada final) e proteção leve contra bots de quadrilha

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 sofreu bullying demais e até se tornou lacaio do UpYoursBot, então seu irmão mais velho, o StrikerBot , veio ajudar.

Não há muita diferença do 1/2 Punch otimizado, mas ele é um pouco mais inteligente e se saiu bem nas corridas que eu fiz (10k e 35k, embora ele possa perder para o KickbanBot)

A última versão acabou, o tempo acabou. A menos que surjam algumas surpresas, deve garantir o segundo lugar, se não ficar em primeiro lugar (há uma pequena chance de vencer o 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
fonte
Você vai ter que mudar o nome dele, já existe um bot camicase ^ _ ^
KBriggs
Até agora, este é o vencedor, embora
KBriggs
Sua função ceilparece não estar definida.
Jonathan Frech
Mudei para np.ceil () para executá-lo
KBriggs
editada, obrigado pelo heads-up
Belhenix 02/10/1918
7

Gang Bot

A ideia era que potencialmente dois ou mais dos bot pudessem ser usados ​​na mesma simulação. O bot tenta dar "vitórias fáceis" a outros bots da gangue, verificando se sua história é múltipla de 7 lances. Obviamente, isso também pode ser facilmente manipulado por outros bots. Depois, calculo um palpite sobre os lances de bots que não são de gangues com base na proporção entre minha saúde e a deles e a proporção entre a saúde anterior e o lance anterior e adiciono 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
fonte
Muito legal. Quantos são necessários? Eu provavelmente vou ter de limitar o número de entradas ...
KBriggs
Seu bloco de código parece não ter a primeira linha da sua fonte.
Jonathan Frech
Não sei ao certo quantas seriam necessárias em uma simulação, mas se algum dos robôs se encontrar, aumentará a chance de um deles vencer. Eu acho que ter 10% da piscina sendo bots de gangue deve ser suficiente para fazer uma diferença significativa. Além disso, o bloco de código está ausente da primeira linha - este é o meu primeiro post aqui. Não sei por que a formatação fez isso, mas sim, é apenas a declaração do método.
Jim Hat
Você tem um erro: o bot irá identificar qualquer pessoa com len (história)> 1 como um membro da gangue
KBriggs
Meu mal, deve ser corrigido agora.
Jim Hat
6

Pior caso

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

Bot simples. Retorna hp - hp / (start - alive + 4)na maioria dos casos e, em caso de empate, aumenta em 2 (precisa de um!) Para cada empate, certificando-se de não retornar um número acima do seu hp.

Quintec
fonte
Isso falha com a divisão por zero se alive==8. Eu posso alterá-lo manualmente para a contagem total de bots, mas está esticando as regras, já que isso não é uma entrada para sua função - tudo o que você sabe se quantos oponentes restam em um determinado momento, e não com quantos você começou.
KBriggs
Atualizei o concurso com base em sua solicitação
KBriggs 2/18/18
@KBriggs Thanks :)
Quintec
Você também precisa adicionar 1 ao start-alive, já que este é 0 na primeira rodada #
KBriggs #
@KBriggs corrigido, na verdade deveria +2 para que ele não retorne 0, lol
Quintec 2/18
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)

O Bot tentará fazer lances mais altos do que o seu oponente pode oferecer quando possível.

Draco18s
fonte
Existe uma condição where np.random.randint(hp/5, hp/2)pode falhar se hp/5 == hp/2, ou seja, se hp==0ouhp==1
KBriggs
3
Se HP for 0, não devo ser chamado. : P Você está certo sobre o 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

Faz um julgamento sobre quanto de sua saúde deve sacrificar com base no número de bots restantes. Se houver apenas dois bots restantes, ele fará lances hp-1, mas se houver três restantes, ele terá metade disso, quatro restantes, um terço etc.

No entanto, em uma competição muito grande, acho que precisarei fazer lances maiores que 3 ou 4 hp para evitar a morte no primeiro turno, por isso coloquei um limite menor em 10. É claro que ainda nunca lances mais que hp-1.

Ele também adiciona 1,5 hp para empate, pois vejo vários bots "adicionar 1 hp para empate". Não tenho certeza se isso conta como trapaça. Se isso acontecer, eu vou mudar.

Ótima idéia, a propósito!

Spitball Bot 2.0

O que há de novo?

  • Alterou para dividir pelo número de rodadas restantes, em vez do número de bots restantes (obrigado a @Heiteira!). Na verdade, agora estou dividindo pelo número aumentado para o poder .8, de modo a antecipar um pouco mais meus lances.

  • Aumento do lance mínimo de 10 para 20 (Obrigado @KBriggs!)

  • Verificação inserida se o lance de spitball está acima do HP atual do oponente e diminua-o, se for.

(SO não processará o código abaixo como código, a menos que eu coloque texto aqui, então tudo bem)

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
fonte
11
Sua oferta deve ser um inteiro, por isso, enquanto você chão ou ceil seu valor de base para se livrar do decimal é OK
KBriggs
Sim, eu aplico logo após fazer todos os cálculos. Obrigado pela resposta rápida!
MegaWidget
2
Você pode otimizar isso se não estiver dividindo seu hp pelo número de participantes restantes, mas pelo número de rodadas restantes (que deve ser math.ceil (math.log (vivo, 2))
Black Owl Kai
11
Com base em outros bots maioria deles parecem lances carregamento frontal, de modo que este pode melhorar se você aumentar o lance de primeira rodada acima de 10
KBriggs
Essas são boas idéias! Eu não tinha percebido que o número de bot não era o mesmo que o número de rodadas restantes (eu interpretei errado as regras do concurso). Vou tentar implementá-los amanhã. Obrigado!
MegaWidget
5

Geométrico

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)
Mnemônico
fonte
5º lugar na primeira tentativa, nada mau
#
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

Tente maximizar as vitórias com o mínimo de esforço:

  • se pudermos vencer, apenas faça
  • se for a última rodada, não morra tentando
  • caso contrário, não se preocupe

Por quê?

Tente tirar proveito da probabilidade: vencer a primeira rodada jogando baixo é a melhor maneira de começar o torneio. 13 parece ser o ponto ideal: a segunda rodada é uma vitória segura, e o resto é um Spaziergang no parque.

GB
fonte
Você assumiu a liderança, muito bom! Cuidado, convém adicionar proteção contra parasitas, pois os robôs que lideram tornam-se alvos de coisas como o UpYoursBot. Confira o SarcomaBots para obter idéias de proteção, se você precisar delas.
precisa saber é o seguinte
5

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

Primeira postagem aqui. Pareceu muito divertido, então estou enviando minha tentativa além do terrível e adivinhando o que os outros bots vão apostar.

Editar 1: Adicionado outro 1 à primeira aposta, simplesmente para reduzir a chance de empate com outras pessoas que apostam 51.

Edit 2: Roubou o movimento de abertura do bot de Sarcoma, pois ele tinha uma boa chance de não ser eliminado primeiro de forma consistente.

Edit 3: Bot sobrevive muito bem no primeiro turno, mas está sendo destruído facilmente nos estágios posteriores. Mudou a maneira como o robô pensa sobre o segundo turno agora que os meio-apostadores estão mortos na água.

Edit 4: Agora que o primeiro turno está bom, mudei a maneira como ele lida com o segundo turno. Morrendo muito no segundo turno, então eu preciso sobreviver de alguma forma.

Blood Bot

Fez um bot com sede procurando uma morte. A idéia é tentar vencer os bots de baixa aposta e, após o banho de sangue do primeiro turno, deve ser imparável, já que deve ter uma quantidade enorme de HP para superar os inimigos.

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)
Markov Chained
fonte
2
Eu acho que len (history) * len (history) pode ser alterado para len (history) ** 2 se meu conhecimento de python estiver correto.
Yodie
Você tem uma divisão por zero para quando len (history) == 0
KBriggs #
O código foi atualizado. Ao não encontrar histórico, ele vai para o primeiro ponto #
Markov Chained
oi .............
Sarcoma
2
@ Sarcoma, é um mundo bot cruel!
Markov acorrentado
5

meh_bot

Apenas ofereça um pouco mais da metade do seu 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
fonte
Existem alguns bots existentes para tirar proveito desse comportamento, por isso é difícil ganhar força!
precisa saber é o seguinte
@KBriggs feito algum update, eu não estava esperando a primeira versão a fazer, assim como ele fez, espero, esta actualização vai dar-lhe uma mais chance de lutar
meh Man
Uau, isso fez uma grande diferença, acho que você está em primeiro. A atualização será publicada em alguns minutos. Pode ser necessário fornecer ao seu bot um sistema imunológico (consulte SarcomaBot) se você continuar a executar isso bem.
precisa saber é o seguinte
@KBriggs Eu não esperava fazer isso bem, pensei que seria o top 10. De qualquer forma, adicionei outro apenas para ver o efeito no primeiro turno hp. Você pode executar os dois para que eu possa ver o resultado de ambos? Obrigado
meh Man
@KBriggs Por favor, faça este também, 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

Esse bot faz uma análise simples da história do bot inimigo ou oferece metade dos pontos de vida restantes

Belgabad
fonte
4

Faça lances mais altos quanto menos concorrência você tiver. Agradecemos aos comentaristas por sugerirem melhorias.

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
fonte
11
Boa ideia, mas vejo duas questões. Um é a maioria dos outros bots que oferecem lances grandes no primeiro turno, portanto esse provavelmente morrerá cedo na maior parte do tempo. A segunda é que na final, a maioria dos bots oferece lances de hp-1, de modo que este os perderá, a menos que você tenha o dobro deles. Mas para as rodadas intermediárias, gosto da ideia. Se você abordar os dois casos especiais, provavelmente poderá melhorar o desempenho.
22418 KBRiggs #
4

SurvivalistBot e HalvsiesBot

Obrigado por responder às minhas perguntas. O resultado final é um bot mais complexo.

HalvsiesBot é um bot caprichoso 'apenas continue passando pela metade' com 50/50 de chance de ganhar. Eu acho.

O SurvivalistBot toma uma série de decisões caso-outra da árvore binária com base no conjunto de dados, incluindo uma substituição em um empate (se atingir 2 empates, kamikazes para evitar a morte do empate triplo).

Meu python está um pouco enferrujado; portanto, o código pode ser um pouco complicado, portanto, fique à vontade para corrigi-lo ou atualizá-lo.

Ele foi criado para tentar calcular bits de dados para inferir coisas como a quantidade de HP restante, o número mínimo de bots com os quais é provável que ele lute, quantidade mínima de HP que sai, lances médios. Ele também explora a randomização em situações ambíguas, como peças de abertura ou problemas ideais de lances.

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
fonte
Opponent_Average_Bid = Opponent_Remaining_HP / float(len(history)) ZeroDivisionError: float division by zero. Esta linha precisa lidar com o caso do histórico de 0 comprimento.
22418 KBriggs #
Obrigado, eu vou corrigi-lo.
SSight3
Fixo. Deixe-me saber se existem outros erros.
SSight3
11
Par de erros de sintaxe: em falta: `depois else, math.[func] -> np.[func]e em um ponto você usar Lowestonde você quer dizer LowestBid. Tudo corrigido no controlador no github e pontuações atualizadas em breve.
22418 KBriggs #
Obrigado. Corrigidos todos os erros acima mencionados na postagem.
SSight3
4

Calculando 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 de cálculo agressivo

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

Anti Kick Bot

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

Se conseguirmos prever as ações do oponente, podemos fazer as melhores apostas! Se não pudermos (dados insuficientes ou oponente são muito aleatórios), podemos pelo menos fazer o que maximizaria nosso potencial de vitória. Teoricamente, pelo menos metade do número de bots vivos morrerá a cada rodada. Assim, posso esperar que haja no máximo log2 (vivo) rodadas. Idealmente, dividiríamos nosso HP igualmente entre todas as rodadas. No entanto, sabemos que alguns bots serão estúpidos e se suicidam / morrem cedo, por isso devemos apostar um pouco mais nas rodadas anteriores.

Cálculo agressivo do bot Modifica o código do calculador do bot para tentar permanecer vivo, sendo mais agressivo, à custa da saúde a longo prazo. Somente simulações dirão se o tempo ou o valor vence.

O Anti Kick Bot deve sempre vencer o atual líder KickBot: P

EDIT: Substituído Bot determinístico por Anti Kick Bot, um bot mais inteligente com quase exatamente os mesmos valores de retorno. Também impediu votar mais do que os adversários HP

Bob Cratchit
fonte
Fofa. Eu acho que este será melhor com um pool de bot muito grande.
21418 KBRiggs #
Eu recebo um erro, por vezes com esta: return np.max(theoreticalBet, hp - 1): AxisError: axis 23 is out of bounds for array of dimension 0. Publiquei um link para o controlador para que você possa testá-lo.
21418 KBRiggs #
@KBriggs Atualizou o código para corrigi-lo.
Bob Cratchit
11
confirmada, atualização de pontuação recebida. Você está no top 10, com certeza.
21818 KBriggs #
@KBriggs eu adicionei mais um par de bots para experimentar :)
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))

É muito tarde ... Estou cansado ... não consigo pensar em um nome ... e o formato desse bot é muito parecido com os outros, apenas com um algoritmo ligeiramente diferente, dado o histórico. Ele tenta obter a taxa atual que o oponente está tendendo para jogar ... ou algo assim ... zzz

Quintec
fonte
você precisa usar em np.maximumvez de np.max, o mesmo paramin
KBriggs
@KBriggs obrigado :) Hmm, parece que os bots genéricos governar este jogo
Quintec
Parece que eles seriam alvos muito fáceis, estou surpreso que ninguém fez um parasita ainda
KBriggs
@KBriggs Sim, estou surpreso. Hora de adicionar proteções ...
Quintec
Ainda pensando em fazer o neuralbot?
KBriggs
4

HalflifeS3

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

Coast Bot [Aposentado]

Tentará percorrer o caminho da competição dividindo uniformemente seu hp entre as rodadas. Oferecerá qualquer HP restante no primeiro turno para ter uma chance melhor de chegar às rodadas "com capacidade para o litoral".

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

Como eu gosto muito desse desafio, eu apenas tive que fazer outro bot. Esta versão sacrifica parte de seu hp mais tarde, usando mais hp nas duas primeiras rodadas.

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

Tenta calcular a porcentagem média de hp gasto pelo adversário e faz lances com base nisso.

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
fonte
Idéia bem legal. Despedir a primeira rodada é uma nova tendência em bots e parece estar funcionando razoavelmente bem.
precisa saber é o seguinte
@KBriggs Atualizei esta resposta para conter minha segunda tentativa. Mencionando você de acordo com as novas regras. Grande quebra-cabeça btw!
Wazz
Deseja que eu insira ambos, ou apenas a versão mais recente? No momento, é apenas V2
KBriggs
@KBriggs Eu gostaria que os dois entrassem se estiver tudo bem, por favor. Seria bom ver como eles se pesam.
Wazz
Desempenho geral bastante semelhante
KBriggs # 418
4

ConsistentBot

Aposta o mesmo valor a cada rodada. Não é muito provável que sobreviva às primeiras rodadas, mas se tiver sorte o suficiente para chegar ao fim, ainda deve haver uma quantidade razoável de HP restante.

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 - Restabelecer Monica
fonte
Filhote, é tarde demais para consertá-lo agora, mas meu bot usou HP suficiente para chegar ao fim de lutar contra cada oponente uma vez, para não chegar à última rodada. P
Kevin - Reinstate Monica
4

Kickban Bot

Este bot simplesmente tenta combater o atual líder Mean Kickbot, vencendo-o na primeira rodada e jogando de forma mais agressiva a partir de então, se o reconhecer.

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
fonte
11
Eu acho que seu recuo está um pouco errado.
Jonathan Frech 5/10
oops, obrigado, editor de código estranho mexeu com a primeira linha
HRSE
uma valiosa lição de confiar código que você não controla
OganM
4

Bot de três quartos

Ele não vai vencer o MehBot ou o SarcomaBot (s), mas acho que ele se sai muito bem. Quando vi o desafio pela primeira vez, essa foi a primeira coisa que me veio à mente: sempre * aposte três quartos da sua saúde, a menos que não haja motivo para isso.

* após baixa bola no primeiro turno.

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

    if alive == 2:
        return hp - 1

    opponent_hp = 100 - sum(history)

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

    return threeQuarters

Four Sevenths Bot

Após o sucesso moderado de 3/4 de bot, há uma nova fração na cidade, é apenas racional.

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

A fração perfeita

Eu sou inteiro

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
fonte
Com base nessas probabilidades de eliminação, você provavelmente também pode se dar bem com lances menores na segunda rodada. Este faz bem, mas alguns pequenos ajustes podem torná-lo muito melhor.
precisa saber é o seguinte
@KBriggs Adicionado um novo bot com chances novas e aprimoradas;)
Joshua Webb
Quer os dois lá, ou apenas 1?
precisa saber é o seguinte
@KBriggs Eu não sei se eu perdi o prazo, mas eu adicionei um bot final, se eu fiz isso no tempo, você pode remover os outros dois bots fração
Joshua Webb
11
Sim, você ainda tem tempo #
KBriggs # 618
4

BandaidBot

BandaidBot quer que todos joguem bem! Se o seu oponente foi bom na última rodada, ele se sacrificará para incentivar um bom comportamento nos outros. Se seu oponente foi malvado na última rodada, ele causará o máximo de dano possível ao oponente, sacrificando-se, se necessário. Oferece um terço do seu hp se não tiver histórico para trabalhar. (Espero que esse bot tenha efeitos interessantes em outras estratégias, não tanto que ele tenha uma alta taxa de vitórias. Pode ser divertido ter alguns deles em jogo)

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 será tão bom quanto necessário para tirar vantagem do BandaidBot. Ele retornará pouco menos de um terço do seu HP, a menos que possa matar seu oponente por menos do que isso. Se o seu oponente se parecer com o BandaidBot, ele fará um lance 2, sabendo que o BandaidBot fará um lance 1 porque o GetAlongBot está se dando tão bem com todos os outros - uma vitória fácil, desde que realmente fosse o BandaidBot do outro lado.

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
fonte
Idéia realmente legal. Gostaria de saber quanto impacto que comprovadamente têm
KBriggs
erro: return np.random.randint(history[-1], hp/2): ValueError: low >= highEste caso precisa ser tratado de alguma forma
KBriggs 6/18
@KBriggs deve ser corrigido agora!
Maya Sol
@KBriggs atualizada para correção randomização
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

Esse bot tenta manter seu valor favorito de 10, mas muda sua escolha ocasionalmente, se necessário, para romper um empate (com seu valor favorito duplicado ou quádruplo) ou para economizar nas próximas rodadas, mas não na quantidade ideal, pois deseja confundir oponentes e não deseja considerar licitar menos de 2 a qualquer momento, pois está convencido de que é muito melhor do que esperar que o oponente lance menos de 1, ou seja, 0.

PS: este bot pode ter problemas estratégicos se houver mais de 2 ^ 9 bots.

AlexRacer
fonte
Eu suspeito que você não precisa se preocupar em ter 2 ^ 9 oponentes ^ _ ^.
22418 KBriggs #
Mas com uma aposta de 10 de abertura, ele raramente vai fazê-lo após a primeira rodada
KBriggs
Esse bot pensa que, se algum bot realmente quiser dar mais de 10 hp no primeiro turno, não vale a pena lutar.
AlexRacer 02/10
Haha justo o suficiente
KBriggs
3

CautiousBot

Primeira submissão para os quebra-cabeças de programação de todos os tempos! Achei seu desafio bastante interessante: P

Se a última rodada tiver um bit abaixo de hp, se nenhum histórico apostar meio hp mais uma pequena quantia aleatória.

Se o histórico verificar hp do oponente e o número de rodadas restantes e tentar superar o hp / 2 do oponente usando um buffer adicional de até a fração do hp restante dividido pelo número de rodadas restantes (ele tenta conservar o hp restante de alguma forma nas rodadas posteriores) . Verifique se você está gastando muito hp (não se mate ou lance mais do que o seu adversário pode).

Sempre corrija os laços como outros bots.

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

Muito agressivo nas primeiras rodadas, agora o CautiousBot fica ainda mais cauteloso ...

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
fonte
Você tem um bug onde ainda está chamando randint quando o buffer = 0: buffer_bet = np.random.randint(0, buffer) if buffer > 0 else 0 File "mtrand.pyx", line 993, in mtrand.RandomState.randint ValueError: low >= high. Observe que buffer é uma palavra-chave em python; convém escolher um nome de variável diferente.
precisa saber é o seguinte
Oh, parece que é porque o buffer nem sempre é um int - você provavelmente está dividindo por zero em algum momento. Por favor, verifique a lógica cuidadosamente. Eu fiz funcionar, mas você provavelmente pode consertar os casos de canto.
22418 KBRiggs #
Boa captura @KBriggs. Acho que eu consertei.
Jesús Ros
Eu ainda recebo um erro: buff_bet = np.random.randint(0, buff) if buff > 0 else 0 File "mtrand.pyx", line 993, in mtrand.RandomState.randint ValueError: low >= high. Parece que o buff às vezes é um número de ponto flutuante entre 0 e 1, que presumivelmente é convertido em 0 por dentro randint. Isso funciona se você converter buffpara intantes da chamada #
KBriggs # 418
@KBriggs provavelmente porque ceilretorna a float. Perdeu aquele ... Ty novamente: P
Jesús Ros
3

Tudo bem, vou tentar minha mão nisso.

SnetchBot

Verificando as frações de saúde com as quais o oponente está passando. Se o oponente estiver aumentando, derrote-o.

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

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

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

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

EDIT: perdendo muito no primeiro turno, ajustado os limites aleatórios do primeiro turno

arrebatar
fonte
Muito bom primeiro tiro, atualizar pontuação recebida
KBriggs
@KBriggs Editou um pouco (apenas os limites aleatórios da primeira rodada). Embora eu já estivesse surpreso por ter chegado ao décimo lugar. Se este faz pior, eu vou apenas rolar de volta para a primeira: D
snetch
Você apertar um pouco mais suco fora dele
KBriggs
3

SquareUpBot

Não parecia que muitos bots estavam jogando com poderes em vez de frações, então eu decidi fazer um, com algumas otimizações padrão e ver onde irei colocar. Bastante simplista.

Também tenta determinar se o bot inimigo não está tentando usar uma fração constante, porque poderes > frações .

EDIT: Eu sou um manequim e meu detector de frações não pôde funcionar. Reparado agora.

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
Pó de diamante
fonte
Não é um mau primeiro tiro, a pontuação foram atualizados
KBriggs
@KBriggs Atualizei o bot para que o detector de frações realmente funcione.
Diamond Dust