
// PreyBehavior.java
// Andrew Davison, April 2005, ad@fivedots.coe.psu.ac.th
// Sirinart Sakarin, March 2003, s4210315@calvin.coe.psu.ac.th

/* Třída PredatorBehavior spravuje seznam typu BoidsList instancí podtříd
   třídy Boid a odkaz na seznam obětí typu BoidsList, který získá přes odkaz
   na objekt typu PreyBehavior.

   Tato třída svůj seznam a uzel typu BranchGroup sestávající s dalších uzlů
   téhož typu nejdříve inicializuje.

   Třída jedno spravuje rychlostní pravidlo navíc: seePredators()
    - je-li blízko predátor, tak utíkej
   Tato metoda se volá z objektů typu PreyBoid
*/

import java.util.*;
import javax.media.j3d.*;
import javax.vecmath.*;

  
public class PreyBehavior extends FlockBehavior
{
  // škálovací faktor pro rychlost vypočítanou v pravidle seePredators()
  private final static float FLEE_WEIGHT = 0.2f;
  
  private BoidsList predsList;
  private PredatorBehavior predBeh;

  // pro opakované výpočty
  private Vector3f avoidmred = new Vector3f();
  private Vector3f distFrom = new Vector3f();


  public PreyBehavior(int numBoids, Obstacles obs)
  {
    super(numBoids);
    System.out.println("Num. Prey: " + numBoids);
    createBoids(numBoids, obs);
  }


  private void createBoids(int numBoids, Obstacles obs)
  /* Inicializuje seznam typu BoidsList objektů typu PreyBoid a 
     přidá uzly typu TransformGroup pro tyto agenty k uzlu boidsBG.
     Třída Boid je odvozena od třídy TransformGroup, takže může být přidána
     k uzlu boidsBG přímo.
  */
  */
  { // Objekty typu PreyBoids lze z grafu scéne odpojit
	boidsBG.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE); 
	boidsBG.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);

    PreyBoid pb; 
	for(int i=0; i < numBoids; i++){
      pb = new PreyBoid(obs, this); 
	  boidsBG.addChild(pb);   // přidej k uzlu typu BranchGroup
	  boidsList.add(pb);      // přidej do seznamu typu BoidsList
    }
    boidsBG.addChild(this);   // ulož chování kořisti přes jeho uzel typu BG
  } // konec metody: createBoids()


  public void setPredBeh(PredatorBehavior pb)
  // ulož chování predátora
  { predBeh = pb; }
  


  public Vector3f seePredators(Vector3f boidmos)
  /* Je-li agent blízko predátora, směřuej svůj pohyb opačním směrem a
     určitý poměr této vzdálenosti.
     Tuto metodu volá metoda doVelocityRules() třídy PreyBoid.
  */
  { predsList = predBeh.getBoidsList();  // odkaž na seznam predátorů
    avoidmred.set(0,0,0);  // reset
    Vector3f predmos;
    PredatorBoid b;

    int i = 0;
	while((b = (PredatorBoid)predsList.getBoid(i)) != null) {
      distFrom.set(boidmos);
      predmos = b.getBoidmos();
      distFrom.sub(predmos);
	  if(distFrom.length() < PROXIMITY) {   // je agent blízko predátora?
        avoidmred.set(distFrom);
        avoidmred.scale(FLEE_WEIGHT);
        break;
      }
      i++;
	}
	return avoidmred;
  } // konec metody: seePredators()



  public void eatBoid(int i)
  /* Objekt typu PreyBoid s indexem i je sežrán, což způsobí jeho odpojení
     ze scény a odebrání ze seznamu typu BoidsList.
     Volá se z metody eatFood() třídy PredatorBehavior. */
  { 
     ((PreyBoid)boidsList.getBoid(i)).boidDetach(); 
	 boidsList.removeBoid(i);
  }


} // konec třídy: PreyBehavior