// JavaScript Document

// Funzione che restituisce un numero casuale tra 0 e N
function getNumeroRandom( n )
{			
	// Funzione comune per la random ma non uniforme ( il primo e l'ultimo hanno meno probabilità di uscire )
	// return Math.round( Math.random() * n );

	// Versione ottimizzata ma con complessità maggiore
	// var temp = Math.round( Math.abs( Math.random() * (n + 1) - 0.5 )) ;	
	// return temp > n ? n : temp;
	
	// Versione ottimizzata e semplice
	return Math.floor( Math.random() * ( n + 0.99999999) );	
}

function preload(percorso)
{
	immaginiPreload[immaginiPreload.length] = new Image();
	immaginiPreload[immaginiPreload.length - 1].src = percorso;
}

// Funzione per l'inizializzazione del gioco
function inizializza()
{
	// Preload delle immagini
	
	preload("images/background.jpg");
	preload("images/vento-0.gif");
	preload("images/vento-1.gif");
	preload("images/vento+0.gif");
	preload("images/vento+1.gif");

	for (var c=0; c<COLORI.length; c++)
	{
		preload("images/" + COLORI[c] + ".gif");
		preload("images/" + COLORI[c] + "bum.gif");
		preload("images/" + COLORI[c] + "Loader.gif");
	}
	
	for (var i= -( NUMERO_IMMAGINI - 1 ) / 2; i<=( NUMERO_IMMAGINI - 1 ) / 2; i++)
	{
		preload("images/cannone" + i + ".gif");
	}
	
	// Prendo le informazioni sul campo di gioco
	divGioco = document.getElementById("gioco");
	LARGHEZZA_GIOCO = parseInt(divGioco.clientWidth);
	ALTEZZA_GIOCO = parseInt(divGioco.clientHeight);
	
	// Prendo le informazioni sul cannone
	divCannone = document.getElementById("cannone");
	PERNO_CANNONE_X = parseInt(divCannone.offsetLeft) + parseInt(divCannone.clientWidth) / 2;
	PERNO_CANNONE_Y = parseInt(divCannone.offsetTop) + parseInt(divCannone.clientHeight) - LARGHEZZA_CANNONE / 2;
	
	// Prendo le informazioni sul caricatore
	divCaricatore = document.getElementById("caricatore");
	POSIZIONE_CARICATORE_X = parseInt(divCaricatore.clientWidth) / 2;
	POSIZIONE_CARICATORE_Y = parseInt(divCaricatore.clientHeight) / 2;
	
	// Prendo il riferimento all'oggetto input per il punteggio e del pulsante per la pausa
	divMenu = document.getElementById("menu");
	inputPunteggio = document.getElementById("txtPunteggio");
	inputPalleResidue = document.getElementById("txtPalleResidue");
	picVento = document.getElementById("picVento");
	inputPausa = document.getElementById("inputPausa");
	inputRiavvia = document.getElementById("inputRiavvia");
	
	// Imposto il cannone in posizione verticale, il vento e il punteggio a 0.
	setAlpha(0);
	setVento(0);
	setPunteggio(0);
	
	creaProiettile();

	timerControlloPreload = setInterval("controlloPreload()", 200);
}

function controlloPreload()
{
	for ( var i = 0; i < immaginiPreload.length; i++ )
		if ( !immaginiPreload[i].complete ) return;
	
	divMenu.style.display = "block";
	clearInterval(timerControlloPreload);
	timerControlloPreload = null;
}

function getPosizioneBoccaCannoneX()
{
	// l'angolo del cannone dipende dalla variabile alpha secondo la seguente formula:
	var angolo = 90 - DELTA_ALPHA * alpha;
	var angoloRad = gradToRad(angolo);
	var ipotenusa = LUNGHEZZA_CANNONE - LARGHEZZA_CANNONE / 2.0;
	return ipotenusa * Math.cos(angoloRad) + PERNO_CANNONE_X;
}

function getPosizioneBoccaCannoneY()
{
	// l'angolo del cannone dipende dalla variabile alpha secondo la seguente formula:
	var angolo = 90 - DELTA_ALPHA * alpha;
	var angoloRad = gradToRad(angolo);
	var ipotenusa = LUNGHEZZA_CANNONE - LARGHEZZA_CANNONE / 2.0;
	return PERNO_CANNONE_Y - ipotenusa * Math.sin(angoloRad);
}

