

#include "generic.h"
#include "lfptypes.h"

#include "define.h"
#include "ml.h"

#include "ctrl.h"

#ifdef PC
 #include "fontcode.h"
 #include "dbugtxt.h"
#endif

#include "audio.h"
#include "res/playerid.h"

#include "targets.c"

static void collision_avoid(void);
static void set_target(playert *plyr, char *tg_ptr);
static void set_targets(playert *plyr, char *tg_ptr);

extern int stupid_fucking_flagrant_foul_flag;

extern int Human3PtMatchPlayers[];

int oobs_sector;			//which out of bounds position table to use

int last_sector;			//sector ball handler was in when target positions assigned last
int last_set;				//which set was used last time target positions assigned
int last_bh;				//who was ball handler last time targets assigned
int last_sec_change;		//lp_ctr last time targets assigned
int last_set_switch;		//lp_ctr last time sets were changed
int set_switch;				//use 1st or 2nd alternate targets

int	HotSpotPlyr=-1;

//definition of sectors
int sectors[]={
-BASE_LINE/2,3,
SIDE_LINE/3,-SIDE_LINE/3,

0,3,
SIDE_LINE/3,-SIDE_LINE/3,

BASE_LINE/3,3,
SIDE_LINE/3,-SIDE_LINE/3,

(BASE_LINE*2)/3,5,
(SIDE_LINE*3)/5,SIDE_LINE/5,-SIDE_LINE/5,-(SIDE_LINE*3)/5,

BASE_LINE,5,
(SIDE_LINE*3)/5,SIDE_LINE/5,-SIDE_LINE/5,-(SIDE_LINE*3)/5,

-1,-1,
};


int dists[5][5];			//how far each player is from opponents


/* *************************************************************************/
/* get_angles_dist()*/
/* *************************************************************************/
/* calculate angles and distances to of player from basket and ball*/
/* *************************************************************************/
/* Inputs   -*/
/* Output   -*/
/* *************************************************************************/


global void get_angles_dist(void )
{
playert *plyr, *op;
int x_diff,y_diff;
int dist;
int i, j;

	for (plyr = player; plyr < &ball; plyr++)
	{
		if (C3PT && plyr->no!=Human3PtMatchPlayers[0] && plyr->no!=Human3PtMatchPlayers[1])
			continue;

		if ((plyr->no != int_recvr) | (ball.main_routine != pass_ball_move))
		{
			int time;

			x_diff  = ball.xco - plyr->xco;
			y_diff  = ball.yco - plyr->yco;

			plyr->ball_dist	 = LFPSqrt((x_diff>>12)*(x_diff>>12) + (y_diff>>12)*(y_diff>>12)) << 12;
			plyr->ball_angle = LFPAtn(x_diff,y_diff);

			if ((ball.main_routine != pass_ball_move) && (!pass_flag) && !C3PT)
			{
				time = (plyr->ball_dist/CH_PASS_SPD) + (ONE_SEC/3);
				plyr->proj_x = plyr->xco + plyr->xvel*time;
				plyr->proj_y = plyr->yco + plyr->yvel*time;
			}
		}
	}

	if ((possession_flag) || (!in_play_flag))
	{
		current_basket_y = (ball_handler>4) ? -BASKET_Y:BASKET_Y;
	}

	for (plyr = player; plyr <= &ball; plyr++)
	{
		if (C3PT && plyr->no!=Human3PtMatchPlayers[0] && plyr->no!=Human3PtMatchPlayers[1])
			continue;

		x_diff	= -plyr->xco;
		y_diff	= current_basket_y - plyr->yco;

		dist	= pythag (x_diff, y_diff);
		if (dist<0x20000)	dist = 0x20000;
		plyr->basket_dist	= dist;

		plyr->basket_angle	= LFPAtn (x_diff, y_diff);
	}



	i=0;

	if (C3PT)
		return;

	for (plyr = player+bhp->base; plyr<player+bhp->base+5; plyr++)
	{
		int	nearest;

		nearest = 0x7fffffff;

		j=0;
		for (op = player+(bhp->base^5); op<player+(bhp->base^5)+5; op++)
		{
			dists[i][j] =
			dist		= MANHATTAN(plyr->xco-op->xco, plyr->yco-op->yco);

			if (dist<nearest)
			{
				nearest = dist;
				plyr->nearest_op   = op->no;
			}
			j++;
		}
		plyr->nearest_dist = nearest;
		i++;
	}


	plyr=player+(bhp->base^5);

	if (!C3PT)
		for (i=0; i<5; i++)
		{
			int	nearest;

			nearest = 0x7fffffff;

			for (j=0; j<5; j++)
			{
				if (dists[j][i]<nearest)
				{
					nearest = dists[j][i];
					(plyr+i)->nearest_op   = j+bhp->base;
				}
			}
			plyr->nearest_dist = nearest;
		}
}


