/*
 * Mind.java
 *
 * Created on 1 of February 2006, 2:06
 */

/**
 *
 * @author Paulo Roque Silva
 */

/**
 * 
	TouchSensor(SensorPort.S1);
	SoundSensor(SensorPort.S2);
	LightSensor(SensorPort.S3);
	UltrasonicSensor(SensorPort.S4);

	Motor.A  Left leg
	Motor.B  Right leg
 */

import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.BrokenBarrierException;
import icommand.nxt.comm.NXTCommand;
import icommand.nxt.LightSensor;
import icommand.nxt.SensorPort;
import icommand.nxt.TouchSensor;
import icommand.nxt.UltrasonicSensor;
import icommand.nxt.SoundSensor;
import icommand.nxt.Motor;
import javax.swing.*;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.Port;
import javax.sound.sampled.TargetDataLine;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Clip;
import javax.sound.sampled.AudioInputStream;
import java.io.*;

public class Mind extends Thread {
	static final int TimeSlize = 0;
					// Tempo (ms) intervalo entre passos
    final int       StartLocal  = 61;
    				// Local de come�o do C. Elegans
	static final int PROFOUNDITY = 6; // Profundidade Sleep
    Brain           brain; // Todo o c�rebro e c�rtex
// CONSTANTES DO CORPO
    private final int FeelWall20 = 20;
    				// Se inferior em cent�metros sente
    				// obst�culo
    static final int Power = 100; // Amplitude
    static final int BANDSROBOT = 7; // Bandas de som
    static final int BANDSNXT = 1; // Bandas de som
    final int		SAMPLE_RATE = 16000; // Amostragem som
    static final int TimeWait  = 64; // Tempo (ms) espera
 // VARI�VEIS DO CORPO
    public static Signal []Action; // A��o do rob�
    public static int Tact[], // Sentido Tacto do rob�
    				NStep; // N�mero passo do rob�
	public static boolean speak;
	int				bottom, // NXT
					ligth, // NXT
					ultraSonic, // NXT
					sound; // NXT
	TouchSensor		bottomN; // NXT
	LightSensor		ligthN; // NXT
	UltrasonicSensor ultraSonicN; // NXT
	SoundSensor     soundN; // NXT
	boolean			feelPain; // Se o rob� sente Dor
    int 			senteTaste[];
    int             senteVision[];
    int             senteTact[];
    int 			senteSound[];
    int 			senteSmell[];
    int             senteProSelf[]; // Propriocetivo
    int				tasteBefore[]; // Sensa��o anterior
    int				smellBefore[];
    int				soundBefore[];
    int				visionBefore[];
    int             tactBefore[];
    int				pleasurePS[], // N�vel de prazer
    				pleasureTa[],
    				pleasureTc[],
    				pleasureSm[],
    				pleasureSo[],
    				pleasureVi[];
    int				quantity[]; // N�vel de prazer
	int				m; // indexe
	int				profoundity; // indexe
    public static int Bom; // Para agir
    public static float	veloc; // Velocidade, 1- Normal
    
    CyclicBarrier   stepBarrierAct; // Barreiras
    CyclicBarrier   stepBarrierDecision;
    CyclicBarrier   stepBarrierDecision2;
    CyclicBarrier   stepBarrierPast;
    CyclicBarrier   stepBarrierCerebellum;
    CyclicBarrier   stepBarrierSleep;

// VARI�VEIS DA SIMULA��O
    int				i; // �ndexe
    boolean         pause; // Se para parar
	public static boolean OpenData; // Se dados antigos
    
