castAspect :: Dice.AbsDepth -> Dice.AbsDepth -> AspectRecord -> IK.Aspect
           -> Rnd AspectRecord
castAspect !ldepth !totalDepth !ar !asp =
  case asp of
    IK.Timeout d -> do
      n <- castDice ldepth totalDepth d
      return $! assert (aTimeout ar == 0) $ ar {aTimeout = n}
    IK.AddSkill sk d -> do
      n <- castDice ldepth totalDepth d
      return $! if n /= 0
                then ar {aSkills = Ability.addSk sk n (aSkills ar)}
                else ar
    IK.SetFlag feat ->
      return $! ar {aFlags = Ability.Flags
                             $ ES.insert feat (Ability.flags $ aFlags ar)}
    IK.ELabel t -> return $! ar {aELabel = t}
    IK.ToThrow tt -> return $! ar {aToThrow = tt}
    IK.PresentAs ha -> return $! ar {aPresentAs = Just ha}
    IK.EqpSlot slot -> return $! ar {aEqpSlot = Just slot}
    IK.Odds d aspects1 aspects2 -> do
      pick1 <- oddsDice ldepth totalDepth d
      foldlM' (castAspect ldepth totalDepth) ar $
        if pick1 then aspects1 else aspects2

-- If @False@, aspects of this kind are most probably fixed, not random
-- nor dependent on dungeon level where the item is created.
castAspect :: Dice.AbsDepth -> Dice.AbsDepth -> AspectRecord -> IK.Aspect
           -> Rnd AspectRecord
castAspect !ldepth !totalDepth !ar !asp =
  case asp of
    IK.Timeout d -> do
      n <- castDice ldepth totalDepth d
      return $! assert (aTimeout ar == 0) $ ar {aTimeout = n}
    IK.AddSkill sk d -> do
      n <- castDice ldepth totalDepth d
      return $! if n /= 0
                then ar {aSkills = Ability.addSk sk n (aSkills ar)}
                else ar
    IK.SetFlag feat ->
      return $! ar {aFlags = Ability.Flags
                             $ ES.insert feat (Ability.flags $ aFlags ar)}
    IK.ELabel t -> return $! ar {aELabel = t}
    IK.ToThrow tt -> return $! ar {aToThrow = tt}
    IK.PresentAs ha -> return $! ar {aPresentAs = Just ha}
    IK.EqpSlot slot -> return $! ar {aEqpSlot = Just slot}
    IK.Odds d aspects1 aspects2 -> do
      pick1 <- oddsDice ldepth totalDepth d
      foldlM' (castAspect ldepth totalDepth) ar $
        if pick1 then aspects1 else aspects2

-- If @False@, aspects of this kind are most probably fixed, not random
-- nor dependent on dungeon level where the item is created.
castAspect !ldepth !totalDepth !ar !asp =
  case asp of
    IK.Timeout d -> do
      n <- castDice ldepth totalDepth d
      return $! assert (aTimeout ar == 0) $ ar {aTimeout = n}
    IK.AddSkill sk d -> do
      n <- castDice ldepth totalDepth d
      return $! if n /= 0
                then ar {aSkills = Ability.addSk sk n (aSkills ar)}
                else ar
    IK.SetFlag feat ->
      return $! ar {aFlags = Ability.Flags
                             $ ES.insert feat (Ability.flags $ aFlags ar)}
    IK.ELabel t -> return $! ar {aELabel = t}
    IK.ToThrow tt -> return $! ar {aToThrow = tt}
    IK.PresentAs ha -> return $! ar {aPresentAs = Just ha}
    IK.EqpSlot slot -> return $! ar {aEqpSlot = Just slot}
    IK.Odds d aspects1 aspects2 -> do
      pick1 <- oddsDice ldepth totalDepth d
      foldlM' (castAspect ldepth totalDepth) ar $
        if pick1 then aspects1 else aspects2

-- If @False@, aspects of this kind are most probably fixed, not random
-- nor dependent on dungeon level where the item is created.