playert *find_closest_plyr(playert *plyr1, int x, int y, int p)
{
playert *np;
int nearest;
int dist;
int i;

	nearest = 0x7fffffff;

	for (i=0;i<p;i++)
	{
		dist = MANHATTAN(x-plyr1->xco, y-plyr1->yco);
		if (dist<nearest)
		{
			nearest = dist;
			np		= plyr1;
		}

		plyr1++;
	}

	return np;
}







int get_oobs_sector(void)
{
int ball_x, ball_y;
int sector;
bool	flippie=FALSE;

	if (foul_flag==ILLEGAL_DEFENSE && ai_team[1-bhp->team].illegalD>1 && !free_throws)
	{
		ball_x = ball.target_x;
		ball_y = ball.target_y;

		if (last_handler > 4)
			ball_y = -ball_y;
		SetBallHandler(get_oobs_sector,(last_handler>4)? 9:4);
		goto where;
	}
	//get targets based on where ball is
	if (scored_flag)
	{
		int	nbh;

		if (stupid_fucking_flagrant_foul_flag)
		{
sffff:
			sector=11;
			nbh=(ball.yco>0)? 4 : 9;
			stupid_fucking_flagrant_foul_flag=FALSE;
		}
		else
		{
			sector = 14;
			nbh=(ball.yco>0)? 9 : 4;
		}

		SetBallHandler(get_obbs_sector,nbh);
	}
	else if (free_throws)
	{
		sector = 15 + (free_thrower % 5)*2;
		if ((foul_flag == FLAGRANT) || (foul_flag==TECHNICAL) || foul_flag==ILLEGAL_DEFENSE)
		{
			sector += 10;
		}
		SetBallHandler(get_obbs_sector,free_thrower);
	}
	else
	{
		if (stupid_fucking_flagrant_foul_flag)
			goto sffff;

		ball_x = ball.target_x;
		ball_y = ball.target_y;

		if (stupid_fucking_flagrant_foul_flag)
		{
			SetBallHandler(get_oobs_sector,(ball.yco>0) ? 4:9);
			stupid_fucking_flagrant_foul_flag=FALSE;
		}
		else
		{
			if (last_handler > 4)		ball_y = -ball_y;
			SetBallHandler(get_oobs_sector,(last_handler>4) ? 4:9);
		}

		//where is ball
where:
		if (abs(ball_y) >= (BASE_LINE+EDGE))
		{
			if ( ball_x > ((SIDE_LINE*2)/3) )		sector = 0;
			else if ( ball_x > ((-SIDE_LINE*2)/3) )	sector = 1;
			else									sector = 2;

			if (ball_y > 0)							sector +=3;
		}
		else
		{
			if (ball_y > (BASE_LINE/2))				sector = 6;
			else if (ball_y > 0)					sector = 7;
			else if (ball_y > (-BASE_LINE/2))		sector = 8;
			else									sector = 9;

			if (ball_x > 0)							sector +=4;
		}
	}

got_sec:

	#if defined(DEBUG)
	{
		char	num[16];
		char	txt[64];

		memset(num,0,sizeof(num));
		IntToDecStr(sector,num);
		sprintf(txt,"OOB Sector %s",num);
		db_out(get_oobs_sector,txt);
	}
	#endif

	bhp = player+ball_handler;

	if (!free_throws)
	{
		playert *p;

		//find player closest to ball and make him the inbounder
		p = (ball_handler>4) ? player+5: player;

		bhp = find_closest_plyr(p+1, ball.target_x, ball.target_y, 4);
		SetBallHandler(get_oobs_sector,bhp->no);
	}

	if (foul_flag!=HALF_COURT && BLY(bhp)<0)
		SetHalfFlag(get_oobs_sector,FALSE);

	return sector;
}