function gradToRad(gradi)
{
	return gradi * Math.PI / 180.0;
}

// Crea una nuova palla nel caricatore
function creaProiettile()
{
	if ( prossimaPalla == null )
	{
		prossimaPalla = new Palla( PALLA_PROIETTILE );
		
		if ( palle.length != 0 )
		{
			//var presenze = new Array(false, false, false, false);
			var presenze = 0;
		
			for (var i=0; i<palle.length; i++)
			{
				if ( palle[i].vy > 0 )
				{
					presenze = (1 << palle[i].colore) | presenze;
					if ( presenze == 15 ) break;
				}
			}
			
			if ( presenze > 0 )
			{
				while ( ((1<<prossimaPalla.colore)&(presenze)) == 0 )
				{
					prossimaPalla.estraiColore();
				}
			}
		}
		
		divCaricatore.style.backgroundImage = "url(images/" + COLORI[prossimaPalla.colore]  + "Loader.gif)";
		
	}
}

function sparaProiettile()
{
	if ( timerMovimento != null)
	{
		if ( palle.length > 0 )
		{
			if ( tempoTrascorso >= tempoMinimoDiAttesa )
			{
				tempoTrascorso = 0;
				// spostiamo la palla	
				prossimaPalla.setX( getPosizioneBoccaCannoneX() );
				prossimaPalla.setY( getPosizioneBoccaCannoneY() );
				
				var vel = getVelocitaDaPunteggio() * 10;
				
				var angolo = 90 - DELTA_ALPHA * alpha;
				var angoloRad = gradToRad(angolo);
				prossimaPalla.vx = vel * Math.cos(angoloRad);
				prossimaPalla.vy = -vel * Math.sin(angoloRad);
				
				divGioco.appendChild( prossimaPalla.ref );
				
				palle[palle.length] = prossimaPalla;
			
				prossimaPalla = null;	
				creaProiettile();
			}
		}
	}
}

function setAlpha(val)
{
	if ( val > (NUMERO_IMMAGINI-1)/2 ) val = (NUMERO_IMMAGINI-1)/2;
	if ( val < -(NUMERO_IMMAGINI-1)/2 ) val = -(NUMERO_IMMAGINI-1)/2;
	   
	alpha = val;
	divCannone.style.backgroundImage = "URL(images/cannone" + alpha + ".gif)";	
}

function setVento(val)
{
	if ( val > 1 ) val = 1;
	if ( val < -1 ) val = -1;

	var img = "";
	if ( (vento == 1) && (val == 0) )
		img = "+0";
	else if ( (vento == -1) && (val == 0) )
	{
		img = "-0";
	}
	else if ( val == 1 )
		img = "+1";
	else if ( val == -1 )
		img = "-1";

	vento = val;
	if ( img != "" )
		picVento.src = "images/vento" + img + ".gif";
	
	// Imposto la nuova velocità a tutte le palle di pioggia
	for ( var i = 0; i < palle.length; i++ )
	{
		if ( palle[i].vy > 0 ) palle[i].vx = vento;
	}
	controllaPalleAlBordo();	
}

function controllaPalleLibere()
{
	setVento(vento);
}

function controllaPalleAlBordo()
{
	// Controllo le palle di pioggia vicine ai bordi
	for ( var i = 0; i < palle.length; i++ )
	{
		if ( palle[i].vy > 0 )
		{
			if ( palle[i].x < RAGGIO ) 
			{
				if ( (palle[i].vy > 0) && ( vento < 0 ) )
				{
					palle[i].vx = 0;
					bloccaPalleVicine(palle[i]);
				}
			}
			if ( palle[i].x > LARGHEZZA_GIOCO - RAGGIO )
			{
				if ( (palle[i].vy > 0) && ( vento > 0 ) )
				{
					palle[i].vx = 0;
					bloccaPalleVicine(palle[i]);
				}
			}
		}
	}
}

