# Lesson 8 - Arena with a mage in Kotlin (inheritance and polymorphism)

In the previous lesson, Inheritance and polymorphism in Kotlin, we went over inheritance and polymorphism in Kotlin. In today's tutorial, we're going to make a sample program using these concepts, as promised. We'll get back to our arena and inherit a mage from the `Warrior` class. These next couple of lessons will be among the most challenging. Which is why you should be working on OOP on your own, solving our exercises and coming up with your own applications. Try putting all that you've learned to practice. Make programs that you would find useful, so it'll be more engaging and fun.

Before we even get to coding, we'll think about what a mage should be capable of doing. The mage will work just like a warrior, but on top of health, he'll also have mana. At first, the mana will be full. When it is, the mage can perform a magic attack which will have a higher damage than a normal attack, depending on how we set it. This attack will bring his mana down to 0. The mana will increase by 10 every round and the mage would only be able to perform regular attacks. Once the mana is full, he'll be able to use his magic attack again. The mana will be displayed using a graphical indicator just like the health bar.

Let's create a `Mage.kt` class. Since we want to inherit it from the `Warrior` class, we have to tell Kotlin that `Warrior` can be inherited first. We'll do that using the `open` modifier:

The beginning of the `Warrior` class:

```open class Warrior(private val name: String, private var health: Int, private val damage: Int, private val defense: Int, private val die: RollingDie) {
// the rest of the implementation...
}```

To the `Mage` class, we'll add extra properties in addition to the ones from the Warrior. The `Mage` class could look like this for now:

```class Mage : Warrior {
private val mana: Int
private val maxMana: Int
private val magicDamage: Int
}```

We won't be able to compile the code yet, because we haven't created a constructor.

We don't have access to all the warrior variables in the `Mage` class because we still have the properties in the `Warrior` class set to private. We'll have to change the `private` property modifiers to `protected` in the `Warrior` class. All we really need now is the `die` and the `name` properties. Either way, we'll set all of the warrior's properties to `protected` because they might come in handy for future descendants. On second thought, it wouldn't be wise to set the `message` property as `protected` since it's not related to the warrior directly.

With all of that in mind, the class would look something like this:

```open class Warrior(protected val name: String, protected var health: Int, protected val damage: Int, protected val defence: Int, protected val die: RollingDie) {
// ...
}```

Moving on to the constructor.

## Descendant constructor

Kotlin does not inherit constructors! This is probably because it assumes the descendant will have extra properties and would make the original constructor irrelevant. Which is correct in our case, since the mage's constructor will have 2 extra parameters (mana and magic damage).

We'll define the constructor in the descendant, which will take both parameters needed to create a warrior and the extra ones needed for the mage.

The descendant constructor must always call the parent constructor. If you forget to do so, the instance may not be properly initialized. The parent constructor will be executed before our constructor and we can call it using the `: Warrior(...)` syntax, passing the parameters needed.

The mage constructor will look like this:

```class Mage(name: String, health: Int, damage: Int, defense: Int, die: RollingDie, private var mana: Int, private val magicDamage: Int) : Warrior(name, health, damage, defense, die) {

private val maxMana: Int

init {
maxMana = mana
}
}```

Our constructor has now all parameters the parent needs and the new ones, that the child needs, as well. We'll pass some of them to the parent and process some of them by ourselves.

Now, let's switch to `Main.kt` and change the second warrior (Shadow) to a mage. Like this:

`val gandalf: Warrior = Mage("Gandalf", 60, 15, 12, die, 30, 45)`

We'll also have to change the line where we put the warrior in the arena. Note that we are still able to store the mage into a variable of the `Warrior` type because it's its ancestor. We could also change the variable type to `Mage`. When you run the application now, it'll work exactly as it did before. Mage inherits everything from the warrior and behaves just like a warrior.

## Polymorphism and overriding methods

It would be nice if the `Arena` could work with the mage in the same way as it does with the warrior. We already know that in order to do so we must apply the concept of polymorphism. The arena will call the `attack()` method, passing an enemy as a parameter. It won't care whether the attack will be performed by a warrior or by a mage, the arena will work with them in the same way. We'll have to override the ancestor's `attack()` method in the mage class. We'll rewrite its inherited method so the attack will use mana, but the header of the method will remain the same.

Talking about methods, we'll certainly need the `setMessage()` method from `Warrior.kt` which is `private` now. Let's make it `protected`:

`protected fun setMessage(message: String) {`

When you create a class you should always consider whether it would have descendants and therefore mark appropriate properties and methods as `protected`. I didn't mean to overwhelm you with all of this information when we first made the `Warrior` class but now that we understand these modifiers, we should use them.

Let's overwrite the `attack()` method of the warrior in the mage. We must first mark the method as `open` in the parent:

`open fun attack(enemy: Warrior) {`

Now we'll declare the method in `Mage.kt` as we're used to and use the `override` keyword with it:

`override fun attack(enemy: Warrior) {`

Similarly, we have overridden the `toString()` method in our objects earlier.

Our descendant's `attack()` method won't be all that different. Depending on the mana value, we'll either perform a normal attack or a magic attack. The mana value will be either increased by 10 each round or in the case where the mage uses a magic attack, it will be reduced to 0.

```override fun attack(enemy: Warrior) {
var hit = 0
// Mana isn't full
if (mana < maxMana) {
mana += 10
if (mana > maxMana) {
mana = maxMana
}
hit = damage + die.roll()
setMessage("\$name attacks with a hit worth \$hit hp")
} else {
hit = magicDamage + die.roll()
setMessage("\$name used magic for \$hit hp")
mana = 0
}
enemy.defend(hit)
}```

