OVERVIEW

DarwinBots e' un software di vita artificiale.
L'idea e' quella di gestire un ambiente all'interno del quale degli individui (i robots) possano nascere, vivere e riprodursi secondo le direttive loro imposte da un codice genetico, il DNA. Lo scopo principale del programma non e' pero' quello di selezionare mutazioni che facciano risolvere ai robots dei problemi definiti; ma semmai di adattarli a delle situazioni ambientali in continua evoluzione. 
In sostanza, l'ambiente cui i robots devono (dovrebbero) adattarsi, e' costituito, in massima parte, dai robots stessi. Percio' ho cercato di assegnare all'universo delle leggi che permettano la piu' intensa interazione possibile fra gli individui che lo popolano.
In particolare, i robots si vedono l'un l'altro attraverso una vista composta da nove recettori. La vista e' prospettica e tiene conto degli ostacoli, e fornisce informazioni ulteriori rispetto alla semplice posizione spaziale di chi sta di fronte. Inoltre esiste un tatto, che registra le collisioni fra gli individui, e un "olfatto" che ne percepisce le emissioni chimiche. Queste ultime svolgono un ruolo fondamentale nella simulazione. I robots si nutrono gli uni degli altri  esclusivamente attraverso l'emissione di un getto "chimico" che forza gli avversari a rimandarne indietro un altro contenente particelle nutritive. Inoltre, il getto puo' trasportare una coppia valore-locazione che va a scrivere un certo valore in una certa locazione di memoria del ricevente. Questo dovrebbe permettere interazioni piu' complesse, quali lo scambio di informazioni e forme di inganno.
Queste possibilita' vengono gestite da un DNA che e' in effetti un linguaggio di programmazione, basato su moduli che si attivano indipendentemente gli uni dagli altri al verificarsi di certe condizioni.

INTERFACCIA

All'inizio il programma presenta una schermata vuota e dei menu.

MENU FILES

New simulation: Scelta delle caratteristiche, dei parametri e degli organismi  (robots) da inserire nella simulazione.
Load simulation: carica una simulazione precedenetemente salvata
Save...   : salva una simulazione

Set autosave: apre una finestra di dialogo in cui impostare i parametri di salvataggio automatico periodico della simulazione (molto utile.. purtroppo)

MENU EDIT 

Edit walls: apre una finestra di dialogo che permette di creare dei muri.


Finestre di dialogo:

Nuova simulazione: impostazioni iniziali

A sinistra in alto compare una lista degli organismi che saranno inseriti all''inizio della simulazione. Si tratta di semplici dna. Per aggiungere un nuovo tipo di organismo alla simulazione selezionare "Add", e quindi un file .dna (nella directory robots). Selezionando uno dei tipi di organismi presenti nella lista, si attiva il riquadro di destra per le proprieta'.
Nell'ordine:

Individui: specifica quanti organismi dotati di quel dna saranno introdotti all'inizio della simulazione

Tasso di mutazione: apre una finestra di dialogo per settare le probabilita' di mutazione per quel tipo di organismo (vedi oltre)

Energia iniziale: specifica una quantita' iniziale di energia da assegnare agli organismi dotati di quel dna. Ogni nuovo nato avra'  pero' la percentuale di energia del genitore a lui assegnata dal genitore stesso, quindi questo settaggio ha effetto, come quelli precedenti, solo sulle condizioni iniziali.

Vegetale: e' necessario introdurre energia nel sistema, dato che ogni operazione compiuta dagli organismi ne consuma un po'. Ma, dato che gli organismi si nutrono gli uni degli altri, bisogna che ci sia una base della catena alimentare. Questo checkbox specifica, per un tipo di organismo, che gli verra' fornita energia direttamente dal programma. Si dovrebbe trattare in linea di massima di vegetali, ovvero di organismi sotanzialmente passivi il cui scopo e' quello, appunto, di fare da base della catena alimentare.

Scegli un colore: permette di specificare un colore iniziale per il tipo di organismo. Ogni successiva mutazione modifichera' questo colore in maniera casuale, ma e' importante settarne uno per distinguere le varie specie.

Posizione iniziale: serve a specificare una zona di partenza per gli organismi di una certa specie. In seguito saranno comunque liberi di muoversi dove gli pare. Il controllo non e' dei migliori, ma funziona :)


RIQUADRO "proprieta' generali"

Grandezza del campo: un moltiplicatore per la dimensione del campo. In sostanza, il campo normalmente e' della dimensione massima dello schermo; ma e' possibile renderlo da due a dieci volte piu' grande, grazie a questo slider. In ogni caso, questa opzione, seppure utile, e' ancora ad un livello di realizzazione piuttosto grossolano: consiglio di non oltrepassare il valore 4.