void set_oobs_targets(int sector)
{
playert *plyr1, *plyr2;
int y_mult;
int i;
int x,y;
int basket_y;
int tbh;
ctrlrT	*oc;

	if (sector<0)	return;

	if (ball_handler>4)
	{
		y_mult=-1;
		plyr1 = player+5;
		plyr2 = player;
	}
	else
	{
		y_mult= 1;
		plyr1 = player;
		plyr2 = player+5;
	}

	tbh=plyr1->no;

	for (i=0; i<5; i++)
	{
		playert *p;

		p=plyr1+i;

		//ball handling team
		x = inbound[sector][i][0];
		if (x & 0xffff0000)		p->target_x = ball.target_x + ((x&0xffff)<<16);
		else					p->target_x = (x & 0xffff) << 16;

		y = inbound[sector][i][1];
		if (y & 0xffff0000)		p->target_y = ball.target_y + (((y*y_mult) & 0xffff)<<16);
		else					p->target_y = ((y*y_mult) & 0xffff) << 16;

		if (MANHATTAN(p->target_x-ball.target_x, p->target_y-ball.target_y) < 0x140000)
		{
			tbh = p->no;
		}

		p->pick_ctr=0;
	}





	if (free_throws)
	{
		sector++;

		for (i=0; i<5; i++)
		{
			//defending team
			x = inbound[sector][i][0];
			if (x & 0xffff0000)		plyr2->target_x = ball.target_x + ((x&0xffff)<<16);
			else					plyr2->target_x = (x & 0xffff) << 16;

			y = inbound[sector][i][1];
			if (y & 0xffff0000)		plyr2->target_y = ball.target_y + (((y*y_mult) & 0xffff)<<16);
			else					plyr2->target_y = ((y*y_mult) & 0xffff) << 16;

			plyr2->pick_ctr=0;
			plyr2++;
		}

		bhp = player+ball_handler;
	}
	else
	{
		//setup defense
		reset_markers();

		//swap ball handler targets with targeted ball handler
		x					 = bhp->target_x;
		bhp->target_x		 = player[tbh].target_x;
		player[tbh].target_x = x;

		y					 = bhp->target_y;
		bhp->target_y		 = player[tbh].target_y;
		player[tbh].target_y = y;

		basket_y = (bhp->no<5) ? BASKET_Y: -BASKET_Y;

		oc=current_ctrlr;
		current_ctrlr=&ctrlrs[0];

		for (i=0; i<5; i++)
		{
			SW ba;
			playert *mark;

			mark = &player[markee[plyr2->no]];

			OFFND.xco = mark->target_x;
			OFFND.yco = mark->target_y;
			OFFND.last_speed = 0;
			OFFND.basket_angle = LFPAtn(-mark->target_x, basket_y - mark->target_y);
			OFFND.basket_dist  = MANHATTAN(-mark->target_x, basket_y - mark->target_y);
			OFFND.no  = mark->no;

			DUMMY.base = plyr2->base;
			DUMMY.team = plyr2->team;
			DUMMY.last_speed = 0;
			DUMMY.no   = plyr2->no;
			DUMMY.markee = &OFFND-player;
			defend(&DUMMY);

  			plyr2->target_x = DUMMY.target_x;
  			plyr2->target_y = DUMMY.target_y;

			plyr2->pick_ctr=0;
			plyr2++;
		}

		current_ctrlr=oc;
	
		if (five_sec_clock >= 2.5*ONE_SEC)
		{
			for (i=0; i<5; i++)
			{
				SW angle;

				if (plyr1 != bhp)
				{
					angle		   = LFPAtn(plyr1->target_x, plyr1->target_y);
					plyr1->target_x = plyr1->target_x - (0x100*LFPCos(angle));
					plyr1->target_y = plyr1->target_y - (0x100*LFPSin(angle));
				}

				plyr1++;
			}
		}
	}
}




void oobs_pos(void)
{
//out of bounds play
int ball_x, ball_y;
int sector;

	sector      =
	oobs_sector = get_oobs_sector();

	set_oobs_targets(oobs_sector);

	int_recvr=5*player[ball_handler].team;

	//don't get positions again
	got_pos_flag = TRUE;
	stealable_flag=FALSE;
}




#define IPF_DIST	0x100000	// Distance for in-play