    static int      local; // Actual local
	int				orient, // Orienta��o do C. Elegans
					wallOrLocal, // Local ou Parede
					tact, // Parede ou n�o
					nutrition, // Comida, �gua ou Terra
					vision, // Vis�o
					nStep; // Passo movimentado pelo rob�
    World           habitat; // Mundo do C. Elegans
    TargetDataLine  line; // Microfone
    AudioFormat		format; // Formato �udio
    int				numBytesRead;
    int				numBytesReadTotal;
    byte[]          data;
    DataLine.Info   info,
                    info2,
    				info3,
    				info4,
    				info5,
    				info6;
    AudioInputStream stream,
    				stream2,
    				stream3,
    				stream4,
					stream5;
    public static Clip clip,
    				clip2,
    				clip3,
    				clip4, // Rir
    				clip5; // Chorar
    /** Creates a new instance of Mind */
    public Mind(boolean od, JTextField txt) {
        
        System.out.println(
        	"VitaLiberu...by Paulo Roque Silva 2004-2026");
        brain        = new Brain(txt);
        Action      = new Signal[Brain.MOVES];
        for (int i=0; i < Action.length; i++)
            Action[i] = new Signal(i, 0, 0);
        if (Liberu.Robot == 0) {
            senteTaste  = new int[Brain.NanalogTaste];
            pleasureTa  = new int[Brain.NanalogTaste];
            tasteBefore = new int[Brain.NanalogTaste];
            senteVision = new int[Brain.NanalogVision];
            pleasureVi  = new int[Brain.NanalogVision];
            senteTact   = new int[Brain.NanalogTact];
            pleasureTc  = new int[Brain.NanalogTact];
            senteSound  = new int[Brain.NanalogSound];
            pleasureSo  = new int[Brain.NanalogSound];
            senteSmell  = new int[Brain.NanalogSmell];
            pleasureSm  = new int[Brain.NanalogSmell];
            Tact		= new int[Brain.NanalogTact];
            tactBefore	= new int[Brain.NanalogTact];
            visionBefore= new int[Brain.NanalogVision];
            smellBefore= new int[Brain.NanalogSmell];
            soundBefore= new int[Brain.NanalogSound];
            }
        if (Liberu.Robot == 1) {
            senteTaste  = new int[Brain.NanalogTasteR];
            pleasureTa  = new int[Brain.NanalogTasteR];
            tasteBefore = new int[Brain.NanalogTasteR];
            senteVision = new int[Brain.NanalogVisionR];
            pleasureVi  = new int[Brain.NanalogVisionR];
            senteTact   = new int[Brain.NanalogTactR];
            pleasureTc  = new int[Brain.NanalogTactR];
            senteSound  = new int[Brain.NanalogSoundR];
            pleasureSo  = new int[Brain.NanalogSoundR];
            senteSmell  = new int[Brain.NanalogSmellR];
            pleasureSm  = new int[Brain.NanalogSmellR];
            Tact		= new int[Brain.NanalogTactR];
            visionBefore= new int[Brain.NanalogVisionR];
            smellBefore= new int[Brain.NanalogSmellR];
            soundBefore= new int[Brain.NanalogSoundR];
        }
        if (Liberu.Robot == 2) {
            senteTaste  = new int[Brain.NanalogTasteN];
            pleasureTa  = new int[Brain.NanalogTasteN];
            tasteBefore = new int[Brain.NanalogTasteN];
            senteVision = new int[Brain.NanalogVisionN];
            pleasureVi  = new int[Brain.NanalogVisionN];
            senteTact   = new int[Brain.NanalogTactN];
            pleasureTc  = new int[Brain.NanalogTactN];
            senteSound  = new int[Brain.NanalogSoundN];
            pleasureSo  = new int[Brain.NanalogSoundN];
            senteSmell  = new int[Brain.NanalogSmellN];
            pleasureSm  = new int[Brain.NanalogSmellN];
            Tact		= new int[Brain.NanalogTactN];
            visionBefore= new int[Brain.NanalogVisionN];
            smellBefore= new int[Brain.NanalogSmellN];
            soundBefore= new int[Brain.NanalogSoundN];
        }
        senteProSelf= new int[Brain.NanalogProSelf];
        pleasurePS  = new int[Brain.NanalogProSelf];
        quantity    = new int[1];
        quantity[0] = 0;
        NStep       = 0;
        speak = false;
        pause 		= true;
    	for (i=0; i<tasteBefore.length; i++)
    		tasteBefore[i] = 0;
    	for (i=0; i<visionBefore.length; i++)
    		visionBefore[i] = 0;
    	for (i=0; i<smellBefore.length; i++)
    		smellBefore[i] = 0;
    	for (i=0; i<soundBefore.length; i++)
    		soundBefore[i] = 0;
        OpenData    = od;
        veloc 		= 1;
        habitat     = new World();
        local = StartLocal;
        orient = World.NORTH;
        tact        = Brain.NO_TACT;
        nutrition   = habitat.element(local);
        vision      = habitat.vision(local, orient);
        display(true, false);
    }
    
    public void step(boolean p) {
        
    	pause = p;
    }
    
    public static int getBom() {
        
        return Math.abs(Bom);
    }
    
    public static void setBom(int b) {
        
        Bom = b;
    }
    
    public void display(boolean ex, boolean w) {
    	
        Liberu.InterFace.displayRobot(brain, ex, w);
        Liberu.InterFace.saveValue(0, local);
        Liberu.InterFace.saveValue(1, tact);
        Liberu.InterFace.saveValue(2, nutrition);
        if (Liberu.Robot == 0)
            Liberu.InterFace.saveValue(3, senteTact[1]);
        Liberu.InterFace.saveValue(4, orient);
        Liberu.InterFace.saveValue(5, vision);

        for (i=0; i<Brain.ACTS; i++)
            if (Action[i].active)
            	Liberu.InterFace.saveValue(8+i, 1);
            else
            	Liberu.InterFace.saveValue(8+i, 0);
        Liberu.InterFace.repaint();
    }
        
    private void ouve() {
    	int n, m, // �ndexes
    		derivada, // Diferen�a no som
    		readBefore, 
    		bandBefore,
    		totalHits;
    	
    	numBytesReadTotal = 0;
    	line.flush();
    	readBefore = 0;
    	System.out.println("Ouvindo...");
    	while (numBytesReadTotal < SAMPLE_RATE * 2) {
    		// Tempo ouvindo
    		numBytesRead = line.read(data, 0, data.length);
    		numBytesReadTotal += numBytesRead;
    		for (n=0; n < numBytesRead; n++) {
    			derivada = Math.abs(data[n] - readBefore);
    			bandBefore = 0;
    			for (m=0; m < senteSound.length; m++) {
    				if (derivada >= bandBefore &&
    						derivada < (int)(32000 /
    								Math.pow(2, 
    								senteSound.length-1-m)/
    								Brain.MaxInSense)) {
    					senteSound[m] += 1;
    					bandBefore = (int)(32000 /
    							    Math.pow(2, 
    								senteSound.length-1-m)/
    							    Brain.MaxInSense);
    				}
    			}
    			readBefore = data[n];
    		}
    	}
		System.out.println("Surdo...");
		totalHits = 0;
		for (m=0; m < senteSound.length; m++)
			totalHits += senteSound[m];
		if (totalHits == 0) totalHits = 1;
		for (m=0; m < senteSound.length; m++)
			senteSound[m] = (int)(senteSound[m] *
					Brain.MaxInSense / totalHits);
		for (m=0; m < senteSound.length; m++)
	        Liberu.InterFace.saveValue(36+m,
	        		senteSound[m]);
    }

