anchor.diff:              G
       end.
   
  +
  +%%% Fitness function stuff
   gen_fit(_G) ->
       rand_between(0, 100).
  +
  +new_block(Ets) ->
  +    ets:insert(Ets, #block{size = random:uniform(?BLOCK_MAX_SIZE),
  +                           x = random:uniform(?AREA_WIDTH),
  +                           y = ?AREA_HEIGHT}).
  +
  +%% Whether we can sense if we're at pos At, and the block is at spec. pos.
  +senses(At, #block{size = S, x = X}) ->
  +    case At >= ?AREA_WIDTH of
  +        true -> At_m = At - ?AREA_WIDTH;
  +        false -> At_m = At
  +    end,
  +    Cmp =
  +        fun(A) when A >= ?AREA_WIDTH ->
  +                A - ?AREA_WIDTH == At_m;
  +           (A) -> A == At_m
  +        end,
  +    lists:any(Cmp, lists:seq(X, X + S - 1)). %% - 1 to avoid blocksize+1
  +
  +sense(Ets) ->
  +    [Block] = ets:lookup(Ets, block),
  +    [{tpos, P}] = ets:lookup(Ets, tpos),
  +    ets:insert(Ets, {sensed, [senses(At, Block) ||
  +                                 At <- lists:seq(P,P + ?TRACKER_SIZE - 1)]}).
  +
  +%% Speed generated by a motor neuron
  +speed(X) when 0.5 =< X, X < 0.9 -> 1;
  +speed(X) when 0.9 =< X, X < 0.95 -> 2;
  +speed(X) when 0.95 =< X -> 4;
  +speed(_) -> 0.
  +
  +actuate(Ets) ->
  +    [{c, _, #vstate{o = C}}] = ets:lookup(Ets, c),
  +    [{d, _, #vstate{o = D}}] = ets:lookup(Ets, d),
  +    [{tpos, OldPos}] = ets:lookup(Ets, tpos),
  +    RawPos = OldPos + speed(D) - speed(C),
  +    if RawPos < 0 ->
  +            NewPos = RawPos + ?AREA_WIDTH;
  +       RawPos >= ?AREA_WIDTH ->
  +            NewPos = RawPos - ?AREA_WIDTH;
  +       true ->
  +            NewPos = RawPos
  +    end,
  +    ets:insert(Ets, {tpos, NewPos}).
  +
  +cognitive_step(_Ets) ->
  +    nil.
  +
  +move_block(_Ets) ->
  +    nil.
  +
  +step(Ets) ->
  +    sense(Ets),
  +    cognitive_step(Ets),
  +    actuate(Ets),
  +    move_block(Ets).
  +
  +simulate_run(G) ->
  +    io:format("whole:~n~p~n~n", [G]),
  +    Ets = ets:new(x, [set]),
  +    Firsts = lists:zip([#edge{from=F, to=T} || T <- [a, b],
  +                                               F <- [1, 2, 3, 4, 5, a, b]],
  +                       lists:sublist(G, 2*7)),
  +    ets:insert(Ets, Firsts),
  +    io:format("first 14:~n~p~n~n", [Firsts]),
  +    OtherEdges = lists:zip([#edge{from=F, to=T} || T <- [c, d],
  +                                                   F <- [a, b, c, d]],
  +                           lists:sublist(G, 2*7 + 1, 2*4)),
  +    io:format("next 8:~n~p~n~n", [OtherEdges]),
  +    ets:insert(Ets, OtherEdges),
  +    Vertices = lists:sublist(G, 2*7 + 2*4 + 1, 4),
  +    io:format("and finally, vertices:~n~p~n~n", [Vertices]),
  +    ets:insert(Ets, [{Name, Vertex, #vstate{}} ||
  +                        Vertex = #vertex{name=Name} <- Vertices]),
  +    ets:insert(Ets, {tpos, 0}),
  +    ets:insert(Ets, {blocks_left, 39}),
  +    new_block(Ets),
  +    ets:insert(Ets, #block{size=6, x=27, y=15}),
  +    sense(Ets),
  +    All = ets:match_object(Ets, '_'),
  +    ets:delete(Ets),
  +    io:format("~P~n", [All, 100]).
  +
  +
  +
   
   refit(#ptype{gtype = G, ref = Ref} = P) ->
       Fitness = gen_fit(G),
  
positive.code: -module(cognitive).
  -import(genetica_utils, [clamp/3, rand_between/2]).
  -export([random_genotype_fn/1, phenotype_to_genotype_fn/1,
           genotype_to_phenotype_fn/1, fitness_fn/1, crossover_fn/1,
           mutation_fn/1, analyze_fn/2]).
  
  -record(ptype, {ref, gtype}).
  -record(vertex, {name, o = 0, y = 1, tau, sigma, gain}).
  -record(edge, {from, to, weight}).
  
  rand_node(Name) ->
      #vertex{name = Name, sigma = rand_between(-10, 0),
  
negative.code:             lists:foreach(fun refit/1, Pop),
              ok
      end.
  
  
  test() ->
      simulate_run((random_genotype_fn(nil))()).
  