/* *************************************************************************/
/* get_positions()*/
/* *************************************************************************/
/* get target positions of attackers based on position of, and who has the ball*/
/* *************************************************************************/
/* Inputs   -*/
/* Output   -*/
/* *************************************************************************/
void get_positions(void)
{
	int		x,y;
	playert *p;
	playert	*pp,*e;
	bool	pf=FALSE;
	static	int	lbt=0;

	if (celebration_flag)	return;

	if (in_play_flag)
	{
		if ((possession_flag) && (!pass_flag))
		{
			if (!in_set_flag) // Check to see if in set
			{
				p=&player[bhp->base];
				e=p+5;

				do
				{
					if (PLY(p)<0)	// Don't check in defensive half of court
						break;
					if (p->no==bhp->no)
						continue;
					if (p->target_dist>IPF_DIST)
					{
						if (!ArcadeMode)
							break;

						if (!HotSpot_Check(p))
							continue;
					}
				} while (++p<e);

				if (p==e)
					in_set_flag=TRUE;
			}

			if (fast_break_flag)
			{
				fast_break_test();
			}

			if (!fast_break_flag)
			{
				int sector;
				int set;

				set = ai_team[bhp->team].current_set;

				sector = get_bh_sector(bhp->xco, bhp->yco);

				//don't go thru this again if no change from previous loop
	#ifndef MOVE

				// Handle the new variable-rate set switch
				switch(lp_ctr-last_set_switch)
				{
				case ONE_SEC:
					break;

				case 2*ONE_SEC:
					break;

				case 3*ONE_SEC:
					break;

				case 4*ONE_SEC:
					set_switch ^= 1;
					last_set_switch=lp_ctr;
					break;

				case 5*ONE_SEC:
					break;

				}

				// Get updated player position
				p=NULL;
				switch (lp_ctr-last_sec_change)
				{
				case 2*ONE_SEC:
					 p = player+bhp->base;
					 break;

				case 5*HALF_SEC:
					 p = player+bhp->base+1;
					 break;

				case 3*ONE_SEC:
					 p = player+bhp->base+2;
					 break;

				case 7*HALF_SEC:
					 p = player+bhp->base+3;
					 break;

				case 4*ONE_SEC:
					 p = player+bhp->base+4;
					 last_sec_change = lp_ctr-ONE_SEC;
					 break;
				}
				if (lp_ctr-last_sec_change>4*ONE_SEC)
					last_bh=-1;

				if (p)
				{
					int	normal=TRUE;

					if (p==bhp && !p->control)
						if (pick_ctr || first_step_flag)
							normal=FALSE;


					if (normal)
					{
						set_target(p, &targets[(sector>5) ? set:0][bhp->no-bhp->base][sector][set_switch^1][p->no % 5][0]);

						if (sector<=5 && bhp->no-bhp->base==3 && sector==4 && set_switch==1 && p->no==3)
							pf=FALSE;
					}
				}

				// If computer is awaiting pick, stay put
				if (!bhp->control)
				{
					if (pick_ctr)
						pf=TRUE;
					else
					{
						pp=&player[bhp->base];
						e=pp+5;
						do
						{
							if (pp->main_routine==picked)
							{
								pf=TRUE;
								break;
							}

							if (pp->main_routine==set_pick && pp->col_flags!=-1)
								if (pp->team!=player[pp->col_flags].team)
								{
									pf=TRUE;
									pp->pickee=pp->col_flags;
									pick_ctr=3;
								}
						} while (++pp<e);
					}
				}

				if (pf && !bhp->control)
				{
					bool	pickf=FALSE;

					switch(bhp->play_flag)
					{
						case 0:
							pp=&player[bhp->base];
							e=pp+5;
							do
							{
								if (pp->main_routine!=picked)
									continue;

								bhp->play_flag=1;
								x=pp->xco-player[pp->pickee].xco;
								y=pp->yco-player[pp->pickee].yco;
								bhp->target_x=bhp->xco+LFPCos(bhp->dunk_angle)*192;
								bhp->target_y=bhp->yco+LFPSin(bhp->dunk_angle)*192;
								pickf=TRUE;
								break;
							} while (++pp<e);
							if (!pickf)
							{
								pp=e-5;
								do
								{
									if (pp->main_routine==set_pick)
										break;
								} while (++pp<e);
								if (pp==e)
									pick_ctr=0;
							}

							break;

						case 1:
							if (bhp->target_dist<0x50000)
							{
								//start_replay(0);
								bhp->play_flag=2;
							}
							break;

						case 3:
							set_target(bhp, &targets[(sector>5) ? set:0][bhp->no-bhp->base][sector][set_switch^1][bhp->no % 5][0]);
							bhp->play_flag=4;
							break;

						default:
							break;
					}
				}

				if ((ball_handler != last_bh) || (sector != last_sector) || (set != last_set))
	#endif
				{
					x=bhp->target_x;
					y=bhp->target_y;

					last_sec_change = lp_ctr;
					last_set_switch = lp_ctr;
					set_switch		= 0;
					last_sector		= sector;
					last_bh			= ball_handler;
					last_set        = set;
					set_targets(player+bhp->base, &targets[(sector>5) ? set:1][bhp->no-bhp->base][sector][set_switch][0][0]);

					if (!bhp->control)
						if (is_pick_on(bhp) || first_step_flag)
						{
							bhp->target_x=x;
							bhp->target_y=y;
						}
				}
			}
		}
	}
	else
	{
		if ((!tip_off_flag) && (timeout_called==0))
		{
			set_oobs_targets(oobs_sector);
		}
	}

	// In arcade mode, have close players run towards the hotspot
	if (ArcadeMode && in_play_flag && ai_team[bhp->team].controllers[0]==0)
	{
		int		i;
		int		hx,hy;
		int		dx,dy;
		int		cd=0x7fff0000;
		int		dist;
		playert	*plyr;
		playert	*runner=NULL;

		HotSpotPlyr=-1;

		// Look for guy nearest hot spot
		if (HotSpot_GetPos(&hx,&hy))
		{
			for (i=0; i<5; i++)
			{
				plyr=&player[bhp->base+i];

				dx=hx-plyr->xco;
				dy=hy-plyr->yco;
				dist=MANHATTAN(dx,dy);

				if (dist<cd)
				{
					cd=dist;
					runner=plyr;
				}
			}

			// Handle player close to spot
			if (cd<0x280000)
			{
				// Check for defenders on spot
				for (i=0; i<5; i++)
					if (HotSpot_Check(&player[5-bhp->base+i]))
						break;

				// If no defender on spot, go to it
				if (i==5)
				{
					HotSpotPlyr=runner->no;
					runner->target_x=hx;
					runner->target_y=hy;
				}
			}
		}
	}

	// Check for standing players
	if (possession_flag)
	{
		if (MANHATTAN(bhp->xco-bhp->target_x,bhp->yco-bhp->target_y)<0xC0000)
		{
			if (++lbt>ONE_SEC*3/2)
				last_bh=-1;
		}
		else
			lbt=0;
	}
	else
		lbt=0;

}