function gestoreTimerVento()
{
	var probabilita = 0.6; // Probabilità associate al valore precedente
	var deltaVento;
	// estrae un deltaVento dando maggiore probabilità al precedente valore di deltaVento (ultimoDeltaVento)
	if ( ultimoDeltaVento == 0 )
	{
		deltaVento = getNumeroRandom(2) - 1; // Equiprobabile tra -1, 0 e 1
	}
	else
	{
		var rnd = Math.random();
		if ( rnd < probabilita )
		{
			deltaVento = ultimoDeltaVento;
		}
		else
		{
			do
			{
				deltaVento = getNumeroRandom(2) - 1; // Equiprobabile tra -1, 0 e 1
			} while (deltaVento == ultimoDeltaVento);
		}
	}

	setVento(vento + deltaVento);
	ultimoDeltaVento = deltaVento;
}

function riavvia()
{
	clearInterval(timerCreazione);
	clearInterval(timerMovimento);
	clearInterval(timerVento);
	clearInterval(timerMovimentoCannone);
	timerCreazione = null;
	timerMovimento = null;
	timerVento = null;
	timerMovimentoCannone = null;
	muoviDestra = false;
	muoviSinistra = false;
	if(timerIA != null)
	{
		clearInterval(timerIA);
		timerIA = null;
	}
	
	inputPausa.disabled = true;
	inputRiavvia.style.display = "none";
	divMenu.style.display = "block";
}

function iniziaPartita()
{
	pallePrese = 0;
	pallePerse = 0;
	setPunteggio(0);
	setVento(0);
	setAlpha(0);
	ultimoDeltaVento = 0;
	tempoTrascorso = tempoMinimoDiAttesa;
	
	// Elimino tutte le palle presenti sullo schermo
	while(palle.length > 0)
		eliminaPalla(palle[0]);
	
	// Imposto e attivo i vari timer di gioco
	gestoreTimerCreazione();
	timerCreazione = setInterval('gestoreTimerCreazione()', delayCreazione);	
	timerMovimento = setInterval('gestoreTimerMovimento()', delayMovimento);
	timerVento = setInterval('gestoreTimerVento()', delayVento);	 
	timerMovimentoCannone = setInterval('gestoreTimerMovimentoCannone()', delayMovimentoCannone);
	// Attivo il pulsante per la messa in pausa e la ripresa del gioco
	inputPausa.disabled = false;
	inputRiavvia.style.display = "inline";
	divMenu.style.display = "none";
}

function livello(valore)
{
	demo = false;
	if(valore<-2) valore = -2;
	if(valore > 3) valore = 3;
	delayCreazione = delayCreazioneBase - 500 * Math.round(valore);
	iniziaPartita();
}

function setPunteggio(val)
{
	punteggio = val;
	inputPunteggio.value = punteggio;
	inputPalleResidue.value = Math.round((-PUNTI_ESPLOSIONE_NEGATIVA/PUNTI_ESPLOSIONE_POSITIVA) * pallePerse
								+ PUNTEGGIO_MASSIMO / PUNTI_ESPLOSIONE_POSITIVA - pallePrese);
	var efficienza;
	if(pallePrese != 0)
		efficienza = Math.round(100.0 * (1.0 - 2 * pallePerse / pallePrese), 2);
	else
		efficienza = 0;
}

function getVelocitaDaPunteggio()
{
	var vel = (punteggio / 200) + 1;
	if ( (vel < 1) || ( delayCreazione == 3500 ) )
	  return 1;
	return vel;
}

function gestoreTimerMovimentoCannone()
{
	if(muoviDestra)
		setAlpha(alpha+1);
	else if(muoviSinistra)
		setAlpha(alpha-1);
}

function gestoreTimerCreazione()
{
	var nuovaPalla = new Palla( PALLA_PIOGGIA );
	nuovaPalla.vx = vento;
	nuovaPalla.vy = getVelocitaDaPunteggio();
	
	palle[palle.length] = nuovaPalla;
}

function collide(palla)
{
	for ( i = 0; i < palle.length; i++ )
	{
		if ( getDistanza(palla, palle[i]) <= 2*RAGGIO )	return true;
	}
	return false;
}

function getDistanza(p1, p2)
{
	return Math.sqrt( Math.pow(p1.x-p2.x, 2) + Math.pow(p1.y-p2.y, 2) );
}

function getDistanzaDaXY(x1, y1, x2, y2)
{
	return Math.sqrt( Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2) );
}

function incrementaPunteggio()
{
	pallePrese++;
	setPunteggio(punteggio+PUNTI_ESPLOSIONE_POSITIVA);
}

