¡Hola, Comunidad Coded!

En el artículo anterior hemos visto cómo mantenernos a distancia respecto al adversario, o por lo menos no aproximarnos constantemente.

En este quinto y último artículo para preparar nuestro primer código básico de competición en CodedArena, vamos a centrarnos en curar a nuestro personaje.

Recordad que esta serie consta de los siguiente artículos.

  1. Detectando al adversario.
  2. Acercándonos al adversario.
  3. Seleccionando un hechizo, y empezando la lucha.
  4. Luchando a distancia.
  5. Comprobando la vida de nuestro personaje, y actuar según la situación.

¡Vamos allá con el quinto artículo!


¿Qué nos queda? ¡Curar al personaje!

Bueno, nuestro personaje ya sabe hacer varias tareas básicas:

  1. Detectar al adversario.
  2. Comprobar si está a distancia de hechizo.
  3. Si está demasiado lejos, acercarse.
  4. Si está a la distancia adecuada, lanzar hechizo.

Queda la última tarea básica: comprobar el estado de su vida, y curarse si es necesario.

Para ello, crearemos un sencillo código:

if self.health < self.max_health / 2 \
   and \
   self.is_ready("heal") \
   and \
   self.mana >= self.cost_of("heal"):
   return ["cast", "heal", self]

Vamos a comentarlo.

Si detectamos que la vida de nuestro personaje está por debajo de la mitad de su vida máxima, es decir, está por debajo del 50%:

if self.health < self.max_health / 2

y

   and

el hechizo de curación Heal está disponible

   self.is_ready("heal") \

y

   and

nuestro personaje tiene maná suficiente para lanzarlo, nos curamos

   return ["cast", "heal", self]

Importante... Sabemos que es de lógica pura, pero invocad Heal sobre vuestro personaje, self, porque si en vez de self utilizáis la variable target... ¡curaréis a vuestro adversario!


¿Dónde ponemos este código?

Bueno, aquí hay varias opciones, pero vamos a comentar un par de opciones buenas.

Al principio del código

Si lo ponemos al principio de nuestro código, le estaremos dando la máxima prioridad a la curación de nuestro personaje:

if self.health < self.max_health / 2 \
   and \
   self.is_ready("heal") \
   and \
   self.mana >= self.cost_of("heal"):
   return ["cast", "heal", self]
   
target = None

for mob in mobs:
    if mob.name != self.name:
        target = mob
        break
        
if self.distance_to(target) > self.max_distance_of("lightning"):
    dir_x = "none"
    dir_y = "none"

    if self.x > target.x:
        dir_x = "left"
    else:
        dir_x = "right"

    if self.y > target.y:
        dir_y = "up"
    else:
        dir_y = "down"

    return ["move", dir_x, dir_y]
else:
    if self.is_ready("lightning") and self.mana >= self.cost_of("lightning"):
        return ["cast", "lightning", target]

Es una opción. Funcionará. Lo que está claro es que, en caso que nuestro personaje esté por debajo del 50% de vida, no de dedicará a otra cosa que a curarse.

Agrupar código de invocación de hechizos

Otra opción es agrupar una zona donde nuestro personaje tome decisiones respecto a los hechizos que lanzar.

En este caso, quizá la curación no tiene prioridad, pero el código puede quedar más ordenado:

target = None

for mob in mobs:
    if mob.name != self.name:
        target = mob
        break
        
if self.distance_to(target) > self.max_distance_of("lightning"):
    dir_x = "none"
    dir_y = "none"

    if self.x > target.x:
        dir_x = "left"
    else:
        dir_x = "right"

    if self.y > target.y:
        dir_y = "up"
    else:
        dir_y = "down"

    return ["move", dir_x, dir_y]
else:
    if self.health < self.max_health / 2 \
       and \
       self.is_ready("heal") \
       and \
       self.mana >= self.cost_of("heal"):
       return ["cast", "heal", self]
   
    if self.is_ready("lightning") and self.mana >= self.cost_of("lightning"):
        return ["cast", "lightning", target]

Ahora la curación no es la acción con más prioridad del código, pero seguiría teniendo prioridad sobre el ataque, al estar por encima de la invocación de Lightning.

Le podemos dar la vuelta a esos dos bloques de código (la invocación de Heal y Lightning:

target = None

for mob in mobs:
    if mob.name != self.name:
        target = mob
        break
        
if self.distance_to(target) > self.max_distance_of("lightning"):
    dir_x = "none"
    dir_y = "none"

    if self.x > target.x:
        dir_x = "left"
    else:
        dir_x = "right"

    if self.y > target.y:
        dir_y = "up"
    else:
        dir_y = "down"

    return ["move", dir_x, dir_y]
else:
    if self.is_ready("lightning") and self.mana >= self.cost_of("lightning"):
        return ["cast", "lightning", target]

    if self.health < self.max_health / 2 \
       and \
       self.is_ready("heal") \
       and \
       self.mana >= self.cost_of("heal"):
       return ["cast", "heal", self]

Ahora el ataque tiene prioridad. El personaje puede estar por debajo del 50% de vida, pero antes atacará que se curará.

En este caso, ya es una decisión personal y de estrategia.

Probando el código

Veamos la ejecución del primer caso. Para este caso, no nos enfrentaremos a Dummy, si no a uno de los bots que también tienen una estrategia de lucha.

Como podemos ver, cuando nuestro personaje llega por debajo del 50% de la vida, antes que lanzar un Lightning siempre se cura con Heal.


¿Qué hemos conseguido?

Una vez sabemos quién es nuestro adversario, cómo aproximarnos, cuándo y cómo lanzar un hechizo, cómo mantenernos a distancia, o por lo menos no acercarnos constantemente, ahora ya sabemos cómo curar a nuestro personaje.


¿Y a partir de aquí?

Ahora toca ir mejorando el código, con más hechizos, estrategias de aproximación o manteniendo la distancia, combos de hechizos, ¡y todo un mundo de posibilidades con CodedArena y Python!


Si os ha gustado este artículo y queréis saber qué es CodedArena, no dudéis en poneros en contacto con nosotros.

También podéis seguirnos en nuestras redes sociales:

https://twitter.com/codedarena
https://instagram.com/codedarena
https://www.youtube.com/channel/CodedArena
https://facebook.com/codedarena