Ruleta de robot: apuestas de robot de alto riesgo


56

Clasificación final

+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +
El | Nombre | Puntuación | WinRate | TieRate | Probabilidad de eliminación |
+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +
El | 1. SarcomaBotMk11 | 0,06333 | 6,13% | 0,41% | [42 24 10 8 6 4]% |
El | 2. WiseKickBot | 0,06189 | 5,91% | 0,56% | [51 12 7 10 7 6]% |
El | 3. StrikerBot | 0,05984 | 5,78% | 0,41% | [46 18 11 8 6 5]% |
El | 4. PerfectFractionBot | 0,05336 | 5,16% | 0,35% | [49 12 14 10 6 4]% |
El | 5. MehRanBot | 0,05012 | 4,81% | 0,41% | [57 12 8 7 6 5]% |
El | 6. OgBot | 0,04879 | 4.66% | 0,45% | [50 15 9 8 7 5]% |
El | 7. SnetchBot | 0,04616 | 4,48% | 0.28% | [41 29 8 9 5 3]% |
El | 8. AntiKickBot | 0,04458 | 4,24% | 0,44% | [20 38 17 10 6 4]% |
El | 9. MehBot | 0,03636 | 3,51% | 0.25% | [80 3 4 4 3 3]% |
El | 10. Meh20Bot | 0,03421 | 3,30% | 0.23% | [57 12 8 7 9 3]% |
El | 11. GenericBot | 0,03136 | 3.00% | 0.28% | [18 39 20 11 5 3]% |
El | 12. HardCodedBot | 0,02891 | 2,75% | 0.29% | [58 21 3 6 5 4]% |
El | 13. GangBot1 | 0,02797 | 2,64% | 0,32% | [20 31 35 6 3 2]% |
El | 14. SarcomaBotMk3 | 0,02794 | 2,62% | 0,34% | [16 15 38 17 7 4]% |
El | 15. GangBot0 | 0,02794 | 2,64% | 0,30% | [20 31 35 6 3 2]% |
El | 16. GangBot2 | 0,02770 | 2,62% | 0,31% | [20 31 35 6 3 2]% |
El | 17. TitTatBot | 0,02740 | 2,63% | 0.21% | [54 10 15 10 5 2]% |
El | 18. MataHari2Bot | 0,02611 | 2,35% | 0,51% | [39 26 11 11 6 5]% |
El | 19. PolyBot | 0,02545 | 2,41% | 0.27% | [53 18 6 13 5 3]% |
El | 20. SpitballBot | 0,02502 | 2,39% | 0.22% | [84 10 1 1 0 1]% |
El | 21. SquareUpBot | 0,02397 | 2,35% | 0,10% | [10 60 14 7 4 3]% |
El | 22. CautiousGamblerBot2 | 0,02250 | 2,19% | 0,13% | [60 18 10 5 3 1]% |
El | 23. Bot13 | 0,02205 | 2,15% | 0,11% | [90 0 2 3 2 1]% |
El | 24. AggroCalcBot | 0,01892 | 1,75% | 0.29% | [26 49 13 5 3 3]% |
El | 25. CautiousBot | 0,01629 | 1,56% | 0.14% | [15 41 27 11 4 1]% |
El | 26. CoastBotV2 | 0,01413 | 1,40% | 0,02% | [83 12 3 1 0 0]% |
El | 27. CalculatingBot | 0,01404 | 1,29% | 0.22% | [87 9 1 1 1 1]% |
El | 28. HalfPunchBot | 0,01241 | 1,15% | 0,18% | [47 20 13 12 5 2]% |
El | 29. HalflifeS3Bot | 0,01097 | 1,00% | 0,20% | [76 9 5 4 2 2]% |
El | 30. AntiGangBot | 0,00816 | 0,76% | 0,11% | [94 1 1 1 1 1]% |
El | 31. GeometricBot | 0,00776 | 0,74% | 0,07% | [19 46 25 7 2 1]% |
El | 32. GuessBot | 0,00719 | 0,05% | 1,34% | [65 17 4 6 5 3]% |
El | 33. BoundedRandomBot | 0,00622 | 0,60% | 0,05% | [42 39 12 5 2 0]% |
El | 34. SpreaderBot | 0,00549 | 0,54% | 0,02% | [32 43 19 4 1 0]% |
El | 35. DeterminBot | 0,00529 | 0,45% | 0.16% | [22 41 20 11 4 2]% |
El | 36. PercentBot | 0,00377 | 0,38% | 0.00% | [85 8 4 2 1 0]% |
El | 37. HalvsiestBot | 0,00337 | 0.29% | 0,08% | [32 43 15 6 2 1]% |
El | 38. GetAlongBot | 0,00330 | 0,33% | 0,01% | [76 18 4 1 0 0]% |
El | 39. BandaidBot | 0,00297 | 0.29% | 0,02% | [76 9 10 4 1 0]% |
El | 40. TENaciousBot | 0,00287 | 0.29% | 0.00% | [94 4 1 0 0 0]% |
El | 41. SurvivalistBot | 0,00275 | 0.25% | 0,04% | [92 6 1 0 0 0]% |
El | 42. RandomBot | 0,00170 | 0,13% | 0,07% | [42 36 14 5 2 1]% |
El | 43. AggressiveBoundedRandomBotV2 | 0,00165 | 0.14% | 0,06% | [8 46 34 9 2 1]% |
El | 44. BloodBot | 0,00155 | 0,01% | 0,30% | [65 28 5 1 1 0]% |
El | 45. OutBidBot | 0,00155 | 0,03% | 0.25% | [65 6 21 6 1 1]% |
El | 46. ​​BoxBot | 0,00148 | 0,10% | 0,09% | [10 51 33 5 1 1]% |
El | 47. LastBot | 0,00116 | 0,08% | 0,07% | [74 6 16 2 1 0]% |
El | 48. UpYoursBot | 0,00088 | 0,07% | 0,03% | [37 40 17 5 1 0]% |
El | 49. AverageBot | 0,00073 | 0,06% | 0,03% | [74 3 10 10 2 0]% |
El | 50. PatheticBot | 0,00016 | 0,01% | 0,02% | [94 0 5 1 0 0]% |
El | 51. OverfittedBot | 0,00014 | 0,01% | 0.00% | [58 40 2 0 0 0]% |
El | 52. RobbieBot | 0,00009 | 0,01% | 0.00% | [32 41 24 2 0 0]% |
El | 53. WorstCaseBot | 0,00002 | 0.00% | 0.00% | [4 71 23 2 0 0]% |
El | 54. SmartBot | 0,00002 | 0.00% | 0.00% | [44 51 5 0 0 0]% |
El | 55. AAAAUpYoursBot | 0,00000 | 0.00% | 0.00% | [40 58 2 0 0 0]% |
El | 56. KickbanBot | 0,00000 | 0.00% | 0.00% | [67 32 1 0 0 0]% |
El | 57. OneShotBot | 0,00000 | 0.00% | 0.00% | [2 95 3 0 0 0]% |
El | 58. KickBot | 0,00000 | 0.00% | 0.00% | [100 0 0 0 0 0]% |
El | 59. KamikazeBot | 0,00000 | 0.00% | 0.00% | [100 0 0 0 0 0]% |
El | 60. MeanKickBot | 0,00000 | 0.00% | 0.00% | [100 0 0 0 0 0]% |
+ ---------------------------------- + --------- + ---- ----- + --------- + ---------------------------- +