function decrementaPunteggio()
{
	pallePerse++;
	setPunteggio(punteggio+PUNTI_ESPLOSIONE_NEGATIVA);
}

function azzeraEsplosioni()
{
	palleDaEsplodere = new Array();
}

function preparaPerEsplosione(palla)
{
	for (var i = 0; i < palleDaEsplodere.length; i++)
	{
		if ( palleDaEsplodere[i] == palla ) return;
	}
	palleDaEsplodere[palleDaEsplodere.length] = palla;
}

function eliminaPalla(palla)
{
	var temp = new Array();
	
	for (var i=0; i<palle.length; i++)
	{
		if ( palle[i] != palla )
		{
			temp[temp.length] = palle[i];
		}
		else
		{
			for (var j = 0; j < divGioco.childNodes.length; j++)
			{
				if ( divGioco.childNodes[j] == palla.ref )
				{
					divGioco.removeChild(divGioco.childNodes[j]);
				}			
			}
		}
	}
	palle = temp;
}

function getTempName()
{
	var letters = new Array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
							'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
							'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6',
							'7', '8', '9', '0');
	var tempName = "";
	for ( var i = 0; i < 10; i++ )
		tempName += letters[ getNumeroRandom(letters.length - 1) ];
	return tempName;
}

function posizionaEsplosione(palla)
{
	var esplosione = new Image();
	esplosione.src = "images/" + COLORI[palla.colore] + "bum.gif";
	esplosione.style.left = palla.ref.style.left;
	esplosione.style.top = palla.ref.style.top;
	esplosione.className = "esplosione";
	var tempName = getTempName();
	esplosione.tempName = tempName;
	divGioco.appendChild(esplosione);
	setTimeout("eliminaEsplosione('" + tempName + "');", DURATA_ESPLOSIONE);
}

function eliminaEsplosione(nome)
{
	for (var i = 0; i < divGioco.childNodes.length; i++)
	{
		if ( divGioco.childNodes[i].tempName == nome )
		{
			divGioco.removeChild(divGioco.childNodes[i]);
			return;
		}			
	}	
}

function eseguiEsplosioni()
{
	for (var i = 0; i < palleDaEsplodere.length; i++)
	{
		posizionaEsplosione(palleDaEsplodere[i]);
		eliminaPalla(palleDaEsplodere[i]);
	}
}

function bloccaPalleVicine(palla)
{
	// Scorro il vettore delle palle per trovare le palle vicine
	for ( var i = 0; i < palle.length; i++)
	{
		// escludendo la palla stessa
		if ( palle[i] != palla )
		{
			// controllo se le 2 palle sono vicine
			if ( getDistanza( palle[i], palla ) <= 2*RAGGIO )
			{
				// Per evitare i cicli infiniti devo evitare di richiamare la funzione sulle palle già bloccate
				if ( (palle[i].vx != 0) )
				{
					// Blocco la palla trovata
					palle[i].vx = 0;
					bloccaPalleVicine(palle[i]);
				}
			}
		}
	}
}

