anchor.diff:              let character = updater character
               { model with BattleCharacters = Map.add characterIndex character model.BattleCharacters }
   
  -        let tickAttack sourceIndex (targetIndexOpt : CharacterIndex option) time timeLocal battleRunning model =
  +        let tickAttack sourceIndex (targetIndexOpt : CharacterIndex option) time timeLocal model =
   
               // if target available, proceed with attack
               let source = getCharacter sourceIndex model
  
positive.code:                 let model =
                      if outcome
                      then updateAllies (fun character -> { character with CharacterAnimationState = (CharacterAnimationState.setCycle (Some time) CelebrateCycle) character.CharacterAnimationState }) model
                      else updateAllies (fun character -> { character with CharacterAnimationState = (CharacterAnimationState.setCycle (Some time) CelebrateCycle) character.CharacterAnimationState }) model
                  just model
              | AdvanceCharacters ->
                  let model = updateCharacters (fun character -> { character with ActionTime = character.ActionTime + Constants.Battle.ActionTimeInc }) model
  
negative.code:                 match timeLocal with
                  | 0L when target.CharacterState.IsHealthy ->
                      if target.CharacterState.IsHealthy then
                          withMsg model (AttackCharacter (sourceIndex, targetIndex))
                      else // target wounded, cancel attack
                          let model = { model with CurrentCommandOpt = None }
                          withMsgs model [ResetCharacter sourceIndex; PoiseCharacter sourceIndex]
                  | _ when timeLocal = 1L * int64 source.CharacterAnimationState.Stutter ->
                      withMsg model (DamageCharacter targetIndex)
                  | _ ->
                      if CharacterAnimationState.finished time source.CharacterAnimationState then
                          if target.CharacterState.IsHealthy then
                              let model = { model with CurrentCommandOpt = None }
                              withMsgs model [PoiseCharacter sourceIndex; PoiseCharacter targetIndex]
                          else
                              let woundCommand = CurrentCommand.make time (ActionCommand.make Wound targetIndex None)
                              let model = { model with CurrentCommandOpt = Some woundCommand }
                              withMsg model (PoiseCharacter sourceIndex)
                      else just model
  
              // else target destroyed, cancel attack
              | None ->
                  let model = { model with CurrentCommandOpt = None }
                  withMsgs model [ResetCharacter sourceIndex; PoiseCharacter sourceIndex]
  
          let tickWound characterIndex time timeLocal model =
              match timeLocal with
              | 0L ->
                  withMsg model (DamageCharacter characterIndex)
              | _ ->
                  let character = getCharacter characterIndex model
                  if character.CharacterState.IsAlly then
                      match character.CharacterAnimationState.CharacterAnimationCycle with
                      | DamageCycle ->
                          if CharacterAnimationState.finished time character.CharacterAnimationState
                          then withMsg { model with CurrentCommandOpt = None } (WoundCharacter characterIndex)
                          else just model
                      | _ -> failwithumf ()
                  else
                      match character.CharacterAnimationState.CharacterAnimationCycle with
                      | DamageCycle ->
                          if CharacterAnimationState.finished time character.CharacterAnimationState
                          then withMsg model (WoundCharacter characterIndex)
                          else just model
                      | WoundCycle ->
                          if CharacterAnimationState.finished time character.CharacterAnimationState
                          then withMsg { model with CurrentCommandOpt = None } (DestroyCharacter characterIndex)
                          else just model
                      | _ -> failwithumf ()
  
          let tickReady time timeStart model =
              let timeLocal = time - timeStart
              match timeLocal with
              | 0L -> withMsg model ReadyCharacters
              | 30L -> withMsg { model with BattleState = BattleRunning } PoiseCharacters
              | _ -> just model
  
          let rec tickCurrentCommand time currentCommand model =
              let timeLocal = time - currentCommand.TimeStart
              match currentCommand.ActionCommand.Action with
              | Attack ->
                  let source = currentCommand.ActionCommand.Source
                  let targetOpt = currentCommand.ActionCommand.TargetOpt
                  tickAttack source targetOpt time timeLocal model
              | Defend -> just model
              | Consume _ -> just model
              | Special _ -> just model
              | Wound ->
                  let source = currentCommand.ActionCommand.Source
                  let (model, signal) = tickWound source time timeLocal model
                  match model.CurrentCommandOpt with
                  | Some _ ->
                      // keep ticking wound
                      withSig model signal
                  | None ->
                      let (model, signal2) =
  