anchor.diff:      element(2, lists:last(lists:sort(AL))).
   
   ucb1_target(0, _, _, _) -> -100; 
  -ucb1_target({0, 0, 0}, _, _, _) -> 100; 
  -ucb1_target({N, Q, _Q2}, NOS, _Prior, Explore) -> 
  +ucb1_target({0, 0}, _, _, _) -> 100; 
  +ucb1_target({N, Q}, NOS, _Prior, Explore) -> 
       Q/N + ?UCB1_BONUS(NOS, N, _Prior, Explore).
   
   % ucb1_target({N,Q}, NOS, Prior, Explore) -> 
  
positive.code: empty_action_qualities(Input, Olen) ->
      {TruncInput,_} = lists:split(Olen,Input),
      [ if 
          Inp==32 ->   {0, 0, 0}; % {N, sum(Q), sum(Q^2)} for legal action
          true ->      0          % illegal move (occupied)
        end
      || Inp <- TruncInput 
  
negative.code: qlearn_add(OldOut, Qmax, OMove, Olen, LearningRate, Discount) ->
      [qlearn_add_one(Old, Pos, Qmax, OMove, LearningRate, Discount) || {Old, Pos} <- lists:zip(OldOut, lists:seq(1, Olen))].
  
  %% Q-learn with immediate reward (Q=0 for TicTacChallenge) from next move's Qmax backpropagation
  %% Add one sample to the Q-learning accumulator (single output vector position)
  %% accumulated Q:                   {AccN,AccQ}={Number of accumulated samples so far, sum of quality for this action}
  %% immediate reward:                {N,Q}       (normally {1,0} for non-final moves, {0,0} for unsampled actions)
  %% invalid actions:                 0 + _ -> 0
  qlearn_add_one(0, _, _, _, _, _) -> 0;                                      % invalid action 
  qlearn_add_one(Qact, Pos, _, OMove, _, _) when Pos/=OMove -> Qact;          % unplayed action
  qlearn_add_one(_, _, {NextN, NextQ}, _, LR, Disc) when LR=:=1,is_integer(Disc) -> 
      {NextN+Disc, -NextQ};                             % inverse integer LR=:=1 -> 100% backpropagation
  qlearn_add_one({AccN, AccQ}, _, {NextN, NextQ}, _, LR, Disc) when is_integer(LR),is_integer(Disc) -> 
      {(LR-1)*AccN+NextN+Disc, (LR-1)*AccQ-NextQ};    % inverse integer LR=:=2 -> 50% backpropagation
  qlearn_add_one({0, 0}, _, {NextN, NextQ}, _, LR, Disc) -> % first sample for this action
      {NextN, -LR*Disc*NextQ};
  qlearn_add_one({AccN, AccQ}, _, {NextN, NextQ}, _, LR, Disc) ->
      AccNN = AccN+1,
      AccQN = AccNN*AccQ/AccN,
      NewAccQ = (1-LR)*AccQN - LR*Disc*NextQ/NextN*AccNN,     % LR=:=0.5 -> 50% backpropagation
      {AccNN, NewAccQ}.
  
  qlearn_max(Output) -> qlearn_max(Output,0,-1.0e200).
  
  qlearn_max([], Max, _) -> Max;  
  qlearn_max([0|Output], Max, MaxQ) -> qlearn_max(Output, Max, MaxQ);         % invalid action
  qlearn_max([{0,_}|Output], Max, MaxQ) -> qlearn_max(Output, Max, MaxQ);     % unsampled action
  qlearn_max([{0,_,_}|Output], Max, MaxQ) -> qlearn_max(Output, Max, MaxQ);   % unsampled action
  qlearn_max([{N,Q}|Output], _Max, MaxQ) when Q/N>MaxQ -> qlearn_max(Output, {N,Q}, Q/N);                 % bigger
  qlearn_max([{N,Q}|Output], {NMax,_}, MaxQ) when Q/N==MaxQ, N>NMax -> qlearn_max(Output, {N,Q}, Q/N);    % more statistics
  qlearn_max([_|Output], Max, MaxQ) -> qlearn_max(Output, Max, MaxQ).         % smaller or equal
  
  -spec play_bot_resp(egGameId(), egAlias(), egBotMove() ) -> ok.
  play_bot_resp(GameId, Player, BotMove) -> 
  