function gestoreTimerMovimento()
{
	azzeraEsplosioni();
	
	tempoTrascorso += getVelocitaDaPunteggio();
	
	for (var i=0; i<palle.length; i++)
	{
		var futX = palle[i].x + palle[i].vx;
		var futY = palle[i].y + palle[i].vy;
		
		if ( futX < RAGGIO ) 
		{
			if ( palle[i].vy > 0 )
			{
				palle[i].vx = 0;
			}
			else
			{
				futX = RAGGIO;
				palle[i].vx = -palle[i].vx;
			}
		}
		if ( (futY < RAGGIO) && (palle[i].vy < 0)) 
		{
			// Un proiettile è arrivato in cima
			futY = RAGGIO;
			palle[i].vx = vento;
			palle[i].vy = getVelocitaDaPunteggio();
			palle[i].ref.className = "pallaPioggia";
		}
		if ( futX > LARGHEZZA_GIOCO - RAGGIO )
		{
			if ( palle[i].vy > 0 )
			{
				palle[i].vx = 0;
			}
			else
			{
				futX = LARGHEZZA_GIOCO - RAGGIO;
				palle[i].vx = -palle[i].vx;
			}
		}
		if ( futY > ALTEZZA_GIOCO - RAGGIO )
		{
			if ( palle[i].vy > 0 )
			{
				preparaPerEsplosione(palle[i]);
				decrementaPunteggio();
			}
		}
		
		palle[i].setX( futX );
		palle[i].setY( futY );
	}
		
	// Ciclo per rilevazione di collisioni
	for (var i=0; i<palle.length; i++)
	{
		for (var j=i+1; j<palle.length; j++)
		{
			//if ( i == j) continue;
			
			if ( getDistanza( palle[i], palle[j] ) <= 2*RAGGIO )
			{
				if ( palle[i].colore == palle[j].colore )
				{
					// I proiettili dello stesso colore esplodono tra di loro
					// per evitare catene lunghe di proiettili uguali che si trasformano in
					// palle di pioggia a contatto.
					preparaPerEsplosione(palle[i]);
					preparaPerEsplosione(palle[j]);
					if ( palle[i].vy * palle[j].vy < 0 )
					{

						// il punteggio aumenta solo se un proiettile incontra una palla di pioggia
						incrementaPunteggio();
						// Se in modalità demo, il tiro dell'IA è andato a buon fine, e si può riavviare il timer
						if(demo && (timerIA == null))
							timerIA = setInterval("intelligenzaArtificiale()", delayIA);
					}
				}
				else
				{
					// I proiettili si agganciano alla pioggia se di diverso colore, come anche la pioggia di diverso colore.
					//         Pioggia+Proiettile                         Pioggia+Pioggia
					if ( (palle[i].vy * palle[j].vy < 0) || ( (palle[i].vy > 0) && (palle[j].vy > 0) ) )
					{
						
						if ( palle[i].vy * palle[j].vy < 0 ) // Pioggia + Proiettile
						{
							var pallaPioggia = palle[i].vy > 0 ? palle[i] : palle[j];
							var pallaProiettile = palle[i].vy < 0 ? palle[i] : palle[j]; // Aggancio spostando il proiettile
						}
						else // Pioggia + Pioggia
						{
							var pallaPioggia = palle[i].vx == 0 ? palle[i] : palle[j];
							var pallaProiettile = palle[i].vx != 0 ? palle[i] : palle[j]; // Aggancio spostando la pioggia non appoggiata al bordo
						}
						// aggancio: il proiettile scende alla velocità della palla di pioggia
						pallaProiettile.vx = vento;
						pallaProiettile.vy = pallaPioggia.vy;
						
						// calcolo di quanto spostare il proiettile per agganciarlo alla palla pioggia
						var d;             // modulo vettore d
						var dx;            // d.x
						var dy;            // d.y
						var angoloRad;     // angolo acuto del vettore direzione
						var s;             // modulo del vettore spostamento
						var sx;            // s.x
						var sy;            // s.y
						
						dx = pallaPioggia.x - pallaProiettile.x;
						dy = pallaPioggia.y - pallaProiettile.y;
						d = getDistanza( pallaPioggia, pallaProiettile );
						s = 2.0 * RAGGIO - d;
						angoloRad = ( dx != 0) ? Math.atan( Math.abs( (dy * 1.0) / dx ) ) : Math.PI / 2.0;
						sx = s * Math.cos(angoloRad);
						sy = s * Math.sin(angoloRad);
						 
						pallaProiettile.setX( pallaProiettile.x + ((dx > 0) ? -sx : sx));
						pallaProiettile.setY( pallaProiettile.y + ((dy > 0) ? -sy : sy));
						pallaProiettile.ref.className = "pallaPioggia";
					}
					else
					{
						// i proiettili con diversi colori si attraversano
					}
										
				}
			}
		}
	}
	
	controllaPalleAlBordo();
	
	eseguiEsplosioni();
	
	controllaPalleLibere();

	// Controllo se hai perso la partita
	if ( punteggio <= PUNTEGGIO_MINIMO )
	{
		demo = false;
		clearInterval(timerCreazione);
		clearInterval(timerMovimento);
		clearInterval(timerVento);
		clearInterval(timerMovimentoCannone);
		timerCreazione = null;
		timerMovimento = null;
		timerVento = null;
		timerMovimentoCannone = null;
		if(timerIA != null)
		{
			clearInterval(timerIA);
			timerIA = null;
		}	
		
		inputPausa.disabled = true;
		
		alert("Mi dispiace. Hai perso!");

		inputRiavvia.style.display = "none";
		divMenu.style.display = "block";
	}
	
	if ( punteggio >= PUNTEGGIO_MASSIMO )
	{
		demo = false;
		clearInterval(timerCreazione);
		clearInterval(timerMovimento);
		clearInterval(timerVento);
		clearInterval(timerMovimentoCannone);
		timerCreazione = null;
		timerMovimento = null;
		timerVento = null;		
		timerMovimentoCannone = null;
		if(timerIA != null)
		{
			clearInterval(timerIA);
			timerIA = null;
		}
		
		inputPausa.disabled = true;
		var efficienza;
		if(pallePrese != 0)
			efficienza = Math.round(100.0 * (1.0 - 2 * pallePerse / pallePrese), 2);
		else
			efficienza = 0;
		alert("Complimenti, hai vinto!! Efficienza: " + efficienza + "%");
		
		inputRiavvia.style.display = "none";
		divMenu.style.display = "block";
	}
	
}

