use crate::alg::{Alg, Move};
use super::super::{KPuzzleDefinition, KTransformationData};
pub(crate) enum MoveLookupResultSource<'a> {
DirectlyDefined(&'a KTransformationData),
DerivedFromAlg(&'a Alg), }
pub(crate) struct MoveLookupResult<'a> {
pub(crate) key_move: &'a Move,
pub(crate) relative_amount: i32,
pub(crate) source: MoveLookupResultSource<'a>,
}
fn move_with_amount_1(r#move: &Move) -> Move {
Move {
quantum: r#move.quantum.clone(),
amount: 1,
}
}
pub(crate) fn lookup_move<'a>(
def: &'a KPuzzleDefinition,
r#move: &Move,
) -> Option<MoveLookupResult<'a>> {
if let Some((key_move, source)) = def.moves.get_key_value(&move_with_amount_1(r#move)) {
return Some(MoveLookupResult {
key_move,
relative_amount: r#move.amount,
source: MoveLookupResultSource::DirectlyDefined(source),
});
};
if let Some(derived_moves) = &def.derived_moves {
if let Some((key_move, source)) = derived_moves.get_key_value(&move_with_amount_1(r#move)) {
return Some(MoveLookupResult {
key_move,
relative_amount: r#move.amount,
source: MoveLookupResultSource::DerivedFromAlg(source),
});
};
}
if let Some((key_move, source)) = def.moves.get_key_value(&r#move_with_amount_1(r#move)) {
return Some(MoveLookupResult {
key_move,
relative_amount: 1,
source: MoveLookupResultSource::DirectlyDefined(source),
});
};
if let Some(derived_moves) = &def.derived_moves {
if let Some((key_move, source)) = derived_moves.get_key_value(r#move) {
return Some(MoveLookupResult {
key_move,
relative_amount: 1,
source: MoveLookupResultSource::DerivedFromAlg(source),
});
};
}
if let Some((key_move, source)) = def.moves.get_key_value(&r#move.invert()) {
return Some(MoveLookupResult {
key_move,
relative_amount: -1,
source: MoveLookupResultSource::DirectlyDefined(source),
});
};
if let Some(derived_moves) = &def.derived_moves {
if let Some((key_move, source)) = derived_moves.get_key_value(&r#move.invert()) {
return Some(MoveLookupResult {
key_move,
relative_amount: -1,
source: MoveLookupResultSource::DerivedFromAlg(source),
});
};
}
None
}