# Borrowing Without the Lecture.

Our game has a `Player` and an `Enemy`

Then, the moment they fight, we strip them back down for parts:

```rust
enemy.health = attack(
    enemy.health,
    player.base_damage,
    player.bonus_damage,
);
```

We built two real game types.

The moment they interact, we go back to passing loose numbers around.

In this article, we are going to change `attack()` so it takes the player and the enemy themselves.

Along the way, Rust will refuse to compile our code three times.

Every time, it will be right.

By the end, our combat loop will say what the game actually does:

```rust
attack(&player, &mut enemy);
```

A player attacks an enemy.

Nothing gets torn apart.

* * *

## Our starting point

You need two structs and four small functions to follow along:

```rust
struct Player {
    base_damage: u32,
    bonus_damage: u32,
}

struct Enemy {
    name: String,
    health: u32,
}

fn click_damage(base: u32, bonus: u32) -> u32 {
    base.saturating_add(bonus)
}

fn health_after_hit(
    health: u32,
    damage: u32,
) -> u32 {
    health.saturating_sub(damage)
}

fn is_defeated(health: u32) -> bool {
    health == 0
}

fn attack(
    health: u32,
    base_damage: u32,
    bonus_damage: u32,
) -> u32 {
    let damage =
        click_damage(base_damage, bonus_damage);

    health_after_hit(health, damage)
}
```

At the bottom of `main.rs`, the `tests` module holds three tests for the small rules and one test that calls `attack()` directly:

```rust
#[test]
fn attack_reduces_enemy_health() {
    assert_eq!(attack(10, 5, 2), 3);
}
```

We will come back to that test once `attack()` changes.

Our combat loop looks like this:

```rust
fn main() {
    let player = Player {
        base_damage: 5,
        bonus_damage: 2,
    };

    let mut enemy = Enemy {
        name: String::from("Training Slime"),
        health: 20,
    };

    while !is_defeated(enemy.health) {
        enemy.health = attack(
            enemy.health,
            player.base_damage,
            player.bonus_damage,
        );

        println!(
            "{} health: {}",
            enemy.name,
            enemy.health
        );
    }

    println!("{} defeated!", enemy.name);
}
```

It works.

But `attack()` does not know what a player is.

It does not know what an enemy is.

It takes three numbers and hands back a fourth, and `main()` has to put that number back where it belongs.

What we want to write is closer to:

```rust
attack(player, enemy);
```

So let us try that.

* * *

## Hand the player to `attack()`

Let us start with the player and leave the enemy alone for a moment.

Change `attack()` so it takes a whole `Player` instead of two loose damage values:

```rust
fn attack(
    player: Player,
    health: u32,
) -> u32 {
    let damage = click_damage(
        player.base_damage,
        player.bonus_damage,
    );

    health_after_hit(health, damage)
}
```

The body barely changed.

We read the damage values from the player with the same dot syntax we used in `main()`.

Now update the call inside the loop:

```rust
enemy.health =
    attack(player, enemy.health);
```

That reads much better.

Run it:

```bash
cargo run
```

Rust refuses to build the program.

Trimmed down, the error says:

```text
error[E0382]: use of moved value: `player`

value moved here, in previous
iteration of loop
```

The full message is longer, and it suggests a few fixes, like cloning the player.

Some of them would work.

None of them is what we want, so let us figure out what actually happened.

The first attack would have been fine.

The second attack is the problem.

Where did the player go?

* * *

## The player moved

In Rust, every value has an owner.

Right now, `main()` owns `player`.

It created it, so it is responsible for it.

When we write:

```rust
attack(player, enemy.health)
```

and `attack()` asks for a `Player`, we are not lending the player to `attack()`.

We are giving it away.

Ownership moves into `attack()`.

When `attack()` finishes, the `Player` it owns is no longer available back in `main()`.

So on the next trip around the loop, `main()` tries to hand over a player it no longer owns.

Rust catches that before the program ever runs.

In game terms, our player attacked once and then vanished.

That is a bold balancing decision.

It is not ours.

The attack was supposed to defeat the enemy.

Not the player.

* * *

## Why did health never move?

We have been passing `enemy.health` into functions all along, and it never disappeared.

That is because `u32` implements Rust's `Copy` trait.

When we pass a `u32` by value, Rust can automatically make a copy, so the original remains available.

Our `Player` does not implement `Copy`, so passing it by value moves ownership instead.

You do not need to understand traits yet.

For now, the useful difference is:

```text
u32     → copied
Player  → moved
```

A `u32` gets photocopied.

A `Player` gets handed over.

We do not want to give the player away.

We want `attack()` to look at it.

* * *

## Borrow the player with `&`

