Un primer código para competir (V)

Quinto y último artículo de esta serie, mediante la cual podréis empezar a competir en CodedArena con vuestro personaje. En esta ocasión toca ver cómo nuestro personaje puede curarse cuando tiene poca vida.

Un primer código para competir (V)

Atención: Contenido visualmente obsoleto. Contiene imágenes y reproducciones animadas de CodedArena 1.0.

La nueva versión del artículo la podéis encontrar aquí.


¡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 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. Detectar al adversario.
  2. Acercarse al adversario.
  3. Seleccionar un hechizo, y empezar la lucha.
  4. Luchar a distancia.
  5. Comprobar la vida del personaje, y curarle o atacar, 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 lejos, acercarse.
  4. Si está cerca, atacar.

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!


De nuevo, ¿dónde ponemos este código?

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

Al final 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]

En el código anterior, la curación tendría prioridad sobre el ataque. Le podemos dar la vuelta al código:

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]

En este caso, 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.

Veamos la ejecución del primer caso:

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, cuando 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!

¡No dejes de seguirnos en nuestro Blog de CodedArena!