<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Flying memes &#187; Processing</title>
	<atom:link href="http://sandropaganotti.com/tag/processing/feed/" rel="self" type="application/rss+xml" />
	<link>http://sandropaganotti.com</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Sun, 25 Jul 2010 12:45:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Game of Life, introducing gray</title>
		<link>http://sandropaganotti.com/2010/04/02/game-of-life-introducing-gray/</link>
		<comments>http://sandropaganotti.com/2010/04/02/game-of-life-introducing-gray/#comments</comments>
		<pubDate>Thu, 01 Apr 2010 22:13:35 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Algoritmi]]></category>
		<category><![CDATA[cellular automata]]></category>
		<category><![CDATA[game of life]]></category>
		<category><![CDATA[Processing]]></category>

		<guid isPermaLink="false">http://sandropaganotti.com/?p=368</guid>
		<description><![CDATA[During the last hour I modified my previous version of Game Of life trying to reproduce the same behavior using an analogic discriminator. Instead of counting the number of neighbours I elaborate their medium color and use this value to decide the next rgb combination of the cell. In the following snippet the two versions [...]]]></description>
			<content:encoded><![CDATA[<p>During the last hour I modified my previous version of Game Of life trying to reproduce the same behavior using an analogic discriminator. Instead of counting the number of neighbours I elaborate their medium color and use this value to decide the next rgb combination of the cell. </p>
<p><span id="more-368"></span>In the following snippet the two versions (classic and analogic) are compared:</p>
<pre><code class="javascript">
//  Classic version:
  void compute(){
    int black_neighbours = 0;
    for(int z=0; z < neighbours.length; z++)
      if(neighbours[z].rgb == black)
        black_neighbours ++;  

    switch(black_neighbours){
      case 0:
      case 1:
      case 4:
      case 5:
      case 6:
      case 7:
      case 8:
        to_color(white);
        break;
      case 2:
        to_color(rgb);
        break;
      case 3:
        to_color(black);
        break;
    }
  } 

// Analogic version
  void compute(){
    int[] medium_color = new int[] {0,0,0};
    for(int z=0; z < neighbours.length; z++)
      for(int c=0; c < 3; c++)
        medium_color[c] = medium_color[c] + neighbours[z].rgb[c];

    int medium_tone = 0;
    for(int c=0; c < 3; c++){
      medium_color[c] = medium_color[c] / neighbours.length;
      medium_tone = medium_tone + medium_color[c];
    }  

    medium_tone = medium_tone / 3;

    if (medium_tone > 191 || medium_tone < 128 ){
      to_color(white);
    }else if(medium_tone > 159 ){
      to_color(rgb);
    }else{
      to_color(black);
    }
  }
</code></pre>
<p>Next I went a step further using &#8216;medium color&#8217; when the classic rules asked insted to keep the previous cell color. This lead to a general acceleration to white because the medium neighbours color is always more bright than pure black, to balance this behavior I expanded the range of medium_tones which results in black. Here&#8217;s the tuned code:</p>
<pre><code class="javascript">
  void compute(){
    int[] medium_color = new int[] {0,0,0};
    for(int z=0; z < neighbours.length; z++)
      for(int c=0; c < 3; c++)
        medium_color[c] = medium_color[c] + neighbours[z].rgb[c];

    int medium_tone = 0;
    for(int c=0; c < 3; c++){
      medium_color[c] = medium_color[c] / neighbours.length;
      medium_tone = medium_tone + medium_color[c];
    }  

    medium_tone = medium_tone / 3;

    if (medium_tone > 191 || medium_tone < 80 ){
      to_color(white);
    }else if(medium_tone > 159 ){
      to_color(medium_color);
    }else{
      to_color(black);
    }
  }
</code></pre>
<p>Now <a href="http://www.youtube.com/watch?v=QheZEcI5bv4">a short video</a> of this new behavior:</p>
<p><object width="640" height="505"><param name="movie" value="http://www.youtube.com/v/QheZEcI5bv4&#038;hl=it_IT&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/QheZEcI5bv4&#038;hl=it_IT&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="505"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://sandropaganotti.com/2010/04/02/game-of-life-introducing-gray/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A processing.org Game of Life</title>
		<link>http://sandropaganotti.com/2010/03/20/a-processing-org-game-of-life/</link>
		<comments>http://sandropaganotti.com/2010/03/20/a-processing-org-game-of-life/#comments</comments>
		<pubDate>Sat, 20 Mar 2010 17:13:13 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Algoritmi]]></category>
		<category><![CDATA[game of life]]></category>
		<category><![CDATA[Jhon Conway]]></category>
		<category><![CDATA[Processing]]></category>

		<guid isPermaLink="false">http://sandropaganotti.com/?p=325</guid>
		<description><![CDATA[Everybody knows the popular Game of Life created by Jhon Conway and becamed famous after been published by Martin Gardner on Scientific American in 1970. It is essentially a cellular automation algorithm with a very few simple rules that determinate how to grow a pool of one-pixel-shaped organisms layed upon a 2D matrix. Here&#8217;s the [...]]]></description>
			<content:encoded><![CDATA[<p>Everybody knows the popular <a href="http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life" target="_blank">Game of Life</a> created by <a href="http://en.wikipedia.org/wiki/John_Horton_Conway" target="_blank">Jhon Conway</a> and becamed famous after been published by <a href="http://en.wikipedia.org/wiki/Martin_Gardner" target="_blank">Martin Gardner</a> on <a href="http://ddi.cs.uni-potsdam.de/HyFISCH/Produzieren/lis_projekt/proj_gamelife/ConwayScientificAmerican.htm" target="_blank">Scientific American</a> in 1970. It is essentially a cellular automation algorithm with a very few simple rules that determinate how to grow a pool of one-pixel-shaped organisms layed upon a 2D matrix.</p>
<p><span id="more-325"></span>Here&#8217;s the rules:</p>
<ul>
<li>if the organism has more than 3 or fewer than 2 neighbours it dies;</li>
<li>if the organism has 2 or 3 neighbours it survives;</li>
<li>if a white cell in the matrix is sorrounded by exactly 3 neighbours it became a living organism.</li>
</ul>
<p>I&#8217;ve implemented this Game Of Life using Processing language and trying to push all of the game logic within the organism class in order to really simulate a cellular behavior, here&#8217;s the class:</p>
<pre><code class="javascript">class Spot{
  int[]   rgb, rgb_next;
  int     x,y;
  Spot[]  neighbours;

  Spot(int gx, int gy, int[] c){
    rgb      = c;
    rgb_next = new int[3];
    x       = gx;
    y       = gy;
  }

  void set_neighbors(Spot[][] grid){
    int xp = (x+1 == grid.length ? 0 : x+1);
    int xm = (x-1 == -1 ? grid.length - 1 : x-1);
    int yp = (y+1 == grid[0].length ? 0 : y+1);
    int ym = (y-1 == -1 ? grid[0].length - 1 : y-1);

    neighbours = new Spot[] {  grid[xm][ym], grid[xm][y ], grid[xm][yp],
                               grid[x ][ym],               grid[x ][yp],
                               grid[xp][ym], grid[xp][y ], grid[xp][yp]
                            };
  }

  void compute(){
    int black_neighbours = 0;
    for(int z=0; z &lt; neighbours.length; z++)
      if(neighbours[z].rgb == black)
        black_neighbours ++;  

    switch(black_neighbours){
      case 0:
      case 1:
      case 4:
      case 5:
      case 6:
      case 7:
      case 8:
        to_color(white);
        break;
      case 2:
        to_color(rgb);
        break;
      case 3:
        to_color(black);
        break;
    }
  } 

  void advance(){
    rgb = rgb_next;
    rgb_next = new int[3];
  }

  void draw(int bw,int bh){
     fill(rgb[0],rgb[1],rgb[2]);
     rect(x*bw,y*bh,bw,bh);
  }

  void to_color(int[] c){ rgb_next = c; }
}
</code></pre>
<p>There are three methods that worth a look:</p>
<ul>
<li><strong>set_neighbors</strong>:<br />
which determinates the sourronding neighbors (as the method name states) by creating an array of pointer to the closest organisms using the matrix passed as parameter as a reference. The first four lines are needed in order to eliminate the boundaries by linking each edge of the matrix to the opposite one.</li>
<li><strong>compute</strong>:<br />
which implements the real logic of the Game, it is divided into two steps, the first part calculates the number of alive neighbors sorrounding the organism and the second one applies the rules stated above.</li>
<li><strong>advance</strong>:<br />
due the fact that all of the organisms need to be processed before each of them can switch to the new state, the Spot class record the result of the &#8216;compute&#8217; method inside a different variable and then, when advance is invoked, it moves this result to the &#8216;live&#8217; variable.</li>
</ul>
<p>Here&#8217;s a short video of my script in action, the source code is, as usually, <a href="http://github.com/sandropaganotti/processing-game-of-life" target="_blank">available on my github account</a>:</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="660" height="405" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/LcHvyVpdnEk&amp;hl=it_IT&amp;fs=1&amp;rel=0&amp;border=1" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="660" height="405" src="http://www.youtube.com/v/LcHvyVpdnEk&amp;hl=it_IT&amp;fs=1&amp;rel=0&amp;border=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://sandropaganotti.com/2010/03/20/a-processing-org-game-of-life/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Q-learning con processing.org</title>
		<link>http://sandropaganotti.com/2009/01/18/q-learning-con-processingorg/</link>
		<comments>http://sandropaganotti.com/2009/01/18/q-learning-con-processingorg/#comments</comments>
		<pubDate>Sun, 18 Jan 2009 16:00:25 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Algoritmi]]></category>
		<category><![CDATA[Apprendimento con Rinforzo]]></category>
		<category><![CDATA[Processing]]></category>
		<category><![CDATA[Q-learning]]></category>
		<category><![CDATA[Reinforcement Learning]]></category>

		<guid isPermaLink="false">http://sandropaganotti.com/?p=102</guid>
		<description><![CDATA[Il reinforcement learning (o apprendimento con rinforzo) è una approcio che appartiene alla categoria dei sistemi intelligenti e che si applica a tutte quelle casistiche nelle quali un agente deve esplorare ed interagire con l&#8217;ambiente circostante. Il principio base che sottende tutti gli algoritmi di reinforcement learning è lo stesso: ad ogni interazione con l&#8217;ambiente [...]]]></description>
			<content:encoded><![CDATA[<p>Il reinforcement learning (o apprendimento con rinforzo) è una approcio che appartiene alla categoria dei sistemi intelligenti e che si applica a tutte quelle casistiche nelle quali un agente deve esplorare ed interagire con l&#8217;ambiente circostante.</p>
<p><span id="more-102"></span><br />
Il principio base che sottende tutti gli algoritmi di reinforcement learning è lo stesso: ad ogni interazione con l&#8217;ambiente circostante l&#8217;agente viene premiato o punito a seconda dell&#8217;azione intrapresa in quel particolare stato. A fronte di questi premi/punizioni l&#8217;agente impara col tempo a collezionare il maggior numero di premi possibili evitando le punizioni.</p>
<p>Possiamo formalizzare quanto appena enunciato come segue: dato un&#8217;insieme di stati  S={s0,s1&#8230;,sn}, un&#8217;insieme di azioni A={a1,a2&#8230;,am} dobbiamo trovare una corrispondenza stato-azione (detta policy p[s,a] ) in modo da massimizzare il reward R={r1,r2&#8230;,rl} che l&#8217;ambiente ci fornisce ogniqualvolta in un determinato stato eseguiamo una determinata azione.</p>
<p>Chiaramente a questo enunciato devono seguire alcune considerazioni (che ci porteranno poi alla stesura dell&#8217;algoritmo Q-learning), ad esempio risulta ovvio pensare che se dall&#8217;azione che eseguo all&#8217;istante t ottengo una punizione questa non sarà (probabilmente) legata solo a quello che ho scelto di fare in quell&#8217;istante ma anche da tutte le scelte che ho fatto prima.</p>
<p>Ecco dunque che nasce la necessità di aggiungere una nuova definizone a quanto già espresso precedentemente, definiamo q[s,a] come la misura del premio/punizione che mi dovrebbe attendere a lungo termine se intraprendo quella azione in quello stato. Quindi una q[s,a] abbastanza alta dovrebbe rassicurare il mio agente e fargli intraprendere quell&#8217;azione in quanto, se prendiamo come esempio gli scacchi, poche mosse dopo quella che stò per fare potrei vincere.</p>
<p>Ottenere un buon indicatore di questa q non è esattamente facile. Per farlo deve necessariamente esplorare l&#8217;ambiente in modo da collezionare un po di &#8216;esperienza&#8217; sul campo, esperienza che poi potrò utilizzare proprio per stillare la policy (perchè unendo i concetti fin qui esposti risulta ben chiaro che se dovessi mai avere la q &#8216;perfetta&#8217; per ogni copia di stato/azione la mia policy si risolverebbe nell&#8217;eseguire di volta in volta l&#8217;azione con la q più alta per quello stato).</p>
<p>L&#8217;algoritmo Q-learning che stò per enunciare unisce il concetto di &#8216;calcolo della q&#8217; al concetto di &#8216;elaborazione della policy&#8217; semplicemente accontentandosi di volta in volta di scelgiere l&#8217;azione con la q più alta tra quelle disponibili in quello stato e successivamente di retro-modificare la q scelta incrementandola se l&#8217;azione (e quelle successive) hanno portato ad un premio e decrementandola viceversa.</p>
<p>In questo modo dopo un certo numero di &#8216;episodi&#8217; la q che l&#8217;agente si è calcolato dovrebbe essere almeno vicina a quella reale.</p>
<p>Scrivo ora l&#8217;algoritmo del Q-learning cosi come descritto nei paragrafi precedenti:</p>
<pre><code>
Variabili iniziali:
S = {s1,s2,...sn}   # Stati  (ad esempio in un labirinto ogni casella)
A ={a1,a2,...an}    # Azioni (potrebbero non esserci tutte per ogni stato, in un labirinto
                    # potrebbero essere su, giu, sx, dx)

Setup iniziale:
q = 0               # Per ogni coppia di stato/azione
r =  0              # Per ogni coppia di stato/azione imposto il reward a zero
imposta_reward()    # Per ogni coppia di stato azione significativa ( ad esempio in un
                    # labirinto l'uscita) imposto un
                    # reward diverso dallo zero ( ad esempio uscita: +10, rovi: -5 )
stati_terminali = s1,s2  # Vanno identificati gli stati terminali (quelli in cui,
                         # cioè l'episodio finisce - ad esempio l'uscaita dal labirinto)
stato_corrente = stato_inizale      # Va impostato uno stato iniziale
azione_corrente = azione_iniziale   # Va impostata la prima azione
alpha = xx          # costante, indica quanto la variazione dei q futuri incida sul q
                    # corrente
gamma = xx          # costante, indica quanto 'ridimensionare' la variazione dei q futuri 

Algoritmo:
Finche la policy non converge:
   prossimo_stato   =  recupera_prossimo_stato(stato_corrente,azione_corrente)
   reward = recupera_reward(stato_corrente,azione_corrente)
   prossima_azione =  recupera_l_azione_col_q_maggiore(prossimo_stato)
   q[stato_corrente,azione_corrente] =  q[stato_corrente,azione_corrente] + alpha * ( reward +
                                        gamma * q[prossimo_stato,prossima_azione] -
                                        q[stato_corrente,azione_corrente])

   # se prossimo_stato è una stato terminale stato_corrente deve tornare ad
   # essere stato_iniziale a meno che la policy non si sia stabilizzata.
   stato_corrente = prossimo_stato
   azione_corrente = prossima_azione
end

</code></pre>
<p>Ho implementato questo algoritmo in Processing.org ma a differenza del post precedente non posso visualizzarlo nel browser in quanto computazionalmente è troppo impegnativo; potere comunque scaricarlo <a href="http://github.com/sandropaganotti/processing.org-q-learning-td-lambda-">dal mio accounti di GitHub.</a></p>
<div id="attachment_122" class="wp-caption aligncenter" style="width: 260px"><img src="http://sandropaganotti.com/wp-content/uploads/2009/01/ishot-88.png" alt="Q-learning in processing.org" title="ishot-88" width="250" height="272" class="size-full wp-image-122" /><p class="wp-caption-text">Q-learning in processing.org</p></div>
<p>Ecco la spiegazione del programma: il quadrato arancio è lo stato terminale, e frutta al nostro agente +1 di ricompensa, i bordi invece quando colpiti fruttano -1 (quindi l&#8217;agente tenderà ad evitarli). Dopo qualche minuto dovreste cominciare a notare dei cambiamenti di colore sulla griglia, le celle con q negativo tendono a colorarsi di blu  mentre quelle con q positivo tendono ad un viola molto acceso.</p>
<p>L&#8217;agente è rappresentato da un quadrato verde e viene disegnato con un scia al seguito; tale scia rappresenta (e lo vedremo meglio la prossima volta) il modo in cui la variazione di q si distribuisce sulle scelte precedenti.</p>
<p>Se avete la pazienza di attendere 5-6 minuti dovreste scorgere con chiarezza una specie di &#8216;percorso più chiaro&#8217;, rappresentato da tutte quelle celle che hanno un q positivo, che parte dallo stato iniziale e guida l&#8217;agente verso quello terminale.</p>
<p><a href="http://github.com/sandropaganotti/processing.org-q-learning-td-lambda-">Scarica Q-learning con Processing.org dal mio account di GitHub</a></p>
]]></content:encoded>
			<wfw:commentRss>http://sandropaganotti.com/2009/01/18/q-learning-con-processingorg/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Uno stormo con processing.org</title>
		<link>http://sandropaganotti.com/2009/01/01/uno-stormo-con-processing/</link>
		<comments>http://sandropaganotti.com/2009/01/01/uno-stormo-con-processing/#comments</comments>
		<pubDate>Thu, 01 Jan 2009 16:56:34 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Algoritmi]]></category>
		<category><![CDATA[Algoritmo]]></category>
		<category><![CDATA[Engine]]></category>
		<category><![CDATA[Flock]]></category>
		<category><![CDATA[Processing]]></category>
		<category><![CDATA[Simulazione]]></category>
		<category><![CDATA[Stormo]]></category>

		<guid isPermaLink="false">http://sandropaganotti.com/?p=83</guid>
		<description><![CDATA[Esiste molta letteratura sul problema di simulazione di uno stormo (detto anche Flocking), queste sono le tre regole principali a cui ogni partecipante allo stormo deve obbedire: muoversi verso il centro del gruppo; mantenere una distanza minima dagli altri; muoversi con una velocità simile alla velocità del gruppo; Sulla base di queste tre regole ho [...]]]></description>
			<content:encoded><![CDATA[<p>Esiste molta letteratura sul problema di simulazione di uno stormo (detto anche <a href="http://en.wikipedia.org/wiki/Flocking_(behavior)">Flocking</a>), queste sono le tre regole principali a cui ogni partecipante allo stormo deve obbedire:</p>
<p><span id="more-83"></span></p>
<ul>
<li>muoversi verso il centro del gruppo;</li>
<li>mantenere una distanza minima dagli altri;</li>
<li>muoversi con una velocità simile alla velocità del gruppo;</li>
</ul>
<p>Sulla base di queste tre regole ho sviluppato un piccolo programma in <a href="http://processing.org">Processing.org</a> che simula il modello comportamentale di un gruppo (mantenendo le tre leggi sopra descritte) in questi passi:</p>
<ul>
<li>per ogni elemento dello stormo viene generata una posizione iniziale random all&#8217;interno del canvas;</li>
<li>per ogni ciclo di ridisegno, per ogni elemento dello stormo:
<ul>
<li>recupero la velocità dell&#8217;elemento più vicino e la assegno (leggermente variata) all&#8217;elemento corrente;</li>
<li>trovo il centro dello stormo (e lo modifico con un pò di noise);</li>
<li>avvicino l&#8217;elemento corrente verso il centro dello stormo alla velocità precedentemente impostata &#8211; eseguo quest&#8217;ultima operazione solo se l&#8217;elemento nella nuova posizione non è troppo vicino a qualche altro elemento dello stormo;</li>
</ul>
</li>
</ul>
<p>A questo ho aggiunto la possibilità, usando i tasti W,S,A,D di spostare il centro dello stormo calcolato automaticamente e, in questo modo, pilotare l&#8217;intero stormo.</p>
<p>Come al solito il codice nella sua interezza è presente <a href="http://github.com/sandropaganotti/processing.org-flock">sul mio account di GitHub</a>, posso però in questa sede mostrarvi una demo di quanto creato grazie alla potentissima libreria <a href="http://ejohn.org/blog/processingjs/">Processing.js</a> regalataci da Jhon Resing che consente di eseguire script scritti per Processing.org all&#8217;interno di un elemento &#8216;CANVAS&#8217; del browser.</p>
<p>Questa libreria non è però al momento 100% cross-browser: io ho personalmente testato il tutto con la versione più aggiornata di Firefox (3.0.5) senza riscontrare nessuna perdità di funzionalità (funzionano anche i comandi da tastiera!); lo stesso però non posso garantire per altri browser.</p>
<p>Per provare il programma non vi resta che cliccare sul link sottostante; ricordate che potete direzionare lo stormo usando la vostra tastiera (tasti: WSAD).</p>
<p><a onclick="$('processing_canvas').show();Processing( $('processing_canvas'), $('processing').textContent ); return false;">Lancia la simulazione di stormo in Processing</a></p>
<p><canvas id="processing_canvas" style="display:none;"></canvas></p>
<pre style="display:none;"><code id="processing">

class Creature {
 int sng_x;
 int sng_y;
 float sng_x_speed;
 float sng_y_speed;

 Creature(){
   sng_x = 0;
   sng_y = 0;
   sng_x_speed = 0;
   sng_y_speed = 0;
 }

 float calc_dist(Creature k){
   return sqrt(pow(this.sng_x - k.sng_x,2) + pow(this.sng_y - k.sng_y,2));
 }
 void to_text(){
   println("X: " + sng_x + " Y: " + sng_y);
 }
}

int canvas_width  = 400;
int canvas_height = 400;
int min_separation = 15;
int circle_size = 5;
int num_sheep = 20;
int max_noise = 250;
int mint_follow_x = 0;
int mint_follow_y = 0;
int follow_amount = 100;
float max_speed_variance = 0.001;
float min_speed = 0.005;
float max_speed = 0.01;

Creature[] flock = new Creature[num_sheep]; 

void setup(){
  int i;
  int j;
  boolean bln_separation;
  size(canvas_width,canvas_height);

  for(int x=0; x < flock.length; x++){
    bln_separation = false;
    flock[x] = new Creature();
    while(!bln_separation){
      flock[x].sng_x = int(random(1,canvas_width));
      flock[x].sng_y = int(random(1,canvas_height));
      bln_separation = true;
      for(int y=0; y < x; y++){
        if(flock[x].calc_dist(flock[y]) <= min_separation){
          bln_separation = false;
          break;
        }
      }
    }
  }
}

void draw(){
  background(100);
  float sng_dist;
  float sng_x_speed = 0.0;
  float sng_y_speed = 0.0;
  int sng_x_sum;
  int sng_y_sum;
  float sng_x_avg;
  float sng_y_avg;
  float sng_x_dist;
  float sng_y_dist;
  int sng_tmp_x;
  int sng_tmp_y;

  for(int x=0; x < flock.length; x++){
    sng_dist = 0;
    for(int y=0; y < flock.length; y++){
      if(x!=y){
        if(sng_dist == 0.0 || flock[x].calc_dist(flock[y]) < sng_dist){
          sng_dist = flock[x].calc_dist(flock[y]);
          sng_x_speed = flock[y].sng_x_speed;
          sng_y_speed = flock[y].sng_y_speed;
        }
      }
    }

    flock[x].sng_x_speed = sng_x_speed + max_speed_variance;
    flock[x].sng_y_speed = sng_y_speed + max_speed_variance;
    if(flock[x].sng_x_speed < min_speed) flock[x].sng_x_speed = min_speed;
    if(flock[x].sng_y_speed < min_speed) flock[x].sng_y_speed = min_speed;
    if(flock[x].sng_x_speed > max_speed) flock[x].sng_x_speed = max_speed;
    if(flock[x].sng_y_speed > max_speed) flock[x].sng_y_speed = max_speed;

    sng_x_sum = 0;
    sng_y_sum = 0;
    for(int y=0; y < flock.length; y++){
      sng_x_sum = sng_x_sum + flock[y].sng_x;
      sng_y_sum = sng_y_sum + flock[y].sng_y;
    }

    sng_x_avg = float(sng_x_sum / num_sheep) + (random(1) * max_noise) - (max_noise / 2.0) + mint_follow_x;
    sng_y_avg = float(sng_y_sum / num_sheep) + (random(1) * max_noise) - (max_noise / 2.0) + mint_follow_y;  

    sng_tmp_x = flock[x].sng_x;
    sng_tmp_y = flock[x].sng_y;
    sng_x_dist = sng_x_avg - flock[x].sng_x;
    sng_y_dist = sng_y_avg - flock[x].sng_y;
    flock[x].sng_x = int(flock[x].sng_x + sng_x_dist * flock[x].sng_x_speed);
    flock[x].sng_y = int(flock[x].sng_y + sng_y_dist * flock[x].sng_y_speed);

    for(int y=0; y < flock.length; y++){
      if( x!=y &#038;&#038; flock[x].calc_dist(flock[y]) <= min_separation ){
        flock[x].sng_x = sng_tmp_x;
        flock[x].sng_y = sng_tmp_y;
        break;
      }
    }

    if(flock[x].sng_x > canvas_width) flock[x].sng_x = flock[x].sng_x - canvas_width;
    if(flock[x].sng_x < 0) flock[x].sng_x = flock[x].sng_x + canvas_width;
    if(flock[x].sng_y > canvas_height) flock[x].sng_y = flock[x].sng_y - canvas_height;
    if(flock[x].sng_y < 0) flock[x].sng_y = flock[x].sng_y + canvas_height;

     ellipse(flock[x].sng_x,flock[x].sng_y,circle_size,circle_size);
  }
}

void keyPressed() {
  if (key == 'w') mint_follow_y = mint_follow_y - follow_amount;
  if (key == 's') mint_follow_y = mint_follow_y + follow_amount;
  if (key == 'a') mint_follow_x = mint_follow_x - follow_amount;
  if (key == 'd') mint_follow_x = mint_follow_x + follow_amount;
}

</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://sandropaganotti.com/2009/01/01/uno-stormo-con-processing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
