anchor.diff:  
   code_change(_OldVsn, State, _Extra) -> {ok, State}.
   
  -explore(GameTypeId) ->
  -    gen_server:call(?BOT_GID(?MODULE, GameTypeId), {explore}).
  -
  -explore(GameTypeId, Fraction) when is_number(Fraction)->
  -    gen_server:call(?BOT_GID(?MODULE, GameTypeId), {explore, Fraction}).
  -
  -flatten(GameTypeId) ->
  -    gen_server:call(?BOT_GID(?MODULE, GameTypeId), {flatten}).
  -
  -flatten(GameTypeId, Fraction)  when is_number(Fraction) ->
  -    gen_server:call(?BOT_GID(?MODULE, GameTypeId), {flatten, Fraction}).
  -
  +call(GameTypeId, Request) ->
  +    gen_server:call(?BOT_GID(?MODULE, GameTypeId), Request).
  +
  +state(GameTypeId) -> call(GameTypeId, state).
  +
  +explore(GameTypeId) -> call(GameTypeId, {explore}).
  +
  +explore(GameTypeId, Fraction) when is_number(Fraction) -> call(GameTypeId, {explore, Fraction}).
  +
  +flatten(GameTypeId) -> call(GameTypeId, {flatten}).
  +
  +flatten(GameTypeId, Fraction)  when is_number(Fraction) -> call(GameTypeId, {flatten, Fraction}).
  +
  +lrate(GameTypeId) -> call(GameTypeId, {lrate}).
  +
  +lrate(GameTypeId, Fraction)  when is_number(Fraction) -> call(GameTypeId, {lrate, Fraction}).
  +
  +discount(GameTypeId) -> call(GameTypeId, {discount}).
  +
  +discount(GameTypeId, Fraction)  when is_number(Fraction) -> call(GameTypeId, {discount, Fraction}).
   
   handle_cast({play_bot_req, GameId, _, [Player|_]}, #state{status=Status} = State) when Status /= playing ->
       play_bot_resp(GameId, Player, ?BOT_NOT_PLAYING),
  
positive.code:     {Input, Sym} = egambo_tictac_sym:norm(Width, Height, Gravity, Periodic, ABoard), 
      % ?Info("play_bot_impl Input (normalized board) and symmetry used ~p ~p", [Input, Sym]),
      {NOS, AccActionQuality} = case imem_meta:read(Table, list_to_binary(Input)) of
          [] ->   {0, new_output(Input, Width, Height, Gravity)};
          [#egTicTacQlSample{nos=Nos, aaq=Aaq}] -> {Nos,Aaq}
      end,
      % ?Info("play_bot_impl ActionQuality ~p",[ActionQuality]),    
      NormIdx = pick(NOS, AccActionQuality, Explore, Flatten),      % 0-based index for predicted move
      NewIdx = egambo_tictac_sym:unmap_move(Width, Height, NormIdx, Sym),    
      % ?Info("play_bot_impl NormIdx, NewIdx (output picked) ~p ~p", [NormIdx, NewIdx]),
      {ok, Idx, NewBoard} = egambo_tictac:put(Gravity, Board, Width, NewIdx, hd(NAliases)),
      % ?Info("play_bot_impl Idx, NewBoard ~p ~p", [Idx, binary_to_list(NewBoard)]),
      {ok, Idx, NewBoard}.
  
  new_output(Input, Width, Height, false) ->
      F = fun(I) -> 
          Inp=lists:nth(I, Input), 
          if 
              Inp==32 ->   {0, 0};      % alternative legal move
              true ->      0            % illegal move (occupied)
          end 
      end, 
      lists:map(F, lists:seq(1, Width*Height));
  new_output(Input, Width, _Height, true) ->
      F = fun(I) -> 
          Inp=lists:nth(I, Input), 
          if 
              Inp==32 ->   {0, 0};      % alternative legal move
              true ->      0            % illegal move (occupied)
          end 
      end, 
      lists:map(F, lists:seq(1, Width)).
  
  pick(NOS, AccActionQuality, Explore, 0) ->
      AL = [{target(A, NOS, Explore), rand:uniform(), I} || {A,I} <- lists:zip(AccActionQuality, lists:seq(0, length(AccActionQuality)-1))],
      element(3, lists:last(lists:sort(AL)));
  pick(NOS, AccActionQuality, Explore, Flatten) ->
      AL = [{target(A, NOS, Explore) + Flatten* rand:uniform(), I} || {A,I} <- lists:zip(AccActionQuality, lists:seq(0, length(AccActionQuality)-1))],
      element(2, lists:last(lists:sort(AL))).
  
  target(0, _, _) -> -100; 
  target({0,0}, _, _) -> 100; 
  target({N,Q}, NOS, Explore) -> 
      DE = 1.0 + Explore*math:sqrt(NOS)/(1+N),
      (Q/N + DE) / DE.
  % target({N,Q}, NOS, Explore) -> Q/N + Explore*math:sqrt(NOS)/(1+N).
  
  
negative.code: 
  handle_info({notify_bot_req, _GameId, Ialiases, Space, finished, Naliases, Nscores, Moves}=_Request
              , #state{ width=Width, height=Height, gravity=Gravity, periodic=Periodic
              , table=Table, lrate=LearningRate, discount=Discount} = State) ->
      % ?Info("received ~p",[_Request]),
      train_game(egambo_tictac:samples(Space, Ialiases, Moves, Naliases, Nscores), Table, Width, Height, Gravity, Periodic, LearningRate, Discount, undefined),
      {noreply, State};
  handle_info(Reqest, State) when element(1, Reqest) == notify_bot_req ->
      % ignore game notifications 
  