Imagine simple game:
type Combatant = {
hp : int
attack : int
}
type CombatantGroup = Combatant list
type CombatantGroups = CombatantGroup list
type Battle = {
combatantGroups : CombatantGroups
}
there is some battle, in which some amount groups participate. In each group there is several combatants. Now I want to implement a function for one combatant to attack another. Due to immutability, I have to replace whole attacked target, and whole group and whole battle. If the battle was just between two participants, I could write code like this:
if target = battle.combatant1 then
{ battle with combatant1 = { battle.combatant1 with hp = battle.combatant1.hp - attacker.attack }}
else
{ battle with combatant2 = { battle.combatant2 with hp = battle.combatant2.hp - attacker.attack }}
which is also terrible code, I would appreciate any advice on it. But with nested collections it gets even more complicated, and event doesn’t look functional to me anymore:
let containsTarget = List.contains target
let transformCombatant combatant = if combatant = target then { combatant with hp = combatant.hp - attacker.attack } else combatant
let transformGroup = List.map transformCombatant
let checkGroup group =
if group |> containsTarget then
group |> transformGroup
else
group
let transformGroups = List.map checkGroup
{ battle with combatantGroups = transformGroups battle.combatantGroups }
Can you please give me advise on how can I use features of F# and functional programming, to make given code more pretty and concise?