/*
void collision_avoid(void)
{
playert *plyr;
SW  va;
int x1, y1;

	for (plyr=player; plyr<player+10; plyr++)
	{
		va = LFPAtn(plyr->xvel, plyr->yvel);

		x1 = LFPSin(va)*0x28;
		y1 = -LFPCos(va)*0x28;

		plyr->a[0] = plyr->xco+x1;
		plyr->a[1] = plyr->yco+y1;
		plyr->b[0] = plyr->xco-x1;
		plyr->b[1] = plyr->yco-y1;
		plyr->d[0] = plyr->a[0]+(plyr->xvel*ONE_SEC);
		plyr->d[1] = plyr->a[1]+(plyr->yvel*ONE_SEC);
		plyr->c[0] = plyr->b[0]+(plyr->xvel*ONE_SEC);
		plyr->c[1] = plyr->b[1]+(plyr->yvel*ONE_SEC);

	}
}
*/




/* *************************************************************************/
/* move_to_set()*/
/* *************************************************************************/
/* move to set target positions for inbounding the ball*/
/* *************************************************************************/
/* Inputs   - table of positions*/
/* Output   -*/
/* *************************************************************************/

static void set_targets (playert *plyr, char *tg_ptr)
{
int ctr;

	for (ctr=0; ctr<5; ctr++)
	{
		set_target(plyr, tg_ptr);
		tg_ptr+=2;
		plyr++;
	}
}