    private void actSimulation(float veloc) {
    	
    	speak = false;
		if (Action[Brain.Vogal1].active) {
			clip.setMicrosecondPosition(0);
			clip.start();
	        speak = true;
	        Cortex.nSpeaks += 1;
			senteProSelf[Brain.Vogal1] = Power;
    	}
		if (Action[Brain.Vogal2].active) {
			clip2.setMicrosecondPosition(0);
			clip2.start();
	        speak = true;
	        Cortex.nSpeaks += 1;
			senteProSelf[Brain.Vogal2] = Power;
		}
		if (Action[Brain.Vogal3].active) {
			clip3.setMicrosecondPosition(0);
			clip3.start();
	        speak = true;
	        Cortex.nSpeaks += 1;
			senteProSelf[Brain.Vogal3] = Power;
		}
    }
    
    private void actNXT(float veloc) {
    	
		if (Action[Brain.WALK].active ) {
			Motor.A.setSpeed((int)(veloc *
					(int)Action[Brain.WALK].actPower));
			// 900 = 100% power
			Motor.B.setSpeed((int)(veloc *
					(int)Action[Brain.WALK].actPower));
			// Graus por segundo
			Motor.A.forward();
			Motor.B.forward();
		}
		if ( Action[Brain.TURN_RIGHT].active) {
			Motor.A.setSpeed((int)(veloc *
					(int)Action[Brain.TURN_RIGHT].
					actPower));
			// 900 = 100% power
			Motor.B.setSpeed((int)(veloc *
					(int)Action[Brain.TURN_RIGHT].
					actPower));
			// Graus por segundo
			Motor.A.backward();
			Motor.B.forward();
		}
		if (Action[Brain.TURN_LEFT].active) {
			Motor.A.setSpeed((int)(veloc *
					(int)Action[Brain.TURN_LEFT].
					actPower));
			// 900 = 100% power
			Motor.B.setSpeed((int)(veloc *
					(int)Action[Brain.TURN_LEFT].
					actPower));
			// Graus por segundo
			Motor.A.forward();
			Motor.B.backward();
		}
		if (Action[Brain.EAT].active) {
			brain.decision.emotionSpeak();;
		}
    }
    
    private void actRobot(float veloc) {
    	
		if (Action[Brain.TURN_LEFT].active) {
    		try {
                Liberu.output.write((byte)112);
                Liberu.output.write('\n');
    		}
        	catch (Exception e) {
                System.err.println(e.toString());
        	}
    		try {
                Liberu.output.write((byte)116);
                Liberu.output.write('\n');
    		}
        	catch (Exception e) {
                System.err.println(e.toString());
        	}
		}
		if (Action[Brain.TURN_RIGHT].active) {
    		try {
                Liberu.output.write((byte)111);
                Liberu.output.write('\n');
    		}
        	catch (Exception e) {
                System.err.println(e.toString());
        	}
    		try {
                Liberu.output.write((byte)115);
                Liberu.output.write('\n');
    		}
        	catch (Exception e) {
                System.err.println(e.toString());
        	}
		}
		if (Action[Brain.WALK].active) {
    		try {
                Liberu.output.write((byte)111);
                Liberu.output.write('\n');
    		}
        	catch (Exception e) {
                System.err.println(e.toString());
        	}
    		try {
                Liberu.output.write((byte)116);
                Liberu.output.write('\n');
    		}
        	catch (Exception e) {
                System.err.println(e.toString());
        	}
		}
		if (Action[Brain.DRINK].active ||
				Action[Brain.EAT].active) {
    		try {
                Liberu.output.write((byte)113);
                Liberu.output.write('\n');
    		}
        	catch (Exception e) {
                System.err.println(e.toString());
        	}
		}
    }
    
    private void updateSensesNXT() { // Comandos NXT
    	int   m; // �ndexe

        // TACT
    	for (i=0; i<pleasureTc.length; i++)
    		pleasureTc[i] = 0;
    	Tact[0] = Brain.NO_TACT;
		feelPain = false;
		if (Brain.Energy)
			pleasureTc[0] = Power;
		if (bottomN.isPressed()) {
	    		feelPain = true;
	            Tact[0] = Brain.TACT;
	    		pleasureTc[0] = -Power;
	         	senteTact[0] = Power; // Sente tato
	    		if (brain.past.time[0][0].step >
	    		Emotions.ActRandom)
	    			brain.decision.emotionPAIN();
	    	}
	    	else
	         	senteTact[0] = (int)Power/2;
				// N�o sente tato

        // TASTE
    	for (i=0; i<pleasureTa.length; i++)
    		pleasureTa[i] = 0;
        senteTaste[0] = ligthN.getLightPercent();
        Interface.Taste[0] = senteTaste[0];
        if (NStep > 1) {
            if (Brain.BackHome)
                pleasureTa[0] = tasteBefore[0] -
                senteTaste[0];
            else
                pleasureTa[0] = senteTaste[0] -
                tasteBefore[0];
        }
    	
        // SOUND
    	for (i=0; i<pleasureSo.length; i++)
    		pleasureSo[i] = 0;
		System.out.println("Lisen..................:)");
		// REMOVER
		for (m=0; m < senteSound.length; m++) {
			senteSound[m] = soundN.getdB();
			Interface.Sound[m] = senteSound[m];
		}
        if (NStep > 1)
    		for (m=0; m < senteSound.length; m++) {
				pleasureSo[m] = senteSound[m] -
				soundBefore[m];
		}

		// SMELL
    	for (i=0; i<pleasureSm.length; i++)
    		pleasureSm[i] = 0;
        if (NStep > 1)
        	for (m=0; m < senteSmell.length; m++)
                pleasureSm[m] = senteSmell[m] -
                smellBefore[m]; // Melhor se brilhante

        // VISION
    	for (i=0; i<pleasureVi.length; i++)
    		pleasureVi[i] = 0;
		senteVision[0] = ultraSonicN.getDistance();
		for (m=0; m < senteVision.length; m++)
			Interface.Vision[m] = senteVision[m];
        if (NStep > 1)
        	for (m=0; m < senteVision.length; m++)
                pleasureVi[m] = visionBefore[m] -
                senteVision[m]; // Melhor se pr�ximo
    	if (senteVision[0] < FeelWall20 ) {
    		feelPain = true;
            Tact[0] = Brain.TACT;
         	senteTact[0] = Power; // Sente tato
    		pleasureTc[0] = -Power;
    		if (brain.past.time[0][0].step >
    		Emotions.ActRandom)
    			brain.decision.emotionPAIN();
    	}
    }