Rust lets a function borrow a value instead of owning it.

Add one character to the parameter type:

```rust
fn attack(
    player: &Player,
    health: u32,
) -> u32 {
    let damage = click_damage(
        player.base_damage,
        player.bonus_damage,
    );

    health_after_hit(health, damage)
}
```

`&Player` means:

> a reference to a `Player` that someone else owns

A reference lets `attack()` reach the player without taking ownership of it.

When the call finishes, the player is still sitting in `main()` where we left it.

Notice that the body did not change.

The dot works the same way through a reference, so:

```rust
player.base_damage
```

still reads the field.

The call needs the same `&`:

```rust
enemy.health =
    attack(&player, enemy.health);
```

`&player` says:

> let `attack()` borrow the player for this call

Run it:

```bash
cargo run
```

The Training Slime goes down in three hits again.

The player survives every one of them.

There is a bonus hiding in that `&`.

A plain `&` reference gives `attack()` read-only access to the player's fields.

If `attack()` tried to assign a new value to:

```rust
player.base_damage
```

Rust would refuse to compile it.

That is exactly the promise we want.

An attack needs to read the player.

It does not need to change the player.

* * *

## Now the enemy

The player is solved.

The enemy is still split apart:

```rust
enemy.health =
    attack(&player, enemy.health);
```

`attack()` gets a copy of the enemy's health, calculates a new number, and returns it.

Then `main()` writes that number back into the enemy.

What we really want is for `attack()` to change the enemy itself.

We just learned that borrowing keeps a value where it is.

Let us borrow the enemy too:

```rust
fn attack(
    player: &Player,
    enemy: &Enemy,
) {
    let damage = click_damage(
        player.base_damage,
        player.bonus_damage,
    );

    enemy.health =
        health_after_hit(enemy.health, damage);
}
```

Two things changed besides the enemy parameter.

There is no:

```rust
-> u32
```

anymore.

`attack()` is not handing back a number for someone else to store.

The result lives in the enemy.

Inside the function, we assign the new health directly to:

```rust
enemy.health
```

Update the call in `main()`:

```rust
attack(&player, &enemy);
```

Run it:

```bash
cargo run
```

Rust refuses again:

```text
error[E0594]: cannot assign to
`enemy.health`, which is behind
a `&` reference
```

You may also see a warning that `enemy` does not need to be mutable.

Ignore it for a moment.

We are about to need that `mut` again.

This is the promise from the last section working against us.

`&Enemy` lets us look at the enemy.

We did not come here to look.

A plain `&` reference is read-only.

That was perfect for the player.

It is wrong for the enemy because the entire point of an attack is that the enemy's health changes.

* * *

## Borrow the enemy with `&mut`

We have already met `mut`.

It is how we told Rust that our enemy is allowed to change.

References can express the same idea.

Change:

```rust
&Enemy
```

to:

```rust
&mut Enemy
```

Our attack becomes:

```rust
fn attack(
    player: &Player,
    enemy: &mut Enemy,
) {
    let damage = click_damage(
        player.base_damage,
        player.bonus_damage,
    );

    enemy.health =
        health_after_hit(enemy.health, damage);
}
```

`&mut Enemy` means:

> a mutable reference to an `Enemy` that someone else owns

In game terms:

> `attack()` may temporarily change this enemy, but it does not own the enemy.

The call needs to ask for the same thing:

```rust
attack(&player, &mut enemy);
```

This only works because `enemy` was already declared with:

```rust
let mut enemy
```

Rust will not let us borrow something mutably if the owner never agreed that it could change.

Run it:

```bash
cargo run
```

You should see:

```text
Training Slime health: 13
Training Slime health: 6
Training Slime health: 0
Training Slime defeated!
```

The same fight as before.

But now the signature tells the whole story:

```text
&Player     → attack reads the player
&mut Enemy  → attack changes the enemy
```

Nobody gets consumed.

Nobody gets torn apart.

Both are still in `main()`, ready for the next attack.

* * *

## One rule worth knowing now

There is one borrowing rule you will run into early, so here it is in game terms.

Suppose that, instead of the combat loop, `main()` grabs a reference to the enemy's name before attacking:

```rust
let name = &enemy.name;

attack(&player, &mut enemy);

println!("{name} took a hit!");
```

Rust refuses for the third time:

```text
error[E0502]: cannot borrow `enemy`
as mutable because it is also
borrowed as immutable
```

A borrow remains active until its last use.

`name` is used by the `println!()` after the attack, so that borrow is still active when `attack()` asks for permission to change the enemy.

Rust will not hand out a mutable borrow while that reading borrow is still being used.

Our combat loop never hits this problem because each borrow is finished before the next conflicting access begins:

```rust
attack(&player, &mut enemy);

println!(
    "{} health: {}",
    enemy.name,
    enemy.health
);
```

In this case, the mutable borrow is finished when `attack()` returns.

Then `println!()` is free to read the enemy.

That is the beginner version of the rule:

> **For the same data at the same time: many readers, or one writer, but not both.**

You do not need more than that today.

* * *

## Update the test

Our `attack()` test still passes three loose numbers, so it needs the new signature:

```rust
#[test]
fn attack_reduces_enemy_health() {
    let player = Player {
        base_damage: 5,
        bonus_damage: 2,
    };

    let mut enemy = Enemy {
        name: String::from("Training Slime"),
        health: 10,
    };

    attack(&player, &mut enemy);

    assert_eq!(enemy.health, 3);
}
```

The rule it checks has not changed.

An attack with five base damage and two bonus damage takes ten health down to three.

What changed is how the test says it.

It builds a player.

It builds an enemy.

It lets one attack the other.

Then it checks the enemy afterward.

That reads like the game.

The other three tests do not touch `attack()`, so they stay exactly as they were.

Run them:

```bash
cargo test
```

All four should pass.

We do not need a separate test proving that `attack()` does not change the player.

With our current `Player` type, an `&Player` reference does not allow `attack()` to assign new values to the player's fields.

The compiler checks that for us every time we build.

* * *

## The complete program

If you have been following along in your editor, here is everything in one place.

At this point, `src/main.rs` should look like this:

```rust
struct Player {
    base_damage: u32,
    bonus_damage: u32,
}

struct Enemy {
    name: String,
    health: u32,
}

fn click_damage(base: u32, bonus: u32) -> u32 {
    base.saturating_add(bonus)
}

fn health_after_hit(
    health: u32,
    damage: u32,
) -> u32 {
    health.saturating_sub(damage)
}

fn is_defeated(health: u32) -> bool {
    health == 0
}

fn attack(
    player: &Player,
    enemy: &mut Enemy,
) {
    let damage = click_damage(
        player.base_damage,
        player.bonus_damage,
    );

    enemy.health =
        health_after_hit(enemy.health, damage);
}

fn main() {
    let player = Player {
        base_damage: 5,
        bonus_damage: 2,
    };

    let mut enemy = Enemy {
        name: String::from("Training Slime"),
        health: 20,
    };

    while !is_defeated(enemy.health) {
        attack(&player, &mut enemy);

        println!(
            "{} health: {}",
            enemy.name,
            enemy.health
        );
    }

    println!("{} defeated!", enemy.name);
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn click_damage_adds_base_and_bonus() {
        assert_eq!(click_damage(3, 4), 7);
    }

    #[test]
    fn health_never_drops_below_zero() {
        assert_eq!(
            health_after_hit(3, 10),
            0
        );
    }

    #[test]
    fn zero_health_is_defeated() {
        assert!(is_defeated(0));
        assert!(!is_defeated(1));
    }

    #[test]
    fn attack_reduces_enemy_health() {
        let player = Player {
            base_damage: 5,
            bonus_damage: 2,
        };

        let mut enemy = Enemy {
            name: String::from("Training Slime"),
            health: 10,
        };

        attack(&player, &mut enemy);

        assert_eq!(enemy.health, 3);
    }
}
```

Run both:

```bash
cargo run
cargo test
```

The Training Slime should fall in three hits, and all four tests should pass.

* * *

## What we learned

Along the way, we encountered:

*   ownership
    
*   moves
    
*   `Copy` values
    
*   `&T` references
    
*   `&mut T` references
    
*   functions that change a value instead of returning a new one
    
*   when borrows stop being used
    
*   why Rust prevents conflicting access
    

You do not need to memorize all of that yet.

The important change is what our attack says.

We started with:

```rust
enemy.health = attack(
    enemy.health,
    player.base_damage,
    player.bonus_damage,
);
```

We ended with:

```rust
attack(&player, &mut enemy);
```

The player is read.

The enemy is changed.

Both stay where they belong.

And the compiler now checks that `attack()` keeps its side of that deal.

* * *

## There is a bigger shape missing

Look at what `main()` is holding now:

```text
player
enemy
the combat loop
```

That is a fight.

It is not a game.

When the Training Slime dies, the program simply ends.

There is no next enemy.

There is no stage counter.

Nobody earns anything for winning.

And every one of those things would become another loose variable inside `main()`:

```text
player
enemy
stage
gold
experience
```

We have seen this problem before.

Three numbers were not a player.

A pile of variables in `main()` is not a game.

The pieces that make up our game need one place to live, and one place that decides what happens when a player clicks.

Next, we will put the game in one place.

**Small function. Bigger game.**
