0
votes

I'm just messing around slowly learning Swift, and I decided to make a really simple fighting game. All the below code worked perfectly fine when it was a class, then I decided to change it to a struct, and now on the lines in the function that would reduce the target's hp, it's giving me the following error:

Cannot use mutating member on immutable value

Here is the struct in it's entirety:

struct Player {
    let name : String
    let maxHealth : Int
    var currentHealth : Int
    let maxMana: Int
    var currentMana: Int

    init(playerName: String) {
        name = playerName
        maxHealth = 100
        currentHealth = 100
        maxMana = 100
        currentMana = 100
    }

    mutating func swingAt(target: Player) {
        if isDead(target: self) {
            print("You are dead!")
            return
        }
        let damage = Int.random(in: 0..<10)
        target.takeDamage(amount: damage) // Error:Cannot use mutating member on immutable value: 'target' is a 'let' constant
        if damage > 0 {
            print("\(self.name) does \(damage) damage to \(target.name)!")
        }
        else {
            print("\(self.name) misses \(target.name)!")
        }
        if isDead(target: target) {
            print("\(self.name) has slain \(target.name)!")
        }
    }

    mutating func swingFiveTimesAt(target: Player) {
        if isDead(target: self) {
            print("You are dead!")
            return
        }
        for _ in 1...5 {
            let damage = Int.random(in: 0..<10)
            target.takeDamage(amount: damage) // Error:Cannot use mutating member on immutable value: 'target' is a 'let' constant
            if damage > 0 {
                print("\(self.name) does \(damage) damage to \(target.name)!")
            }
            else {
                print("\(self.name) misses \(target.name)!")
            }
        }
        if isDead(target: target) {
            print("\(self.name) has slain \(target.name)!")
        }
    }

    mutating func castFireball(target: Player) {
        if isDead(target: self) {
            print("You are dead!")
            return
        }
        if self.currentMana < 50 {
            print("\(self.name) only has \(self.currentMana), but needs 50 mana to cast this spell!")
            return
        }
        let damage = Int.random(in: 1..<50)
        target.takeDamage(amount: damage) // Error:Cannot use mutating member on immutable value: 'target' is a 'let' constant
        self.currentMana -= 50
        print("\(self.name) throws a huge fireball at \(target.name), doing \(damage) damage!")
        if isDead(target: target) {
            print("\(self.name) has slain \(target.name)!")
        }
    }

    func isDead(target: Player) -> Bool {
        if target.currentHealth <= 0 {
            return true
        } else {
            return false
        }
    }

    mutating func takeDamage(amount: Int) {
        self.currentHealth -= amount
    }
}

Any ideas how I can achieve the desired functionality?

1

1 Answers

1
votes

I searched for about 45 minutes before posting this, and of course immediately after posting this I was able to find an answer. Turns out adding 'inout' fixed it!

Broken: mutating func swingAt(target: Player) {

Working: mutating func swingAt(target: inout Player) {