    private void updateSensesRobot() { // Comandos Formica
    	int   m, space;
    	String s;

    	for (m=0; m < senteVision.length; m++)
    		senteVision[m] = 0;
    	for (m=0; m < senteTact.length; m++)
    		senteTact[m] = 0;
    	for (m=0; m < senteSmell.length; m++)
    		senteSmell[m] = 0;
    	for (m=0; m < senteTaste.length; m++)
    		senteTaste[m] = 0;
    	for (m=0; m < senteSound.length; m++)
    		senteSound[m] = 0;
    	for (m=0; m < senteProSelf.length; m++)
    		senteProSelf[m] = 0;
        // TACT
    	s="";
    	for (i=0; i<pleasureTc.length; i++)
    		pleasureTc[i] = 0;
    	Tact[0] = Brain.NO_TACT;
		feelPain = false;
		try {
			if (brain.past.time[0][0].step == 0)
	            sleep(5000);
		}
    	catch (Exception e) {
            System.err.println(e.toString() + "Inicio");
    	}
		try {
            Liberu.output.write((byte)99);
            Liberu.output.write('\n');
            while (!Liberu.input.ready())
                sleep(1);
            s = Liberu.input.readLine();
		}
    	catch (Exception e) {
            System.err.println(e.toString() + "Tact");
    	}
		if (Brain.Energy)
			pleasureTc[0] = Power;
		if (s.length()>0) {
	    	if (s.contentEquals("1")) {
	    		feelPain = true;
	            Tact[0] = Brain.TACT;
	    		pleasureTc[0] = -Power;
	         	senteTact[0] = Power; // Sente tato
	    		if (brain.past.time[0][0].step >
	    		Emotions.ActRandom)
	    			brain.decision.emotionPAIN();
	    	}
	    	else
	         	senteTact[0] = (int)Power/2;
	    	// N�o Sente tato
		}

        // TASTE
    	for (i=0; i<pleasureTa.length; i++)
    		pleasureTa[i] = 0;
    	s = "";
		try {
			Liberu.output.write((byte)100);
            Liberu.output.write('\n');
            while (!Liberu.input.ready())
                sleep(1);
            s = Liberu.input.readLine();
		}
    	catch (Exception e) {
            System.err.println(e.toString() + "Taste");
    	}
		if (s.length()>0)
	        senteTaste[0] = Integer.parseInt(s);
        Interface.Taste[0] = senteTaste[0];
        if (NStep > 1) {
            if (Brain.BackHome)
                pleasureTa[0] = tasteBefore[0] -
                senteTaste[0];
            else
                pleasureTa[0] = senteTaste[0] -
                tasteBefore[0];
        }
        
        // SOUND
    	for (i=0; i<pleasureSo.length; i++)
    		pleasureSo[i] = 0;
		System.out.println("Lisen..................:)");
		// REMOVER
		s = "";
		try {
            Liberu.output.write((byte)103);
            Liberu.output.write('\n');
            while (!Liberu.input.ready())
                sleep(1);
            s = Liberu.input.readLine();
		}
    	catch (Exception e) {
            System.err.println(e.toString() + "Sound");
    	}
		space=0;
		for (m=0; m < senteSound.length; m++) {
			if (s.length()>0) {
				space = s.indexOf(' ');
				senteSound[m] =
						Integer.parseInt(s.substring(0,
								space));
				s = s.substring(space+1, s.length());
			}
			Interface.Sound[m] = senteSound[m];
		}
        if (NStep > 1)
    		for (m=0; m < senteSound.length; m++)
				pleasureSo[m] = senteSound[m] -
				soundBefore[m];

		// SMELL
    	for (i=0; i<pleasureSm.length; i++)
    		pleasureSm[i] = 0;
		s = "";
		try {
            Liberu.output.write((byte)98);
            Liberu.output.write('\n');
            while (!Liberu.input.ready())
                sleep(1);
            s = Liberu.input.readLine();
		}
    	catch (Exception e) {
            System.err.println(e.toString() + "Smell");
    	}
		space=0;
		for (m=0; m < senteSmell.length; m++) {
			if (s.length()>0) {
				space = s.indexOf(' ');
				senteSmell[m] = Integer.parseInt(
						s.substring(0, space));
				s = s.substring(space+1, s.length());
			}
			Interface.Smell[m] = senteSmell[m];
		}
        if (NStep > 1)
        	for (m=0; m < senteSmell.length; m++)
                pleasureSm[m] = senteSmell[m] -
                smellBefore[m]; // Melhor se brilhante

        // VISION
    	for (i=0; i<pleasureVi.length; i++)
    		pleasureVi[i] = 0;
		s = "";
		try {
            Liberu.output.write((byte)101);
            Liberu.output.write('\n');
            while (!Liberu.input.ready())
                sleep(1);
            s = Liberu.input.readLine();
		}
    	catch (Exception e) {
            System.err.println(e.toString() + "VisionD");
    	}
		if (s.length()>0)
			senteVision[0] = Integer.parseInt(s);
		s = "";
		try {
            Liberu.output.write((byte)102);
            Liberu.output.write('\n');
            while (!Liberu.input.ready())
                sleep(1);
            s = Liberu.input.readLine();
		}
    	catch (Exception e) {
            System.err.println(e.toString() + "VisionE");
    	}
		if (s.length()>0)
			senteVision[1] = Integer.parseInt(s);
		for (m=0; m < senteVision.length; m++)
			Interface.Vision[m] = senteVision[m];
        if (NStep > 1)
        	for (m=0; m < senteVision.length; m++)
                pleasureVi[m] = visionBefore[m] -
                senteVision[m]; // Melhor se pr�ximo
    	if (senteVision[0] < FeelWall20 || senteVision[1] <
    			FeelWall20) {
    		feelPain = true;
            Tact[0] = Brain.TACT;
         	senteTact[0] = Power; // Sente tato
    		pleasureTc[0] = -Power;
    		if (brain.past.time[0][0].step >
    		Emotions.ActRandom)
    			brain.decision.emotionPAIN();
    	}

		if (Action[Brain.DRINK].active)
			senteProSelf[Brain.DRINK] = Power;
		if (Action[Brain.EAT].active)
			senteProSelf[Brain.EAT] = Power;
		if (Action[Brain.WALK].active)
			senteProSelf[Brain.WALK] = Power;
		if (Action[Brain.TURN_LEFT].active)
			senteProSelf[Brain.TURN_LEFT] = Power;
		if (Action[Brain.TURN_RIGHT].active)
			senteProSelf[Brain.TURN_RIGHT] = Power;
		if (Action[Brain.Motive].active)
			senteProSelf[Brain.Motive] = Power;
    }

