Roguelike Dev Day 5: More Monsters
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.