static void set_target(playert *plyr, char *tg_ptr)
{
int y_mult;
int off;
int x, y;

	y_mult	= 1;
	if (plyr->no > 4)		y_mult	= -1;

	off=0;

	//shake thing up a bit for PG crossing half-court line
	if ( (plyr==bhp) && (plyr->no==plyr->base))
	{
		switch (last_sector)
		{
		case 1:
			if (side==-1)	side= (ReadRnd250()*3)>>8;

		case 0:
		case 2:
		case 3:
		case 4:
		case 5:

			if (side>=0)
			{
				off -= (last_sector%3) * 10;
				off += side*10;
			}
			break;
		
		case 6:
			if (ReadRnd250()&2)			off=10;
			last_sec_change = lp_ctr;
			side = -1;
			break;

		case 7:
			side = -1;
			switch (ReadRnd250() & 3)
			{
			case 0:
			case 1:
				off = 0;
				break;

			case 2:
				off = 10;
				break;

			case 3:
				off = -10;
				break;
			}
			last_sec_change = lp_ctr;
			break;

		case 8:
			side = -1;
			if (ReadRnd250()&2)			off=-10;
			last_sec_change = lp_ctr;
			break;
		}
	}

	x = (int)(s8)tg_ptr[off];
	x *= (SIDE_LINE-EDGE)/127;
	tg_ptr++;

	y = (int)(s8)tg_ptr[off] * y_mult;
	y *= (BASE_LINE-EDGE)/127;

#ifdef ML
 #if DEBUG
	/*
	 * ignore all new positions AI
	 */
	//x = plyr->xco;
	//y = plyr->yco;
 #endif
#endif

	plyr->target_x = x;
	plyr->target_y = y;
}



/* *************************************************************************/
/* turn_to()*/
/* *************************************************************************/
/* turn towards a target angle*/
/* *************************************************************************/
/* Inputs   - ptr to player data, ideal angle*/
/* Output   - flag TRUE reached ideal angle, FALSE didn't*/
/* *************************************************************************/

bool turn_to (playert *plyr,SW ideal_a)
{
SW diff;

	diff = (plyr->angle - ideal_a);

	if (abs(diff)<TURN_SPEED)
	{
		plyr->angle = ideal_a;
		return TRUE;
	}

	if (diff < 0)	plyr->angle = plyr->angle+TURN_SPEED;
	else			plyr->angle = plyr->angle-TURN_SPEED;

	return FALSE;
}





/* *************************************************************************/
/* move_to_place2()														   */
/* *************************************************************************/
/* move to dead ball positions											   */
/* *************************************************************************/
/* Inputs   - ptr to player data,										   */
/* Output   - j_pad														   */
/* *************************************************************************/

bool move_to_place2(playert *plyr)
{
SW face_angle;

	CallChainP(move_to_place2);

	if (celebration_flag)
	{
		face_angle = LFPAtn(-plyr->target_x,
							-plyr->target_y);
	}
	else
	{
		face_angle = LFPAtn(ball.xco-plyr->target_x,
							ball.yco-plyr->target_y);
	}

	if (free_throws)	face_angle = plyr->basket_angle;

	if (attack_home_in(plyr, face_angle))
	{
		return turn_to(plyr, face_angle);
	}
	return FALSE;
}






void start_pick_up_ball(playert *plyr)
{
	CallChainP(start_pick_up_ball);

	if (free_throws || ball.zco<0x100000)
	{
		five_sec_clock = 0;
		get_new_controls(&ai_team[plyr->team], plyr);

		ball.zco = BALL_RADIUS;
		last_bx = ball.xco;
		last_by = ball.yco;
		last_bz = ball.zco;

		if (bhp->team!=plyr->team)
			in_set_flag=FALSE;
		SetMain(start_pick_up_ball,&ball,follow_player);
		SetBallHandler(start_pick_up_ball,plyr->no);
		bhp				=
		ai_team[plyr->team].main_plyr = plyr;
		//set possession flags
		loose_flag      = FALSE;
		rebound_flag    = FALSE;
		rebound_time	= 0;
		SetPossession(start_pick_up_ball,TRUE);

		reset_play();

//		foul_reset();

		if (free_throws==0)
		{
			last_bounce = lp_ctr+20;
			SetMain(start_pick_up_ball,plyr,pick_up_ball);
			plyr->top_routine  = NULL;
			plyr->leg_routine  = NULL;
			start_blend_anim2(plyr, TOP_PICKUP, ONE_SEC*3/4);

			if (CAMERAS==1)	CameraSpecialEnd();
		}
		else
		{
			FreeThrowStop();

			SetMain(start_pick_up_ball,plyr,free_throw_pick_up);
			plyr->top_routine  = NULL;
			plyr->leg_routine  = NULL;
			if (IS_PLYR_ONLY(JEFF_HORNACEK_UTA))
				start_blend_anim(plyr,TOP_HORNACEK1);
			else if (IS_PLYR_ONLY(ANTHONY_MASON_CHA))
				start_blend_anim2(plyr,TOP_MASON1,ONE_SEC);
			else
				start_blend_anim2(plyr, TOP_FREE1, ONE_SEC);

			if ((last_free_throw-time_left)>0)
			{
			 	last_free_throw=time_left;
				//ft_commentary();
			}

			stats_player_card(plyr->no, CARD_FTS);
		}
	}
}