function tastieraUp(ev)
{
	switch ( ev.keyCode )
	{
		case LEFTARROW:
		case NUM_4:
			if ( timerMovimento != null)
			{
				muoviSinistra = false;
			}
			break;
		
		case NUM_6:
		case RIGHTARROW:			
			if ( timerMovimento != null)
			{
				muoviDestra = false;
			}
			break;
	}
}

function tastieraDown(ev)
{
	switch ( ev.keyCode )
	{
		case LEFTARROW:
		case NUM_4:
			if ( timerMovimento != null)
			{
				muoviDestra = false;
				muoviSinistra = true;
			}
			break;
		
		case NUM_6:
		case RIGHTARROW:			
			if ( timerMovimento != null)
			{
				muoviDestra = true;
				muoviSinistra = false;
			}
			break;
		
		case NUM_7:
		case LEFTUPARROW:
			if ( timerMovimento != null)
			{
				setAlpha(alpha-3);
			}
			break;
			
		case NUM_9:
		case RIGHTUPARROW:
			if ( timerMovimento != null)
			{
				setAlpha(alpha+3);
			}
			break;		

		case SPAZIO:
		case UPARROW:
		case NUM_8:
			sparaProiettile();
			break;

		case PAUSA:
			mettiInPausa();
			break;
	}
}

function mettiInPausa()
{
	if ( divMenu.style.display == "none" )
	{
		if ( timerMovimento == null )
		{
				timerCreazione = setInterval('gestoreTimerCreazione()', delayCreazione);	
				timerMovimento = setInterval('gestoreTimerMovimento()', delayMovimento);
				timerVento = setInterval('gestoreTimerVento()', delayVento);
				timerMovimentoCannone = setInterval('gestoreTimerMovimentoCannone()', delayMovimentoCannone);
				if(demo)
					timerIA = setInterval("intelligenzaArtificiale()", delayIA);
				inputPausa.value = "Pausa";
		}
		else
		{
			clearInterval(timerCreazione);
			clearInterval(timerMovimento);
			clearInterval(timerVento);
			clearInterval(timerMovimentoCannone);
			timerCreazione = null;
			timerMovimento = null;
			timerVento = null;
			timerMovimentoCannone = null;
			if(timerIA != null)
			{
				clearInterval(timerIA);
				timerIA = null;
			}
			inputPausa.value = "Riprendi";
		}
	}
	
	inputPausa.blur();
}

function startDemo(valore)
{
	livello(valore);
	demo = true;
	timerIA = setInterval("intelligenzaArtificiale()", delayIA);
}

function riabilitaDemo()
{
	if(demo && (timerIA == null))
		timerIA = setInterval("intelligenzaArtificiale()", delayIA);
}

