

#ifndef BasicEntity_h
#define BasicEntity_h

#include "a5dll.h"
#include "a5funcs.h"	// C++ inline functions for the library
#include <iostream>
#include <string>

using namespace std;

struct distance_vector
{ 
	int x; 
	int y;
	int z;
};

///////////////////////////////////////////////////////////////////////
// example for passing a string to create an entity
/*long PSTRING(char* chars)
{
// works only for strings no longer than 79 chars!
	static A4_STRING tempstring;
	static char tempname[80];
	strcpy(tempname,chars);
	tempstring.chars = tempname;
	return (long)&tempstring;
}*/

//  BasicEntity is the superclass of all entities.
//  For Assignment 3, extend BasicEntity with your own 
//  class.  Note that BasicEntity is abstract, because it
//  has at least one "pure virtual function" (namely the
//  ones with "=0" at the end of their signatures, and
//  with no method bodies).

class BasicEntity
{ 
  protected: 
	  int n;
	  distance_vector current_pos;  //  Current x,y,z coordinates of
									//  of the entity in the game world.
	                                //  Uses world coordinate system.
	  distance_vector temp_vector;  

	  fixedPoint myEntityPointer;   //  A pointer to the gameworld entity FROM
									//  within the gameworld.
	  A4_ENTITY* me;                //  A pointer to the gameworld entity FROM
									//  within the C++ DLL.
	  fixedPoint* my_entity_ptr_ptr;//  A pointer to the "my" pointer in the
									//  gameworld, which is a global var. in the gw.

      //   GAMEWORLD FUNCTION POINTERS, to allow DLL to call gw functions
	  wdlfunc2 ent_move_fcn_ptr;	//  Pointer to the gw "entworld" fcn.
	  wdlfunc3 entityCreate_fcn_ptr;
	  wdlfunc2 trace_fcn_ptr;
	  fixedPoint* trace_mode_ptr;   //  Pointer to gw data holding the trace_mode flags
	  wdlfunc2 vec_rotate_fcn_ptr;
	  long action_ptr;              //  Pointer to a user-designed action or fcn in the .wdl file

	  //  ROTATE_ME rotates the gw entity clockwise (i.e., toward the entities right)
	  //  by "angle" degrees.  Will handle neg. angles (turn left) as well as
	  //  angles > 360.  Will NOT show a smooth turn.
	  void rotate_me(int turn_angle);

	  //  ENT_MOVE moves the gw entity from its current position
	  //  to the position given by x,y,z in ENTITY COORDINATE SYSTEM.
	  //  Thus, "move(-5,0,0)" will move the entity 5 quants backwards
	  //  from where the entity is facing, regardless of entity's world
	  //  coordinates.  Note units are "quants", and that 3DGS's "ent_move"
	  //  function is used to actually effect the move.  Thus the entity
	  //  WILL stop on the way to x,y,z IF there is an obstacle (e.g., 
	  //  map entity, such as a block, a sprite, or another dynamic entity).
	  //  Also tries to simulate gravity by moving entity down if no floor.
	  //  directly under it.
	  //  Updates "current_pos" with actual position after the move.
	  void ent_move(int x, int y, int z);
	  void ent_move(distance_vector one, distance_vector two);

	  //  TRACE_FROM_ENTITY returns the distance, in quants,
      //  from entity's current_pos to the first obstacle 
	  //  found between current_pos and the x,y,z position "to"
	  //  (assumed to be in ENTITY COORDINATES.  If no obstacle
      //  found between current_pos and "to", then returns 0.
      
	  int trace_from_entity(distance_vector to);

      //  The following three methods were moved from "private" to 
	  //  "protected" 12-6-03, so that they can be inherited by classes
	  //  created for HW3.
	  void createMeInWorld(string model_name, int init_position[], string action_name);
	  int trace(distance_vector from, distance_vector to);
	  distance_vector vec_rotate(distance_vector from, distance_vector to);

      //  The following vector manipulation methods were added
	  //  to BasicEntity on 12-6-03, so that they can be used for
	  //  classes for HW3, via inheritance. 

	  wdlfunc2 vec_to_angle_fcn_ptr;
	  int vector_to_pan(distance_vector direction);  //  Takes an x,y,z vector and
	                         // returns the integer pan angle that "points" to that
	                         // given x,y,z location, from the origin.  So if you are
	                         // an entity at 0,0,0, and you set your "pan" variable to
	                         // vector_to_pan(dir), where dir = {40,100,33), 
	                         // then you would be facing the
	                         // point (40,100,0) (note:  affects "pan" only, not "tilt"!)
	  distance_vector subtract_vectors(distance_vector v1, distance_vector v2);
	                         //  "distance_vector_subtract(v1,v2), returns an x,y,z 
	                         // vector v3 that is equal in value to v1-v2 (using vector
	                         // subtraction:  v3.x = v1.x-v2.x, v3.y = v1.y-v2.y, and 
	                         // v3.z=v1.z-v2.z
	  int pan_angle_from_v1_to_v2(distance_vector v1, distance_vector v2);
	                         // "pan_angle_from1_to_v2" returns the integer angle that
	                         // is the direction (angle) of position v2 FROM the position
	                         // v1.  Thus if an entity were standing at v1, and rotated by
	                         // "pan_angle_from_v1_to_v2" degrees, that entity would be
	                         // facing position v2.
	  void rotate_me_to(int new_pan_angle);  // "rotate_me_to(new_pan_angle)" simply
	                         // sets the "pan" variable of the "me" entity (whatever the
	                         // local "me" entity pointer points to) to the given  
	                         // "new_pan_angle".  Thus the "me" entity will point in the
	                         // "new_pan_angle" direction.


  public:

	  BasicEntity(); 

	  void create(distance_vector init_locale, string model_file, string action_name);

	  ~BasicEntity();

 //   The three pure Virtual Functions for Assign. 3.  
 //   See "Gerbil.h" for example implementations.

	  virtual void move()=0;
	  virtual void set_goal(distance_vector goal)=0;    
	  virtual void create(distance_vector init_locale)=0;

 //   "move" is supposed to move the entity toward the goal 
 //   location while avoiding obstacles, traps (e.g., pools!), etc.

 //    "set_goal" should allow the calling program to change
 //    the goal location that the entity is trying to get to 
 //    in "move" above
  
 //  "create" is called by the Controller (or other) code to
 //  cause the entity to be created in the game world, using
 //  the initial location given as input parameter.  In this
 //  method the model file to be used, as well as the C-script
 //  action to assign, if any, can be set.  See "Gerbil" for an 
 //  example.  Note, if you do not want to use a C-script action,
 //  then when calling BasicEntity::create(distance_vector, modelfile,
 //  action), be sure to use the string " " (i.e., one blank space)
 //  for the action parameter.

      
};

#endif