¡Gracias a todos los que participaron y felicidades a @Sarcoma por la victoria!

Reglas:

Todos comienzan con 100 hp. En cada ronda, se eligen al azar 2 jugadores del grupo de concursantes que aún no han competido en esa ronda. Ambos jugadores eligen un número entre 0 y su HP actual, y revelan esos números al mismo tiempo. El jugador que eligió el número más bajo muere inmediatamente. El otro jugador resta su número elegido de sus CV restantes y pasa a la siguiente ronda.

El torneo funciona así:

Del grupo de concursantes, 2 son elegidos al azar. Se enfrentan y uno o ambos mueren. Un jugador muere si:

  1. Eligen un número más pequeño que el de su oponente.
  2. Su CV cae a cero o menos
  3. Empatan tres veces seguidas con su oponente

En el caso de los empates, ambos jugadores simplemente generan nuevos números, hasta 3 veces. Después del enfrentamiento, el sobreviviente (si lo hay) es trasladado al grupo para la siguiente ronda, y el proceso se repite hasta que hayamos agotado el grupo de ronda actual. Si hay un número impar en el grupo, entonces el número impar pasa a la siguiente ronda de forma gratuita.

Su tarea es escribir una función en python2.7 que tome como entradas su actual hp, una lista de la oferta de su oponente historyy un número entero tiesque le indica cuántas veces ya ha empatado con su oponente actual, y un número entero que le dice cómo todavía hay muchos bots alive(incluido usted) y un número entero que enumeró el número de bots en startel torneo. Tenga en cuenta que la historia no incluye lazos. La función debe devolver un número entero entre 0 y su hp total actual. A continuación se muestran algunos ejemplos simples, que ignoran los lazos:

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

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

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

Si su función devuelve un número mayor que su HP, se restablecerá a 0. Sí, es posible suicidarse. Su función no debe intentar acceder o modificar ningún miembro de ningún objeto de la clase RouletteBot. No tienes permitido realizar ninguna acción que identifique inequívocamente a tu oponente, independientemente de futuros bots adicionales. La inspección de la pila está permitida siempre y cuando sea teóricamente posible que más de un oponente distinto pueda haber producido la información que obtienes de ella, incluso si actualmente solo existe un bot que pueda. es decir, no puedes leer la pila para ver qué función enemiga se llamó.

Según estas reglas, es posible que no haya un ganador, y los dos últimos concursantes se matan entre sí. En ese caso, ambos finalistas obtienen medio punto cada uno.

Este es mi primer intento de rompecabezas de programación, ¡así que las críticas son bienvenidas!

El controlador se puede encontrar aquí .


44
FWIW, planeo usar una red neuronal entrenada en todos los otros bots solo por diversión una vez que configure el controlador :)
Quintec

2
La verificación de tipo fue en beneficio de antiantiantiantiupyoursbot. Encontraré otra manera
KBriggs el

