aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2019-07-15 22:07:43 +0200
committerNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2019-07-15 22:07:43 +0200
commit1513c7918875ede6e0c0ae33d381fd4d18eaf4be (patch)
treec7ba678c71fc085b333053383e993d826089b60b
parent3f928c81070ab3c9efa5b0dfd2ae97ca7f7efcf6 (diff)
downloadtacticians-server-1513c7918875ede6e0c0ae33d381fd4d18eaf4be.zip
tacticians-server-1513c7918875ede6e0c0ae33d381fd4d18eaf4be.tar.bz2
Starting work on an automatic balancer tool.
-rw-r--r--include/base_attributes.hrl8
-rw-r--r--src/balancer/struct/blc_armor.erl331
2 files changed, 339 insertions, 0 deletions
diff --git a/include/base_attributes.hrl b/include/base_attributes.hrl
new file mode 100644
index 0000000..2ceb6f7
--- /dev/null
+++ b/include/base_attributes.hrl
@@ -0,0 +1,8 @@
+%%%%
+% Base value for character attributes.
+
+-define(BASE_DAMAGE_MODIFIER_ATTRIBUTE, 100).
+-define(BASE_MOVEMENT_POINTS_ATTRIBUTE, 32).
+-define(BASE_HEALTH_ATTRIBUTE, 100).
+-define(BASE_DODGE_ATTRIBUTE, 50).
+-define(BASE_DEFENSE_SCORE, 50).
diff --git a/src/balancer/struct/blc_armor.erl b/src/balancer/struct/blc_armor.erl
new file mode 100644
index 0000000..d15a09a
--- /dev/null
+++ b/src/balancer/struct/blc_armor.erl
@@ -0,0 +1,331 @@
+-module(blc_armor).
+
+-include('base_attributes.hrl').
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-type defense_entry() :: {atom(), non_neg_integer()}.
+
+-record
+(
+ proto_armor,
+ {
+ health :: non_neg_integer(),
+ damage_modifier :: non_neg_integer(),
+ dodge :: non_neg_integer(),
+ defense :: list(defense_entry()),
+ defense_score :: non_neg_integer()
+ }
+).
+
+-record
+(
+ factors,
+ {
+ health :: float(),
+ damage_modifier :: float(),
+ dodge :: float(),
+ defense :: float()
+ }
+).
+
+-opaque proto_armor() :: #proto_armor{}.
+-opaque factors() :: #factors{}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-export_type([proto_armor/0, armor/0, factors/0]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%% Generic %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec get_relative_attribute
+ (
+ non_neg_integer(),
+ non_neg_integer(),
+ non_neg_integer()
+ )
+ -> non_neg_integer().
+get_relative_attribute (Value, BaseValue, BaseTarget) ->
+ (
+ BaseTarget
+ -
+ math:floor((Value - BaseValue) * (BaseTarget/BaseValue))
+ ).
+
+%%%% Defense %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec calc_defense_score (list(defense_entry())) -> non_neg_integer().
+calc_defense_score (Defense) ->
+ DescSortedDefense =
+ lists:sort
+ (
+ fun ({_NameA, ValueA}, {_NameB, ValueB}) ->
+ (ValueA >= ValueB)
+ end,
+ Defense
+ ),
+
+ {_LastIndex, Result} =
+ lists:foldl
+ (
+ fun (E, {Index, Current}) ->
+ {(Index + 1), (Current + (Index * E))}
+ end,
+ {1, 0},
+ DescSortedDefense
+ ),
+
+ Result.
+
+-spec apply_defense_score_modifier
+ (
+ non_neg_integer(),
+ integer(),
+ list(defense_entry())
+ )
+ -> list(defense_entry()).
+apply_defense_score_modifier (AbsModifier, Mod, S0DescSortedDefense) ->
+ {S1DescSortedDefense, EndModifier} =
+ lists:mapfoldl
+ (
+ fun ({Name, S0Value}, {Index, RemainingModifier}) ->
+ case ((RemainingModifier > 0) and (S0Value > 0)) of
+ true ->
+ S1Value = (S0Value + Mod),
+ {
+ {Name, S1Value},
+ {
+ (Index + 1),
+ RemainingModifier - (Index * S1Value)
+ }
+ };
+
+ false -> {{Name, S0Value}, {(Index + 1), RemainingModifier}}
+ end
+ end,
+ {1, AbsModifier},
+ S0DescSortedDefense
+ ),
+
+ case (EndModifier > 0) of
+ false -> S1DescSortedDefense;
+ true ->
+ apply_defense_score_modifier
+ (
+ EndModifier,
+ Mod,
+ S1DescSortedDefense
+ )
+ end.
+
+%%%% Movement Points %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec get_maximum_movement_points_with_factors
+ (
+ non_neg_integer(),
+ non_neg_integer(),
+ float()
+ )
+ -> non_neg_integer().
+get_maximum_movement_points_with_factors (Value, BaseValue, Factor) ->
+ math:floor((Value * ?BASE_MOVEMENT_POINTS_ATTRIBUTE) / (BaseValue * Factor)).
+
+-spec get_maximum_factor_with_movement_points
+ (
+ non_neg_integer(),
+ non_neg_integer(),
+ non_neg_integer()
+ )
+ -> float().
+get_maximum_factor_with_movement_points (Value, BaseValue, MovementPoints) ->
+ (
+ Value
+ /
+ (
+ (
+ (MovementPoints / ?BASE_MOVEMENT_POINTS_ATTRIBUTE)
+ + 1
+ )
+ * BaseValue
+ )
+ ).
+
+-spec proto_armor_auto_dodge
+ (
+ list(defense_entry()),
+ non_neg_integer(),
+ non_neg_integer()
+ )
+ -> proto_armor().
+proto_armor_auto_dodge (Defense, Health, DamageModifier) ->
+ DefenseScore = get_defense_score(Defense),
+
+ Dodge =
+ relative_attribute
+ (
+ DefenseScore,
+ ?BASE_DEFENSE_SCORE,
+ ?BASE_DODGE_ATTRIBUTE
+ ),
+
+ #proto_armor
+ {
+ health = Health,
+ damage_modifier = DamageModifier,
+ dodge = Dodge,
+ defense = Defense,
+ defense_score = DefenseScore
+ }.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec get_maximum_damage_modifier () -> non_neg_integer().
+get_maximum_damage_modifier () -> (?BASE_DAMAGE_MODIFIER_ATTRIBUTE * 2).
+
+-spec get_maximum_movement_points () -> non_neg_integer().
+get_maximum_movement_points () -> (?BASE_MOVEMENT_POINTS_ATTRIBUTE * 2).
+
+-spec get_maximum_health () -> non_neg_integer().
+get_maximum_health () -> (?BASE_HEALTH_ATTRIBUTE * 2).
+
+-spec get_maximum_dodge () -> non_neg_integer().
+get_maximum_dodge () -> (?BASE_DODGE_ATTRIBUTE * 2).
+
+-spec get_maximum_defense_score () -> non_neg_integer().
+get_maximum_defense_score () -> (?BASE_DEFENSE_SCORE * 2).
+
+
+-spec get_maximum_movement_points
+ (
+ factors(),
+ proto_armor()
+ )
+ -> non_neg_integer().
+get_maximum_movement_points (Factor, ProtoArmor) ->
+ lists:min
+ (
+ [
+ get_maximum_movement_points_with_factors
+ (
+ ProtoArmor#proto_armor.health,
+ ?BASE_HEALTH_ATTRIBUTE,
+ Factor#factors.health
+ ),
+ get_maximum_movement_points_with_factors
+ (
+ ProtoArmor#proto_armor.damage_modifier,
+ ?BASE_DAMAGE_MODIFIER_ATTRIBUTE,
+ Factor#factors.damage_modifier
+ ),
+ get_maximum_movement_points_with_factors
+ (
+ ProtoArmor#proto_armor.defense_score,
+ ?BASE_DEFENSE_SCORE,
+ Factor#factors.defense
+ ),
+ get_maximum_movement_points_with_factors
+ (
+ ProtoArmor#proto_armor.dodge,
+ ?BASE_DODGE_ATTRIBUTE,
+ Factor#factors.dodge
+ )
+ ]
+ ).
+
+-spec get_maximum_factorss (non_neg_integer(), proto_armor()) -> factors().
+get_maximum_factorss (MovementPoints, ProtoArmor) ->
+ #proto_armor
+ {
+ health =
+ get_maximum_factor_with_movement_points
+ (
+ ProtoArmor#proto_armor.health,
+ ?BASE_HEALTH_ATTRIBUTE,
+ MovementPoints
+ ),
+ damage_modifier =
+ get_maximum_factor_with_movement_points
+ (
+ ProtoArmor#proto_armor.damage_modifier,
+ ?BASE_DAMAGE_MODIFIER_ATTRIBUTE,
+ MovementPoints
+ ),
+ dodge =
+ get_maximum_factor_with_movement_points
+ (
+ ProtoArmor#proto_armor.dodge,
+ ?BASE_DODGE_ATTRIBUTE,
+ MovementPoints
+ ),
+ defense =
+ get_maximum_factor_with_movement_points
+ (
+ ProtoArmor#proto_armor.defense_score,
+ ?BASE_DEFENSE_SCORE,
+ MovementPoints
+ )
+ }.
+
+-spec proto_armor_through_health
+ (
+ list(defense_entry()),
+ non_neg_integer()
+ )
+ -> proto_armor().
+proto_armor_through_health (Defense, Health) ->
+ DamageModifier =
+ relative_attribute
+ (
+ Health,
+ ?BASE_HEALTH_ATTRIBUTE,
+ ?BASE_DAMAGE_MODIFIER_ATTRIBUTE
+ ),
+
+ proto_armor_auto_dodge(Defense, Health, DamageModifier).
+
+-spec proto_armor_through_damage_modifier
+ (
+ list(defense_entry()),
+ non_neg_integer()
+ )
+ -> proto_armor().
+proto_armor_through_damage_modifier (Defense, DamageModifier) ->
+ Health =
+ relative_attribute
+ (
+ DamageModifier,
+ ?BASE_DAMAGE_MODIFIER_ATTRIBUTE,
+ ?BASE_HEALTH_ATTRIBUTE
+ ),
+
+ proto_armor_auto_dodge(Defense, Health, DamageModifier).
+
+-spec finalize_to_omnimods
+ (
+ non_neg_integer(),
+ factors(),
+ proto_armor()
+ )
+ -> shr_omnimods:type().
+finalize_to_omnimods (MovementPoints, Factors, ProtoArmor) ->
+ shr_omnimods:new
+ (
+ [
+ {movement_points, MovementPoints},
+ {
+ },
+ {
+ },
+ {
+ },
+ {
+ }
+ ],
+ [],
+ [
+ ]
+ ).