| summaryrefslogtreecommitdiff | 
diff options
| author | nsensfel <SpamShield0@noot-noot.org> | 2018-03-01 14:30:24 +0100 | 
|---|---|---|
| committer | nsensfel <SpamShield0@noot-noot.org> | 2018-03-01 14:30:24 +0100 | 
| commit | 21a949eb40407ab61e5dac956303ec1618bdfe1e (patch) | |
| tree | d88a20219e70cf2aa0db64261c4232caa02d3707 /src/query/character_turn.erl | |
| parent | 55c32019f5b82fd488c4ceed8c80e1b7a0fa114f (diff) | |
...
Diffstat (limited to 'src/query/character_turn.erl')
| -rw-r--r-- | src/query/character_turn.erl | 550 | 
1 files changed, 110 insertions, 440 deletions
| diff --git a/src/query/character_turn.erl b/src/query/character_turn.erl index cb4e8ea..adfc542 100644 --- a/src/query/character_turn.erl +++ b/src/query/character_turn.erl @@ -12,19 +12,18 @@     {        player_id :: player:id(),        session_token :: binary(), -      battlemap_instance_id :: binary(), +      battle_id :: binary(),        character_instance_ix :: non_neg_integer(), -      path :: list(binary()), -      target_ix :: (-1 | non_neg_integer()) +      actions :: list(battle_action:struct())     }  ).  -record  ( -   query_state, +   relevant_data,     { -      battlemap_instance :: battlemap_instance:struct(), -      character_instance :: character_instance:struct() +      battle :: battle:struct(), +      played_character_instance :: character_instance:struct()     }  ). @@ -34,401 +33,99 @@     {        is_new_turn :: boolean(),        updated_character_instance_ixs :: list(non_neg_integer()), -      updated_battlemap_instance :: battlemap_instance:struct() +      updated_battle :: battle:struct()     }  ).  -type input() :: #input{}. --type query_state() :: #query_state{}.  -type query_result() :: #query_result{}. + +-type relevant_data() :: #relevant_data{}.  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  -export([out/1]). +-export_type([relevant_data/0]).  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -decode_action (EncodedAction) -> -   JSONActionMap = jiffy:decode(EncodedAction, [return_maps]),  -spec parse_input (binary()) -> input().  parse_input (Req) ->     JSONReqMap = jiffy:decode(Req, [return_maps]),     CharacterInstanceIX = binary_to_integer(maps:get(<<"cix">>, JSONReqMap)), -   TargetIX = binary_to_integer(maps:get(<<"tix">>, JSONReqMap)),     EncodedActions = maps:get(<<"act">>, JSONReqMap), -   Actions = decode_action_sequence(EncodedActions), +   Actions = lists:map(fun battle_action:decode/1, EncodedActions), +     #input     {        player_id = maps:get(<<"pid">>, JSONReqMap),        session_token = maps:get(<<"stk">>, JSONReqMap),        battle_id = maps:get(<<"bid">>, JSONReqMap),        character_instance_ix = CharacterInstanceIX, -      path = maps:get(<<"p">>, JSONReqMap), -      target_ix = TargetIX +      actions = Actions     }. --spec fetch_data (input()) -> query_state(). -fetch_data (Input) -> +-spec fetch_relevant_data (input()) -> battle:struct(). +fetch_relevant_data (Input) ->     PlayerID = Input#input.player_id, -   BattlemapInstanceID = Input#input.battlemap_instance_id, +   BattleID = Input#input.battle_id,     CharacterInstanceIX = Input#input.character_instance_ix, -   BattlemapInstance = -      timed_cache:fetch -      ( -         battlemap_instance_db, -         PlayerID, -         BattlemapInstanceID -      ), +   Battle = timed_cache:fetch(battle_db, PlayerID, BattleID),     CharacterInstance = -      array:get -      ( -         CharacterInstanceIX, -         battlemap_instance:get_character_instances(BattlemapInstance) -      ), +      battle:get_character_instance(CharacterInstanceIX, Battle), -   #query_state +   #relevant_data     { -      battlemap_instance = BattlemapInstance, -      character_instance = CharacterInstance +      battle = Battle, +      played_character_instance = CharacterInstance     }.  -spec assert_character_instance_can_be_played     ( -      query_state(), +      relevant_data(),        input()     ) -   -> 'ok'. -assert_character_instance_can_be_played (QueryState, Input) -> -   BattlemapInstance = QueryState#query_state.battlemap_instance, +   -> true. +assert_character_instance_can_be_played (RData, Input) ->     PlayerID = Input#input.player_id, -   ControlledCharacterInstance = QueryState#query_state.character_instance, - -   PlayerID = -      array:get -      ( -         player_turn:get_player_ix -         ( -            battlemap_instance:get_current_player_turn(BattlemapInstance) -         ), -         battlemap_instance:get_player_ids(BattlemapInstance) -      ), -   PlayerID = -      character:get_owner_id -      ( -         character_instance:get_character(ControlledCharacterInstance) -      ), -   true = character_instance:get_is_active(ControlledCharacterInstance), - -   ok. - --spec handle_character_instance_moving -   ( -      query_state(), -      input() -   ) -   -> {list(any()), query_state()}. -handle_character_instance_moving (QueryState, Input) -> -   BattlemapInstance = QueryState#query_state.battlemap_instance, -   ControlledCharacterInstance = QueryState#query_state.character_instance, -   ControlledCharacter = -      character_instance:get_character(ControlledCharacterInstance), -   ControlledCharacterIX = Input#input.character_instance_ix, - -   Path = Input#input.path, -   Battlemap = battlemap_instance:get_battlemap(BattlemapInstance), -   ControlledCharacterStatistics = -      character:get_statistics(ControlledCharacter), -   ControlledCharacterMovementPoints = -      statistics:get_movement_points(ControlledCharacterStatistics), - -   % FIXME: The controlled character's old location should not be considered to -   % be a forbidden location. -   ForbiddenLocations = -      array:map -      ( -         fun (_IX, CharacterInstance) -> -            character_instance:get_location(CharacterInstance) -         end, -         battlemap_instance:get_character_instances(BattlemapInstance) -      ), -   {NewLocation, Cost} = -      movement:cross -      ( -         Battlemap, -         ForbiddenLocations, -         Path, -         character_instance:get_location(ControlledCharacterInstance) -      ), - -   io:format -   ( -      "~nMoving from ~p to ~p (cost ~p) with ~p movement points.~n", -      [ -         character_instance:get_location(ControlledCharacterInstance), -         NewLocation, -         Cost, -         ControlledCharacterMovementPoints -      ] -   ), - -   true = (Cost =< ControlledCharacterMovementPoints), - -   UpdatedQueryState = -      QueryState#query_state -      { -         character_instance = -            character_instance:set_location -            ( -               NewLocation, -               ControlledCharacterInstance -            ) -      }, -   { -      [{move, ControlledCharacterIX, NewLocation}], -      UpdatedQueryState -   }. - --spec handle_character_instance_switching_weapons -   ( -      query_state(), -      input() -   ) -   -> {list(any()), query_state()}. -handle_character_instance_switching_weapons (QueryState, Input) -> -   ControlledCharacterInstance = QueryState#query_state.character_instance, -   ControlledCharacter = -      character_instance:get_character(ControlledCharacterInstance), -   ControlledCharacterAttributes = -      character:get_attributes(ControlledCharacter), -   {PrimaryWeapon, SecondaryWeapon} = -      character:get_weapon_ids(ControlledCharacter), -   ControlledCharacterIX = Input#input.character_instance_ix, - -   UpdatedWeapons = {SecondaryWeapon, PrimaryWeapon}, -   UpdatedControlledCharacterStatistics = -      statistics:new -      ( -         ControlledCharacterAttributes, -         UpdatedWeapons -      ), -   UpdatedControlledCharacter = -      character:set_statistics -      ( -         UpdatedControlledCharacterStatistics, -         character:set_weapon_ids -         ( -            UpdatedWeapons, -            ControlledCharacter -         ) -      ), -   UpdatedControlledCharacterInstance = -      character_instance:set_character -      ( -         UpdatedControlledCharacter, -         ControlledCharacterInstance -      ), -   UpdatedQueryState = -      QueryState#query_state -      { -         character_instance = UpdatedControlledCharacterInstance -      }, - -   { -      [{switch_weapons, ControlledCharacterIX}], -      UpdatedQueryState -   }. - --spec set_new_healths_in_query_state -   ( -      non_neg_integer(), -      non_neg_integer(), -      query_state(), -      input() -   ) -   -> query_state(). -set_new_healths_in_query_state -( -   RemainingAttackerHealth, -   RemainingDefenderHealth, -   QueryState, -   Input -) -> -   BattlemapInstance = QueryState#query_state.battlemap_instance, -   ControlledCharacterInstance = QueryState#query_state.character_instance, -   CharacterInstances = -      battlemap_instance:get_character_instances(BattlemapInstance), -   TargettedCharacterInstanceIX = Input#input.target_ix, -   TargettedCharacterInstance = -      array:get -      ( -         TargettedCharacterInstanceIX, -         CharacterInstances -      ), - -   QueryState#query_state -   { -      battlemap_instance = -         battlemap_instance:set_character_instances -         ( -            array:set -            ( -               TargettedCharacterInstanceIX, -               character_instance:set_current_health -               ( -                  RemainingDefenderHealth, -                  TargettedCharacterInstance -               ), -               CharacterInstances -            ), -            BattlemapInstance -         ), -      character_instance = -         character_instance:set_current_health -         ( -            RemainingAttackerHealth, -            ControlledCharacterInstance -         ) -   }. - --spec handle_character_instance_attacking -   ( -      query_state(), -      input() -   ) -   -> {list(attack:attack_desc()), query_state()}. -handle_character_instance_attacking (QueryState, Input) -> -   BattlemapInstance = QueryState#query_state.battlemap_instance, -   ControlledCharacterInstance = QueryState#query_state.character_instance, -   ControlledCharacter = -      character_instance:get_character(ControlledCharacterInstance), -   ControlledCharacterStatistics = -      character:get_statistics(ControlledCharacter), -   TargettedCharacterInstance = -      array:get -      ( -         Input#input.target_ix, -         battlemap_instance:get_character_instances(BattlemapInstance) -      ), -   TargettedCharacter = -      character_instance:get_character(TargettedCharacterInstance), -   TargettedCharacterStatistics = character:get_statistics(TargettedCharacter), -   RequiredRange = -      movement:steps_between -      ( -         character_instance:get_location(ControlledCharacterInstance), -         character_instance:get_location(TargettedCharacterInstance) -      ), -   {AttackingWeaponID, _} = character:get_weapon_ids(ControlledCharacter), -   AttackingWeapon = weapon:from_id(AttackingWeaponID), -   {DefendingWeaponID, _} = character:get_weapon_ids(TargettedCharacter), -   DefendingWeapon = weapon:from_id(DefendingWeaponID), -   BaseAttackerHealth = -      character_instance:get_current_health(ControlledCharacterInstance), -   BaseDefenderHealth = -      character_instance:get_current_health(TargettedCharacterInstance), - -   AttackSequence = -      attack:get_sequence(RequiredRange, AttackingWeapon, DefendingWeapon), - -   AttackEffects = -      lists:map -      ( -         fun (AttackOrder) -> -            attack:get_description_of -            ( -               AttackOrder, -               ControlledCharacterStatistics, -               TargettedCharacterStatistics -            ) -         end, -         AttackSequence -      ), - -   {AttackSummary, RemainingAttackerHealth, RemainingDefenderHealth} = -      lists:foldl +   CharacterInstance = RData#relevant_data.played_character_instance, +   Battle = RData#relevant_data.battle, +   Character = character_instance:get_character(CharacterInstance), +   CurrentPlayerIX = +      player_turn:get_player_ix        ( -         fun -         ( -            AttackEffect, -            { -               CurrentAttackEffects, -               CurrentAttackerHealth, -               CurrentDefenderHealth -            } -         ) -> -            {AttackTrueEffect, NewAttackerHealth, NewDefenderHealth} = -               attack:apply_to_healths -               ( -                  AttackEffect, -                  CurrentAttackerHealth, -                  CurrentDefenderHealth -               ), -            { -               [AttackTrueEffect|CurrentAttackEffects], -               NewAttackerHealth, -               NewDefenderHealth -            } -         end, -         {[], BaseAttackerHealth, BaseDefenderHealth}, -         AttackEffects +         battle:get_current_player_turn(Battle)        ), +   CurrentPlayer = battle:get_player_id(CurrentPlayerIX, Battle), +   CharacterOwner = character:get_owner_id(Character), -   { -      AttackSummary, -      set_new_healths_in_query_state -      ( -         RemainingAttackerHealth, -         RemainingDefenderHealth, -         QueryState, -         Input -      ) -   }. +   PlayerID = CurrentPlayer, +   PlayerID = CharacterOwner, --spec get_type_of_turn (input()) -> list(atom()). -get_type_of_turn (Input) -> -   case {Input#input.path, Input#input.target_ix} of -      {[], -1} -> [nothing, nothing]; -      {[], _} -> [nothing, attack]; -      {[<<"S">>], -1} -> [switch, nothing]; -      {[<<"S">>], _} -> [switch, attack]; -      {_, -1} -> [move, nothing]; -      {_, _} -> [move, attack] -   end. +   true = character_instance:get_is_active(CharacterInstance). --spec finalize_character_instance +-spec finalize_and_fuse_relevant_data     ( -      query_state(), +      relevant_data(),        input()     ) -   -> query_state(). -finalize_character_instance (QueryState, Input) -> -   BattlemapInstance = QueryState#query_state.battlemap_instance, +   -> battle:struct(). +finalize_and_fuse_relevant_data (RData, Input) -> +   Battle = RData#relevant_data.battle, +   CharacterInstance = RData#relevant_data.played_character_instance,     FinalizedCharacterInstance = -      character_instance:set_is_active -      ( -         false, -         QueryState#query_state.character_instance -      ), +      character_instance:set_is_active(false, CharacterInstance), -   QueryState#query_state -   { -      battlemap_instance = -         battlemap_instance:set_character_instances -         ( -            array:set -            ( -               Input#input.character_instance_ix, -               FinalizedCharacterInstance, -               battlemap_instance:get_character_instances(BattlemapInstance) -            ), -            BattlemapInstance -         ), -      character_instance = FinalizedCharacterInstance -   }. +   battle:set_character_instance +   ( +      Input#input.character_instance_ix, +      FinalizedCharacterInstance, +      Battle +   ).  -spec activate_relevant_character_instances     ( @@ -472,15 +169,14 @@ activate_relevant_character_instances (IXs, CharacterInstances, Owner, IX) ->     (        query_state()     ) -   -> {list(non_neg_integer()), battlemap_instance:struct()}. +   -> {list(non_neg_integer()), battle:struct()}.  start_next_players_turn (QueryState) -> -   BattlemapInstance = QueryState#query_state.battlemap_instance, -   PlayerIDs = battlemap_instance:get_player_ids(BattlemapInstance), -   PlayerTurn = battlemap_instance:get_current_player_turn(BattlemapInstance), +   Battle = QueryState#query_state.battle, +   PlayerIDs = battle:get_player_ids(Battle), +   PlayerTurn = battle:get_current_player_turn(Battle),     CurrentPlayerIX = player_turn:get_player_ix(PlayerTurn),     CurrentTurnNumber = player_turn:get_number(PlayerTurn), -   CharacterInstances = -      battlemap_instance:get_character_instances(BattlemapInstance), +   CharacterInstances = battle:get_character_instances(Battle),     NextPlayerIX = ((CurrentPlayerIX + 1) rem (array:size(PlayerIDs))),     NextPlayerTurn = @@ -501,23 +197,23 @@ start_next_players_turn (QueryState) ->           array:get(NextPlayerIX, PlayerIDs),           (array:size(CharacterInstances) - 1)        ), -   UpdatedBattlemapInstance = -      battlemap_instance:set_character_instances +   UpdatedBattle = +      battle:set_character_instances        (           UpdatedCharacterInstances, -         battlemap_instance:set_current_player_turn +         battle:set_current_player_turn           (              NextPlayerTurn, -            BattlemapInstance +            Battle           )        ), -   {ActivatedCharacterInstanceIXs, UpdatedBattlemapInstance}. +   {ActivatedCharacterInstanceIXs, UpdatedBattle}.  -spec finalize_character_turn (query_state()) -> query_result().  finalize_character_turn (QueryState) -> -   BattlemapInstance = QueryState#query_state.battlemap_instance, +   Battle = QueryState#query_state.battle,     CharacterInstances = -      battlemap_instance:get_character_instances(BattlemapInstance), +      battle:get_character_instances(Battle),     AnActiveCharacterInstanceRemains =        array:foldl @@ -536,108 +232,62 @@ finalize_character_turn (QueryState) ->           {              is_new_turn = false,              updated_character_instance_ixs = [], -            updated_battlemap_instance = BattlemapInstance +            updated_battle = Battle           };        false ->           io:format("~nThere are no more active characters.~n"), -         {UpdatedCharacterInstanceIXs, UpdatedBattlemapInstance} = +         {UpdatedCharacterInstanceIXs, UpdatedBattle} =              start_next_players_turn(QueryState),           #query_result           {              is_new_turn = true,              updated_character_instance_ixs = UpdatedCharacterInstanceIXs, -            updated_battlemap_instance = UpdatedBattlemapInstance +            updated_battle = UpdatedBattle           }     end. --spec play -   ( -      list(any()), -      query_state(), -      list(atom()), -      input() -   ) -   -> {list(any()), query_state()}. -play (DiffUpdate, QueryState, [], _Input) -> -   {DiffUpdate, QueryState}; -play (DiffUpdate, QueryState, [nothing|Next], Input) -> -   play(DiffUpdate, QueryState, Next, Input); -play (DiffUpdate, QueryState, [move|Next], Input) -> -   {AddedDiffContent, NewQueryState} = -      handle_character_instance_moving(QueryState, Input), -   play -   ( -      (AddedDiffContent ++ DiffUpdate), -      NewQueryState, -      Next, -      Input -   ); -play (DiffUpdate, QueryState, [switch|Next], Input) -> -   {AddedDiffContent, NewQueryState} = -      handle_character_instance_switching_weapons(QueryState, Input), -   play -   ( -      (AddedDiffContent ++ DiffUpdate), -      NewQueryState, -      Next, -      Input -   ); -play (DiffUpdate, QueryState, [attack|Next], Input) -> -   {AddedDiffContent, NewQueryState} = -      handle_character_instance_attacking(QueryState, Input), -   play -   ( -      (AddedDiffContent ++ DiffUpdate), -      NewQueryState, -      Next, -      Input -   ). - --spec send_to_database (query_result(), any(), input()) -> 'ok'. -send_to_database (QueryResult, _TurnType, Input) -> +%-spec send_to_database (list(database_diff:struct()), input()) -> 'ok'. +-spec send_to_database (battle:struct(), input()) -> 'ok'. +send_to_database (FinalizedBattle, Input) ->     PlayerID = Input#input.player_id, -   BattlemapInstanceID = Input#input.battlemap_instance_id, -   BattlemapInstance = QueryResult#query_result.updated_battlemap_instance, +   BattleID = Input#input.battle_id,     %% TODO: differential commit     database_shim:commit     ( -      battlemap_instance_db, +      battle_db,        PlayerID, -      BattlemapInstanceID, -      BattlemapInstance +      BattleID, +      FinalizedBattle     ).  -spec update_cache (query_result(), input()) -> 'ok'.  update_cache (QueryResult, Input) ->     PlayerID = Input#input.player_id, -   BattlemapInstanceID = Input#input.battlemap_instance_id, -   BattlemapInstance = QueryResult#query_result.updated_battlemap_instance, +   BattleID = Input#input.battle_id, +   Battle = QueryResult#query_result.updated_battle,     timed_cache:update     ( -      battlemap_instance_db, +      battle_db,        PlayerID, -      BattlemapInstanceID, -      BattlemapInstance +      BattleID, +      Battle     ).  -spec generate_reply     ( -      query_result(), -      list(any()), -      any(), -      input() +      list(turn_result:struct())     )     -> binary(). -generate_reply (_QueryResult, DiffUpdate, _TurnType, _Input) -> +generate_reply (ClientUpdate) ->     %% TODO     jiffy:encode     (        [           [              <<"raw">>, -            list_to_binary(io_lib:format("~p", [DiffUpdate])) +            list_to_binary(io_lib:format("~p", [ClientUpdate]))           ]        ]     ). @@ -645,22 +295,42 @@ generate_reply (_QueryResult, DiffUpdate, _TurnType, _Input) ->  -spec handle (binary()) -> binary().  handle (Req) ->     Input = parse_input(Req), -   security:assert_identity(Input#input.player_id, Input#input.session_token), -   security:lock_queries(Input#input.player_id), -   QueryState = fetch_data(Input), -   assert_character_instance_can_be_played(QueryState, Input), -   TurnType = get_type_of_turn(Input), -   {DiffUpdate, UpdatedQueryState} = play([], QueryState, TurnType, Input), -   QueryResult = -      finalize_character_turn +   PlayerID = Input#input.player_id, +   PlayerSessionToken = Input#input.session_token, +   Actions = Input#input.actions, + +   security:assert_identity(PlayerID, PlayerSessionToken), +   security:lock_queries(PlayerID), + +   RData = fetch_relevant_data(Input), + +   assert_character_instance_can_be_played(RData, Input), + +   {ActionsDiffUpdate, ClientUpdate, UpdatedRData} = +      lists:foldl        ( -         finalize_character_instance(UpdatedQueryState, Input) +         fun (Action, Prev) -> +            battle_action:handle(Action, Prev) +         end, +         {[], [], RData}, +         Actions        ), -   send_to_database(QueryResult, TurnType, Input), -   update_cache(QueryResult, Input), + +   UpdatedBattle = finalize_and_fuse_relevant_data(UpdatedRData, Input), + +   {TurnDiffUpdate, FinalizedBattle} = end_of_turn:apply_to(UpdatedBattle), + +   DiffUpdate = (TurnDiffUpdate ++ ActionsDiffUpdate), + +   %send_to_database(DiffUpdate, Input), +   send_to_database(FinalizedBattle, Input), +   update_cache(FinalizedBattle, Input), +     io:format("~nCharacter turn result:~n~p~n", [DiffUpdate]), -   security:unlock_queries(Input#input.player_id), -   generate_reply(QueryResult, DiffUpdate, TurnType, Input). + +   security:unlock_queries(PlayerID), + +   generate_reply(ClientUpdate).  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 