3
@ Sarcoma Parece que esta competencia ha desencadenado una seria guerra de códigos. Esta competencia no ha terminado, pero ya estoy deseando que evolucione. Tal vez incluso el siguiente paso, la IA mejoró la competencia: P
Markov encadenado el

3
WOOOOOOOOOOOOOO!
Sarcoma

55
Oh Dios mío. El trolling deliberado de cambiar mean_kick para siempre devolver cero cuando se usó en tantos lugares es brillante.
Magua

Respuestas:


12

BinaryBot

¿Alguien ha hecho esto todavía? Apuesta la mitad de su salud cada ronda derribada.

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

SarcomaBot

Si la última batalla ofreció hp: 1. Si es la primera ronda de batalla, ofrezca medio hp más una cantidad aleatoria adicional de hasta un cuarto de hp. Si puede vencer a un oponente con una oferta directa después de esa oferta, el oponente hp + 1. Si tiene una salud menor que la cantidad aleatoria de la oferta del oponente entre 75% y su actual 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

Ajustes menores intentan reducir el 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

Actualizar 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

Actualización de
protección UpYoursBot agregada

Actualización de la
protección AntiAntiUpYoursBot agregada

Actualizar
AntiAnitAntiAntiUpYoursBot Estoy derrotado


Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
Mego

17

UpYours

Llegando tarde para ingresar, pasé un tiempo admirando los bots existentes, pasé un tiempo complicando demasiado las ideas de sus muchachos, luego las descompuse en exceso. Entonces vino a mí

Buenos artistas copian grandes artistas roban. - Pablo Picasso Me


"Up Yours" porque estoy robando descaradamente (y algunas veces agregando un punto o dos en las ofertas de tus bots para aumentarlos).

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

Pero de verdad, esta es una gran competencia, muchachos. Amo a esta comunidad en días como este.


1
Jajajaja esto es hermoso. Estoy indeciso si debería permitirlo, pero lo dejaré jugar por ahora ya que no pensé decir que no estaba permitido. Te equivocaste en los nombres de las funciones en algunos lugares: mira el controlador en github.
KBriggs el

1
Obviamente, lo hace muy bien, pero todavía pierde ante Kick Bot
KBriggs el

1
Ja, buen esfuerzo!
Sarcoma

1
@ Sarcoma No podría haberlo hecho sin ti. ;) También me gusta mucho tu bot, amigo.
Qfwfq

1
La protección Upyoursbot de Sarcomabot realmente se mete con esta
KBriggs el

15

Kamikaze

¿Por qué molestarse con una lógica complicada cuando todos vamos a morir de todos modos ...

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


Un trago

Sobrevivirá al menos una ronda si no encuentra el kamikaze.

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

11
Welp, eso era inevitable
KBriggs

Iba a agregar un robot pacifista también, pero no quiero inundar tu desafío con robots con muerte cerebral
DobromirM

55
Basado en algunas pruebas rápidas, el bot kamikaze no cambia mucho, todo lo que hace es eliminar otro bot de la ronda al azar, que, en un número suficientemente grande de torneos, simplemente promedia a cero. Sin embargo, el One hot está limpio. Sin él, mi AverageBot tiende a dar lo mejor, pero si hay algunos OneShots en juego, sesga el promedio hacia grandes números y tiende a hacer que los AverageBots mueran rápidamente. Lo mismo para LastBot. Realmente puede meterse con el comportamiento de otros robots sesgando sus propios patrones de apuestas. Con OneShot en juego, RandomBot gana. Sin él, AverageBot gana.
KBriggs

14

Pathetic Bot obtiene una actualización muy necesaria:

El intento patético de un bot que intenta incorporar las características de otros 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 características de Survivalist Bot y Geometric Bot para derribos de bot más eficientes.

Pre-actualización:

El intento patético de un bot que analiza la historia de su 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

Si hay un historial previo de su oponente, entonces calcula el HP de su oponente. Luego, realiza una de las siguientes acciones:

  • Si su oponente es el último oponente vivo, entonces ofertará uno menos que su HP.
  • Si su oponente no es el último oponente vivo pero el oponente tiene menos de 16 hp, entonces superará a los hp de su oponente.
  • Si su oponente no es el último oponente vivo y hay un historial de empates, entonces ofrecerá su HP porque está aburrido de los empates.
  • De lo contrario, superará a su oponente.

Si no hay historial, entonces hace algunos cálculos sofisticados que pirateé juntos y los oferta. Si el valor excede 100, entonces automáticamente ofrece su hp menos 1.

Pirateé este código juntos durante el trabajo y esta es mi primera presentación, por lo que probablemente no gane ni nada, y perderá ante el kamikaze.

EDITAR: debido a algunas sugerencias, el comportamiento inicial del bot ha cambiado para ofrecer un valor más alto.

EDIT 2: parámetro de inicio agregado que no hace nada

EDITAR 3: Se agregó un nuevo bot spin-off:

[El intento patético de un bot que ataca a Gang Bots (además de hacer todo lo que hace el bot anterior)] ELIMINADO

[Este bot analiza si su oponente es un gangbot o no y pretende ser uno también para obtener las dulces ofertas bajas que puede superar fácilmente.]

