Tallo: struttura del programma

Iniziamo vedendo la struttura da dare al programma, almeno inizialmente.

I blocchi principali da considerare sono quello che aggiorna la situazione fisica dei Talli, quello che aggiorna la parte legata all’intelligenza artificiale e quello che aggiorna la visualizzazione.

Il blocco che aggiorna la situazione fisica dei talli si preoccupa per ogni Tallo di calcolare le nuove coordinate in base alla posizione attuale, alla direzione e alla velocità; Inoltre si occupa di eventuali sovrapposizioni fra Tallo e cibo per permetterne l’assimilazione. 

Il cibo

Cibo, finora non ne avevamo parlato, il cibo in realtà è un contenitore di energia che cade dall’alto ad una velocità variabile; nell’aggiornamento della posizione fisica dei Talli ci occupiamo anche dell’aggiornamento del cibo, calcolando la nuova posizione. Il cibo che arriva in fondo è perso. La definizione del cibo è la seguente: 

type
   tcibo = record
     stato: string;
     x: integer;
     y: integer;
     x_int : integer;
     y_int : integer;
     energia: Integer;
     velocita: Integer;
   end;

Il blocco che si occupa dell’intelligenza artificiale è ancora tutto da pensare, l’idea è quella di realizzare virtualmente dei blocchi tipo lego, attaccati ad uno o più di altri blocchi ognuno con una specializzazione.

Sicuramente ci sarà un blocco in grado di gestire la velocità del flagello, uno in grado assimilare energia dal cibo, uno collegato ad un sensore per la rilevazione di quanto ci circonda, uno in grado di prendere decisioni logiche in base ai valori presenti nei blocchi collegati, uno in grado di memorizzare valori e quant’altro mi verrà in mente, ma lo vedremo in un secondo momento.

Aggiorniamo la visualizzazione

Il blocco che aggiorna la visualizzazione in qualche modo lo abbiamo già visto; poichè l’elaborazione dei blocchi precedenti può essere pesante, la visualizzazione può essere sospesa o eseguita ogni tot numero di cicli, per non pesare sulla elaborazione. Mi riprometto migliorare le varie funzioni utilizzando anche l’assembler, visto che Delphi 5 permette di utlizzare l’assembler inline.

Quindi, la funzione eseguita dal timer ogni Timer1.interval è la seguente:

procedure TForm1.Timer1Timer(Sender: TObject);
var
  i : integer;
  start : Cardinal;
begin
ciclo := ciclo + 1;
start := GetTickCount;
for i := 1 to punta_tallo do begin
    disegna_tallo(i,'c');
    cervello_tallo(i);
    aggiusta_direzioni(i);
    aggiorna_tallo(i);
    disegna_tallo(i,'d');
    mangia_tallo(i);
    end;
for i := 1 to punta_cibo do begin
    disegna_cibo(i,'c');
    aggiorna_cibo(i);
    disegna_cibo(i,'d');
    end;
if strtofloat(statictext7.caption) < (GetTickCount - start) then
   statictext7.Caption := floattostr(GetTickCount - start);
statictext4.Caption := floattostr(GetTickCount - start);
statictext6.Caption := floattostr(ciclo);
genera_cibo();
if ciclo_singolo then begin
   ciclo_singolo := false;
   timer1.enabled := false;
   end;
end;

La variabile start viene impostata con il valore dell’orario in millisecondi, questo per poter poi visualizzare la durata del ciclo.

Quanti talli

Punta_tallo contiene il numero dei talli presenti, con un ciclo quindi per ogni tallo innazitutto lo cancello disegnandolo con il colore di sfondo, aggiorno il cervello (quando ne avrà uno), aggiusta la direzione poichè i due flagelli del tallo spingono in direzioni differenti con forze differenti il tallo non si muove in linea retta e questa funzione calcola la rotazione in base alle spinte dei flagelli.

Subito dopo aggiorno il tallo nel senso che in base alla direzione e alla velocità provvedo a calcolare le nuove coordinate.

Fra l’altro in questa funzione viene aggiornata la velocità in base alla spinta; la velocità rappresenta la velocità attuale mentre la spinta rappresenta le velocità voluta. se il tallo vuole correre ad esempio a 100, non passa immediatamente a 100, la spinta sarà 100 ma la velocità partirà da zero e ad ogni ciclo verrà incrementata finchè non raggiunge la spinta. finito di aggiornare tutti i valori disegno il tallo nella nuova posizione.

Visualizziamo anche il cibo

Rifaccio poi un ciclo simile per il cibo dove mi limito a cancellarlo, calcolare nuove coordinate o eliminarlo se ha raggiunto il fondo e lo ridisegno.

A questo punto avendo quasi finito posso, facendo la differenza fra la variabile start e il valore dell’orario attuale in millisecondi, visualizzaere in statictext4 la durata dell’ultimo ciclo, in statictext7 il ciclo di maggior durata e in statictext6 il numero del ciclo attuale.

Per ultime le istruzioni che mi permetto di gestire il ciclo singolo di cui abbiamo parlato in precedenza.

Maurizio

Lascia un commento