I am implementing the board game Nine Man's Morris in Rust. I have a Game
struct which owns a Board
struct. Board
stores a RefCell<HashSet>
of references to a Position
struct. Board
and Game
share lifetime parameters.
pub struct Board<'a> {
pub positions: Vec<Position>,
pub ids_to_positions: HashMap<String, usize>,
p1_mills: RefCell<HashSet<(&'a Position, &'a Position, &'a Position)>>,
p2_mills: RefCell<HashSet<(&'a Position, &'a Position, &'a Position)>>,
can_mill: Cell<bool>,
}
pub struct Game<'a> {
pub board: Board<'a>,
pub player1: Player,
pub player2: Player,
current_player_id: i8,
}
Game::game_loop
loops through a set of methods (get input, update the board, etc) until the game has ended. This has been working fine as I've added methods to it.
impl<'a> Game<'a> {
pub fn print(&self) {
self.board.print();
}
pub fn game_loop(&'a mut self) {
loop {
self.print();
self.make_move();
print!("can_mill: {}", self.board.can_mill());
self.board.update_mills(self.current_player_id);
self.switch_player();
}
}
pub fn make_move(&mut self) {}
pub fn switch_player(&self) {}
}
There is a mix of methods with mutable and immutable references to self
, and 2 calls on Board
:
pub fn can_mill(&self) -> bool {}
pub fn update_mills(&'a self, player_id: i8) {}
update_mill
updates the p1_mills
and p2_mills
fields, and can_mill
references the can_mill
field.
If I remove the update_mills
call in game_loop
, the code compiles. With it, I get
cannot borrow
*self
as mutable becauseself.board
is also borrowed as immutable.
I'm pretty sure this has something to with the explicit lifetime in that method, but in all my reading around I haven't been able to get it to work or understand what isn't working. It's confusing because without I don't get any borrowing errors. I'm also not clear if having the mill sets in RefCell
s is breaking anything (I can't actually remember why there are in them in the first place to be honest).
I realise this is quite involved but I'd really appreciate some help. I tried to recreate the issue with a simpler example but couldn't sadly.