Este bot ha sido descartado, por favor quítelo de las tablas de clasificación.

EDIT 4: errores corregidos, función de empate cambiada.


Muy bien, gracias por el bot! Daré algunas estadísticas cuando obtenga algunas más.
KBriggs

Soy un novato en Python, así que no estoy seguro de si la sintaxis es correcta, no
dudes en

Funciona, así que no te preocupes allí
KBriggs

@Yodie Como una mini revisión de código: el cuerpo de su función debe estar sangrado por un nivel (necesidad sintáctica); opp_hp +1le falta un espacio para ser pitónico; sus comentarios comienzan con cantidades desequilibradas de espacios en blanco. Finalmente, su función carece de una cadena de documentación.
Jonathan Frech

2
Creo que este bot funciona bastante bien si supera la primera ronda, pero debido a que muchas personas apuestan mucho en la primera ronda, casi siempre muere temprano. Puede mejorar el rendimiento cambiando el comportamiento inicial para ofertar más cuando no hay historial. Por ejemplo, si triplica su apuesta sin historial, este bot gana por un margen cómodo entre los concursantes hasta el momento.
KBriggs

11

Kick Bot

La mejor opción para mi oponente es apostar la mitad de su vida. Luego ofertamos hasta la mitad de su vida + 1 si no podemos eliminarlo con una oferta sólida, que es una oferta menor a la mitad de nuestra 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))

¡El kick bot es obviamente el enemigo del punch bot!

Mean Kick Bot

Este nuevo KickBot patea más suave en la primera ronda para que pueda patear más fuerte en las siguientes rondas, ¡eso es malo!

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

Sabio Kick Bot

Tanto su hermano tuvo que suicidarse, pero WiseKickBot aprendió de los caídos.

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

Agradable. Estoy viendo muchas presentaciones que contrarrestan directamente a otros ahora, eso es exactamente lo que esperaba
KBriggs

Doble retorno en la última línea?
Veskah

Ah, aún no lo había ejecutado o lo habría captado.
KBriggs

¡Este ha tomado una ventaja cómoda!
KBriggs

1
@KBriggs aquí hay una copia de seguridad!
Johan

8

Tat bot

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

Un intento de un equivalente de un bot tit-for-tat. Asume que la mayoría de las apuestas son aproximadamente iguales entre rondas. Usando esa suposición, intenta vencer al bot enemigo mientras se mantiene bastante frugal. Gasta alrededor de 40 de salud en la primera ronda.

AntiAntiAntiAntiUpYoursBot

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

Una solución para la protección anti-UpYours de SarcomaBot, ¡robando la mayor parte de su código para mi propio uso! ¿O estoy tomando el código de UpYoursBot? Una pregunta para reflexionar mientras lees mi bot ...

¡AntiAntiUpYours Bot ha evolucionado para convertirse en AntiAntiAntiAntiUpYours Bot! Ahora con más parches de mono.

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) 

Polybot realiza una regresión polinómica en el historial de tu bot y supera la puntuación prevista en una pequeña cantidad.

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)

El robot con clase lo ha pasado bien, pero ha decidido acostarse temprano. Duerme bien, elegante bot.


Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
Mego

8

1/2 Punch Bot, revisitado

Creo que morirá bastante rápido. Vale la pena. Función renombrada, olvidé cambiar el nombre allí.

La versión revisada está disponible, mejores posibilidades de ganar (aún más en la ronda final) y una ligera protección contra los bots de pandillas

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 fue intimidado demasiado e incluso se convirtió en un lacayo para UpYoursBot, por lo que su hermano mayor, el StrikerBot , vino a ayudar.

No es una gran diferencia con 1/2 Punch optimizado, pero es un poco más inteligente y lo hizo bien en las carreras que hice (10k y 35k, aunque podría perder con KickbanBot)

Se acabó la última versión, se acabó el tiempo. A menos que surjan algunas sorpresas, debería asegurar el segundo lugar, si no es el primero (hay una pequeña posibilidad de vencer a 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

Tendrás que cambiarle el nombre, ya hay un bot kamikaze ^ _ ^
KBriggs

Hasta ahora, este es el ganador, sin embargo
KBriggs

Su función ceilparece no estar definida.
Jonathan Frech

Cambié a np.ceil () para ejecutarlo
KBriggs

editado, gracias por el
aviso

7

Gang Bot

La idea era que potencialmente dos o más bot podrían usarse en la misma simulación. El bot intenta dar "victorias fáciles" a otros bots de la pandilla, al ver si su historial es múltiplo de 7 ofertas. Por supuesto, esto también podría ser fácilmente manipulado por otros bots. Luego calculo una suposición sobre las ofertas de bots que no pertenecen a pandillas en función de la relación de mi salud con la de ellos y la relación de su salud anterior con su oferta anterior y agrego 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

Muy genial. Cuantos se necesitan? Probablemente tendré que
limitar

Su bloque de código parece perder la primera línea de su fuente.
Jonathan Frech

No estoy seguro de cuántos se necesitarían en una simulación, pero si alguno de los bots alguna vez se ven, deberían aumentar las posibilidades de que uno de ellos gane. Supongo que tener el 10% del grupo siendo bots de pandillas debería ser suficiente para hacer una diferencia significativa. Además, al bloque de código le falta la primera línea:> esta es mi primera publicación aquí. No sé por qué el formato lo hizo, pero sí, es solo la declaración del método.
Jim Hat

Tiene un error: el bot identificará a cualquier persona con len (historial)> 1 como miembro de una pandilla
KBriggs

Mi mal, debería arreglarse ahora.
Jim Hat

6

Peor de los casos

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

Bot simple Se devuelve hp - hp / (start - alive + 4)para la mayoría de los casos, y en caso de empate, aumenta en 2 (¡tengo uno arriba!) Para cada empate, asegurándose de no devolver un número por encima de él hp.


Esto falla con dividir por cero si alive==8. Puedo cambiarlo manualmente al recuento total de bots, pero está estirando las reglas ya que eso no es una entrada para tu función: todo lo que sabes si cuántos oponentes te quedan en un momento dado, no con cuántos empezaste.
KBriggs


@KBriggs Gracias :)
Quintec