void pick_up_ball(playert *plyr)
{
//wait for end of pick up ball routine
	CallChainP(pick_up_ball);

	pass_flag	   = FALSE;
	ten_sec_clock  = 0;
	five_sec_clock = 0;

	if (blend_to_end(plyr, TOP_OVER_BALL, LEG_STAND, 3))
	{
		if (!steal_flag && !timeout_called && (last_blocker==-1 || player[last_handler].team!=plyr->team))
			new_shot_clock();

		steal_flag = FALSE;

		start_anim(plyr, TOP_OVER_BALL);
		start_leg_anim(plyr, LEG_STAND);

		SetMain(pick_up_ball,plyr,stand_with_ball2);
		plyr->leg_routine  = leg_deflt;

		reset_play();

		SetDribbleFlag(pick_up_ball,2);
		plyr->ctr2=random(32);
	}
}




int get_bh_sector(int x, int y)
{
int *sptr;
int no_x_sectors;
int sec;
int i;

	sec = 0;
	sptr = sectors;

	if (ball_handler>4)	y=-y;

	while(y > *sptr)
	{
		no_x_sectors = *(sptr+1);

		if (*sptr > *(sptr + no_x_sectors + 1) )	break;
		sptr += no_x_sectors + 1;
		sec  += no_x_sectors;
	}

	no_x_sectors = *(sptr+1);

	sptr += 2;
	for (i=1; i<no_x_sectors;i++)
	{
		if (x>*sptr)	break;
		sptr++;
		sec++;
	}

	return sec;
}