    private void updateSenses() { // Comandos C.Elegants
    	int m, temp;
    	
    	for (m=0; m < senteVision.length; m++)
    		senteVision[m] = 0;
    	for (m=0; m < senteTact.length; m++)
    		senteTact[m] = 0;
    	for (m=0; m < senteSmell.length; m++)
    		senteSmell[m] = 0;
    	for (m=0; m < senteTaste.length; m++)
    		senteTaste[m] = 0;
    	for (m=0; m < senteSound.length; m++)
    		senteSound[m] = 0;
    	for (m=0; m < senteProSelf.length; m++)
    		senteProSelf[m] = 0;
    	// OUVE  	
    	for (i=0; i<pleasureSo.length; i++)
    		pleasureSo[i] = 0;
		System.out.println("Lisen..................:)");
		// REMOVER
    	ouve();
        if (NStep > 1)
    		for (m=0; m < senteSound.length; m++)
				pleasureSo[m] = senteSound[m] -
				soundBefore[m];

    	if (Action[Brain.TURN_RIGHT].active &&
    			Action[Brain.TURN_LEFT].active)
    	 	   ;
    	 	else {
    	    	if (Action[Brain.TURN_LEFT].active)
    	            orient = habitat.orientate(orient,
    	            		Brain.TURN_LEFT);
    	        if (Action[Brain.TURN_RIGHT].active)
    	            orient = habitat.orientate(orient,
    	            		Brain.TURN_RIGHT);
    	 	}
        
        // TACT
    	for (i=0; i<pleasureTc.length; i++)
    		pleasureTc[i] = 0;
    	Tact[0] = Brain.NO_TACT;
		feelPain = false;
        tact = Brain.NO_TACT;
        if (Action[Brain.WALK].active) {
            wallOrLocal = habitat.move(local, orient);
            if (wallOrLocal != World.WALL) {
                local = wallOrLocal; // Novo local
	         	senteTact[0] = (int)Power/2;
	         	// N�o sente tato
            }
            else {
                tact = Brain.TACT; // Sente obst�culo
             	senteTact[0] = Power; // Sente tato
        		if (brain.past.time[0][0].step >
        		Emotions.ActRandom) {
        			feelPain = true;
        	        Tact[0] = Brain.TACT;
        			pleasureTc[0] = -Power;
        	     	senteTact[0] = Power; // Sente tato
        			if (brain.past.time[0][0].step >
        			Emotions.ActRandom)
        				brain.decision.emotionPAIN();
        		}
            }
        }
		if (Brain.Energy)
			pleasureTc[0] += Power;

		nutrition = habitat.element(local);
        vision = habitat.vision(local, orient);

        if (vision == World.WALL)
        	senteTact[1] = (int)Power/2;
        else
        	senteTact[1] = Power;
        
        if (NStep > 1)
        	for (m=0; m < senteTact.length; m++)
                pleasureTc[m] = senteTact[m] -
                tactBefore[m]; // Melhor se distante
        
        temp = orient;
        
        // TASTE
    	for (i=0; i<pleasureTa.length; i++)
    		pleasureTa[i] = 0;

    	senteTaste[nutrition-1] = Power;

        if (Action[Brain.EAT].active &&
        		nutrition != World.FOOD) {
			feelPain = true;
			if (brain.past.time[0][0].step >
			Emotions.ActRandom)
				brain.decision.emotionPAIN();
        }

        if (Action[Brain.DRINK].active &&
        		nutrition != World.WATER) {
			feelPain = true;
			if (brain.past.time[0][0].step >
			Emotions.ActRandom)
				brain.decision.emotionPAIN();
        }

    	for (m=0; m < senteTaste.length; m++)
            if (NStep > 1) {
                if (Brain.BackHome)
                    pleasureTa[m] = (senteTaste[m] -
                    		tasteBefore[m]) * 5;
                else
                    pleasureTa[m] = (tasteBefore[m] -
                    		senteTaste[m] * 5);
            }
    	
		// SMELL
    	for (i=0; i<pleasureSm.length; i++)
    		pleasureSm[i] = 0;
     	senteSmell[local-1] = Power;
        pleasureSm[0] = local * 5;

        // VISION
    	for (i=0; i<pleasureVi.length; i++)
    		pleasureVi[i] = 0;
        temp = habitat.orientate(orient, Brain.TURN_LEFT);
        senteVision[0] = habitat.vision(local, temp);
        temp = habitat.orientate(orient, Brain.TURN_RIGHT);
        senteVision[2] = habitat.vision(local, temp);
     	senteVision[1] = vision;
		for (m=0; m < senteVision.length; m++)
			Interface.Vision[m] = senteVision[m];
        if (NStep > 1)
        	for (m=0; m < senteVision.length; m++)
                pleasureVi[m] = (visionBefore[m] -
                		senteVision[m]) * 5;
        
        // PROPRIOCETIVO
		if (Action[Brain.DRINK].active)
			senteProSelf[Brain.DRINK] = Power;
		if (Action[Brain.EAT].active)
			senteProSelf[Brain.EAT] = Power;
		if (Action[Brain.WALK].active)
			senteProSelf[Brain.WALK] = Power;
		if (Action[Brain.TURN_LEFT].active)
			senteProSelf[Brain.TURN_LEFT] = Power;
		if (Action[Brain.TURN_RIGHT].active)
			senteProSelf[Brain.TURN_RIGHT] = Power;
		if (Action[Brain.Motive].active)
			senteProSelf[Brain.Motive] = Power;
		
    }
    