También debe agregar 1 para comenzar vivo, ya que este es 0 para la primera ronda
KBriggs

@KBriggs solucionado, en realidad debería +2 para que no devuelva 0, jajaja
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 intentará ofertar más de lo que su oponente puede ofertar cuando sea posible.


Hay una condición que where np.random.randint(hp/5, hp/2)puede fallar si hp/5 == hp/2, es decir, si hp==0ohp==1
KBriggs

3
Si HP es 0, entonces no debería ser invocado. : P Sin embargo, tienes razón sobre 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

Decide cuánto de su salud debería sacrificar en función de la cantidad de bots restantes. Si solo quedan dos bots, hace una oferta hp-1, pero si quedan tres, muerde la mitad, quedan cuatro, un tercio, etc.

Sin embargo, en un concurso muy grande, creo que tendré que pujar más de 3 o 4 hp para evitar morir en la primera ronda, así que puse un límite inferior en 10. Por supuesto, todavía no pujaré más que hp-1.

También agrega 1.5 hp para lazos, ya que veo varios bots de "agregar 1 hp para lazos". No estoy seguro si eso cuenta como trampa. Si lo hace, lo cambiaré.

¡Gran idea por cierto!

Spitball Bot 2.0

¿Qué hay de nuevo?

  • Cambió a dividir por el número de rondas restantes en lugar del número de bots restantes (¡Gracias a @Heiteira!). En realidad, ahora estoy dividiendo por ese número elevado a la potencia .8, para adelantar mis ofertas un poco más.

  • Oferta mínima mejorada de 10 a 20 (¡Gracias @KBriggs!)

  • Comprobación insertada de si la oferta de spitball está por encima del HP actual del oponente, y baje si es así.

(SO no representará el siguiente código como código a menos que ponga texto aquí, así que OK)

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

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

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

    if value > opponentHp:
        value = opponentHp

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

    return value

1
Su oferta debe ser un número entero, por lo tanto, siempre y cuando aplique o limite su valor base para deshacerse del decimal, está bien
KBriggs

Sí, lo suelo justo después de hacer todos los cálculos. ¡Gracias por la rápida respuesta!
MegaWidget

2
Es posible que pueda optimizar esto si no está dividiendo su HP por el número de concursantes restantes, sino por el número de rondas restantes (que debería ser math.ceil (math.log (vivo, 2))
Black Owl Kai

1
Según otros bots, la mayoría de ellos parecen presentar ofertas de carga frontal, por lo que esto podría mejorar si aumenta la oferta de la primera ronda por encima de 10
KBriggs

¡Ambas son buenas ideas! No me había dado cuenta de que la cantidad de bot no era la misma que la cantidad de rondas restantes (al principio malinterpreté las reglas del concurso). Intentaré implementarlos mañana. ¡Gracias!
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)

5to lugar en el primer intento, nada mal
KBriggs

5

Bot 13

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

Intenta maximizar las ganancias con el menor esfuerzo:

  • si podemos ganar, solo hazlo
  • si es la última ronda, no te mueras en el intento
  • de lo contrario, no te molestes

¿Por qué?

Trata de aprovechar la probabilidad: ganar la primera ronda jugando bajo es la mejor manera de comenzar el torneo. 13 parece ser el punto ideal: la segunda ronda es una victoria segura, y el resto es un Spaziergang en el parque.


Has tomado la iniciativa, muy bien! Tenga cuidado, es posible que desee agregar protección contra parásitos, ya que los bots que toman la delantera se convierten en objetivos para cosas como UpYoursBot. Consulte SarcomaBots para obtener ideas de protección si las necesita.
KBriggs el

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)

Primera vez publicando aquí. Esto parecía muy divertido, así que estoy enviando mi intento más allá de lo terrible y adivinando qué apostarán los otros bots.

Edición 1: se agregó otro 1 a la primera apuesta, simplemente para reducir la posibilidad de un empate con otras personas que apuestan 51.

Edición 2: Robó el movimiento de apertura del bot Sarcoma ya que tenía una buena posibilidad de no ser eliminado primero de manera consistente.

Edición 3: Bot sobrevive muy bien en la primera ronda, pero se destruye fácilmente en etapas posteriores. Cambió la forma en que el robot piensa en la segunda ronda ahora que los mejores jugadores están muertos en el agua.