function intelligenzaArtificiale()
{
	var precisione = 1.5;
	var attesa = true;
	var vel = getVelocitaDaPunteggio() * 10;			
	var angolo = 90 - DELTA_ALPHA * alpha;
	var angoloRad = gradToRad(angolo);
	var vx = vel * Math.cos(angoloRad);
	var vy = -vel * Math.sin(angoloRad);
	var x0 = getPosizioneBoccaCannoneX();
	var y0 = getPosizioneBoccaCannoneY();
	var x = x0;
	var y = y0;
	var esci = false;
	var collideInPosizioneCorrente = false;
	var colore = prossimaPalla.colore;
	var sponda = false;
	while( y>=0 )
	{
		// controllo la posizione attuale
		for(var i = 0; i < palle.length; i++)
		{
			if(getDistanzaDaXY(x, y, palle[i].x, palle[i].y) < precisione*RAGGIO)
			{
				// Un urto potrebbe verificarsi
				// in ogni caso, colore uguale o diverso, devo smettere di tentare questa direzione
				if((colore == palle[i].colore) && (palle[i].vy > 0))
				{
					// Urterei una palla pioggia del colore giusto
					sparaProiettile();
					
					if(sponda)
					{
						//document.title = "Colpisco la " + COLORI[palle[i].colore] + " di sponda";
					}
					if(attesa)
					{
						clearInterval(timerIA);
						timerIA = null;
						timeoutSicurezza = setTimeout("riabilitaDemo()", 1000);
					}
					return;
				}
				else
				{
					// La palla è un proiettile o una pioggia di altro colore.
					// smetto di testare le palle e le altre profondità
					esci = true;
					break;
				}
			}
		}
		if(esci)
		{
			break;
		}
		// Nessun urto, seguo la direzione data dalla velocità
		x += vx;
		y += vy;
		// Controlla anche le sponde
		if( (x >= LARGHEZZA_GIOCO) || (x <= 0) )
		{
			sponda = true;
			vx = -vx;
		}
	}
	if(!esci)
	{
		collideInPosizioneCorrente = false;
	}
	else
	{
		collideInPosizioneCorrente = true;
	}
	// In questa posizione non posso colpire una palla con il colore di quella nel caricatore.
	// Cerco una palla dello stesso colore
	var direzione;
	var trovata = false;
	if (alpha >= 0)
	{
		// Sono più vicino alle posizioni a destra, cerco prima a destra
		direzione = 1;
	}
	else
	{
		// Sono più vicino alle posizioni a sinistra, cerco prima a sinistra
		direzione = -1;
	}
	
	var alphaTmp;
	// Cerco i colpi diretti (hanno maggiore priorità rispetto alle sponde)
	for(var c = 0; c < 2; c++)
	{
		alphaTmp = alpha+direzione;
		while ( (alphaTmp <= (NUMERO_IMMAGINI-1)/2) && (alphaTmp >= -(NUMERO_IMMAGINI-1)/2) )
		{
			angolo = 90 - DELTA_ALPHA * alphaTmp;
			angoloRad = gradToRad(angolo);
			vx = vel * Math.cos(angoloRad);
			vy = -vel * Math.sin(angoloRad);
			x0 = getPosizioneBoccaCannoneX();
			y0 = getPosizioneBoccaCannoneY();
			x = x0;
			y = y0;
			esci = false;
			while( (x >= 0) && (y>=0) && (x<=LARGHEZZA_GIOCO) )
			{
				// controllo la posizione selezionata
				for(var i = 0; i < palle.length; i++)
				{
					if(getDistanzaDaXY(x, y, palle[i].x, palle[i].y) < precisione*RAGGIO)
					{
						// Un urto potrebbe verificarsi
						// in ogni caso, colore uguale o diverso, devo smettere di tentare questa direzione
						if((colore == palle[i].colore) && (palle[i].vy > 0))
						{
							// Urterei una palla pioggia del colore giusto
							if(Math.abs(alpha-alphaTmp)>=2)
								setAlpha(alpha + 2*direzione)
							else
								setAlpha(alpha + direzione);
							return;
						}
						else
						{
							// La palla è un proiettile o una pioggia di altro colore.
							// smetto di testare le palle e le altre profondità
							esci = true;
							break;
						}
					}
				}
				if(esci) break;
				// Nessun urto, seguo la direzione data dalla velocità
				x += vx;
				y += vy;
			}
			alphaTmp += direzione;
		}
		// Non sono riuscito a trovare nulla in quella direzione
		//cambio direzione e riparto
		direzione = -direzione;
	}
	
	// Provo di sponda
	for(var c = 0; c < 2; c++)
	{
		alphaTmp = alpha+direzione;
		while ( (alphaTmp <= (NUMERO_IMMAGINI-1)/2) && (alphaTmp >= -(NUMERO_IMMAGINI-1)/2) )
		{
			angolo = 90 - DELTA_ALPHA * alphaTmp;
			angoloRad = gradToRad(angolo);
			vx = vel * Math.cos(angoloRad);
			vy = -vel * Math.sin(angoloRad);
			x0 = getPosizioneBoccaCannoneX();
			y0 = getPosizioneBoccaCannoneY();
			x = x0;
			y = y0;
			esci = false;
			while( y>=0 )
			{
				// controllo la posizione selezionata
				for(var i = 0; i < palle.length; i++)
				{
					if(getDistanzaDaXY(x, y, palle[i].x, palle[i].y) < precisione*RAGGIO)
					{
						// Un urto potrebbe verificarsi
						// in ogni caso, colore uguale o diverso, devo smettere di tentare questa direzione
						if((colore == palle[i].colore) && (palle[i].vy > 0))
						{
							// Urterei una palla pioggia del colore giusto
							if(Math.abs(alpha-alphaTmp)>=2)
								setAlpha(alpha + 2*direzione)
							else
								setAlpha(alpha + direzione);
							return;
						}
						else
						{
							// La palla è un proiettile o una pioggia di altro colore.
							// smetto di testare le palle e le altre profondità
							esci = true;
							break;
						}
					}
				}
				if(esci) break;
				// Nessun urto, seguo la direzione data dalla velocità
				x += vx;
				y += vy;
				if( (x >= LARGHEZZA_GIOCO) || (x <= 0) )
					vx = -vx;
			}
			alphaTmp += direzione;
		}
		// Non sono riuscito a trovare nulla in quella direzione
		//cambio direzione e riparto
		direzione = -direzione;
	}
	// Non ho trovato nulla nè da una parte nè dall'altra, nè di sponda, butto la palla
	if((palle.length > 0) && !collideInPosizioneCorrente)
	{
		// Ho la linea libera
		if(alpha > (NUMERO_IMMAGINI-1)/4 -1)
		{
			// Mi posiziono in modo + centrale per evitare le sponde
			setAlpha(alpha - 1);
			return;
		}
		else if (alpha < -(NUMERO_IMMAGINI-1)/4 -1)
		{
			// Mi posiziono in modo + centrale per evitare le sponde
			setAlpha(alpha + 1);
			return;
		}
		sparaProiettile();
		if(attesa)
		{
			clearInterval(timerIA);
			timerIA = null;
			timeoutSicurezza = setTimeout("riabilitaDemo()", 300);
		}
	}
	else
	{
		
		// Cerco una linea vuota
		for(var a = -(NUMERO_IMMAGINI-1)/4 -1; a <= (NUMERO_IMMAGINI-1)/4 -1; a++)
		{
			var angolo = 90 - DELTA_ALPHA * a;
			var angoloRad = gradToRad(angolo);
			var vx = vel * Math.cos(angoloRad);
			var vy = -vel * Math.sin(angoloRad);
			var x0 = getPosizioneBoccaCannoneX();
			var y0 = getPosizioneBoccaCannoneY();
			var x = x0;
			var y = y0;
			var esci = false;
			var collideInPosizioneCorrente = false;
			var colore = prossimaPalla.colore;
			while( (x >= 0) && (y>=0) && (x<=LARGHEZZA_GIOCO) )
			{
				// controllo la posizione attuale
				for(var i = 0; i < palle.length; i++)
				{
					if(getDistanzaDaXY(x, y, palle[i].x, palle[i].y) < precisione*RAGGIO)
					{
						// Un urto potrebbe verificarsi
						// in ogni caso, colore uguale o diverso, devo smettere di tentare questa direzione
						esci = true;
						break;
					}
				}
				if(esci)
				{
					break;
				}
				// Nessun urto, seguo la direzione data dalla velocità
				x += vx;
				y += vy;
			}
			if(!esci)
			{
				// Ho trovato una linea libera
				if ( a < alpha )
					setAlpha(alpha-1);
				else
					setAlpha(alpha+1);
				return;
			}
		}
		// Non ho trovato nessuna linea libera
		sparaProiettile();
		if(attesa)
		{
			clearInterval(timerIA);
			timerIA = null;
			timeoutSicurezza = setTimeout("riabilitaDemo()", 300);
		}
	}
}