    private void senseProSelfNXT() {
    	
		// PROPRIOCETIVO
    	for (i=0; i<pleasurePS.length; i++)
    		pleasurePS[i] = 0;
        pleasurePS[0] = brain.proSelfNXT(senteProSelf,
        		ligthN, Power); // Atualiza propriocetivo
        brain.motivationNXT(senteProSelf, Power);
        // Motiva��o NXT
        if (feelPain)
        	pleasurePS[0] += -Power;
        brain.feelProSelf(senteProSelf, pleasurePS);

    	for (m=0; m < senteProSelf.length; m++)
    		senteProSelf[m] = 0;
    }

    private void senseProSelfRobot() {
    	
		// PROPRIOCETIVO
    	for (i=0; i<pleasurePS.length; i++)
    		pleasurePS[i] = 0;
        pleasurePS[0] = brain.proSelfRobot(senteProSelf,
        		Power); // Atualiza propriocetivo
        brain.motivationNXT(senteProSelf, Power);
        // Motiva��o
        if (feelPain)
        	pleasurePS[0] += -Power;
        brain.feelProSelf(senteProSelf, pleasurePS);
    }

    private void senseProSelf() {
    	
		// PROPRIOCETIVO
    	for (i=0; i<pleasurePS.length; i++)
    		pleasurePS[i] = 0;
        pleasurePS[0] = brain.proSelf(senteProSelf,
        		senteTaste, Power);
        // Atualiza propriocetivo
        brain.motivationNXT(senteProSelf, Power);
        // Motiva��o
        if (feelPain)
        	pleasurePS[0] += -Power;
        brain.feelProSelf(senteProSelf, pleasurePS);
    }
    
    public void Sono() {
    	
        // Sleep in action ********************************
		Brain.Ansiedade = false;
		Brain.Saudade = false;
        brain.clearBusSleepPreviews();
        brain.clearBusSleepPreviews2();
		setBom(Math.abs(Emotions.Good));
		Brain.Best = brain.past.time[getBom()]
				[Brain.ProSelf].finalQuality;
		Brain.BusSleepPreviews.add(new Signal(Bom,Bom,
				brain.past.time[getBom()][Brain.ProSelf].
				finalQuality));
    	for (i=0; i<brain.past.time[getBom()][0].
    			learn.size(); i++)
    		Brain.BusSleepPreviews2.add(new Signal(
    				brain.past.time[getBom()][0].
    				getLearn(i).emitter,
    				brain.past.time[getBom()][0].
    				getLearn(i).emitter,
    				brain.past.time[getBom()]
    						[Brain.ProSelf].finalQuality));
		profoundity = 0;
		while (profoundity < PROFOUNDITY) {
			brain.pollSleepOut();
			brain.pollSleepOut2();
	        try {
	            stepBarrierSleep.await(); // In�cio Sleep 
	            while (stepBarrierSleep.
	            		getNumberWaiting() <
	            		stepBarrierSleep.getParties() - 1)
	                sleep(TimeWait);
	        }
	        catch (InterruptedException ex) { 
	        }
	        catch (BrokenBarrierException ex) { 
            }
			profoundity += 1;

	        brain.decide(profoundity);

			brain.transferOutIn();
			
			
			System.out.println("SONO acting...");
			// REMOVER
			brain.decide2(profoundity);

			brain.transferOutIn2();
		}
		if (Brain.Ansiedade || Brain.Saudade)
			brain.past.time[brain.past.time[0][0].pointer]
					[Brain.ProSelf].setFinalQuality(
							Brain.Best);

		Cortex.exec = Bom;
    	System.out.print("Bom= "); //REMOVER
    	System.out.println(Bom); //REMOVER
   }