Edición 4: ahora que la primera ronda es buena, cambié la forma en que maneja la segunda ronda. Muriendo mucho en la segunda ronda, así que necesito sobrevivir de alguna manera.

Blood Bot

Hizo un robot sediento buscando una muerte. La idea es tratar de ganar contra los bots de apuestas bajas y una vez que haya pasado el baño de sangre de la primera ronda, debería ser imparable ya que debería tener enormes cantidades de HP para superar a los enemigos.

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
Creo que len (historial) * len (historial) podría cambiarse a len (historial) ** 2 si mi conocimiento de Python es correcto.
Yodie

Tiene una división entre cero para cuando len (historial) == 0
KBriggs

El código ha sido actualizado. Al no encontrar historia, pasa a la primera cosa
Markov encadenado el

oi .............
Sarcoma

2
@ Sarcoma es un mundo de bot despiadado por ahí hombre!
Markov encadenado el

5

meh_bot

Solo oferte un poco más de la mitad de su CV

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

    if ties > 1:
        ties += 1

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

    opponent_hp = 100 - sum(history)

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

MehBot 20

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

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

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

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

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

mehRan

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

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

Existen bastantes bots para aprovechar exactamente este comportamiento, por lo que es posible que tenga dificultades para ganar tracción.
KBriggs el

@KBriggs Hizo alguna actualización, no esperaba que la primera versión funcionara tan bien como lo hizo, con suerte, esta actualización le dará más posibilidades de pelea
meh Man

Wow, eso hizo una gran diferencia, creo que estás en primer lugar. La actualización se publicará en un par de minutos. Es posible que deba darle a su bot un sistema inmunitario (consulte SarcomaBot) si continúa para que funcione bien.
KBriggs

@KBriggs No esperaba hacer esto bien, pensé que en el mejor de los casos sería el top 10. De todos modos, he agregado otro solo para ver el efecto de la primera ronda de HP. ¿Puedes ejecutar ambos para que pueda ver el resultado de ambos? Gracias
meh Man

@KBriggs Por favor, haz esto también, Muchas gracias
meh Man

4

Ruleta Robbie

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

Este bot realiza un análisis simple de la historia del bot enemigo o, de lo contrario, ofrece la mitad de los puntos de golpe restantes


4

Haga una oferta más alta cuanto menos competencia tenga. Gracias a los comentaristas por sugerir mejoras.

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

1
Buena idea, pero veo dos problemas. Uno es que la mayoría de los otros bots ofertan mucho en la primera ronda, por lo que este probablemente morirá temprano la mayor parte del tiempo. El segundo es que en la final, la mayoría de los bots ofertan hp-1, por lo que este perderá esos a menos que tenga el doble de sus hp. Pero para las rondas intermedias me gusta la idea. Si aborda los dos casos especiales, probablemente pueda mejorar el rendimiento.
KBriggs

4

SurvivalistBot and HalvsiesBot

Gracias por responder mis preguntas. El resultado final es un bot más complejo.

HalvsiesBot es un robot caprichoso de 'solo sigue pasando la mitad' con una probabilidad de 50/50 de ganar. Supongo.

SurvivalistBot toma una serie de decisiones de árbol binario if-else basadas en el conjunto de datos, incluida una anulación en un empate (si golpea 2 empates, kamikazes evita la muerte del triple empate).

Mi python está un poco oxidado, por lo que el código puede ser un poco defectuoso, así que siéntase libre de corregirlo o actualizarlo.

Está diseñado para tratar de obtener fragmentos de datos para inferir cosas como cuánto HP le queda, la cantidad mínima de bots con los que es probable que luche, la cantidad mínima de HP que queda, la oferta promedio. También explota la aleatorización en situaciones ambiguas, como las jugadas de apertura o los problemas de pujas óptimos.

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


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

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

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


    HP_Difference = hp - Opponent_Remaining_HP

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

    RemainderTree = RemainingBots

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

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

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

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

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

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

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

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

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

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

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


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

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

    else:

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

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

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

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

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

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

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

BoxBot

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

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

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

Opponent_Average_Bid = Opponent_Remaining_HP / float(len(history)) ZeroDivisionError: float division by zero. Esta línea necesita manejar el caso del historial de longitud 0.
KBriggs

Gracias, lo corregiré.
SSight3

Fijo. Avíseme si hay otros errores.
SSight3

