3

This code built ok previously using Anchor Build, but after upgrade of Anchor and Solana I am getting lifetime errors on build. Can anyone help point me in the right direction? enter image description here

use anchor_lang::prelude::*; use crate::{ Game, MoveAction, PlayerGameRecord, TurnMovesRecord, Coordinates, Army }; pub use crate::errors::ErrorCode;

pub fn submit_player_turn(_ctx: Context, _turns: Vec) -> Result<()> {

let player_turn = &mut _ctx.accounts.turn_moves_record;

//If this player has already submitted a turn then return error
if _ctx.accounts.game.current_turn < _ctx.accounts.player_game_record.current_turn {
    return Err(ErrorCode::TurnAlreadySubmitted.into());
};

//for all army accounts that have been passed in using remaining_accounts, check that the army x and y position matched the from_x and from_y in the move action

let mut no_armies_passed = false;
let mut move_not_to_neighbor = false;
let mut not_moving_from_starting_position = false;

_turns.iter().for_each(|move_action| {

    //You must pass in army accounts for each of your armies that is moving
    if _ctx.remaining_accounts.len() == 0 {
        no_armies_passed = true;
    }
    _ctx.remaining_accounts.iter().for_each(|army_account| {
            let army = Account::<Army>::try_from(&army_account).unwrap();
            if army.key() == move_action.army {
                if army.x == move_action.from_x && army.y == move_action.from_y {
                    if !are_hex_neighbors(move_action.from_x, move_action.from_y, move_action.to_x, move_action.to_y) {
                        move_not_to_neighbor = true;
                    } else {
                        //msg!("Army x: {}, y: {}", army.x, army.y);
                    }
                } else {
                    not_moving_from_starting_position = true;
                }
            }
    });
});

if no_armies_passed {
    return Err(ErrorCode::NoArmiesPassed.into());
}
if move_not_to_neighbor {
    return Err(ErrorCode::MoveNotToNeighbor.into());
}
if not_moving_from_starting_position {
    return Err(ErrorCode::NotMovingFromStartingPosition.into());
}

player_turn.game_id = _ctx.accounts.player_game_record.game_id;
player_turn.player = _ctx.accounts.player.key();
player_turn.game_turn = _ctx.accounts.player_game_record.current_turn;
player_turn.moves = _turns;
player_turn.bump = _ctx.bumps.turn_moves_record;

//Update player turn as this turn has been submitted
let player_record = &mut _ctx.accounts.player_game_record;
player_record.current_turn = player_record.current_turn + 1;

//Update game with hexes and coordinates to process.  Game turn can only be incremented once all armies and hexes have been processed
let game = &mut _ctx.accounts.game;

//for each army in _turns add to game.armies_to_process if not already in list
player_turn.moves.iter().for_each(|move_action| {
    if !game.armies_to_process.iter().any(|&a| a == move_action.army)  {
        game.armies_to_process.push(move_action.army);
    }
});

//Create coordinates from each move's to_x and to_y then add to game.hexes_to_process if not already in list
let mut hexes_to_process: Vec<Coordinates> = Vec::new();
player_turn.moves.iter().for_each(|move_action| {
    let coordinate = Coordinates { x: move_action.to_x, y: move_action.to_y };
    if !game.hexes_to_process.iter().any(|c| c.x == coordinate.x && c.y == coordinate.y)  {
        hexes_to_process.push(coordinate);
    }
});
game.hexes_to_process.append(&mut hexes_to_process);

Ok(())      

}

#[instruction(turns: Vec<MoveAction>)]
pub struct SubmitPlayerTurn<'info> {
    #[account(mut)]
    pub player: Signer<'info>,   
    #[account(mut)] 
    pub player_game_record: Account<'info, PlayerGameRecord>,        
    #[account(
        init,
        payer = player,
        space = 8 + TurnMovesRecord::MAXIMUM_SIZE, seeds = [
            b"turn-moves-record".as_ref(), 
            player_game_record.game_id.key().as_ref(),
            player.key().as_ref(),
            &player_game_record.current_turn.to_le_bytes()
            ],
        bump
    )]        
    pub turn_moves_record: Account<'info, TurnMovesRecord>,    
    #[account(mut)] 
    pub game: Account<'info, Game>,
    pub system_program: Program<'info, System>
}

//Utlilty functions
fn are_hex_neighbors(x1: u8, y1: u8, x2: u8, y2: u8) -> bool {
    // Calculate the absolute distance between the x and y coordinates
    let dx = (x1 as i16 - x2 as i16).abs();
    let dy = (y1 as i16 - y2 as i16).abs();
    msg!("x1: {}, y1: {}, x2: {}, y2: {}", x1, y1, x2, y2);
    // Two hexagons are neighbors if the absolute difference in x and y coordinates
    // is no more than 1, and the sum of those differences is no more than 2
    dx <= 1 && dy <= 1 && dx + dy <= 2
}

1 Answer 1

4

remaining_accounts usage in anchor-lang 0.29.0 requires explicit lifetime annotions:

pub fn submit_player_turn<'c: 'info, 'info>(
    ctx: Context<'_, '_, 'c, 'info, SubmitPlayerTurn>,
    turns: Vec<MoveAction>, 
) -> Result<()> {

Note: _ prefix for identifiers in Rust indicates that you don't want to deal with the values but you seem to be using both _ctx and _turns parameters so I've removed the prefix in the solution above.

Example

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.