I am writing a small strategic game, but I have a problem with implementing a circular linked list.
The game involves several people taking actions one by one and round by round until the game ends. I though that this could be done by using a circular linked list where each element is a player with a reference to the next player. The structure is like this:
#[derive(Debug, Clone)]
struct Player {
name: String,
killed: bool,
next: Option<Box<Player>>,
}
I also want a pointer to the current active player and be able to modify the status of it, but I think Rust does not allow me to have two mutable references to the same object because each player already has a mutable reference to the next player.
What I came up with is that I can use a simple mutable reference to the Box
which is owned by its previous player and pointing to the current player. I wrote a simple main function where the problem occurs:
fn main() {
let mut p3: Player = Player {
name: "C".to_string(),
killed: false,
next: None,
};
let mut p2: Player = Player {
name: "B".to_string(),
killed: false,
next: Some(unsafe { Box::from_raw(&mut p3) }),
};
let mut p1: Player = Player {
name: "A".to_string(),
killed: false,
next: Some(unsafe { Box::from_raw(&mut p2) }),
};
p3.next = Some(unsafe { Box::from_raw(&mut p1) });
println!("GAME STARTED!");
let mut current_player = p3.next.as_mut().unwrap();
let mut count = 0;
while count < 10 {
println!("Player to kill/save {}", current_player.name);
(*current_player).killed = !(*current_player).killed;
println!(
"Player {} is killed: {}",
(*current_player).name,
(*current_player).killed
);
current_player = (*current_player).next.as_mut().unwrap();
count = count + 1
}
println!("End!");
}
The error is also about the mutability but I have no idea how to fix it. I wonder if there is a better way to implement the idea in Rust rather than using a circular linked list and a pointer to the current player. Maybe should I switch to another structure?
The error message is quite long, here are the first few lines:
error[E0502]: cannot borrow `current_player` (via `current_player.name`) as immutable because `current_player` is also borrowed as mutable (via `current_player.next`)
--> src/main.rs:29:44
|
29 | println!("Player to kill/save {}", current_player.name);
| ^^^^^^^^^^^^^^^^^^^ immutable borrow of `current_player.name` -- which overlaps with `current_player.next` -- occurs here
...
36 | current_player = (*current_player).next.as_mut().unwrap();
| ---------------------- mutable borrow occurs here (via `current_player.next`)
...
40 | }
| - mutable borrow ends here
If I change the as_mut()
method to as_ref()
which returns the immutable reference of the Box
, and comment the line
// (*current_player).killed = !(*current_player).killed;
The program can build successfully but there will be an unknown runtime error when it finishes. Don't know why that happens either.
GAME STARTED!
Player to kill/save A
Player A is killed: false
Player to kill/save B
Player B is killed: false
......
Player to kill/save C
Player C is killed: false
Player to kill/save A
Player A is killed: false
End!
error: An unknown error occurred