-module(btl_action). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -record ( move, { actor_ix :: non_neg_integer(), path :: list(shr_direction:enum()) movement_points :: non_neg_integer() } ). -record ( switch_weapon, { actor_ix :: non_neg_integer() } ). -record ( attack, { actor_ix :: non_neg_integer(), target_ix :: non_neg_integer(), is_opportunistic :: boolean() } ). -type category() :: ( 'move' | 'switch_weapon' | 'attack' | 'nothing' ). -opaque type() :: ( #move{} | #switch_weapon{} | #attack{} | #attack_of_opportunity{} ). -export_type([category/0, type/0]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -export ( [ from_map_marker/2, maybe_decode_move/2, maybe_decode_weapon_switch/2, maybe_decode_attack/2, can_follow/2 ] ). -export ( [ new_interrupted_move/2 ] ). -export ( [ get_path/1, get_movement_points/1, get_target_index/1, get_actor_index/1, get_category/1 ] ). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec maybe_decode_move ( non_neg_integer(), list(shr_direction:type()) ) -> list(type()). maybe_decode_move (_CharacterIX, []) -> []; maybe_decode_move (CharacterIX, PathInBinary) -> Path = lists:map(fun shr_direction:decode/1, PathInBinary), [#move{ actor_ix = CharacterIX, path = Path }]. -spec maybe_decode_attack ( non_neg_integer(), integer() ) -> list(type()). maybe_decode_attack (_CharacterIX, TargetIX) when (TargetIX < 0) -> []; maybe_decode_attack (CharacterIX, TargetIX) -> [#attack{ actor_ix = CharacterIX, target_ix = TargetIX }]. -spec maybe_decode_weapon_switch ( non_neg_integer(), boolean() ) -> list(type()). maybe_decode_weapon_switch (_CharacterIX, false) -> []; maybe_decode_weapon_switch (CharacterIX, true) -> [#switch_weapon{ actor_ix = CharacterIX }]. -spec can_follow (category(), category()) -> boolean(). can_follow (nothing, attack) -> true; can_follow (nothing, switch_weapon) -> true; can_follow (nothing, move) -> true; can_follow (move, switch_weapon) -> true; can_follow (move, attack) -> true; can_follow (_, _) -> false. -spec get_path (type()) -> list(shr_direction:type()). get_path (Action) when is_record(Action, move) -> Action#move.path; get_path (Action) when is_record(Action, interrupted_move) -> Action#interrupted_move.path; get_path (_) -> []. -spec get_movement_points (type()) -> non_neg_integer(). get_movement_points (Action) when is_record(Action, interrupted_move) -> Action#interrupted_move.movement_points; get_movement_points (_) -> 0. -spec get_target_index (type()) -> non_neg_integer(). get_target_index (Action) when is_record(Action, attack) -> Action#attack.target_ix; get_target_index (Action) when is_record(Action, attack_of_opportunity) -> Action#attack_of_opportunity.target_ix; get_target_index (_) -> 0. -spec get_actor_index (type()) -> (non_neg_integer() | -1). get_actor_index (Action) when is_record(Action, attack) -> Action#attack.actor_ix; get_actor_index (Action) when is_record(Action, attack_of_opportunity) -> Action#attack_of_opportunity.actor_ix; get_actor_index (Action) when is_record(Action, move) -> Action#move.actor_ix; get_actor_index (Action) when is_record(Action, switch_weapon) -> Action#switch_weapon.actor_ix; get_actor_index (_) -> -1. -spec new_interrupted_move ( list(shr_direction:type()), non_neg_integer() ) -> type(). new_interrupted_move (Path, MovementPoints) -> #interrupted_move{ path = Path, movement_points = MovementPoints }. -spec get_category (type()) -> category(). get_category (Action) when is_record(Action, attack) -> attack; get_category (Action) when is_record(Action, move) -> move; get_category (Action) when is_record(Action, switch_weapon) -> switch_weapon; get_category (Action) when is_record(Action, interrupted_move) -> interrupted_move; get_category (Action) when is_record(Action, attack_of_opportunity) -> attack_of_opportunity. -spec from_map_marker ( btl_character:type(), shr_map_marker:type() ) -> list(type()). from_map_marker (_Character, Marker) -> case shr_map_marker:get_category(Marker) of matk -> [ #attack_of_opportunity { target_ix = shr_map_marker:get_character_index(Marker) } ]; _ -> [] end.