1
Un par de errores de sintaxis: falta: `después else, math.[func] -> np.[func]y en un momento dado se utiliza Lowestcuando quieres decir LowestBid. Todo arreglado en el controlador en github y las puntuaciones se actualizaron en breve.
KBriggs

Gracias. Se corrigieron todos los errores mencionados anteriormente en la publicación.
SSight3

4

Bot calculador

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 agresivo

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

Anti Kick Bot

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

Si podemos predecir las acciones del oponente, ¡podemos hacer las apuestas óptimas! Si no podemos (no hay suficientes datos o el oponente es demasiado aleatorio), entonces al menos podemos hacer lo que maximizaría nuestro potencial de ganancia. Teóricamente, al menos la mitad del número de bots vivos morirá en cada ronda. Por lo tanto, puedo esperar que haya como máximo rondas log2 (vivas). Idealmente, dividiríamos nuestro HP de manera uniforme entre todas las rondas. Sin embargo, sabemos que algunos bots serán estúpidos y se suicidarán / morirán temprano, por lo que deberíamos apostar un poco más en las rondas anteriores.

El código de Bot calculador agresivo modifica el código de Bot calculador para intentar mantenerse vivo siendo más agresivo, a costa de la salud a largo plazo. Solo las simulaciones dirán si el tempo o el valor ganan.

Anti Kick Bot siempre debe vencer al actual líder KickBot: P

EDITAR: Bot determinista reemplazado con Anti Kick Bot, un bot más inteligente con casi exactamente los mismos valores de retorno. También impidió votar más que los oponentes HP


Linda. Creo que este funcionará mejor con un grupo de bot muy grande.
KBriggs

Me aparece un error a veces con éste: return np.max(theoreticalBet, hp - 1): AxisError: axis 23 is out of bounds for array of dimension 0. Publiqué un enlace al controlador para que pueda probarlo.
KBriggs

@KBriggs Actualizó el código para solucionarlo.
Bob Cratchit

1
confirmado, actualización de puntaje entrante. Estás en el top 10 seguro.
KBriggs

@KBriggs Agregué un par de bots más para probar :)
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))

Es muy tarde ... Estoy cansado ... no puedo pensar en un nombre ... y el formato de este bot es realmente similar a otros, solo con un algoritmo ligeramente diferente dado el historial. Intenta obtener la tasa actual que el oponente tiende a apostar ... o algo así ... zzz


necesita usar en np.maximumlugar de np.max, lo mismo paramin
KBriggs

@KBriggs Gracias :) Hmm, parece que los bots genéricos gobiernan este juego
Quintec

Parece que serían objetivos bastante fáciles, me sorprende que nadie haya hecho un parásito todavía
KBriggs

@KBriggs Sí, estoy sorprendido. Es hora de agregar protecciones ...
Quintec

¿Todavía estás planeando hacer Neuralbot?
KBriggs

4

HalflifeS3

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

4

Coast Bot [Retirado]

Intentará atravesar la competencia dividiendo equitativamente su HP entre las rondas. Ofrecerá cualquier HP restante en la primera ronda para tener una mejor oportunidad de llegar a las rondas "costeables".

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 me gusta tanto este desafío, solo tuve que hacer otro bot. Esta versión sacrifica parte de su posterior inercia de HP al usar más hp en las dos primeras rondas.

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

Porcentaje de bot

Trata de calcular el porcentaje promedio de HP que gasta el oponente, y las ofertas basadas en eso.

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)

Muy buena idea. Sacar la primera ronda es una nueva tendencia en los bots, y parece estar funcionando razonablemente bien.
KBriggs

@KBriggs He actualizado esta respuesta para contener mi segundo intento. Mencionándote según las nuevas reglas. Gran rompecabezas por cierto!
Wazz

¿Quieres que ingrese ambas o solo la última versión? En este momento es solo V2
KBriggs

@KBriggs Me gustaría que ingresen los dos si está bien, por favor. Sería bueno ver cómo se comparan entre sí.
Wazz

Rendimiento bastante similar en general
KBriggs el

4

ConsistenteBot

Apuesta la misma cantidad en cada ronda. No es muy probable que sobreviva a las primeras rondas, pero si tiene la suerte de llegar al final, aún debería tener una cantidad razonable de 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

Caray, es demasiado tarde para arreglarlo ahora, pero mi bot usó suficiente HP para llegar al final de luchar contra cada oponente una vez, no para llegar a la última ronda. Ese es mi mal: P
Kevin - Restablecer Mónica

4

Kickban Bot

Este bot simplemente trata de contrarrestar al líder actual Mean Kickbot al vencerlo en la primera ronda y jugar más agresivamente a partir de entonces si lo reconoce.

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

    if not history:
        return 36

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

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

1
Creo que tu sangría está un poco apagada.
Jonathan Frech

¡Vaya! Gracias, el editor de código extraño se
metió

una valiosa lección sobre el código de confianza que no controlas
OganM

4

Bot de tres cuartos

No va a vencer a MehBot o SarcomaBot (s), pero creo que lo hace bastante bien. Cuando vi el desafío por primera vez, esto fue lo primero que me vino a la mente: siempre * apuesta tres cuartos de tu salud a menos que no haya razón para hacerlo.

* después de batear la primera ronda.

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

Cuatro Séptimos Bot

Después del éxito moderado de 3/4 bot hay una nueva fracción en la ciudad, solo es 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

La fracción perfecta

Estoy completo

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

Con base en estas probabilidades de eliminación, probablemente también podría salirse con ofertas más pequeñas en la ronda 2. Este funciona bien, pero algunos ajustes menores pueden hacerlo mucho mejor.
KBriggs

@KBriggs Agregó un nuevo bot con probabilidades nuevas y mejoradas;)
Joshua Webb

¿Los quiere a ambos allí o solo 1?
KBriggs

@KBriggs No sé si no cumplí con la fecha límite, pero agregué un bot final, si llego a tiempo, puedes eliminar los otros dos bots de fracciones
Joshua Webb

1
Sí, todavía tienes tiempo
KBriggs

4

BandaidBot

¡BandaidBot quiere que todos jueguen bien! Si su oponente fue bueno la última ronda, se sacrificará para incentivar un buen comportamiento en los demás. Si su oponente fue malo la última ronda, causará el mayor daño posible a su oponente, sacrificándose si es necesario. Ofrece una tercera parte de su CV si no tiene historial para trabajar. (Espero que este bot tenga interesantes efectos en otras estrategias, no tanto como para que este bot tenga una alta tasa de victorias en sí mismo. Podría ser divertido tener un par de estos en juego)

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á tan bueno como sea necesario para aprovechar BandaidBot. Regresará un poco menos de un tercio de su CV a menos que pueda matar a su oponente por menos de eso. Si su oponente se parece a BandaidBot, ofertará 2, sabiendo que BandaidBot ofertará 1 porque GetAlongBot se ha llevado muy bien con todos los demás, una victoria fácil siempre que realmente fuera BandaidBot en el otro extremo.

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)

Muy buena idea. Me pregunto cuánto impacto tendrá
KBriggs

error: return np.random.randint(history[-1], hp/2): ValueError: low >= higheste caso debe ser manejado de alguna manera
KBriggs

¡@KBriggs debería arreglarse ahora!
Maya Sol

@KBriggs actualizado para corregir la aleatorización
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

Este bot intenta mantener su valor favorito de 10, pero cambia su elección ocasionalmente si es necesario para romper un empate (con su valor favorito duplicado o cuadruplicado) o para ahorrar para rondas futuras, pero no por una cantidad óptima porque quiere confundir oponentes y no quiere considerar ofertar menos de 2 en ningún momento ya que está convencido de que es mucho mejor que esperar que el oponente oferte menos de 1, es decir, 0.

PD: este bot puede tener problemas estratégicos si hay más de 2 ^ 9 bots.


Sospecho que no tienes que preocuparte por tener 2 ^ 9 oponentes ^ _ ^.
KBriggs

Pero con una apuesta inicial de 10, rara vez pasará la primera ronda
KBriggs

Este bot piensa que, si algún bot realmente quiere dar más de 10 CV en la primera ronda, no vale la pena luchar.
AlexRacer

Jaja bastante justo
KBriggs

3

CautelosoBot

¡Primera presentación a Puzzles de programación! Encontraste tu desafío bastante interesante: P

Si la última ronda mordió uno menos que hp, si no hay historial, apueste medio hp más una pequeña cantidad aleatoria.

Si el historial verifica la HP del oponente y el número de rondas restantes e intenta superar a hp / 2 del oponente usando un búfer adicional de hasta la fracción de HP restante dividido por el número de rondas restantes (intenta conservar el HP restante de alguna manera para las rondas posteriores) . Comprueba si estás gastando demasiado HP (no te mates ni pujes más de lo que tu adversario puede).

Siempre corrija las ataduras como lo hacen otros 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

Demasiado agresivo en las primeras rondas, ahora CautiousBot se vuelve aún más 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)

Usted tiene un error en el que se sigue llamando randint cuando 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. Tenga en cuenta que el búfer es una palabra clave en python, es posible que desee elegir un nombre de variable diferente.
KBriggs

Oh, parece que es porque el búfer no siempre es un int; probablemente en algún momento esté dividiendo por cero. Por favor revise la lógica cuidadosamente. Lo hice correr, pero probablemente puedas arreglar las esquinas.
KBriggs

Buena captura @KBriggs. Creo que lo arreglé.
Jesús Ros

Todavía consigo un error: 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 buff es a veces un número de coma flotante entre 0 y 1, que presumiblemente se convierte en 0 en el interior randint. Esto funciona si lanzas buffa intantes de la llamada
KBriggs

@KBriggs probablemente porque ceildevuelve a float. Se lo perdió ... Ty nuevamente: P
Jesús Ros

3

Muy bien, intentaré con esto.

SnetchBot

Verificando las fracciones de salud con las que el oponente ha estado yendo. Si el oponente ha estado subiendo, golpéalo.

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

EDITAR: perder mucho en la primera ronda, ajustar los límites aleatorios del primer turno


Primer disparo bastante bueno, actualización de puntaje entrante
KBriggs

@KBriggs Editado un poco (solo los límites aleatorios de la primera ronda). Aunque ya me sorprendió estar tan alto como el décimo lugar. Si esto empeora, volveré al primero: D
snetch

Le exprimes un poco más de jugo
KBriggs

3

SquareUpBot

No parecía que muchos bots estuvieran jugando con poderes en lugar de fracciones, así que decidí hacer uno, con algunas optimizaciones estándar y ver dónde colocaré. Bastante simplista.

También trata de determinar si el robot enemigo no está tratando de usar una fracción constante, porque poderes > fracciones .

EDITAR: Soy un tonto y mi detector de fracciones no pudo funcionar. Reparado ahora

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

No es un mal primer golpe, las puntuaciones se han actualizado
KBriggs

@KBriggs He actualizado el bot para que el detector de fracciones realmente funcione.
Diamond Dust
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.