int inbound[][5][2] = {
//3
0x0000ffc0, 0x00000080,
0x00000020, 0x000000c0,
0x00010000,	0x00010006,
0x0000ffc0,	0x00000080,
0x00000040,	0x00000060,

//4
0x00000070, 0x00000080,
0x0000ffc0, 0x00000060,
0x00010000,	0x00010006,
0x0000ffb0,	0x000000b0,
0x00000038,	0x000000c0,

//5
0x0000ffc0, 0x00000080,
0x00000020, 0x000000c0,
0x00010000,	0x00010006,
0x0000ffc0,	0x00000020,
0x00000040,	0x00000060,


//0
0x0000ffc0, 0x0000ff80,
0x00000020, 0x0000ff40,
0x00010000,	0x0001fffa,
0x0000ffc0,	0x0000ffe0,
0x00000040,	0x0000ffa0,

//1
0x00010000, 0x00010020,
0x00000020, 0x0000ff40,
0x00010000,	0x0001fffa,
0x0000ffc0,	0x0000ffe0,
0x00000040,	0x0000ffa0,

//2
0x0000ffc0, 0x0000ff80,
0x00000020, 0x0000ff40,
0x00010000,	0x0001fffa,
0x0000ffc0,	0x0000ffe0,
0x00000040,	0x0000ffa0,

//6
0x0000ffa0, 0x00010000,
0x00000020, 0x0000ff80,
0x0001fff6,	0x00010000,
0x0000ffc0,	0x0000ffe0,
0x00000040,	0x0000ffa0,

//7
0x0000ffc0, 0x00010000,
0x00000020, 0x00010020,
0x0001fff6,	0x00010000,
0x0000ffc0,	0x00010050,
0x00000060,	0x00010050,

//8
0x0000ffc0, 0x00000008,
0x00000040, 0x00000008,
0x0001fff6,	0x00010000,
0x0000ffc0,	0x00010020,
0x00000060,	0x00010020,

//9
0x00000040, 0x00000060,
0x0000ffc0, 0x00000060,
0x0001fff6,	0x00010000,
0x0000ffb0,	0x000000c0,
0x00000050,	0x000000c0,

//10
0x00000040, 0x0000ff80,
0x0000ffc0, 0x0000ff80,
0x0001000a,	0x00010000,
0x00000040,	0x0000ffe0,
0x0000ffa0,	0x0000ffe0,

//11
0x00000060, 0x00010000,
0x0000ffe0, 0x00010020,
0x0001000a,	0x00010000,
0x0000ffc0,	0x00010050,
0x00000060,	0x00010050,

//12
0x0000ffc0, 0x0001ffc0,
0x00000040, 0x0001ffe0,
0x0001000a,	0x00010000,
0x0000ffc0,	0x00010020,
0x00000060,	0x00010020,

//13
0x00000040, 0x00000060,
0x0000ffc0, 0x00000060,
0x0001000a,	0x00010000,
0x0000ffc0,	0x000000c0,
0x00000040,	0x000000c0,

//14 (inbound ball after basket)

0x00010000,	0x00010020,
0xffc0, 0x50,
 0x40,  0x50,
 0xffd0,  0xff40,
0x00010000,	0x0001fffa,

//free throw (PG)
0x0000,0x007f,
0x0050,0x0000,
0xffc0,0x0000,
0xffd0,0x00c0,
0x002e,0x00c0,

0xffc0,0x0040,
0x0050,0x0040,
0xffd2,0x00b0,
0xffd2,0x00d0,
0x002e,0x00d0,

//free throw (SG)
0x0050,0x0000,
0x0000,0x007f,
0xffc0,0x0000,
0xffd0,0x00c0,
0x002e,0x00c0,

0x0050,0x0040,
0xffc0,0x0040,
0xffd2,0x00b0,
0xffd2,0x00d0,
0x002e,0x00d0,

//free throw (SF)
0xffc0,0x0000,
0x0050,0x0000,
0x0000,0x007f,
0xffd0,0x00c0,
0x002e,0x00c0,

0xffc0,0x0040,
0x0050,0x0040,
0xffd2,0x00b0,
0xffd2,0x00d0,
0x002e,0x00d0,

//free throw (PF)
0xffc0,0x0000,
0x0050,0x0000,
0xffd0,0x00c0,
0x0000,0x007f,
0x002e,0x00c0,

0xffc0,0x0040,
0x0050,0x0040,
0xffd2,0x00b0,
0xffd2,0x00d0,
0x002e,0x00d0,

//free throw (C)
0xffc0,0x0000,
0x0050,0x0000,
0xffd0,0x00c0,
0x002e,0x00c0,
0x0000,0x007f,

0xffc0,0x0040,
0x0050,0x0040,
0xffd2,0x00b0,
0xffd2,0x00d0,
0x002e,0x00d0,



//free throw (PG)
0x0000,0x007f,
0x005a,0x0000,
0xffa0,0x0000,
0xffd0,0x0000,
0x002e,0x0000,

0xffa0,0xffc0,
0x0060,0xffc0,
0xffd2,0xffc0,
0x0000,0xffc0,
0x003e,0xffc0,

//free throw (SG)
0x0050,0x0000,
0x0000,0x007f,
0xffc0,0x0000,
0xffd0,0x0000,
0x002e,0x0000,

0xffa0,0xffc0,
0x0060,0xffc0,
0xffd2,0xffc0,
0x0000,0xffc0,
0x003e,0xffc0,

//free throw (SF)
0x0050,0x0000,
0xffc0,0x0000,
0x0000,0x007f,
0xffd0,0x0000,
0x002e,0x0000,

0xffa0,0xffc0,
0x0060,0xffc0,
0xffd2,0xffc0,
0x0000,0xffc0,
0x003e,0xffc0,

//free throw (PF)
0x0050,0x0000,
0xffc0,0x0000,
0xffd0,0x0000,
0x0000,0x007f,
0x002e,0x0000,

0xffa0,0xffc0,
0x0060,0xffc0,
0xffd2,0xffc0,
0x0000,0xffc0,
0x003e,0xffc0,

//free throw (C)
0x0050,0x0000,
0xffc0,0x0000,
0xffd0,0x0000,
0x002e,0x0000,
0x0000,0x007f,

0xffa0,0xffc0,
0x0050,0xffc0,
0xffd2,0xffc0,
0x0000,0xffc0,
0x002e,0xffc0,




};




