Approach to modify a struct using helpers within the struct?

apply_turn(&mut self, ...) is probably fine itself - it’s the entrypoint for mutation. Once you’re inside apply_turn, you can borrow individual fields of self separately.

For example, you mentioned a sell_item function that’s called from apply_turn:

fn sell_item(&mut self, hero : usize, name : &str ) {
		let item = self.find_item(name).unwrap();
		self.us.gold += item.cost / 2;

This is a good example to zoom in on. The issue, as you’ve discovered, is find_item makes it look to the compiler like you’re holding a reference to all of self. In reality, it’s a reference to an element in the Vec<Item> only. The us field, which owns gold, is disjoint ... but the way the methods are structured, the compiler cannot see this.

A couple of simple tweak options for this case:
(1) Define a private struct called Items, which is just a wrapper around a Vec<Item> and then hang the find_item function on it. The sell_item then looks like this:

fn sell_item(&mut self, hero : usize, name : &str ) {
		let item = self.items.find_item(name).unwrap();
		self.us.gold += item.cost / 2;

(2) Add a helper find_item associated function (rather than method):

fn find_item<'a>(v: &'a Vec<Item>, name: &str) -> Option<&'a Item> { ...} 
fn sell_item(&mut self, hero : usize, name : &str ) {
		let item = Self::find_item(&self.items, name).unwrap();
		self.us.gold += item.cost / 2;

In both cases, you want to make the compiler see that disjoint fields are being borrowed.

2 Likes