Notice how we limit `mana` to `maxMana` since it could be that it exceeds the maxim value when increasing it by `10` each round. When you think about it, the normal attack is already implemented in the ancestor's `attack()` method.

In Kotlin, there's also the `super` keyword similar to `this` we already know. Unlike `this`, which refers to a particular class instance, `super` refers to the parent**. That means we can call parent methods even though the child has overridden them.

Certainly, it'd be better to just call the ancestor's `attack()` instead of copying its behavior. We'll use the `super` keyword to do just that:

```override fun attack(enemy: Warrior) {
// Mana isn't full
if (mana < maxMana) {
mana += 10
if (mana > maxMana) {
mana = maxMana
}
super.attack(enemy)
} enemy { // Magic attack
val hit = magicDamage + die.roll()
setMessage("\$name used magic for \$hit hp")
enemy.defend(hit)
mana = 0
}
}```

There are lots of time-saving techniques we can set up using inheritance. In this case, all it did is save us a few lines, but in a larger project, it would make a huge difference.

The application now works as expected.

```-------------- Arena --------------

Warriors health:

Zalgoren [###########         ]
Gandalf [##############      ]
Gandalf attacks with a hit worth 23 hp
Zalgoren defended against the attack but still lost 9 hp```

For completeness' sake, let's make the arena show us the mage's current mana state using a mana bar. We'll add a `public` method and name it `manaBar()`. It will return a `String` with a graphical mana indicator.

We'll modify the `healthBar()` method in `Warrior.kt` to avoid writing the same graphical bar logic twice. Let me remind us how the original method looks:

```fun healthBar(): String {
var s = "["
val total = 20
var count = round((health.toDouble()/maxHealth) * total).toInt()
if ((count == 0) && (alive()))
count = 1
s = s.padEnd(count + s.length, '#')
s = s.padEnd(total - count + s.length, ' ')
s += "]"
s.length
return s
}```

The health method doesn't really depend on a character's health. All it needs is a current value and a maximum value. Let's rename the method to `graphicalBar()` and give it two parameters: current value and maximum value. We'll rename the `health` and `maxHealth` variables to `current` and `maximum`. We'll also make the method `protected` so we could use it in descendants:

```protected fun graphicalBar(current: Int, maximum: Int): String {
var s = "["
val total = 20
var count = round((current.toDouble()/maximum) * total).toInt()
if ((count == 0) && (alive()))
count = 1
s = s.padEnd(count + s.length, '#')
s = s.padEnd(total - count + s.length, ' ')
s += "]"
s.length
return s
}```

Let's implement the `healthBar()` method in `Warrior.kt` again. It'll be a one-liner now. All we have to do now is call the `graphicalBar()` method and fill the parameters accordingly:

```fun healthBar(): String {
return graphicalBar(health, maxHealth)
}```

Of course, I could add the `graphicalBar()` method in the `Warrior` class like I did with `attack()` before, but I wanted to show you how to deal with cases where we would need to accomplish similar functionality multiple times. You'll need to put this kind of parametrization in practice since you never know exactly what you'll need from your program at any given moment during the design stage.

Now, we can easily draw graphical bars as needed. Let's move to `Mage.kt` and implement the `manaBar()` method:

```fun manaBar(): String {
return graphicalBar(mana, maxMana)
}```

Simple, isn't it? Our mage is done now, all that's left to do is tell the arena to show mana in case the warrior is a mage. Let's move to `Arena`.

## Recognizing the object type

We'll add a separate printing method for warriors, `printWarrior()`, to keep things nice and neat. Its parameter will be a `Warrior` instance:

```private fun printWarrior(w: Warrior) {
println(w)
print("Health: ")
println(w.healthBar())
}```

Now, let's tell it to show the mana bar if the warrior is a mage. We'll use the `is` operator to do just that:

```private fun printWarrior(w: Warrior) {
println(w)
print("Health: ")
println(w.healthBar())
if (w is Mage)
print("Mana: \${w.manaBar()}") // Kotlin is smart, casting the Warrior to Mage automatically
}```

This is it, we'll cal `printWarrior()` in the `render()` method, which now looks like this:

```private fun render() {
println("-------------- Arena -------------- \n")
println("Warriors: \n")
printWarrior(warrior1)

println()
printWarrior(warrior2);

println("\n")
}```

Done

```-------------- Arena --------------

Warriors:

Zalgoren
Health: [####                ]

Gandalf
Health: [#######             ]
Mana:  [#                   ]

Gandalf used magic and took 48 hp off
Zalgoren defended against the attack but still lost 33 hp```

I added an ASCIIart Arena heading that I made using this application, http://patorjk.com/software/taag. I also modified the rendering method of the indicators so it prints filled rectangles instead of # (you can type full rectangles using Alt + 219). Mine looks like this now, but you could do whatever you want with yours:

```                __    ____  ____  _  _    __
/__\  (  _ \( ___)( \( )  /__\
/(__)\  )   / )__)  )  (  /(__)\
(__)(__)(_)\_)(____)(_)\_)(__)(__)
Warriors:

Zalgoren
Health: ████░░░░░░░░░░░░░░░░

Gandalf
Health: ███████░░░░░░░░░░░░░
Mana:   █░░░░░░░░░░░░░░░░░░░

Gandalf used magic and took 48 hp off
Zalgoren received and blow and lost 33 hp```

You can download the code below. If there is something you don't quite understand, try reading the lesson several times, this content is extremely important for you to know. In the next lesson, Companion objects in Kotlin, we'll explain the concept of static class members.

Article has been written for you by Samuel Kodytek
User rating: