[Hearthstone] Puzzle Alterac / Kurtrus

mamiemando Messages postés 33149 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 13 juin 2024 - Modifié le 15 juil. 2022 à 03:40

Introduction

Cette astuce propose un programme écrit en python pour résoudre le puzzle de Kurtrus (voir cette page) en s'appuyant sur ce document.

Principe du puzzle

Le plateau est rempli chez l'adversaire par 7 minions dont les points de vie (HP) sont tirés aléatoirement. Chacun d'entre eux correspond en réalité à un ballon caractérisé par :

  • une hauteur
    • La hauteur n'est pas explicitement indiquée (et c'est pour ça que le puzzle est assez horrible). Elle est déterminée par les points de vie du minion, conformément à ce document.
  • une vitesse
    • Si la vitesse est positive le ballon monte.
    • Si la vitesse est négative le ballon chute.
    • La vitesse est initialisée aléatoirement entre 0 et -7 inclu).

Chaque tour se déroule comme suit.

  • Pendant chacun des 15 premiers tours, le joueur peut choisir d'activer son pouvoir héroïque sur le ballon de son choix.
    • La vitesse du ballon choisi passe à +3 (peu importe à quelle vitesse il était)
    • La vitesse des autre ballons est décrémentée. Exemple
      • Si un ballon avait une vitesse -4 au tour précédent, il tombera à la vitesse de -5 (si on ne le choisit pas)
      • Si un ballon avait une vitesse de +3, il tombera à une vitesse de -2  (si on ne le choisit pas)
  • Pendant les tours 16 à 20, le joueur ne peut plus choisir de ballon.
  • À chaque fin de tour, la hauteur des ballons est corrigée en fonction de leur vitesse.
  • Si un ballon tombe à une hauteur nulle ou négative avant la fin du 20e tour, le jeu est perdu. Si tous les ballons sont encore en l'air au 20 tour, la partie est gagnée.

Stratégie

Pendant les 15 premiers tours il faut se focaliser sur :

  • les ballons qui chutent le plus rapidement
  • les ballons qui sont les plus bas

Pour survivre aux 5 derniers tours, il faut s'assurer que les ballons les plus bas ne sont pas en train de chuter trop vite.

Programme

Le programme ci-dessous ne fournit pas de solution, mais permet de suivre la hauteur et la vitesse de chaque ballon.

Pour l'utiliser il faut saisir les HPs de chaque minion au début de la partie, puis passer le premier tour. Cela permet au programme de calculer la vitesse de chaque ballon. Aux tours suivants il faut saisir l'index du minion sur lequel on a choisi d'appliquer le pouvoir héroïque. Le programme maintient et affiche à chaque tour les HPs, la hauteur, et la vitesse de chaque minion, ce qui facilite grandement la prise de décision.

#/usr/bin/env python3
# See https://docs.google.com/document/d/1HAalaWTrJZtL9K91Z2f-rtC5F_1kIJgHhL4rawZ0KFk/edit

map_hp_height = [
    1, 31, 77, 50, 3, 81, 14, 8, 9, 59, 11, 4, 54, 10, 15, 22, 99, 18,
    36, 40, 21, 28, 23, 75, 25, 26, 27, 7, 70, 30, 94, 79, 47, 34, 35,
    2, 89, 16, 39, 17, 41, 42, 56, 44, 90, 76, 83, 48, 61, 60, 51, 52,
    53, 98, 5, 29, 57, 58, 43, 65, 19, 24, 63, 64, 67, 66, 20, 46, 69,
    33, 6, 72, 74, 45, 62, 95, 68, 78, 71, 80, 97, 13, 37, 84, 85, 86,
    87, 88, 92, 73, 91, 55, 93, 38, 82, 96, 32, 49, 12, 100, 101, 102,
    103, 104, 105
]

map_height_hp = {
    height : hp
    for (hp, height) in enumerate(map_hp_height)
}

def prompt_hps(n):
    return [
        int(input(f"HP({i+1})? "))
        for i in range(n)
    ]

def hps_to_heights(hps):
    return [
        map_hp_height[hp]
        for hp in hps
    ]

def heights_to_hps(heights):
    return [
        map_height_hp[height]
        for height in heights
    ]

def compute_speed(heights0, heights1):
    return [
        h1 - h0
        for (h0, h1) in zip(heights0, heights1)
    ]

def update_speed(speeds, choice):
    return [
        speed - 1 if i != choice else 3
        for (i, speed) in enumerate(speeds)
    ]

def update_heights(heights, speeds):
    return [
        height + speed
        for (height, speed) in zip(heights, speeds)
    ]

def fmt(v):
    return "\t".join(str(i) for i in v)

n = 7
heights0 = hps_to_heights(prompt_hps(n))
print(f"Current heights: {fmt(heights0)}")
print("Click 'Next Turn'")
heights = hps_to_heights(prompt_hps(n))
print(f"Current heights: {fmt(heights)}")
speeds = compute_speed(heights0, heights)

for turn in range(20):
    print("-"*80)
    print(f"TURN {turn}")
    print("-"*80)
    hps = heights_to_hps(heights)
    print(f"Minion        : {fmt(range(1, n+1))}")
    print(f"HPs           : {fmt(hps)}")
    print(f"Heights       : {fmt(heights)}")
    print(f"Speeds        : {fmt(speeds)}")
    choice = None
    if turn < 15:
        while choice not in range(n):
            choice = int(input(f"Target minion [1-{n}]? ")) - 1
    else:
        choice = -1
    speeds = update_speed(speeds, choice)
    heights = update_heights(heights, speeds)
    hps = heights_to_hps(heights)

Bon puzzle !