/* This file is part of MINPANTU.
   See file `COPYRIGHT' for pertinent copyright notices.

   Common definitions to all source: mostly macros that hide
   constants, occasionally also convenient macros with
   functionality. */


#ifndef INCL_DEFS
#define INCL_DEFS 1


#include <math.h>


/* There are three kinds of constants defined below: 

   Those tagged with `C' are genuine constants defined here mostly for
   giving them more descriptive names, and should not be varied
   without careful consideration and appropropriate changes elsewhere.
   
   The constants tagged with `B' can be varied, and nothing probably
   fails, but changing these constants may decrease the performance of
   the computer player.  

   The definitions tagged with `A' can probably be changed, and
   nothing should break down or cause the computer to play much
   weaker.  The nature of the game may change, however.  It may also
   be necessary to tweak the integration step length
   `INTEGRATE_STEP'. */


#define XMIN 0			/* C */
#define XMAX 400		/* A */
#define YMIN 0			/* C */
#define YMAX 300		/* A */

/* The maximal speed the players can give to their hit balls. */
#define MAX_X_SPEED 600		/* A */
#define MAX_Y_SPEED 600		/* A */


/* The locations and sizes of the base areas can be changed, as long
   as the goals don't intersect.  Changing these will quite easily
   change the nature of the game. */
#define PLAYER0_BASE_X 99	/* B */
#define PLAYER0_BASE_Y 150	/* A */
#define PLAYER0_BASE_RADIUS 30	/* A */

#define PLAYER1_BASE_X 299	/* B */
#define PLAYER1_BASE_Y 150	/* A */
#define PLAYER1_BASE_RADIUS 30	/* A */

/* Put the above constants in a struct -- easier to use that way. */
static const struct {
  double x, y, radius;
} base[] = {
  { PLAYER0_BASE_X, PLAYER0_BASE_Y, PLAYER0_BASE_RADIUS },
  { PLAYER1_BASE_X, PLAYER1_BASE_Y, PLAYER1_BASE_RADIUS },
};

#define NEUTRAL_AREA_XMIN 150	/* B */
#define NEUTRAL_AREA_XMAX 250	/* B */
#define NEUTRAL_AREA_YMIN 15	/* A */
#define NEUTRAL_AREA_YMAX 270	/* A */

/* How long does it take to play a turn during which both sides move
   once (in "seconds"). */
#define MOVE_TIME 1.0		/* A */

/* Time for either player to move once, i.e. the time of a `ply',
   cf. literature on computer chess. */
#define PLY_TIME (MOVE_TIME/2.0)

/* The frequency with which the user is kept up with the state of the
   playing arena (in "seconds"). */
#define STEP_TIME 0.025		/* class A, but the GUI should be
				   modified accordingly. */

#define STEPS_PER_PLY ((int) (PLY_TIME/STEP_TIME))
#define STEPS_PER_MOVE ((int) (MOVE_TIME/STEP_TIME))

/* Darned it would be nice to write the structure describing the state
   of the ball as

     struct {
       struct {
         double x, y;
       } location;
       struct {
         double x, y;
       } speed;
     } state;

   But this would mean the values can no longer be treated as a
   vector, which would is nice in e.g. the integration routine.  So,
   we use the following compromise: use an array, but define macros to
   access it more descriptively. */

#define NUMBER_OF_GOAL_BALLS 4	/* A */
#define NUMBER_OF_BALLS (2 + NUMBER_OF_GOAL_BALLS)
/* The balls `0' and `1' are the hit balls of player 1 and 2,
   respectively. */
#define IS_GOAL_BALL(ball_num) ((ball_num) >= 2)
#define IS_HIT_BALL(ball_num) (!IS_GOAL_BALL(ball_num))

#define BALL_X_LOCATION(state, ball_num) state[4 * (ball_num)]
#define BALL_Y_LOCATION(state, ball_num) state[4 * (ball_num) + 1]
#define BALL_X_SPEED(state, ball_num) state[4 * (ball_num) + 2]
#define BALL_Y_SPEED(state, ball_num) state[4 * (ball_num) + 3]
#define BALL_STATE_VECTOR_LENGTH  (4 * NUMBER_OF_BALLS)


/* Some other common phrases. */

#define SQR(x) ((x) * (x))
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define MIN(x,y) ((x) < (y) ? (x) : (y))

#define DISTANCE_SQR(x1, y1, x2, y2) \
  (((x1)-(x2)) * ((x1)-(x2)) + ((y1)-(y2)) * ((y1)-(y2)))

#define DISTANCE(x1, y1, x2, y2) \
  sqrt(DISTANCE_SQR((x1), (y1), (x2), (y2)))

/* Most systems have a library function `nint' which rounds a double
   to its nearest integer.  But some systems lack it.  The macro below
   should do approximately the same thing. */
#define NINT(x) ((int) ((x) < 0 ? (x) - 0.5 : (x) + 0.5))


#endif /* INCL_DEFS */