Limita popolazione massima: mette in atto un metodo per limitare la popolazione totale, che se sale sopra un certo numero di individui ("piante" comprese) viene limitata tagliando il nutrimento alla base della catena alimentare. Settando "Carestia" si attiva un meccanismo che distrugge i vegetali troppo vicini fra loro, oltre a smettere di nutrirli quando e' raggiunto il limite.

Salvataggio periodico: apre la finestra di dialogo per il settaggio del salvataggio periodico.

Tutti i settaggi fino a qui visti possono essere salvati o caricati in blocco tramite Load e Save Settings. Salvando dei settaggi con il nome "default.set", verranno caricati ogni volta che si fa partire il programma e si seleziona "new simulation" dal menu.


FINESTRA "WALLS":

Cliccando sul pulsante "Draw path for wall" e' possibile iniziare a disegnare un muro, come una serie di linee dritte. Al termine del disegno, recuperando la finestra e cliccando su "crea muro", il muro verra' creato.


FINESTRA "ROBOT DATA"

Fornisce alcuni dati sul robot cliccato (evidenziato da un quadrato bianco), e permette di compiere alcune operazioni su di esso.

Founder name: il nome del dna originario del robot.
Robot number: un identificatore unico del robot
Parent number: l'identificatore del padre.
Energy: il valore di energia del robot
Generation: il numero di generazioni dal dna del capostipite 
Mutations: il numero di mutazioni rispetto al genitore
Overall mutations: il numero di mutazioni rispetto al dna del capostipite
Age: l'eta', in centinaia di cicli (nota: la morte e' probabilmente il prodotto di una precisa strategia evolutiva, e come tale non e' contemplata fra le leggi fondamentali della simulazione: non esiste un limite di vita per gli organismi)
Number of offspring: il numero di figli del robot selezionato

Pulsanti:

Mutation rates: apre la finestra con i vari tassi di mutazione (vedi oltre)
View parent: passa ad evidenziare il genitore del robot corrente, se e' ancora in vita.
Reproduce: forza una riproduzione (con cessione del 50% dell'energia al figlio)
Save DNA: permette di salvare il DNA dell'organismo con un nome. Il dna cosi' salvato potra' poi essere letto (e' un file di testo), editato, e ricaricato come tipo di organismo in una successiva simulazione.

FINESTRA "MUTATION RATES"

Le mutazioni che intervengono su un DNA durante una riproduzione possono essere di vari tipi, e ciascuno ha una propria probabilita' indipendente di verificarsi. Esiste anche la possibilita' che un tasso di mutazione muti a sua volta casualmente durante una riproduzione (primo riquadro in alto)

Value->value: il tasso di mutazione da un valore immediato in un altro.
Instruction->instruction: da un'istruzione a un'altra
Instruction duplication: duplicazione di un blocco istruzione, con i suoi parametri
Gene duplication: duplicazione di un intero blocco da "cond" a "stop", cioe' un gene.
Gene deletion: cancellazione di un gene
Condition->condition: modifica una delle condizioni nel blocco di attivazione di un gene (fra cond e start)
Condition insertion: inserisce una condizione completamente nuova nel blocco attivazione
Condition deletion: cancella una condizione
Condition duplication: duplica una condizione (senza effetto sul momento, ma puo' mutare successivamente)
Variable->variable: sostituisce una variabile con un'altra, pescata da una lista delle variabili attualmente in uso
New variables introduction: introduce una nuova variabile nella lista di quelle in uso.

Nota: ogni tasso di mutazione e' espresso in 1/n, dove n e' il valore inserito nel riquadro; e rappresenta la probabilita' di mutazione di ogni singola variabile, condizione, gene, istruzione o valore nel dna di un organismo.
Nota bis: il tasso di mutazione dei vegetali dovrebbe essere quanto piu' basso possibile, dato che sono li' solo per farsi mangiare.





DETTAGLI

Iniziamo dalla struttura dei robots. Le loro componenti fondamentali sono il DNA, cioe' il programma che li gestisce, scritto in un apposito linguaggio che viene interpretato in tempo reale, e una memoria, nella quale il programma del DNA puo' leggere e scrivere valori, e compiere operazioni su di essi.
Il DNA e' costituito da moduli indipendenti (i geni) ognuno dei quali e' costituito a suo volta da un blocco attivatore, che verifica una serie di condizioni su certi valori in memoria, e un blocco di esecuzione, che compie delle operazioni leggendo e scrivendo nella memoria. Certe particolari locazioni della memoria sono poi collegate direttamente ai sensi e agli attuatori, in modo che scrivendo o leggendo da esse si possano far compiere al robot delle operazioni.
Il DNA viene mutato casualmente durante la riproduzione, con frequenze che sono regolabili dall'utente ma sono a loro volta soggette a mutazione; ma l'utente puo' scriverlo da se', utilizzando il linguaggio  apposito.
Sullo schermo, ogni robot appare come un quadratino colorato con un puntino bianco fermo o in movimento su uno dei lati. In effetti, i robots sarebbero da considerare tondi, e quel puntino rappresenta la direzione verso la quale sono voltati. Tutto cio' che emettono (segnali chimici, figli) lo emettono nella direzione di quel puntino. Ogni informazione spaziale che ricevono o emettono, e' relativa esclusivamente a quel punto, quindi i robots non dispongono di nessuna informazione assoluta sull'ambiente, ad esempio coordinate assolute e cosi' via. Anche i movimenti sono relativi alla loro direzione.


IL DNA

La costituzione di un tipico gene e' la seguente (le parole chiave sono scritte in minuscolo):

cond
  VALORE
  VALORE
  CONFRONTO
  VALORE
  VALORE
  CONFRONTO
  (ecc...)
start
  OPERAZIONI VARIE
stop

al termine del DNA deve inoltre essere presente la parola chiave "end", subito dopo l'ultimo "stop". 

Il blocco compreso fra le parole chiave start e stop viene eseguito solo se l'AND logico fra le varie condizioni e' verificato. All'interno dei blocchi, fra le parole chiave start e stop, non sono permesse istruzioni di confronto. 


VALORE: il modo di espressione dei valori e' duplice: immediato, specifica un valore fisso; puntatore, specifica una locazione della memoria da cui estrarre il valore.

es.:

cond 
  10
  1
  <
start
.....

viene eseguito solo quando il valore 10 e' minore di uno (cioe' mai)