    private void runStepBrain() {
    	int i;
    	
        // COME�A O CICLO
        NStep = brain.addStep();
        System.out.print("Passo = "); // REMOVER
        System.out.println(NStep); // REMOVER
    	if (brain.past.time[0][0].step == 0)
    		brain.past.time[0][0].standby2 = true;
        
    	// Come�a o passo de vida do rob�
        if (Liberu.Robot == 0)
            updateSenses();
        if (Liberu.Robot == 1)
            updateSensesRobot();
        if (Liberu.Robot == 2)
            updateSensesNXT();
        brain.clearBusesIn(true);
		brain.feelSound(senteSound, pleasureSo); // Sente
        brain.feelTaste(senteTaste, pleasureTa); 
		brain.feelSmell(senteSmell, pleasureSm);
        brain.feelVision(senteVision, pleasureVi);
        brain.feelTact(senteTact, pleasureTc);
        if (Liberu.Robot == 0)
            senseProSelf();
        if (Liberu.Robot == 1)
            senseProSelfRobot();
        if (Liberu.Robot == 2)
            senseProSelfNXT();

    	for (m=0; m < senteVision.length; m++)
    		visionBefore[m] = senteVision[m];
    	for (m=0; m < senteSmell.length; m++)
    		smellBefore[m] = senteSmell[m];
    	for (m=0; m < senteSound.length; m++)
    		soundBefore[m] = senteSound[m];
    	for (m=0; m < senteTaste.length; m++)
    		tasteBefore[m] = senteTaste[m];
    	for (m=0; m < senteTact.length; m++)
    		tactBefore[m] = senteTact[m];

        display(true, false); // Mostra ecr�

        // Fim do tempo real

        for (i=0; i<Action.length; i++)	{ // reset actions
            Action[i].setActive(false);
            Action[i].setActPower(0);
            Action[i].setPleasure(0);
        }

        Remember.Lovely = 0;
        Interface.Lovely = 0;
    	Remember.RecentMost = 0;
		Remember.threshold = 0;
        for (i=0; i<Brain.SENSES; i++)
        	Remember.NewSense[i] = true;
    	// Remember em a��o ****************************
        try {
            stepBarrierPast.await(); // Sincroniza
            while (stepBarrierPast.getNumberWaiting() <
            		stepBarrierPast.getParties() - 1)
                sleep(TimeWait);
        }
        catch (InterruptedException ex) { 
            return;
        }
        catch (BrokenBarrierException ex) { 
            return;
            }
		System.out.println("Past Remember..."); // REMOVER
		Emotions.Good = Remember.RecentMost;
    	brain.clearBusSleepPreviews();
    	brain.clearBusSleepPreviews2();
        // Emotions em a��o ***************************
        try {
            stepBarrierDecision.await(); // Sincroniza 
            while (stepBarrierDecision2.
            		getNumberWaiting() <
            		stepBarrierDecision2.getParties() - 1)
                sleep(TimeWait);
        }
        catch (InterruptedException ex) { 
            return;
        }
        catch (BrokenBarrierException ex) { 
            return;
            }
		System.out.println("Emotions acted..."); // REMOVER
    	System.out.print("recent= "); //REMOVER
    	System.out.println(Remember.RecentMost); //REMOVER
        display(true, false); // shows in screen
		if (!Emotions.ActualPain && Emotions.IdAct1 ==
				Cerebellum.ESCape) {
			brain.past.time[Math.abs(Cortex.
					lastExec)][0].standby2 =
					true;
	    	System.out.println(Cortex.lastExec);
	    	//REMOVER
    		Cortex.lastExec = Cortex.exec;
		}
		if (Emotions.Good >= 0 && Emotions.IdAct1 ==
				Cerebellum.ESCape)
	        // Sleep em ação ***************************
			Sono();
    	System.out.print("exec= "); //REMOVER
    	System.out.println(Cortex.exec); //REMOVER
		// Cerebellum em a��o *************************
        try {
            stepBarrierCerebellum.await(); // Sincroniza
            while (stepBarrierCerebellum.
            		getNumberWaiting() <
            		stepBarrierCerebellum.getParties() - 1)
                sleep(TimeWait);
        }
        catch (InterruptedException ex) { 
            return;
        }
        catch (BrokenBarrierException ex) { 
            return;
            }
		System.out.println("Cerebellum acted...");
		// REMOVER
        // Act em a��o ********************************
        try {
            stepBarrierAct.await(); // Sincroniza 
            while (stepBarrierAct.getNumberWaiting() <
            		stepBarrierAct.getParties() - 1)
                sleep(TimeWait);
        }
        catch (InterruptedException ex) { 
            return;
        }
        catch (BrokenBarrierException ex) { 
            return;
            }
		System.out.println("Acting Nodes..."); // REMOVER
        // Emotions parte 2 em a��o *******************
        try {
            stepBarrierDecision2.await(); // Sincroniza
            while (stepBarrierDecision.getNumberWaiting() <
            		stepBarrierDecision.getParties() - 1)
                sleep(TimeWait);
        }
        catch (InterruptedException ex) { 
            return;
        }
        catch (BrokenBarrierException ex) { 
            return;
            }
		System.out.println("Decision 2 acted...");
		// REMOVER
        
        // Come�o do tempo real
		brain.act(Action); // Rob� age
        if (Liberu.Robot == 0)
            actSimulation(veloc);
        if (Liberu.Robot == 1)
            actRobot(veloc);
        if (Liberu.Robot == 2)
            actNXT(veloc);
        display(true, Cortex.Warn); // Mostra ecr�
        veloc = 1;
        // Fim do passo de vida do rob�
    }

    public void continueRun() {
        
        System.out.println("Continue...");
        pause = false;
    }
    
    public void pause() {
        
        System.out.println("Pause...");
        pause = true;
    }
    
