LessNoise.Sh some signal

Roguelike Dev Day 5: More Monsters

(1 minute) programming, rust, game, roguelike

Continuing with Chapter 7

It's been a little while! I got distracted playing Dwarf Fortress and reading The Silmarillion and ended up starting a simple language generator project.

I'm continuing with combat stats from last time, but I only have 30 minutes.

Done Reading

I've read through the chapter online. This stuff is getting complicated. I know lots of code goes into games, but... The code seems to be fighting the borrow checker a bunch. In this snippet, for example, we're creating a mutable variable and using explicit scopes to appease the borrow checker. Is this a clue that there is a better way, or is this how things are in rust?

let mut newrunstate;
{
    let runstate = self.ecs.fetch::<RunState>();
    newrunstate = *runstate;
}

match newrunstate {
    RunState::PreRun => {
        self.run_systems();
        newrunstate = RunState::AwaitingInput;
    }
    // ... more matching on newrunstate

Without the scope, the line self.run_systems(); generates the error cannot borrow `*self` as mutable because it is also borrowed as immutable. I think I understand this: self.run_systems() mutates self, and we can't mutate state while it's also being read, which happens at let runstate = self.ecs.fetch::<RunState>();; so the bracketed scope is telling the compiler when it can drop the temporary runstate variable.

My question isn't why we need the explicit bracketed scope; I want to know if there is a better pattern that avoids the need of an explicitly bracketed scope.

Also, I don't like the idea of sticking the player's entity into the ECS as a bare object. What if we need to save some other entity later? I'd prefer to put it in a named field somewhere. But I'm guessing that will be addressed later.