NLinker icon

Calling the `retain` on the part of the game state

NLinker | PRO | 07/13/18 12:00:20 PM UTC | 0 ⭐ | 947 👁️ | Never ⏰ | []
Rust |

2.69 KB

|

None

|

0 👍

/

0 👎

/// ### The problem
 
        for k in 0..np {
            if k == index {
                gs.players[k].body_mut().clear();
                gs.players[k].body_mut().push(new_head);
            } else if gs.players[k].body().is_empty() {
                panic!("Broken invariant");
            } else {
                let head = *gs.players[k].head().expect("Broken invariant");
                // let cells = &gs.field.cells;
                gs.players[k].body_mut().retain(|ref p| {
                    // remove the points from the body if they are owned by someone else
                    match gs.field.cells[p.0 as usize][p.1 as usize] {
                        Cell::Owned(_) => false,
                        _ => true
                    }
                });
                // just in case
                if gs.players[k].body().is_empty() {
                    gs.players[k].body_mut().push(head);
                }
            }
        }
 
/*
We get the error:
```
error[E0502]: cannot borrow `gs` as immutable because `gs.players` is also borrowed as mutable
   --> src/model.rs:723:49
    |
723 |                 gs.players[k].body_mut().retain(|ref p| {
    |                 ----------                      ^^^^^^^ immutable borrow occurs here
    |                 |
    |                 mutable borrow occurs here
724 |                     // remove the points from the body if they are owned by someone else
725 |                     match gs.field.cells[p.0 as usize][p.1 as usize] {
    |                           -- borrow occurs due to use of `gs` in closure
...
729 |                 });
    |                  - mutable borrow ends here
*/
 
/// ### Fix
 
        for k in 0..np {
            if k == index {
                gs.players[k].body_mut().clear();
                gs.players[k].body_mut().push(new_head);
            } else if gs.players[k].body().is_empty() {
                panic!("Broken invariant");
            } else {
                let head = *gs.players[k].head().expect("Broken invariant");
                // make the closure to refer only the part of the game state, not the whole one
                let cells = &gs.field.cells;
                gs.players[k].body_mut().retain(|ref p| {
                    // remove the points from the body if they are owned by someone else
                    match cells[p.0 as usize][p.1 as usize] {
                        Cell::Owned(_) => false,
                        _ => true
                    }
                });
                // just in case
                if gs.players[k].body().is_empty() {
                    gs.players[k].body_mut().push(head);
                }
            }
        }

Comments