    public void setToEnd() {
        
    	stepBarrierAct.reset();
    	stepBarrierDecision.reset();
    	stepBarrierDecision2.reset();
    	stepBarrierPast.reset();
    	stepBarrierCerebellum.reset();
    	stepBarrierSleep.reset();
		if (Liberu.Robot == 1) {
    		try {
                Liberu.output.write((byte)113);
                Liberu.output.write('\n');
    		}
        	catch (Exception e) {
                System.err.println(e.toString());
        	}
		}
        if (Liberu.Robot == 2) {
        	Motor.A.stop();
			Motor.B.stop();
        }
    }
    
    public void run() {
        
        if (Liberu.Robot == 2) {
        	NXTCommand.open();
    		bottomN = new TouchSensor(SensorPort.S1);
    		ligthN = new LightSensor(SensorPort.S3);
    		ultraSonicN = new UltrasonicSensor(
    				SensorPort.S4);
    		soundN = new SoundSensor(SensorPort.S2);

    		Motor.A.setSpeed(150); // 900 = 100% power
    		Motor.B.setSpeed(150); // Graus por segundo
        }
    	if (!OpenData)
    		brain.past.bornTime();
    	
        if (Liberu.Robot != 2)
			bottom = Brain.NO_TACT;
		ligth = 0;
        if (Liberu.Robot == 2)
        	ligthN = new LightSensor(SensorPort.S3);
		ultraSonic = vision;
		sound = 0;

        if (Liberu.Robot == 2) {
        	Motor.A.setSpeed(150); // 900 = 100% power
        	Motor.B.setSpeed(150); // Graus por segundo
        }

		format = new AudioFormat(Encoding.PCM_SIGNED,
				SAMPLE_RATE, 8, 1, 1, SAMPLE_RATE, true);
    	info = new DataLine.Info(TargetDataLine.class,
    			format);
    	if (AudioSystem.isLineSupported(
    			Port.Info.MICROPHONE)) {
    		try {
    			line = (TargetDataLine)AudioSystem.
    					getLine(info);
    	    	line.open(format);
    	    	data = new byte[line.getBufferSize()/5];
    	    	line.start();
    			System.out.print("microfone...");
    			System.out.println(line.getBufferSize());
    		}
    		catch (LineUnavailableException ex) {
    			System.out.println("Sem microfone...");
    		}
    	}
    	else
			System.out.println("Sem microfone......");
    	if (AudioSystem.isLineSupported(
    			Port.Info.SPEAKER)) {
        	try {
            	stream = AudioSystem.getAudioInputStream(
            			new File("audiofile1nxt.wav"));
            	stream2 = AudioSystem.getAudioInputStream(
            			new File("audiofile2nxt.wav"));
            	stream3 = AudioSystem.getAudioInputStream(
            			new File("audiofile3nxt.wav"));
            	stream4 = AudioSystem.getAudioInputStream(
            			new File("Rir.wav"));
            	stream5 = AudioSystem.getAudioInputStream(
            			new File("Choro.wav"));
        	}
        	catch (IOException e) {
                e.printStackTrace();
            }
           	catch (UnsupportedAudioFileException e) {
                e.printStackTrace();
            }
            AudioFormat format = stream.getFormat();
            info2 = new DataLine.Info(Clip.class,
            		stream.getFormat(),
                    ((int) stream.getFrameLength() *
                    		format.getFrameSize()));
            info3 = new DataLine.Info(Clip.class,
            		stream2.getFormat(),
                    ((int) stream2.getFrameLength() *
                    		format.getFrameSize()));
            info4 = new DataLine.Info(Clip.class,
            		stream3.getFormat(),
                    ((int) stream3.getFrameLength() *
                    		format.getFrameSize()));
            info5 = new DataLine.Info(Clip.class,
            		stream4.getFormat(),
                    ((int) stream4.getFrameLength() *
                    		format.getFrameSize()));
            info6 = new DataLine.Info(Clip.class,
            		stream5.getFormat(),
                    ((int) stream5.getFrameLength() *
                    		format.getFrameSize()));
    		try {
                clip = (Clip) AudioSystem.getLine(info2);
                clip.open(stream);
                clip2 = (Clip) AudioSystem.getLine(info3);
                clip2.open(stream2);
                clip3 = (Clip) AudioSystem.getLine(info4);
                clip3.open(stream3);
                clip4 = (Clip) AudioSystem.getLine(info5);
                clip4.open(stream4);
                clip5 = (Clip) AudioSystem.getLine(info6);
                clip5.open(stream5);
    		}
    		catch (LineUnavailableException ex) {
    		}
        	catch (IOException e) {
            }

            clip.start();
    	}
    	else
			System.out.println("Sem Som......");

    	stepBarrierPast  = brain.initiatePastTime();
        stepBarrierDecision   = brain.initiateDecision();
        stepBarrierDecision2  = brain.initiateDecision2();
        stepBarrierCerebellum = brain.initiateCerebellum();
        stepBarrierSleep 	 = brain.initiateSleep();
		stepBarrierAct   = brain.initiateAct();
		try {
            while(!interrupted() && !Neuron.end)
                if (pause)
                    sleep(200); // Espera pelo Mentor (ms)
                else {
                	brain.past.startTime();
                    runStepBrain();
                    if (Liberu.Robot == 0)
                        sleep(TimeSlize); // Espera ciclo
                    if (Liberu.Robot == 1)
                        sleep(1500); // Espera ciclo
                    brain.past.addTime();
                }
        }
        catch(InterruptedException e) {
        }
        if (Liberu.Robot == 2)
        	NXTCommand.close();
        if (Liberu.Robot == 1)
    		try {
                Liberu.input.close();
                Liberu.output.close();
    	    }
        catch(IOException e) {
        }
        line.close();																// NXT
        System.out.println("End of Mind Thread...");
    }
}