o banner também é f(seed) — gerado por assets/gerar_rain.py com a seed default do universo (20260628), em loop perfeito
Um experimento meio filosófico, meio de programação: construir uma "Matrix"
de brinquedo onde "blocos" parecem vivos — sem nenhuma física hiper-realista.
Tudo roda no terminal, em ASCII, e é um único arquivo C (main.c) sem
dependências além da libc.
🐇 A motivação filosófica do projeto — podemos criar um bloco senciente? onde acaba a programação e começa a consciência? — está em
FILOSOFIA.md. Este README é o como; aquele é o porquê.
Onde estamos: escada completa — níveis 0 → 6 implementados. 🪜 A população agora evolui sozinha (seleção natural de personalidades).
Em vez de tentar criar consciência (o hard problem — indecidível e paralisante), trocamos a pergunta metafísica por uma funcional: que comportamentos associamos a um ser senciente, e quais conseguimos implementar? Daí uma escada, do mais barato ao mais caro. Senciência aqui não é um botão liga/desliga, é uma posição na escada — e a gente decide até que degrau sobe.
| Nível | Propriedade | Estado |
|---|---|---|
| 0 | Reatividade — responde a estímulo local | ✅ |
| 1 | Memória / estado interno — o passado importa | ✅ |
| 2 | Valência — coisas são boas/ruins (energia: viver × morrer) | ✅ |
| 3 | Modelo de mundo — simula o futuro e decide por ele | ✅ |
| 4 | Agência — pondera motivos em conflito p/ regular a valência | ✅ |
| 5 | Auto-modelo — o bloco se inclui na simulação; lê a intenção dos vizinhos | ✅ |
| 6 | Aprendizado — os traços são herdados com mutação → seleção natural | ✅ |
Do diretório raiz do projeto (c_training/):
make matrix # compila -> bin/matrix
./bin/matrix # roda a animação (Ctrl+C para sair)Precisa de um terminal de verdade (a tela se redesenha a cada tick via códigos ANSI; não funciona com a saída redirecionada para arquivo/pipe). Deixe a janela com pelo menos ~70 colunas de largura.
./bin/matrix [seed] [ticks] [delay_ms] [foco]| Arg | Default | O que faz |
|---|---|---|
seed |
20260628 |
escolhe o universo (mesma seed = mundo idêntico, sempre) |
ticks |
0 (infinito) |
quantos passos rodar; 0 = até Ctrl+C |
delay_ms |
80 |
pausa entre frames; menor = mais rápido |
foco |
-1 (visão de deus) |
entra já em 1ª pessoa nesse bloco (ver abaixo) |
./bin/matrix 42 # outro universo
./bin/matrix 42 500 30 # 500 ticks, rápido
./bin/matrix 7 200 150 # devagar, pra acompanhar
./bin/matrix 7 400 0 # o mais rápido possível (sem pausa)A flag --log <arquivo> escreve um CSV, uma linha de estatísticas por tick.
Ela é independente da animação (pode rodar junto com a tela ou headless), e
combina com os posicionais em qualquer posição:
./bin/matrix 7 2000 0 --log run7.csv # 2000 ticks, sem pausa, gravando tudo
./bin/matrix --log run7.csv 7 2000 0 # idêntico (a flag pode vir antes)Colunas: seed, tick, pop, energia_media, comida_total; para cada um dos 4
traços do nível 6, a média (_m) e o desvio-padrão (_sd)
(hor_*, desc_*, urg_*, esp_*); e os mostradores da bateria (abaixo),
todos normalizados em [0,1]: modelo, agencia, modelo_do_outro, phi, relato; a
fração da população por estratégia de sinalização, hon_f (honesta) e blef_f
(blefe) — o resto é muda; autocausa; a fração por arquitetura de escuta
(introspecção — nota 07), esc_plano_f e esc_monitor_f — o resto lê a
própria ação (nota 29); e, nas duas últimas colunas, média e desvio do peso
do auto-modelo temporal, arrep_m/arrep_sd (nota 30). Como o universo é
f(seed) (ver abaixo), o CSV é reproduzível bit-a-bit: qualquer pessoa
regenera o mesmo dataset a partir da seed. É a base para virar instrumento de
pesquisa — varrer seeds/parâmetros e medir o que a evolução faz, em vez de só
assistir.
Cada "mostrador" (0..1) mede se uma faculdade carrega o comportamento, em
duas famílias: ablação (arranca-se a faculdade — a decisão muda?) e
calibração (uma estrutura interna bate com a realidade?). Se arrancar não
muda nada, a palavra mental desbota. Mede função (papel causal), nunca
experiência — cada mostrador é uma caricatura honesta, no espírito do Φ~.
O porquê disso tudo — a ponte para sistemas complexos, a pergunta que costura o
projeto e o desfecho honesto — está em FILOSOFIA_v2.md.
| Mostrador | Palavra | Família | Como mede |
|---|---|---|---|
modelo |
"prevê / sabe" | calibração | o mapa do bloco (prever_valor: horizonte, desconto, partilha) promete uma colheita descontada ao entrar no alvo; ao longo dos seus próprios horizonte ticks compara-se com a colheita real, descontada igual — `1 − |
agencia |
"quer / escolhe" | ablação | fração cuja decisão muda em algum ponto do domínio da fome. Como utilidade é, por célula, uma reta em λ = peso_espaco·(1−fome)/(1+urgencia·fome), varrer λ ∈ [0, peso_espaco] percorre o domínio interno inteiro — sem ponto de sonda arbitrário |
modelo_do_outro |
"o outro também decide" | ablação (intervenção) | fração (não-encurralada) cuja escolha mudaria ao antecipar que rivais miram a mesma célula — varre a força da antecipação por todo o domínio [0,∞), não no ponto arbitrário ANTECIPACAO. Zero exato sem rivais: mede o outro, não o self |
phi (Φ~) |
"integra" | calibração | a menor distância de Kendall entre a ordem integrada (utilidade) e a ordem de cada módulo isolado (comida-agora, espaço, mapa), em [0,1]. Se um módulo sozinho reproduz a decisão, phi = 0: integrar uma coisa só não é integrar (redefinida na nota 05; a 1ª versão, contra a comida só, era infalseável) |
relato |
"diz de si" | calibração | κ de Cohen (concordância acima do acaso) entre o motivo que o intérprete leigo infere da ação executada e o motivo real da decisão. O intérprete não lê o estado interno nem o plano — só o 3×3 e o que o bloco fez (introspecção como percepção do próprio comportamento, Nisbett & Wilson). Pré-registrado antes de construir (ROADMAP.md §2.0; nota 06) |
autocausa |
"eu sou uma causa" | ablação (intervenção) | fração (não-encurralada) cuja escolha muda ao escalar por σ ∈ [0,1] o termo em que o bloco modela que ele próprio vai esvaziar a célula (food -= σ·garfada, em prever_valor). σ=1 é o código de hoje; σ=0 é um previsor cego a si. O único mostrador que o eremita possui — e horizonte = 1 o zera exato: o self exige um futuro. Pré-registrado antes de construir (ROADMAP.md §5.0; nota 09) |
⚠️ A primeira versão demodeloestava quebrada, e a conclusão que ela sustentava ("o bloco modela a física com exatidão; o único buraco é o social") era falsa. Aquele mostrador liacomida[alvo]— o array do mundo — e comparava com a garfada tirada da mesma célula: a mesma fórmula dos dois lados. Dava1,000até para um bloco sem modelo de mundo nenhum, marchando para a extinção. Um mapa que não pode discordar do território não é um mapa. Verpapers/notes/01-quatro-modos-de-errar.md.
Com o mostrador corrigido (a previsão sai de prever_valor, o mapa do bloco),
modelo lê ~0,63 — e o achado se inverte: o buraco entre o mapa e o
território não é só social, é uma crença falsa sobre o social. O bloco
acredita, via partilha, que os rivais dividem a comida da célula que ele ocupa;
mas ocup[][] guarda um bloco por célula, e ninguém divide nada. Zerar só
COMPETICAO recupera a calibração (0,63 → 0,79) sem mexer na população
(290,3 × 290,0): ao nível do grupo, partilha é puro custo epistêmico. Quem
carrega o valor adaptativo de enxergar rivais é o termo espaco, não a partilha
— um bloco que ignora os rivais por completo prevê melhor (0,78) e paga só
~2,4% de população.
modelo_do_outro acende com a lotação — começa em 0 (mundo esparso, ninguém
disputa) e sobe a ~0.35 conforme a população adensa. Ele nasceu com três defeitos:
era uma observação lida de graça (intencao ≠ alvo, subproduto de decidir()),
não uma intervenção; a leitura escalava com a constante ANTECIPACAO (varrê-la
de 0 a ∞ leva a leitura de 0 até a assíntota — 0.5 era só um ponto no meio);
e o nome mentia. O conserto o torna uma intervenção ancorada — pergunta se
antecipar os rivais poderia mudar a escolha, varrendo a força da antecipação por
todo o seu domínio, sem depender de ANTECIPACAO (o critério é exato, sem
amostragem). E assume o nome honesto: é identicamente zero para um bloco que não
percebe rivais (o teste do eremita), logo mede um modelo do outro, não de si —
uma relação, não uma posse. Um automodelo de verdade (o self na simulação) é outra
coisa, ainda por construir (ver "Aprofundar o auto-modelo", abaixo).
→ papers/notes/04-o-automodelo-era-um-modelo-do-outro.md.
E o achado mais duro do projeto até aqui: a evolução extingue a agência. Ao
longo de 30 000 ticks peso_espaco desaba de 3,0 para 0,08, e agencia desaba
junto, de 0,43 para 0,05. Não é defeito da régua: congelando peso_espaco, o
mostrador fica plano (0,46 → 0,44). É seleção — num ensaio de invasão, o
reflexo (peso_espaco = 0) fixa contra o agente em ~6000 ticks
(0,997 / 1,000 / 1,000). Neste mundo, ter um segundo motivo pesado pelo estado
interno é individualmente caro; a população converge para uma política que não
depende de nada que se passe dentro dela. Ver
papers/notes/03-a-evolucao-extingue-a-agencia.md.
E phi conta a mesma história um andar acima: a evolução extingue a
integração. O mesmo peso_espaco que carrega a agência é o que mantém a decisão
irredutível a um módulo só — quando ele morre, phi desaba (0,044 → 0,005);
congelado, ela fica de pé. A suspeita do ROADMAP (que phi fosse sinônimo de
profundidade de planejamento) estava errada — era co-tendência de 30 000
ticks, não acoplamento; congelar a profundidade não segura phi. Ver
papers/notes/05-phi-media-o-segundo-motivo.md.
E o relato entregou, já na primeira medição, o embrião do experimento do
intérprete: resolver() intervém de graça nas ações (nega células
disputadas), e nos blocos negados a calibração desaba (0,78 → 0,47) — o
intérprete explica a ação imposta, não a decisão. Ele não confabula sempre:
barrado, diz "não sei" em ~79% dos casos e racionaliza nos ~21% ("fiquei
porque aqui é o melhor" — sem ter escolhido ficar). E não entende ~35% das
próprias escolhas livres — as movidas pelo planejador que a heurística leiga
não acompanha. O eremita, contra a predição P5, fica mudo (κ ≈ 0,005): sem
segundo motivo, toda decisão tem o mesmo porquê, e não há informação acima do
acaso a relatar. Escopo honesto da v1: o sinal é medido, mas nenhum vizinho o
consome ainda — o relato é epifenomenal por construção, e isso é resultado,
não defeito. Ver papers/notes/06-o-interprete-leigo.md.
E o relato virou causal (Fase 4): até aqui pretendentes_em lia a
intencao dos vizinhos — telepatia. Agora cada bloco emite um sinal sobre
a própria intenção e os vizinhos leem o sinal, não a mente; a estratégia de fala
(honesto/mudo/blefe) é um traço herdável. O canal deixou de ser
epifenomenal — silenciar a população muda o mundo (energia ≈ 6,5 muda × 5,7
honesta) — e, sem nenhuma multa artificial, a honestidade evolui: fixa contra
o silêncio (0,50 → 0,95) e resiste ao blefe (0,50 → 0,87), sobrando um polimorfismo
estável de ~10% de blefe. O modelo_do_outro de um mundo todo-mudo é zero
exato: silêncio e cegueira são, para a régua, o mesmo estado. Ver
papers/notes/08-o-sinal-e-a-mentira.md.
E a arquitetura de escuta (ler a ação / ler o plano / monitorar os dois —
nota 07) também virou traço herdável (escuta, nível 6) — mas, de
propósito, sem custo nenhum ligado ao jogo ainda: só troca qual fórmula o
mostrador relato usa por bloco. Instalação inócua confirmada (a simulação
inteira fica bit-a-bit igual, qualquer que seja a mistura de arquiteturas na
população) e a deriva é mesmo neutra: 30 000 ticks, três seeds, sem
vencedor consistente — ao contrário de hon_f, que convergiu sob custo real.
Achado extra: populações de ESC_MONITOR (admite "não sei" quando detecta a
própria negação) tiram kappa mais alto que ESC_ACAO (confabula) — admitir
ignorância acerta contra uma verdade que também é "não sei" mais do que
confabular erra. Ver
papers/notes/29-escuta-evolutiva.md.
E o auto-modelo temporal deixou de ser ausência e virou mecanismo: um
bloco negado por resolver() cuja vice-célula (a segunda melhor da própria
varredura de decisão) ninguém disputou tem um contrafactual verificável
— "eu poderia ter ido para a esquerda" deixa de ser especulação. O sinal
(remorso, que decai pelo próprio desconto do bloco) alimenta um novo
traço herdável, peso_arrependimento, que decide se a memória volta a
pesar na decisão seguinte. A surpresa não foi se a seleção usaria essa
memória, foi para onde: o desenho apostava que aprender significava
perseguir mais espaço livre depois de barrado (peso positivo) — mas isso
custa energia (medido, pequeno e sem exceção em três seeds) e não vence
disputas de invasão contra o traço zerado (placar exato de 3×3). A
população, semeada livre e deixada evoluir, converge nas três seeds para o
lado oposto: um peso negativo, que faz o bloco menos propenso a
fugir da lotação depois de perder uma disputa — hipótese em aberto:
persistir onde a disputa valia a pena compensa mais que fugir para uma
célula vazia só por estar vazia. Ver
papers/notes/30-auto-modelo-temporal.md.
E o self já estava no código, sem que ninguém o tivesse notado. Em
prever_valor, a linha food -= garfada é o bloco prevendo que a célula vai
empobrecer porque ele próprio vai comer dela — o único ponto em que a ação
futura do bloco realimenta a previsão do bloco. O mostrador autocausa mede isso
(escalando o termo por σ e vendo se a escolha muda), e o resultado decide a
pergunta que a FILOSOFIA_v3.md chama de "a costura da escada":
- É o único mostrador que o eremita possui (0,03 na solidão, contra
0,0000exato deagenciaemodelo_do_outro). Existe, sim, uma faculdade que é do bloco e não da relação. - Mas o eremita tem 1/5 do que tem um bloco acompanhado (0,03 × 0,14). O outro não constitui o self — amplifica-o, e a amplificação é quase todo o número.
horizonte = 1o zera exato: quem não olha além da própria garfada não tem onde se modelar. O self exige um futuro.- A mesma seleção que apaga a agência constrói o self: em 3000 ticks a
agenciacai (0,46 → 0,36) e aautocausaquase dobra (0,089 → 0,169) — porque a agência depende de um traço (peso_espaco → 0) e o self depende do horizonte, que sobe. Degraus diferentes andam em sentidos opostos sob a mesma pressão.
Ver papers/notes/09-o-self-ja-estava-la.md
— que traz também uma errata: a agencia do eremita não era "zero exato", e sim
zero com um piso de arredondamento de ~0,003 em float32 (some em double). A
régua tem um chão, e ele caiu justamente sobre uma condição de falseamento.
Pendente: o Bandersnatch evolutivo (as arquiteturas de introspecção como traço),
o custo de pensar (Fase 3), e a auditoria em double dos mostradores restantes.
Durante a animação, num terminal de verdade, dá pra descer para dentro de um bloco e ver o mundo só como ele percebe (a vizinhança 3×3), com o que ele sente (energia, fome, traços) e quer (a utilidade que imagina para cada jogada). É a vista em primeira pessoa — o lado de dentro do explanatory gap.
| Tecla | Faz |
|---|---|
p ou TAB |
alterna visão de deus ↔ primeira pessoa |
, . |
troca o bloco habitado (anterior / próximo) |
espaço |
pausa / retoma o tempo |
q |
sai |
Por que isso importa filosoficamente está em FILOSOFIA.md
(§3, "A pílula vermelha: a vista de dentro").
Todo o universo é f(seed) — geração do mundo e decisões/nascimentos dos
blocos vêm da mesma semente. Mesma seed ⇒ simulação idêntica, sempre. Esse é o
gancho filosófico central: o universo é determinístico e gerado, mas de dentro
parece aberto. Você, ao escolher a seed, é o relojoeiro.
Pra conferir a população num tick específico sem assistir à animação:
./bin/matrix 7 200 0 | grep -a -o 'pop [0-9]*' | tail -1main.c a simulação inteira (um arquivo, só libc)
README.md o como — arquitetura, parâmetros, efeitos medidos
FILOSOFIA.md o porquê, v1 — o manifesto da escada
FILOSOFIA_v2.md o porquê, v2 — a bateria de desbotamento
CLAUDE.md guia para Claude Code
assets/ imagens do README
datasets/ CSVs congelados + gerar.sh (proveniência: comando + commit)
notebooks/ análise dos datasets (commitados sem outputs)
papers/ escrita formal (fonte + PDF)
Como o universo é f(seed, código), um CSV congelado só é reproduzível no
commit de main.c que o gerou — o manifesto em datasets/README.md registra
o comando e o commit exatos de cada arquivo, e datasets/gerar.sh regenera
tudo (servindo de teste de regressão: diff não-vazio = comportamento mudou).
@colorido = um bloco. A cor é a energia (valência):- 🟢 verde forte (
>10) · 🟡 amarelo (>4) · 🔴 vermelho (fraco, perto da morte).
- 🟢 verde forte (
. : *em verde fraco = densidade de comida no solo (recurso).(vazio) = deserto / comida quase zero.- HUD embaixo, quatro linhas: (1)
seed,tick,pop(população viva),energia media,comida(total no mundo) eΦ~(a "luz acesa" — um proxy de integração; a intuição está emFILOSOFIA.md§5, a definição atual na nota 05); (2) traçosmédia±desvioda população (horizonte,desconto,urgencia,espaco) — a média deriva (evolução do nível 6 ao vivo) e o desvio mostra se a população converge (todos parecidos, desvio→0) ou diversifica em nichos (desvio cresce); (3) a bateria (modelo,agencia,modelo_do_outro) — os mostradores de desbotamento descritos acima, ao vivo; (4) a legenda.
Dá pra ver emergir: manadas em torno de manchas férteis, colapsos por escassez, ciclos de fartura/fome, blocos saciados colonizando a fronteira (nível 4) e — deixando rodar uns milhares de ticks — a personalidade média da população mudando conforme o mundo (nível 6). Tudo a partir de regras estritamente locais (cada bloco só enxerga sua vizinhança 3×3).
E há duas janelas para o mesmo mundo: a visão de deus (o que está descrito
acima) e a primeira pessoa — tecle p para entrar num bloco (a pílula
vermelha) e ver o mundo só como ele percebe. A diferença entre as duas janelas
é o assunto de FILOSOFIA.md.
Um arquivo, organizado num pipeline de 4 partes (mesma filosofia do
apps/plotter/plotter.c):
| Parte | Papel |
|---|---|
| PART 1 — Mundo procedural | O mundo é f(seed, x, y): um hash inteiro vira value-noise, que vira manchas de comida (gerar_mundo, ruido, hash2). |
| PART 2 — Blocos / cognição | A "mente" do bloco. É aqui que mora a escada (ver abaixo). |
| PART 3 — Simulação (o tick) | Fases separadas: decidir → resolver (conflitos) → aplicar_e_comer → reproduzir → rebrotar. |
| PART 4 — Render + loop | Desenho ASCII num buffer + HUD, laço principal em main, Ctrl+C limpa o cursor e sai. |
- Estado em globais file-static:
comida[][],capacidade[][](teto de rebrota por célula, vindo do ruído),ocup[][](índice do bloco numa célula ou-1), o arrayblocos[]e o RNG do universo (rng_estado). - Um bloco é
{ x, y, energia, vivo }. Aenergiaé a valência: chega a zero ⇒ morte.vivo == 0marca slot livre (mortos deixam buracos no array). - Leitura × escrita separadas no tick. Todos decidem (
decidirpreenchealvo_x/alvo_y) lendo o estado; só depois o mundo aplica. Isso evita que a ordem de varredura vire "física fantasma" (o bug do organismo que anda mais rápido pra um lado só porque o laço o visita antes). - Resolução de conflito (
resolver): dois blocos, uma célula → só um entra. Para simplicidade e zero bugs de "troca de lugar", só se move para células que estavam vazias no início do tick, e cada célula vai para um único pretendente (o de menor índice); os demais ficam parados. - Sem
<math.h>. A regra padrão do Makefile compilagames/<nome>/*.csem-lm. Por isso o ruído usa aritmética inteira + polinômios e não hásin/exp/sqrt. Mantenha assim, senãomake matrixquebra.
Toda a inteligência está em decidir e nas funções que ela chama. A cada nível,
só essa parte mudou:
-
Nível 2 (valência): o bloco olhava a vizinhança 3×3 e ia para a célula com mais comida agora. Puramente reativo.
-
Nível 3 (modelo de mundo):
prever_valor(cx,cy,...)simulaHORIZONTEticks no futuro "de cabeça" — come → rebrota → come… — aplicando a mesma regra de rebrota do mundo e descontando o futuro (DESCONTO). O bloco passa a preferir mancha fértil momentaneamente raspada (que vai voltar) a um tesouro de uso único, e desconta células disputadas (COMPETICAO). Nasce a fresta entre o mundo e o mundo segundo o bloco — o modelo interno, que pode errar. -
Nível 4 (agência):
utilidade(cx,cy,b)combina motivos em conflito pesados pelo estado interno:utilidade = comida_prevista · (1 + URGENCIA·fome) ← motivo FOME + PESO_ESPACO · espaco_livre · (1 − fome) ← motivo ESPACO + PESO_ARREPENDIMENTO · remorso · espaco_livre ← motivo do nv6, §4.3com
fome = clamp(1 − energia/SACIADO, 0, 1). Faminto → forrageia obstinado; saciado → busca espaço aberto (menos disputa, lugar pra cria). O mesmo bloco no mesmo mundo decide diferente conforme a necessidade. Ele age para regular a própria valência — isso é agência, não reação. (A terceira linha só existe desde o nível 6/nota 30 —remorsoé memória de curto prazo, não um traço; ver abaixo.) -
Nível 5 (auto-modelo): até aqui o bloco modelava o mundo mas se esquecia de si — avaliava uma célula como se fosse o único a cobiçá-la. Agora o tick tem três passagens (
declarar→emitir→decidir): primeiro todos declaram a intenção (a decisão do nível 4, emintencao_x/y), depois cada um emite um sinal sobre ela (emitir, emsinal_x/y), e por fim cada um reconsidera lendo os sinais dos vizinhos (pretendentes_em) e desvaloriza alvos que outros também miram — só um entra (resolver), então cede para a célula livre, a menos que o alvo disputado seja muito melhor (pesoANTECIPACAO). É um lampejo de teoria da mente: decidir contando que os outros também decidem. O que os vizinhos leem já não é a intenção crua (isso seria telepatia) e sim o sinal — que pode mentir: a estratégia de fala é um traço herdável (nível 6), e a honestidade evolui porque a mentira custa (nota 08). As passagens leem o mesmo estado estável (arrays separados) pra não reintroduzir a "física fantasma" da ordem de varredura.Efeito medido (A/B com
ANTECIPACAO0 vs 0.5, 5 seeds, tick 300): a população sobe ~5–7 % e a energia média cai (≈6 → ≈4). Lendo as intenções, os blocos colidem menos e param menos vezes "negados", espalham-se e ocupam mais o mapa — mas a mesma comida finita é dividida entre mais indivíduos. O auto-modelo não engorda os blocos: torna a população mais densa e enxuta. Coordenação emergente, sem ninguém combinar nada. -
Nível 6 (aprendizado): até aqui todos os blocos partilhavam a mesma política (as constantes globais). Agora
urgencia,peso_espaco,descontoehorizontesão campos dostruct Bloco— a personalidade de cada um.semear_blocossorteia traços iniciais variados; emreproduzira cria herda os do pai com uma mutação (muta_traco/muta_horizonte, escalaMUTACAO). Ninguém projeta a melhor estratégia: quem por acaso herda uma política que come mais vive mais e deixa mais filhos, então a média da população deriva para o que funciona — seleção natural, sem gradiente nem recompensa explícita. As médias dos traços aparecem no HUD pra você ver a evolução ao vivo. Mais três traços se juntaram aos quatro originais, cada um com o próprio mecanismo de mutação/herança: a estratégia de fala (estrategia— nota 08), a arquitetura de escuta (escuta— nota 29, sem custo ainda) e o peso do arrependimento (peso_arrependimento— nota 30, a única que a seleção já empurrou numa direção clara e inesperada).Efeito medido (seed 7, traço médio ao longo de 800 ticks):
horizonte6.0 → 7.6 epeso_espaco3.2 → 2.7 — planejar mais fundo é favorecido, buscar espaço aberto é podado. E a direção depende do mundo: em 3 seeds ohorizonteevoluiu para 7.6 / 8.5 / 8.1. O mesmo código, mundos diferentes, personalidades diferentes — selecionadas pelo ambiente, não fixadas.
São as "leis da física" deste mundinho. Mude, recompile (make matrix), observe.
| Constante | Default | Efeito |
|---|---|---|
LARG, ALT |
64, 22 | tamanho do mundo (cuidado com a largura do terminal) |
MAX_COMIDA |
5.0 | teto de comida por célula |
REGROW |
0.06 | velocidade de rebrota da comida |
N_INICIAL |
60 | quantos blocos nascem no começo |
ENERGIA0 |
6.0 | energia inicial de um bloco |
INGESTAO |
2.0 | quanto come por tick |
METABOLISMO |
0.35 | energia gasta só por existir |
REPRO |
12.0 | energia a partir da qual o bloco se divide |
HORIZONTE |
6 | (nv3→6) ticks simulados no futuro — agora traço, isto é a média inicial |
DESCONTO |
0.80 | (nv3→6) peso do futuro distante — traço (média inicial) |
COMPETICAO |
0.5 | (nv3) quanto cada rival reduz a colheita prevista |
SACIADO |
10.0 | (nv4) energia em que a fome zera |
URGENCIA |
2.0 | (nv4→6) quanto a fome amplifica a comida — traço (média inicial) |
PESO_ESPACO |
3.0 | (nv4→6) força do desejo de espaço aberto — traço (média inicial) |
ANTECIPACAO |
0.5 | (nv5) quanto cada vizinho que mira a mesma célula a desvaloriza (0 = volta ao nv4) |
MUTACAO |
0.12 | (nv6) magnitude da mutação herdada (0 = clones perfeitos, sem evolução) |
HORIZONTE_MAX |
12 | (nv6) teto do horizonte que um bloco pode evoluir |
Experimentos divertidos:
HORIZONTE 1→ bloco míope (quase nível 2) vsHORIZONTE 12→ estrategista.PESO_ESPACOalto → blocos "agorafílicos" que se espalham feito colônia.URGENCIAalta → blocos que entram em pânico e brigam por comida.REGROWbaixo → mundo avaro, ciclos de fome mais dramáticos.ANTECIPACAO 0→ desliga o auto-modelo (vira nível 4); alto → blocos muito "educados" que quase nunca disputam a mesma célula.MUTACAO 0→ desliga a evolução (clones perfeitos, traços médios congelam); alto → deriva rápida e caótica das personalidades.- Deixe rodar milhares de ticks (
./bin/matrix 7 0 10) e observe a linha de traços médios no HUD migrar — é a seleção natural ao vivo.
Os 7 degraus (0→6) estão implementados. Daqui pra frente não há um "nível 7" canônico; o espaço se abre em duas direções.
A primeira foi descer a toca do coelho: em vez de mais um degrau, encarar a
pergunta que a escada toda evitou — podemos criar um bloco senciente? onde acaba
a programação e começa a consciência? Isso virou a pílula vermelha (entrar
num bloco), o auto-relato (o bloco que diz "eu") e o Φ~ (medir a "luz
acesa"), tudo destrinchado em FILOSOFIA.md — o manifesto
do projeto.
A segunda é mais simulação. Algumas ideias, da mais barata à mais ambiciosa:
- Aprofundar o auto-modelo (nv5): em
prever_valor, separar o próprio consumo do consumo dos rivais (hoje ambos entram juntos viapartilha), modelando que a célula escolhida fica deprimida pelo próprio bloco. É o que falta para haver umautomodelode verdade: o mostrador atual mede um modelo do outro (zero para um eremita — ver a nota 04). Predição falseável: feita essa edição, um mostrador do self ficaria> 0na solidão. Ao contrário das outras ideias desta lista, esta mexe na simulação (a decisão muda), então não é conserto de régua — é a bifurcação da Fase 5 doROADMAP.md. - Variância no HUD: além da média dos traços, mostrar o desvio — dá pra ver a população convergir (todos parecidos) ou se diversificar (nichos).
- Genealogia / espécies: colorir o
@pelo traço dominante (ex.: horizonte) em vez da energia, e assistir "linhagens" pintarem regiões do mapa. - Sexo / recombinação: cria herda traços de dois pais vizinhos saciados, não de um só — abre co-evolução e seleção sexual.
- Predadores: uma segunda espécie que come blocos em vez de comida, criando uma corrida armamentista evolutiva (presa fica mais arisca, predador mais...).
- Custo do pensar:
horizontealto consumir maisMETABOLISMO— aí o planejamento profundo deixa de ser grátis e a evolução tem um trade-off real.
Cada uma mexe só na PART 2 (cognição) ou na fase de reprodução — o resto do pipeline (mundo, render, tick) segue de pé.
Depois da v2 o espaço abriu bem mais do que essas duas direções: as linhas de
pesquisa possíveis — e as que o projeto deliberadamente não vai seguir —
estão em ROADMAP.md.
- 2 — valência: quando um
@vermelho "luta" pra não chegar a zero, a diferença entre sofrer e manter umfloatalto é qual, exatamente? - 3 — modelo de mundo: pela primeira vez há diferença entre o mundo e o mundo segundo o bloco — e essa fresta entre mapa e território é o que torna possível tudo que vem depois.
- 4 — agência: dois blocos idênticos no código podem querer coisas opostas
porque sentem coisas diferentes (a fome é só deles). É o primeiro lampejo de
algo como preferência subjetiva num punhado de
floats. - 5 — auto-modelo: o bloco aparece dentro da própria simulação. O sistema começa a modelar o observador-de-si.
- 6 — aprendizado: ninguém projeta as personalidades; elas são selecionadas. O relojoeiro escolhe só a seed e as leis — o resto se descobre sozinho.
Código e UI em pt-BR (sem acentos no código, por causa do terminal). Veja
main.c — está todo comentado, parte por parte.