invece

cond
  *10
  1
  <
start
....

viene eseguito quando il valore contenuto nella locazione 10 e' minore di 1

eccetera.

Ecco l'elenco delle istruzioni _finora disponibili_.

istruzioni di flusso:

cond, start, stop, end

condizioni:

<, >, =, != (diverso), %= (circa uguale, da migliorare), %!= (circa diverso, idem)

istruzioni vere e proprie

store - inserisce un valore in una locazione

sintassi:  VALORE
           LOCAZIONE
           store

add - somma due valori

sintassi:
  
           VALORE
           VALORE
           add

sub - sottrae il secondo dal primo
mult - moltiplica
div - divide il primo per il secondo


SENSI

I sensi finora attivi sono:

vista: nove sensori che forniscono una vista "prospettica" (le virgolette sono d'obbligo) degli altri robottini (non dei segnali chimici, o colpi) fino ad una certa distanza. Il valore contenuto nelle locazioni aumenta all'avvicinarsi dell'oggetto visto. I sensori forniscono un valore in memoria dalla locazione 501 alla 509, che possono anche essere indicate con il codice mnemonico eye1 eye2..eye9

dettaglio: l'oggetto inquadrato al centro del campo visivo (eye5) fornisce anche alcuni suoi dati che vanno ad occupare le locazioni 701-708: i dati sono

701 numero totale delle variabili dirup utilizzate dal rob di fronte
702 ""  dirdn
703 ""  dirsx
704 ""  dirdx
705 ""  aimdx
706 ""  aimsx
707 ""  shoot
708 energia del rob di fronte

velocita': 200 o vel, la propria velocita' _assoluta_ in modulo

dolore: 203 o pain l'energia persa nell'ultimo ciclo di calcolo

piacere: 204 o pleas l'energia acquistata ""

tatto: 205- 208 o hitup hitdn ecc.. la collisione con altri robot

olfatto: 210- 213 o shup, shdn ecc.. la locazione scritta dagli ultimi colpi ricevuti

energia: 310 o nrg, la propria energia, variabile fra 0 e 32000 (a zero un robot muore e scompare)


ATTUATORI:

dirup: velocita' in avanti (il lato di un robot e' 120, non ci si dovrebbe muovere di piu' di circa 30 per volta)
dirdn: velocita' all'indietro
dirdx: velocita' a destra
dirsx: velocita' a sinistra
aimdx: rotazione a sinistra di un angolo (pi=200*3.14)
aimdx: rotazione a destra
shoot: emissione di un segnale chimico (-1 per quello che forza l'emissione di un tot di energia dall'avversario, altrimenti con il valore della locazione di memoria dell'avversario che andra' scritta). La velocita' dei colpi e' casuale ma limitata al massimo da un multiplo della velocita' assoluta del robottino che li ha generati. Il che significa che un robottino fermo produce segnali chimici fermi, una traccia, insomma. Questi segnali poi restano li' per un tempo determinato a priori, qundi scompaiono.

shootval: il valore che verra' scritto nella locazione dell'avversario
repro: innesca la riproduzione: al figlio verra' passata una percentuale della propria energia specificata in repro, fra 10 e 90.


ALTRI FATTI

All'inizio della simulazione si dovrebbe specificare per una o piu' "specie" di robots che saranno nutrite "artificialmente". In genere questi sono "vegetali" cioe' robots che stanno fermi e aspettano solo di essere mangiati. Serve a introdurre energia nel sistema. Comunque possiedono anch'essi un DNA e devono provvedere da soli alla propria riproduzione.

Introdurre energia nel sistema e' importante, perche' ogni operazione attuata su un elemento di memoria (solo quando queste vengono effettivamente eseguite) ha un costo in termini di energia.

E' possibile inserire muri che vengono gestiti esattamente come dei robots (sono in effetti formati da "corpi" di robots). Quindi vengono visti, urtati, ecc., ma sono inamovibili.


ESEMPIO DI DNA

Porto ad esempio uno dei DNA dei robottini da me creati, per fissare le idee. (Ne taglio delle parti, per brevita').

'ballerino :ogni riga preceduta da ' funge da commento

cond         :inizio attivatore primo gene
start         :il primo gene si attiva sempre, non ci sono condizioni 
  *40         :viene messo il valore della locazione 40 nello stack
  1             :viene messo 1 nello stack
  add         :i due valori vengono sommati
  40       
  store      :il risultato viene rimesso nella locazione 40
stop         :fine gene

cond         :inizio attivatore
  *40        :se il valore
  29          :della locazione 40
  >           :e' maggiore di ventinove
start         :inizio bocco
  0      
  40
  store       :la locazione 40 viene azzerata
stop          :fine gene

cond         :attivatore             
  *40         :se il valore della loc 40
  15
  <            :e' minore di 15
  *.eye5    :E SE il centro della vista
  0            :(il punto e' necessario prima di un alias mnemonico)
  =            :e' vuoto
start         :inizia blocco
  10           :mette 10
  .dx         :nell'attuatore movimento a destra
  store       :cioe' si sposta di 10 a destra
stop

...................
...................

cond         :in ogni caso
start      
  1
  .aimdx
  store
stop          :si gira di 1/200 di radiante verso destra

cond       
  *.eye6     : se vede qualcosa sulla destra del centro visivo
  0
  >        
start     
  15
  .aimdx
  store       :si gira di 15/200 di radiante a destra
stop

..............................
..............................

cond
  *.eye5            :se vede qualcosa al centro del suo campo visivo
  0
  >
  *.refshoot      :e inoltre quel qualcosa non ha nel suo dna
  0                    :riferimenti allo sparo
  =                    :cioe' e' una pianta (ma potrebbe essere anche un muro)
start         
  -1                   :emette un segnale chimico per farsi restituire energia
  .shoot
  store        
  10                   :questo in questo contesto non ha importanza
  .shootval
  store
  10                   :e poi si sposta di 10 in avanti (verso la preda!)
  .up         
  store
stop

.................
.................

cond          
  *.nrg  	     :se la sua energia e' superiore a 21000
  21000
  >
start
  314
  .aimdx          :si gira da un'altra parte
  store
  50
  .repro          :e fa un figlio con meta' della sua energia
  store
stop

cond
  *.vel            :se la sua velocita'e' inferiore a 5
  5                  :puo' darsi si sia incastrato
  <
start
  100         
  .aimdx
  store           :e si gira
stop

cond
  *.pain         :se sta perdendo troppa energia
  20
  >
start             :meglio fuggire di lato
  15
  .dx
  store
stop
end              :fine del DNA


MUTAZIONE

Attualmente, e' la routine di mutazione che ha bisogno di maggiori ritocchi. L'ideale sarebbe quello di creare routine in grado di produrre il maggior numero di risultati interessanti nel minor numero di tentativi. In particolare, come primo passo, le mie routines producono solo mutazioni sintatticamente corrette.

Le mutazioni possono essere:

variabile->variabile: un'occorrenza di una variabile viene cambiata in un'altra
valore->valore: idem
istruzione->istruzione: idem
condizione->condizione: idem
duplicazione gene: un gene viene "raddoppiato" nel DNA
cancellazione gene: un gene viene cancellato
duplicazione condizione: una condizione viene duplicata
inserimento condizione: una condizione completamente nuova viene inserita
cancellazione condizione: ovvio
duplicazione istruzione: ovvio
nuove variabili: per rendere le mutazioni piu' interessanti, le variabili vengono mutate in altre provenienti da una lista, che contiene tutte quelle standard piu' tutte quelle gia'usate. Ma questa lista puo' essere ampliata a caso.

Per ognuno di questi diversi tipi e' possibile definire una diversa probabilita' di mutazione, nonche' la probabilita' che la probabilita' di mutazione muti a sua volta.

Le variabili di sistema con relativi codici mnemonici sono elencate nel file sysvars.txt. E' possibile aggiungerne delle altre, agendo sullo stesso file, che viene caricato alla partenza.
