#include "generic.h"
#include "lfptypes.h"
#include "define.h"
#include "ml.h"
#include "ctrl.h"
#include "audio.h"
#include "crowd.h"
#include "menu.h"
#include "shell.h"
#include "overgfx.h"
#include "file.h"
#include "stats.h"

#ifdef PC
 #include "textcode.h"
 #include "kernel.h"
#endif

#ifdef N64
 #include "tmem.h"
 #include "ft.h"
 #include "sub.h"
#endif

#if defined(NOAH)
	#include "camera.h"
#endif

#include "speech.h"
#include "comment.h"

#include "res/playerid.h"
#include "playbyplay.h"

#if defined(DEBUG) || defined(LOGGING)
#include "animres/anames.c"
#endif

#include "playgfx.h"

#define	DD_TIME	7

extern s8 ShowTrails;

extern int menuScoreboardFlag, camFirstFrame;

extern int demoMode,demoTimeout,fl___gDemoFlag;
extern int inTimeOut;
extern int SubCard;

extern void GiveBallToShooter();

int exitArcade;

bool ArcadeMode=ARCADE_MODE;
bool	InfoFlag=1;

int foul_cheat_flag=FALSE;

int invalid_pick=0;
int	AR_Time;			// Time until action replay
int	AR_Parm=0;			// Parameter to pass into routine

int	SR_Team;		// Scoring run information
int	SR_Points;

int	momentum;
int	mom_team;
bool	ice;

int	last_timeout;

int	BigPoints=0;

#if	defined(DEBUG)
char	*last_pos_rou;

int	testthisthing=0;
#endif

#ifdef PC
 static TXTCEL_T *rel_txt_cel;
 static TXTCEL_T *rel_txt_cel1;
 static TXTCEL_T *rel_txt_cel2;
 static TXTCEL_T *rel_txt_cel3;
 static TXTCEL_T *leg_txt_cel;
 static TXTCEL_T *top_txt_cel;
 static TXTCEL_T *main_txt_cel;

 char mikeStatusString[80];
 char statusString[80];
 char statusString2[80];

 int demoMode = FALSE;
 int gameOver = 0;

#endif

#define	RSB_MASK	(CTRL_UP|CTRL_DOWN|CTRL_LEFT|CTRL_RIGHT|CTRL_START|CTRL_FIRE_A|CTRL_FIRE_B|CTRL_TRIGGER)


char mikeStatusString[80];
char statusString[80];
char statusString2[80];

int demoMode;				//shell flags to trigger demo
#if 0
int demoTimeout;
#endif

bool infinite_turbo=FALSE;

bool	slo_mo=FALSE;
bool	slo_mo_skippie=0;

int status_var1;
int status_var2;
int status_var3;
int status_var4;
int status_var5;
int status_var6;
int status_var7;
int status_var8;

#ifdef N64
extern int exitArcade,gameOver;
#endif


#define	BACKDOWN_DIST	0x180000
#define	BACKDOWN_ZONE	0x1C0000

//#define	QUARTER_LENGTH	(ONE_MIN*5)

/**/
/**/
/**/

#define	FAA(p,n,f)	( (fadeaway_test(p))? (f) : (n) )

int	first_step_anims[2][2]=
		{
			{-TOP_FIRSTSTR, TOP_FIRSTSTL},
			{-TOP_FIRSTSTL, TOP_FIRSTSTR}
		};

int	fake_first_anims[2][2]=
		{
			{-TOP_FSTFLGOR, TOP_FSTFRGOL},
			{-TOP_FSTFRGOL, TOP_FSTFLGOR}
		};

int kobe_walk_anims[2][2]=
		{
			{-TOP_KSPNLGOR,TOP_KHOPFLGOR},
			{-TOP_KHOPFLGOR,TOP_KSPNLGOR}
		};

int kobe_fake_walk_anims[2][2]=
		{
			{-TOP_KSPNLGOR,TOP_KSPIN},
			{-TOP_KSPIN,TOP_KSPNLGOR}
		};

int	kobe_fake_run_anims[2][2]=
		{
			{-TOP_KBHFLGOR, TOP_KBHFRGOL},
			{-TOP_KBHFRGOL, TOP_KBHFLGOR}
		};

int	fake_run_anims[2][2]=
		{
			{-TOP_FLGOR, TOP_FRGOL},
			{-TOP_FRGOL, TOP_FLGOR}
		};

int	tempo=256;					// Current speed of the game >256 is faster than original
int	mtempo;						// Master tempo since tempo can change during the game
int	time_frame=0;
int	time_rate=0x100;
int	rep_frame=-1;
int	rep_frame2=-1;

int timeout_called;			//flags set by shell
int substitution_made;		//flag set by shell

int current_basket_y;		//y of basket being attacked

int lp_ctr;					//general purpose AI ctr inc every 30th sec
int possession_ticks;		//how long ball handler has had ball (30th sec)
int steal_ticks;			//how long since last steal attempt (to discourage repeated steals)
int freeze;					//if non-zero will freeze action and dec every ai loop until 0

playert *bhp;				//ptr to ball handler in player[]

int		ball_handler=0;		//index in player[] to ball handler
int		last_blocker;		//index of last player to block the ball
int		last_handler;		//index in player[] to last player to touch ball
int		last_shooter;		//index in player[] to last player to have shot the ball
int		last_dunker;		//last guy to dunk or layup the ball
int		assister;			//index in player[] to last player pass ball to ball handler (used for assist stats)
int		int_recvr;			//intended receiver of pass

int		pass_flag;			//stops get_recvr() whilst pass animation performed
bool	picked_up_flag;		//some body picking up loose ball
int		rebound_flag;		//rebounded shot ?
bool    human_reb_flag;		//if human is about to grab rebound, don't let CPU guy get it
bool	steal_flag;			//stolen ball
bool	alley_flag;			//alley-oop flag
char	dribble_flag;		//dribble picked up?
bool	in_play_flag;		//is ball inplay 0=NO, 1=yes
bool	got_pos_flag;		//have out of bound target positions been assigned
bool	not_there_yet;		//is everybody in position for free throw
bool	time_flag;			//clock running
bool	half_flag;			//has ball crossed half court line
bool	switch_flag;		//switch off switching control this loop
bool	ai_off_flag;		//1 = switch AI off
int		fast_break_flag;	//fast break AI active	
int     cam3_flag;			//flashy 3 way replay

int		inbounds_flag;		// 0 if ball inbounds 1,2,3,4 depending upon which line has been crossed to go out of bounds
bool	cut_flag;			// 1 if the CTRL_PICK button is held down to call a cut to basket

playert player[18];

teamt	ai_team[3];			//structure for teams
teamt	*cur_team;			//ptr to which team being processed currently

void check_boards(playert *plyr);
void check_routines(playert *plyr);
void move_player(playert *plyr);
playert	*check_cc_pick(playert *plyr);
bool make_first_step(playert *plyr);
void	check_fronting(teamt *tm);
bool	should_i_backdown(playert *plyr, int dist);
void	check_intentional_foul(playert *plyr);

extern  int	 CardCtr;

void reset_ai_flags(void)
{
	int	i;

	pass_flag	   =
	picked_up_flag =
	human_reb_flag =
	rebound_flag   =
	steal_flag	   =
	alley_flag	   =
	in_play_flag   =
	time_flag	   =
	half_flag      =
	switch_flag	   =
	ai_off_flag    =
	loose_flag	   =
	tip_off_flag   =
	cut_flag	   =

	time_flag = FALSE;
	cam3_flag      =0;
	scored_flag     = 0;
	timeout_called=0;
	release_flag=0;

	assister   = -1;
	last_shooter=-1;
	last_blocker=-1;
	SR_Team=-1;
	SR_Points = 0;	// fixes bug # 907?!? 9/23/99 - mjk
	
	SetDunkFlag(reset_ai_flags,FALSE);
	SetDribbleFlag(reset_ai_flags,0);

	new_shot_clock();

	mom_team=0;
	momentum=0;

	crossX = crossY = 0;

	five_sec_clock =
	ten_sec_clock  =
	steal_ticks = 0;
	possession_ticks = 0;
	back_down_ticks = 0;

	special_time = lp_ctr = 0;
	last_bounce  =0;

	last_pick=
	pick_ctr = 0;
	ft_flag = 0;
	free_throws = 0;

	foul_flag  =
	foul_flag2 =
	rebound_time = 0;
	shoot_stage  = 0;

	last_replay  = -ONE_MIN;

	last_sector   = -1;
	last_bh       = -1;
	last_sec_change = 0;

	last_free_throw = -1;
	oobs_sector     = -1;

	last_squeek_ctr = 0;
	last_grunt_ctr = 0;

	hang_flag      = 0;

	jingle_time    = 0;
	defense_time   = 0;
	defense_on     = 0;

	celebration_flag = 0;

	ice=TRUE;

	reset_play();

	memset(&player, 0x00, sizeof(player));

	for(i=0; i<10; i++)  player[i].no = i;		//mjk - set now and for ever

	ai_team[0].plyr1     =
	ai_team[0].main_plyr =
	ai_team[0].chaser    =
	ai_team[0].dt        =
	ai_team[0].helper	 = NULL;

	ai_team[1].plyr1     =
	ai_team[1].main_plyr =
	ai_team[1].chaser    =
	ai_team[1].dt        =
	ai_team[1].helper	 = NULL;

	ai_team[0].last_set_change = time_left+ONE_MIN;
	ai_team[1].last_set_change = time_left+ONE_MIN;

	ai_team[0].foul=0;
	ai_team[1].foul=0;

	CameraSpecialEnd();
	FreeThrowReturn();
	OverGfx_ResetCard();

	DC_Play=0;
	for (i=0; i<4; i++)
		PadFlash[i]=0;

	time_rate=0x100;
	SubCard = CardCtr = 0;	// fixes bug #983b
}


#define	TD(m,s)		((m)*ONE_MIN+(s)*ONE_SEC)
#define	DIST_FOUL	0x280000


check_for_fouling(int team)
{
	int	i;
	int	ds;
	int	dx,dy;
	int	dist;
	static int	breakdowns[][3]=
					{
					TD(0,9),	2,	10,
					TD(0,24),	3,	10,
					TD(0,48),	4,	10,
					TD(1,12),	6,	12,
					TD(1,36),	8,	12,
					TD(2,00),	10,	15,
					};

	ai_team[team].foul=0;	// before the return -
	// (end game with foul on for CPU away, if human is AWAY next game, flag was never cleared)


	if (ai_team[team].controllers[0])
		return;


	if (!in_play_flag)
		return;

	if (!possession_flag || bhp->zco)
		return;

	if (pcl__gMatch->sb___mQuarter<3)
		return;

	if (time_left>2*ONE_MIN)
		return;

	ds=pcl__gMatch->apcl_mTeamRam[1-team]->uw___tPoints-pcl__gMatch->apcl_mTeamRam[team]->uw___tPoints;
	if (ds<0 || ds>15)
		return;

	// Determine correct time interval
	for (i=0; i<sizeof(breakdowns)/sizeof(breakdowns[0]); i++)
		if (time_left<breakdowns[i][0])
			break;

	// Check to see if foul-time
	if (ds<breakdowns[i][1] || ds>breakdowns[i][2])
		return;

	ai_team[team].foul=1;
}

/* *************************************************************************/
/* move_team()*/
/* *************************************************************************/
/* move all players on a team,*/
/* checks for lane violations*/
/* checks replay buttons*/
/* starts double teams*/
/* make defenders help*/
/* *************************************************************************/
/* Inputs   - ptr to team*/
/* Output   -*/
/* *************************************************************************/

void move_team(teamt *tm)
{
int	   	p_no;
playert	*plyr, *plyr1;

	//clear other teams bump flags
	plyr=&player[tm->base^5];
	for (p_no=0; p_no<5; p_no++, plyr++)
	{
		plyr->bumped_into_2=plyr->bumped_into;
		plyr->bumped_into_me = 0;
		plyr->bumped_into    = 0;
	}

	if (PracticeMode && tm->base)
		return;

	switch_flag = FALSE;
	cur_team    = tm;

	plyr = tm->main_plyr;

    ctrlrs[0].ctrlr = ctrlrs[0].mctrlr = 0;

	if ( (loose_flag) || ((rebound_time!=0) && (rebound_time-lp_ctr < 10)) )
	{
		pick_a_chaser();
	}

	if (( ((ball_handler - tm->base) < 0) || ((ball_handler - tm->base) > 4) ) && (!loose_flag))
	{
		/*
		 * DEFENSE
		 */

		if ((possession_flag) && (cur_team->dt == NULL))
		{
			if (bhp->basket_dist < 0x480000)
			{
				playert *p;
				int dt;

				dt=-1;

				//which player has dt info for bhp
				for (p=player; p<&ball; p++)
				{
					if (markee[p->no] == ball_handler)
					{
						if (dt>0)	BRK;
						dt = doubles[p->no];
					}
				}
				if (dt<0)	BRK;


				if (dt>0)
				{
					switch(dt)
					{
						case 1:
						if (dribble_flag==0)					break;
						if (possession_ticks>(1.5*ONE_SEC))		break;

						case 2:
						if (!fast_break_flag)
							call_double_team(tm);
						break;
					}
				}
			}
		}


		// check for open ball handler
		rotate(tm);

		//check for dunk block
		if (dunk_flag)
		{
			look_for_blocker();
		}

		check_for_fouling(bhp->team^1);

	}
	else if ( ((ball_handler - tm->base) >= 0) && ((ball_handler - tm->base) < 5) )
	{
		/*
		 * OFFENSE
		 */
		check_target_dist(tm->plyr1);

		find_threat(bhp);

 		get_recvr();
	}


	plyr = tm->main_plyr;					/* move main man 1st*/
	move_player(plyr);

	plyr1	= plyr;
	plyr	= tm->plyr1;
	for (p_no=0; p_no<5; p_no++)
	{
        if (plyr != plyr1)
		{
			move_player(plyr);
		}

		plyr++;
	}
}



void move_player(playert *plyr)
{
playert *plyr2;
int kc;
int	i;

	CallChainP(move_player);

#if 0
	if (IS_PLYR_ONLY(JIM_HOLDEMAN_NIN))
	{
		int	phase;
		int	delta;
		int	hz=ONE_SEC*2;
		int	amplitude=0x30;
		int	scale= (((plyr->plyrROM->ub___pHgt & 0xf0)>>4) * 12);

		phase=lp_ctr%hz;
		if (phase>hz/2)
			phase=hz-phase;

		delta=(phase*amplitude/(hz/2))-(amplitude/2);
		plyr->scale=0x100+delta;
	}
#endif

	if (ArcadeMode || PracticeMode)
		plyr->turbo=plyr->max_turbo;

	if (ArcadeMode || PracticeMode)
		plyr->plyrRAM->sw___pEnergy=MAX_PLAYER_ENERGY;

	memset(&ctrlrs[0],0,sizeof(ctrlrs[0]));
	ctrlrs[0].roleplay=CPL_NOLOCK;

	current_ctrlr = ctrlrs + plyr->control;

	if (plyr->control)
		i=7;

	if (ICCL_ROOKIE)
	{
		int	mask=RSB_MASK;

		if (PracticeMode)
			mask|=CTRL_SHOULDER_L;

		if (plyr==bhp)
			mask|=CTRL_C_LEFT;
		else if (DEFENDING)
			mask|=CTRL_C_DOWN;
			
		current_ctrlr->ctrlr&=mask;
		current_ctrlr->mctrlr&=mask;
		current_ctrlr->tap&=mask;
		current_ctrlr->hold&=mask;
	}

	if (plyr->no==bhp->no && !plyr->control)
		if (is_pick_on(plyr) && plyr->play_flag==2)
		{
			float	r;

			plyr->play_flag=3;

			r=ReadRnd250()/256.0;
			if (r<0.85)	// Shoot
			{
				CTL_SETDOWN(current_ctrlr,CTRL_SHOOT);
			}
			else if (blocked_basket_test(plyr)==0xe)	// Cut
			{
				SetMain(move_player,plyr,cut_to_basket2);
			}

		}


	plyr->target_dist=MANHATTAN(plyr->xco-plyr->target_x,plyr->yco-plyr->target_y);

	if ((plyr->turbo) && (current_ctrlr->ctrlr & CTRL_TURBO) && (!ft_flag) )
	{
		if ((current_ctrlr->force > 0x80) && (plyr->turbo>TURBO_DEPLETE))
			current_ctrlr->force = 0x100;

		//deplete turbo
		plyr->turbo -= TURBO_DEPLETE;
		if (plyr->turbo < 0)
			plyr->turbo = 0;
	}
	else
	{
		current_ctrlr->ctrlr &= ~CTRL_TURBO;
		//recover turbo
		plyr->turbo += TURBO_RECOVER;
		if (plyr->turbo > plyr->max_turbo)
			plyr->turbo = plyr->max_turbo;
	}

	if (infinite_turbo && plyr->control)
		plyr->turbo=TURBO_LIMIT;

	kc = 0;
	if (ATTACKING)
	{
		if (in_play_flag)
		{
			if (KEY_ON)
			{
				if (((possession_flag) || (ball.main_routine == pass_ball_move)) && (!dunk_flag) && (shoot_stage==0))
				{
					if (time_left>ONE_SEC)
					{
						int y;

						y = plyr->yco;
						if (plyr->no > 4)	y = -y;

						if (y > (FOUL_LINE+EDGE) && y<BASE_LINE+EDGE )
						{
							if (abs(plyr->xco) < LANE_X)
							{
								kc = plyr->key_ctr+1;

								if (kc > 4*ONE_SEC)
								{
//phil									CommentQueue(PHRASE_3SECV, 0, HALF_SEC);
									FoulSet(move_player,plyr, THREE_SECOND);
									SetHalfFlag(move_player,FALSE);
								}
								else if (kc > 2*ONE_SEC)
								{
									reset_play();
								}
							}
						}
					}
				}
			}
		}

	plyr->key_ctr = kc;
	}

	// Handle collision avoidance here
#if 0
	if (ATTACKING && plyr->no!=bhp->no)
	{
		playert	*p,*e;

		//p=&player[plyr->base^5];
		//e=p+5;
		p=player;e=p+10;

		do
		{
			avoid_plyr(plyr,p,plyr->target_x,plyr->target_y);
		} while (++p<e);
	}
#endif

	// Check for illegal defense here
	if (plyr->control && DEFENDING && in_play_flag && !ICCL_ROOKIE &&
		!fast_break_flag && in_set_flag && pcl__gMatch->pcl__mOptions->sb___IllegalDef)
	{
		int		y;
		int		by;
		bool	illegal=TRUE;

		if (dunk_flag || shoot_stage || ball.main_routine==shot_ball_move)
			goto not_il;

		y=plyr->yco;
		if (plyr->no<5)
			y=-y;

		by=ball.yco;
		if (plyr->no<5)
			by=-by;

		if (by>0 && y>0)
		{
			playert *end;
			bool	kf=FALSE;

			plyr2=&player[plyr->base^5];
			end=plyr2+5;
			if ( y>(FOUL_LINE+EDGE) && abs(plyr->xco)<LANE_X )	// check if defender in key
				kf=TRUE;

			// Check other team for a close player
			while(plyr2!=end)
			{
				if (MANHATTAN(plyr2->xco-plyr->xco,plyr2->yco-plyr->yco)<ILLEGAL_DIST)
				{
					if (!(kf && (abs(plyr2->xco)<LANE_X && abs(plyr2->yco)<(FOUL_LINE+EDGE)) ) )
					{
						illegal=FALSE;
						break;
					}
				}

				plyr2++;
			}

			if (illegal)
			{
				if (++plyr->key_ctr>ILLEGAL_TIME)
				{
					FoulSet(move_player,plyr, ILLEGAL_DEFENSE);
					plyr->key_ctr=0;
				}
			}
			else
				goto not_il;
		}
		else
not_il:		plyr->key_ctr=0;
	}

	// Handle switching here
	if (plyr->control)
	{
		//can't switch from ball handler
		if (!BALL_HANDLER)
		{
			//can't switch from intended receiver
			if ((plyr->no != int_recvr) || (ball.main_routine != pass_ball_move))
			{
				if (!tip_off_flag)
				{
					if (AUTO_SWITCH)
					{
						// Do not allow auto-switch while in the middle of a give-n-go
						if (!((plyr==bhp && CCTL_PRESS(CTRL_PASS) && ball.main_routine==pass_ball_move) ||
							(plyr!=bhp && bhp->main_routine==return_pass)))
						{
							//switch button disables auto switching
							if (!(current_ctrlr->ctrlr & CTRL_SWITCH))
							{
								//released switch button triggers switch
								if (current_ctrlr->last & CTRL_SWITCH)
								{
									switch_plyr(plyr, cur_team, ball_score);
									switch_flag = TRUE;	//no more switching this team this loop
								}
								//how long since last switch?
								else if (lp_ctr - current_ctrlr->last_switch > ONE_SEC || current_ctrlr->last_switch>lp_ctr)
								{
									auto_switch_plyr(plyr, cur_team, ball_score);
									switch_flag = TRUE;	//no more switching this team this loop
								}
							}
						}
					}
					else
					{
						if (switch_flag==FALSE)
						{

							//test switch buttons
							if (CCTL_PRESS(CTRL_C_UP))
							{
								//jmask(CTRL_C_UP);
								CTL_RMASK(current_ctrlr,CTRL_C_UP);
						#ifdef USA
								switch_plyr(plyr, cur_team, basket_score);
						#endif
						#ifdef PAL
								switch_plyr(plyr, cur_team, basket_score);
						#endif
						#ifdef JAPAN
								switch_plyr(plyr, cur_team, joy_score);
						#endif
						

								switch_flag = TRUE;	//no more switching this team this loop
							}
							else if (CTL_PRESS(current_ctrlr,CTRL_SWITCH))
							{
								CTL_RMASK(current_ctrlr,CTRL_SWITCH);
								switch_plyr(plyr, cur_team, ball_score);
								switch_flag = TRUE;	//no more switching this team this loop
							}
						}
					}
				}
				//use new controller
				current_ctrlr = ctrlrs + plyr->control;
			}
		}
		else	// Ballhandler code from this point
		{
			if (icon_flag==ICON_OFF && !(ft_flag || free_throws))	// Only call picks & cuts if not in icon passing
			{
				if (CTL_TAP(current_ctrlr,CTRL_PICK))	// Check for a pick
				{
					if ((pick_ctr==0) && (lp_ctr-last_pick>ONE_SEC))
					{
						jmask(CTRL_PICK);

						if (player[int_recvr].control==0)
						{
							plyr->pick_arm=TRUE;
							start_set_pick(player+int_recvr);
						}
					}
				}
				else if (CTL_HOLD(current_ctrlr,CTRL_PICK))	// Check for a cut to basket here
					cut_flag=TRUE;
				else if (cut_flag && in_play_flag)	// End of cut to basket?
				{
					cut_flag=FALSE;
					new_main(&player[int_recvr],cut_to_basket);
				}
			}
		}
	}

	// Check for computer-selected picks & cuts
	if ((!plyr->control || ICCL_ROOKIE) && BALL_HANDLER && !shoot_stage && !ft_flag && !free_throws)
		if ( plyr->basket_dist>0x500000 && plyr->basket_dist<0x800000) //IN_DOMAIN(plyr->basket_dist,0x800000,0xA00000))	//y<FOUL_LINE && y>FOUL_LINE/2)
			if ((pick_ctr==0) && (lp_ctr-last_pick>ONE_SEC))
			{
				playert	*pp;

				// Command a teammate to place a pick on the defender
				//if (ReadRnd250()<20)
#if 1
				if (pp=check_cc_pick(plyr))
				{
					plyr->play_flag=FALSE;
					plyr->target_x=plyr->xco;
					plyr->target_y=plyr->yco;
					plyr->pick_arm=(plyr->control)? FALSE : TRUE;
					start_set_pick(pp);
				}

				// Command a teammate to cut to the basket?
				else
#endif
					if ( (!plyr->control && ReadRnd250()<10) || (plyr->control && ReadRnd250()<2) )
				{
					int		flag=TRUE;	// Have man cut to basket?
					playert	*p,*e;

					p=&player[plyr->base];
					e=p+5;
					while(p<e)
					{
						if (p->main_routine==cut_to_basket)
							flag=FALSE;

						p++;
					}

					if (flag)
					{
						playert	*p;
						void (*mr)(playert *);

						p=&player[int_recvr];
						mr=p->main_routine;
						if (mr==deflt)
							new_main(p,cut_to_basket);
					}
				}
			}

	if (BALL_HANDLER)
	{
#ifdef MOVE

		if (KernelGetKeyStatus(KEY_X) & 1)
		{
			dribble_to_place(plyr);
		}

#else
		if (plyr->control == 0)
		{
			ball_handling_ai();

			// Do not allow shooting from behind the backboard
			if (CTL_DOWN(current_ctrlr,CTRL_SHOOT) || CTL_PRESS(current_ctrlr,CTRL_SHOOT))
				if (PLY(plyr)>GLASS_Y && abs(plyr->xco)<0x1C0000)
				{
					current_ctrlr->ctrlr&=~CTRL_SHOOT;
					current_ctrlr->mctrlr&=~CTRL_SHOOT;
				}
		}
#endif
	}

	// Handle arcade mode crap here
	if (BALL_HANDLER && plyr->main_routine==dribble && plyr->control && ICCL_ROOKIE)
	{
		if (CTL_DOWN(current_ctrlr,CTRL_SHOOT))
			if (plyr->basket_dist<0x500000)
				if (postup_test(plyr))
					goto revelation;

		if (plyr->backdown)	// currently backing down
		{
			if (!should_i_backdown(plyr,BACKDOWN_ZONE))		// Might be time to stop backing down
			{         
				if (++plyr->bdcc>5)		// Enough time passed to disengage from backing down
				{
					plyr->bdcp=0xe;
					plyr->backdown=0;
				}
				else		// Do not disengage yet, continue to back down
					current_ctrlr->ctrlr|=CTRL_SHUFFLE;
			}
			else		// Continue backing down
			{
				current_ctrlr->ctrlr|=CTRL_SHUFFLE;
				plyr->bdcc=0;
			}
		}
		else	// Not currently backing down
		{
			if (plyr->bdcp!=0xe)	// Player already chosen, but not yet time to backdown
			{
				if (!should_i_backdown(plyr,BACKDOWN_DIST))	// Disengaging from defensive player, not backing down
				{
						plyr->bdcp=0xe;
						plyr->bdcc=0;
				}
				else if (++plyr->bdcc>5)	// Engaged defensive player long enough, back down now
				{
					plyr->backdown=1;
					current_ctrlr->ctrlr|=CTRL_SHUFFLE;
					plyr->bdcc=0;
				}
			}
			else	// No player bumps yet
				if (should_i_backdown(plyr,BACKDOWN_DIST))
				{
					plyr->bdcp=5-plyr->base;
					plyr->bdcc=1;
				}
		}

	}

revelation:
	check_routines(plyr);

	if ((plyr->no == int_recvr) && (ball.main_routine == pass_ball_move))
	{
		//don't get ideas when being passed to

		if (plyr->control)
		{
			ctrlrs[0].force   = plyr->force;
			ctrlrs[0].d_angle = plyr->d_angle;
		}
		current_ctrlr = ctrlrs;
	}

	pivot_flag2 = FALSE;	//pivot forward by default;


	// Check ballhandler stuff
	if (possession_flag && in_play_flag && plyr->no==bhp->no && !plyr->zco)
	{
		// Check to see if the ballhandler goes out of bounds
		if (!PracticeMode && BOUNDARIES && player_inbounds_check(plyr))
		{
			drop_ball(plyr);
			FoulSet(move_player,plyr, OUT_OF_BOUNDS);
			possession_ticks=0;
		}

		// Check for points
		if (!(shoot_stage || dunk_flag || plyr->main_routine==finger_roll1))
			BigPoints=HotSpot_Check(plyr);
	}

	if ((plyr->main_routine == block_rou1) || (!in_play_flag))
	{
		plyr->kb_ctr =
		plyr->freeze_ctr = 0;
	}

	if (plyr->cross_ctr)	plyr->cross_ctr--;

	if ((plyr->kb_ctr) && ((rebound_time==0) || (plyr->ball_dist>0x300000)))
	{
		knocked_back(plyr);
	}
	else if (plyr->freeze_ctr)
	{
		frozen(plyr);
	}
	else
	{
		if (plyr->main_routine)		plyr->main_routine(plyr);

		plyr->force   = current_ctrlr->force;  // keep copies of the controller settings
		plyr->d_angle = current_ctrlr->d_angle;
		plyr->ctrlr   = current_ctrlr->ctrlr;
		plyr->bump_force=plyr->force;

		/* move legs */
		if (plyr->leg_routine)		plyr->leg_routine(plyr);
		/* move top */
		if (plyr->top_routine)		plyr->top_routine(plyr);
	}

	//make sure players havn't run into crowd
	check_boards(plyr);

	/* animate */
    animate(plyr);

	plyr->flags &= ~COLLIDE;

	if (ArcadeMode || PracticeMode)
		plyr->turbo=plyr->max_turbo;
}


#define CCP_TD	0x400000		// Maximum distance from target for offensive players
#define	CCP_CD	0x70000			// Closest distance offensive player can be for picking
#define	CCP_MD	0x140000		// Maximum distance to marker in which a pick will be called
#define	CCP_MC	0x1000			// Angle of cone in which marker is considered blocking

playert *check_cc_pick(playert *plyr)
{
	int		i;
	int		far;
	int		g;			// Number of players at a greater angle
	int		l;			// Number of players at a lesser angle
	int		cgm;		// Closest player on my team greater than me
	int		clm;		// Closest player on my team less than me
	int		t;			// Team that I'm on
	int		dl;			// Distance between lesser defenders
	int		dg;			// Distance between greater defenders
	int		dx,dy;		// Delta between two people
	SW		a;			// Angle of move
	playert	*gp[4];		// Players greater than me
	playert	*lp[4];		// Players less than me
	playert	*mgp;		// Closest player on my team greater than me
	playert	*mlp;		// Closest player on my team less than me
	playert	*p,*e;
	playert	*pp;		// Pick player

	t=plyr->team;
	TPPB(p,e);

	// Make sure ballhandler has the dribble available
	if (bhp->main_routine!=dribble)
		return NULL;

	// Check that its not too early on the clock yet
#if 0
	if (shot_clock>15*ONE_SEC)
		return NULL;
#endif

	// Make sure that the ball handler is in the right range
	if (bhp->basket_dist<0x600000 || bhp->basket_dist>0x900000)
		return NULL;

	// Check to see if marker is in correct position
	p=&player[bhp->marker];
	dx=p->xco-bhp->xco;
	dy=p->yco-bhp->yco;

	if (MANHATTAN(dx,dy)>CCP_MD)	// Is he close to me?
		return NULL;

	if (p->basket_dist>bhp->basket_dist)	// Is he closer to the basket
		return NULL;

	a=LFPAtn(dx,dy)-p->basket_angle;
	if (abs(a)>CCP_MC)
		return NULL;

	// Check that all the players are in their set positions
	far=0;
	do
	{
		if (p->no==bhp->no)
			continue;

		if (p->target_dist>CCP_TD) // In set defense?
			far++;

	} while(++p<e);

	if (far>1)
		return NULL;

	// Determine strong side
	g=0;
	l=0;
	cgm=clm=0x7fffffff;
	mlp=0;
	mgp=0;
	for(i=0; i<10; i++)
	{
		p=&player[i];

		// Skip the check if undesirable
		if (p->no==plyr->no)		// Don't check myself
			continue;

		if (p->markee==bhp->no)		// Don't check the guy defending me
			continue;

		// Classify and save player pointer
		if (p->basket_angle>=plyr->basket_angle)
		{
			if (p->team!=t)
				gp[g++]=p;
			else if ((dg=MANHATTAN(plyr->xco-p->xco,plyr->yco-p->yco))<cgm)
			{
				cgm=dg;
				mgp=p;
			}
		}
		else
		{
			if (p->team!=t)
				lp[l++]=p;
			else if ((dl=MANHATTAN(plyr->xco-p->xco,plyr->yco-p->yco))<clm)
			{
				clm=dl;
				mlp=p;
			}
		}
	}

	// If one side empty, call no pick
	if (!l || !g)
		return NULL;

	// If sides even, choose based on how loose the side is
	if (l==g)		// This better be 2 vs. 2
	{
		dl=MANHATTAN(lp[0]->xco-lp[1]->xco,lp[0]->yco-lp[1]->yco);
		dg=MANHATTAN(gp[0]->xco-gp[1]->xco,gp[0]->yco-gp[1]->yco);

		if (dl>dg)
			g++;
		else
			l++;
	}

	// Is any offensive player too close to pull off pick
	if (clm<CCP_CD || cgm<CCP_CD)
		return NULL;

	// Choose the lessor or greater?
	a=plyr->basket_angle;
	if (l<g)	// choose the lesser
	{
		if (plyr->basket_angle<0x1000)
			return NULL;

		pp=mlp;
		a+=0x3000;
	}
	else		// choose the greater
	{
		if (plyr->basket_angle>0x7000)
			return NULL;

		pp=mgp;
		a-=0x3000;
	}

	// Bug fix - phil
	if (!pp)
		return( NULL );

	// Can't set a human-controlled player to pick
	if (pp->control)
		return NULL;

	plyr->dunk_angle=a;
	return pp;
}

/* *************************************************************************/
/* inbounds_check()*/
/* *************************************************************************/
/* has a player or ball gone out of bounds?*/
/* *************************************************************************/
/* Inputs-  pointer to player data*/
/* Output   0 Ok, 2 near baseline, 1 far baseline, -1 right side,1 left side*/
/* *************************************************************************/
#define	BSL	0x768000
#define BBL	(BASE_LINE-(0xe00000-0xDF6AE0))

#define	PBL	(BASE_LINE-(0xe00000-0xDCA000))	// BASE_LINE

SW inbound_angles[]={
	0,
	0x4000,
   -0x4000,
	0x8000,
	0};

int player_inbounds_check(playert *plyr)
{
int flag;

	flag = 0;

	if (PracticeMode)
	{
		if (plyr->yco<0)
			flag=1;
	}
	else
		if (plyr->yco < -PBL)
			flag = 1;

	if (plyr->yco > PBL)	flag = 2;

	if (plyr->xco > SIDE_LINE)	flag = 3;

	if (plyr->xco < -SIDE_LINE)	flag = 4;

#if 1
	if (flag==0 && plyr->no==bhp->no && ball.zco<BALL_RADIUS*3/2)
	{
	#if 0
		if (PracticeMode)
		{
			if (ball.yco<0)
				flag=1;
		}
		else
	#endif
			if (ball.yco < -BBL)
				flag = 1;

		if (ball.yco > BBL)
			flag = 2;

		if (ball.xco > BSL)
			flag = 3;

		if (ball.xco < -BSL)
			flag = 4;
	}
#endif

	inbounds_flag	= flag;
	last_dunker = -1;

	return flag;
}




void shove_back_inbound(playert *plyr)
{
	if (PracticeMode)
	{
		if (plyr->yco<0)
		{
			plyr->yco=0;
			if (plyr->no==10)
				plyr->yvel/=-2;
		}
	}
	else
		if (plyr->yco < -BASE_LINE)
		{
			plyr->yco = -BASE_LINE;
			if (plyr->no==10)
				plyr->yvel/=-2;
		}

	if (plyr->yco > BASE_LINE)
	{
		plyr->yco = BASE_LINE;
		if (plyr->no==10)
			plyr->yvel/=-2;
	}

	if (plyr->xco > SIDE_LINE)
	{
		plyr->xco = SIDE_LINE;
		if (plyr->no==10)
			plyr->xvel/=-2;
	}

	if (plyr->xco < -SIDE_LINE)
	{
		plyr->xco = -SIDE_LINE;
		if (plyr->no==10)
			plyr->xvel/=-2;
	}
}


/* *************************************************************************/
/* check boards(plyr)*/
/* *************************************************************************/
/* has a player or ball gone beyond the boards? If so put him back at edge.*/
/* less strict than inbounds_check*/
/* *************************************************************************/
/* Inputs-  pointer to player data*/
/* *************************************************************************/


void check_boards(playert *plyr)
{
	if (PracticeMode && ((plyr->no==10 && (plyr->main_routine!=follow_player && plyr->main_routine!=shot_ball_move)) || plyr->no<5) )
	{
		shove_back_inbound(plyr);
		return;
	}

	if (plyr->yco < -BOARD_EDGE_Y )
	{
		plyr->yco = -BOARD_EDGE_Y;
	}
	else if (plyr->yco > BOARD_EDGE_Y )
	{
		plyr->yco = BOARD_EDGE_Y;
	}

	if (plyr->xco > BOARD_EDGE_X)
	{
		plyr->xco =  BOARD_EDGE_X;
	}
	else if (plyr->xco < -BOARD_EDGE_X )
	{
		plyr->xco = -BOARD_EDGE_X;
	}
}


/* *************************************************************************/
/* nothing*/
/* *************************************************************************/
/* dummy routine for player moves*/
/* *************************************************************************/
/* Inputs-  pointer to player data*/
/* Output   -*/
/* *************************************************************************/

void nothing (playert *plyr)
{

}


/* *************************************************************************/
/* deflt()*/
/* *************************************************************************** */
/* default movement main_routine. If cpu defend or move to attacking position. */
/* *************************************************************************** */
/* Inputs-  pointer to player data											   */
/* Output   -																   */
/* *************************************************************************** */

void deflt(playert *plyr)
{

	CallChainP(deflt);

#if defined(NOAH)
// hack to call up free throw from button A on controller 4...
	if (DEFENDING)
	{
		int mask=CTRL_FIRE_A;

		if (plyr->markee==ball_handler && bhp->control && possession_flag)
			if ((ctrlrs[4].ctrlr&mask)==mask)
			{
				FoulSet(deflt,plyr, HACKING2);
				free_thrower = ball_handler;
			}
	}
#endif

	if (plyr->pick_ctr)
		plyr->pick_ctr--;

	//CALLCHAIN(deflt);

	if (time_left==0)	return;

	//if ((plyr->leg_routine==NULL) && (int_recvr != plyr->no))	BRK;


	// Check for fall down due to dunker
	if (dunk_flag && plyr->team!=bhp->team)
	{
		int x,y;
		int	dx,dy;

		x=bhp->xco;
		y=bhp->yco;
		dx=plyr->xco-x;
		dy=plyr->yco-y;
		if (collide_check(bhp,plyr,dx,dy,COL_DI)!=-1)
		{
			int	a;

			a=LFPAtn(plyr->xco-bhp->xco,plyr->yco-bhp->yco);
			if (abs(a-bhp->angle)<0x2000)
			{
				int	dw;
				int	pct;

				dw=bhp->plyrROM->ub___pWgt-plyr->plyrROM->ub___pWgt;
				
				if (dw>=0)
					pct=15+dw*45/70;
				else
					pct=0;

				if (ReadRnd250()*100<pct*255)
				{
					start_fall(plyr,-plyr->basket_angle);
					return;
				}
			}

			bhp->xco=x;
			bhp->yco=y;
		}
	}

	// Check for falling down due to dribbler
	if (bhp->main_routine==first_step && bhp->top_frame<plyr->top_rate && plyr->team!=bhp->team)
	{
		int	dx,dy;

		dx=plyr->xco-bhp->xco;
		dy=plyr->yco-bhp->yco;

		if (MANHATTAN(dx,dy)<COL_DI*3)
		{
			SW a;

			a=LFPAtn(dx,dy);

			if (abs(a-bhp->angle)<0x2000 && abs((SW)(-a-plyr->angle))<0x2000)	// Both must face each other
			{
				int	delta;

				delta=bhp->plyrROM->ub___pAttrDribble+bhp->plyrROM->ub___pAttrSpeed/2-plyr->plyrROM->ub___pAttrSpeed;

				if (delta>=0)
				{
					int	pct;

					if (delta<40)
						pct=delta/8;
					else if (delta>=70)
						pct=60;
					else
						pct=delta-10;

					if (ReadRnd250()*100<pct*255)
					{
						int	da;

						start_fall(plyr,-plyr->basket_angle);
						da=LFPAtn(bhp->xco-plyr->xco,bhp->yco-plyr->yco)-plyr->angle;

						start_blend_anim(plyr,(da>0)? TOP_GRDFAKED:-TOP_GRDFAKED);
						plyr->zvel=0;
						plyr->flags|=MOVE_ROOT;

						return;

					}
				}
			}
		}
	}

	// When putting the ball in play, keep defenders away from the man taking the throw-in
	if (!in_play_flag)
	{
		if (free_throws==0)
		{
			if ((plyr->control) && (plyr->no != ball_handler))
			{
				if ((current_ctrlr->zero_timer<ONE_SEC) && ((plyr->no != play_cel) || (cel_ctr<2*ONE_SEC)) )
				{

					#define	PUSH_DIST	(COL_DI*3/2)
					#define	STOP_DIST	(PUSH_DIST+COL_DI/2)

					if (plyr->ball_dist<STOP_DIST)
					{
						switch(player_inbounds_check(plyr))	// Determine if the player is on the court or where out of bounds
						{
							case 1:			// Baseline
								current_ctrlr->d_angle=0x4000;
								current_ctrlr->force=0x80;
								break;

							case 2:			// Baseline
								current_ctrlr->d_angle=0xC000;
								current_ctrlr->force=0x80;
								break;

							case 3:			// Sideline
								current_ctrlr->d_angle=0x8000;
								current_ctrlr->force=0x80;
								break;

							case 4:			// Sideline
								current_ctrlr->d_angle=0x0000;
								current_ctrlr->force=0x80;
								break;

							default:		// On the court, check against the ball
								if (plyr->ball_dist<PUSH_DIST)	// Very close, automatically push out
								{
									int	bd,dx,dy;
									SW	ba;

									dx=plyr->xco-ball.xco;
									dy=plyr->yco-ball.yco;
									ba=LFPAtn(dx,dy);

									dx-=plyr->xvel;
									dy-=plyr->yvel;
									bd=LFPSqrt((dx>>12)*(dx>>12)+(dx>>12)*(dy>>12))<<12;

									current_ctrlr->d_angle=ba;
									current_ctrlr->force=0x80;

								}
								else if (plyr->ball_dist<STOP_DIST)		// Fairly close, allow no closer
								{
									int	bd,dx,dy;
									SW	ba;

									dx=plyr->xco-ball.xco;
									dy=plyr->yco-ball.yco;
									ba=LFPAtn(dx,dy);

									if (abs(current_ctrlr->d_angle-ba)>0x4800)	// Only zero out if trying to head towards ball
										current_ctrlr->force=0;
								}
								break;
						}
					}

					free_move(plyr);
					return;
				}
			}
		}


		if (move_to_place2(plyr))
		{
			if (plyr->no == ball_handler)
			{
				if (got_pos_flag)
				{
					if (!hang_flag)
					{
						start_pick_up_ball(plyr);
					}
				}
			}

			if (celebration_flag)
			{
				if ((plyr->no/5) == (celebration_flag-1))
				{
					if (plyr->no==plyr->base)
					{
						SetPossession(deflt,TRUE);
						SetBallHandler(deflt,plyr->no);
						bhp = plyr;
						SetMain(deflt,&ball,follow_player);
						start_anim(plyr, TOP_TROPHYF);
					}
					else
					{
						start_blend_anim(plyr, TOP_TROPHYA+plyr->no-plyr->base);
					}

					SetMain(deflt,plyr,nothing);
					plyr->leg_routine =
					plyr->top_routine = NULL;
				}
				else
				{
					start_blend_anim(plyr, TOP_TIRED);
					start_blend_leg_anim(plyr, LEG_RDY);
					SetMain(deflt,plyr,nothing);
					plyr->leg_routine =
					plyr->top_routine = NULL;
				}
			}
		}
		else
		{
			//note not everybody in position yet
			not_there_yet = TRUE;
		}
	}
	else
	{
		if (loose_flag)
		{
			if (ball_pickup_check(plyr))	return;
		}

		if (plyr->control)
		{
			if (DEFENDING)
			{
				if ((current_ctrlr->zero_timer > ONE_SEC/3) || (current_ctrlr->ctrlr & CTRL_SHUFFLE))
				{
					if (possession_flag)
					{
						//if covering ball handler, might be doubl teaming so don't switch
						if (markee[plyr->no] != ball_handler)
						{
							if (loose_covered(bhp, plyr))
							{
								goto no_switch;
							}
						}
					}

					if (!loose_covered(player+plyr->markee, plyr))
					{
						playert *op, *mark;

						mark=NULL;

						for (op=player+(plyr->base^5); op<player+(plyr->base^5)+5; op++)
						{
							if (op->no != plyr->markee)
							{
								if (loose_covered(op, plyr))
								{
									if (!mark)	mark = op;
								}
							}

						}

						if(mark)
						{
							switch_markers(mark, player+plyr->markee);
							current_ctrlr->zero_timer = 0;
						}
					}
				}
			}
no_switch:
			free_move(plyr);
		}
		else
		{
			if (ai_off_flag)	return;

			// Chase down a loose ball
			if (loose_flag && ai_team[plyr->team].chaser==plyr)
			{
				chase_loose_ball(plyr);
				return;
			}

			if ((DEFENDING)
				&& (ball.main_routine != shot_ball_move) )
			{
#if 0
				check_intentional_foul(plyr);
				if (CCTL_DOWN(CTRL_FOUL) && in_play_flag && (DEFENSIVE_FOULS || plyr->control) )
						foul_start(plyr);

				else
#endif 
				if (cur_team->dt ==  plyr)
				{
					double_team(plyr);
				}
				else if (cur_team->helper == plyr)
				{
					help(plyr);
				}
				else
				{
					defend(plyr);
				}
			}
			else
			{
				move_to_place(plyr);
			}
		}
	}
}

/* *************************************************************************/
/* dribble*/
/* *************************************************************************/
/* main_routine for dribbling players*/
/* *************************************************************************/
/* Inputs-  pointer to player data*/
/* Output   -*/
/* *************************************************************************/



void dribble (playert *plyr)
{
int temp;
int	c;
int dunk_type;
int	d;
int	an;
int	rate;		// animation rate
bool	flag=FALSE;

	CallChainP(dribble);

//	current_ctrlr->d_angle = (lp_ctr & 0x80)	? 0: 0x8000;
//	current_ctrlr->force   = 0xd0;

	//team_test();

	if (!project_flag)
	{
		if (dunk_flag)
		{
			BRK;
			SetDunkFlag(dribble,FALSE);
		}

		if (pass_flag)
		{
			//BRK;
			pass_flag = FALSE;
		}

	}

	//get_shoot_score(bhp);

	cur_team->main_plyr = plyr;

	loose_flag		= FALSE;

	if (!project_flag)
		SetDribbleFlag(dribble,1);

	pivot_flag      = NO_PIVOT;


	if (dribble_inbounds(plyr))	return;


#if 0
	c=current_ctrlr->mctrlr;
	if (c&(CTRL_C_UP|CTRL_C_DOWN|CTRL_C_LEFT|CTRL_C_RIGHT) && //c&CTRL_SHOULDER_R &&
		dunk_test(plyr)
		&& !(c&CTRL_SHOULDER_R))
		{
		// Determine the type of dunk
		if (c&CTRL_C_UP)
			dunk_type=0;
		else if (c&CTRL_C_DOWN)
			dunk_type=1;
		else if (c&CTRL_C_LEFT)
			dunk_type=2;
		else	// must, by default, be CTRL_C_RIGHT
			dunk_type=3;

		if (dunk_called(plyr,dunk_type))
			return;
		}
#endif

	if (current_ctrlr->mctrlr & CTRL_SHOOT)
	{
#if 1
		// Do a running dunk if valid
		if ((an=dunk_test(plyr)))
		{
			dunk_start(plyr,an);
			return;
		}

		// Do a standing dunk if valid
		if (sdunk_test(plyr))
			return;

		if (postup_test(plyr))
			return;

		if (finger_roll_test(plyr))
			return;
#endif
		// Do a standard floor shot if no dunk available
		shoot(plyr,select_shot(plyr));
		return;
	}

	/*  make pass */
	if ( ((current_ctrlr->mctrlr&(~current_ctrlr->last)&CTRL_PASS) && icon_flag==ICON_OFF) || CCTL_TAP(CTRL_PASS))
	{
		//if (!is_pick_on(plyr))
			start_pass(plyr);
		return;
	}


	if ((current_ctrlr->mctrlr & CTRL_POST_PASS) && (icon_flag == ICON_OFF))
	{
		// decide who to pass to and which pass sequence to follow
		start_post_pass(plyr);
		return;
	}

	if (possession_ticks > 3)
	{
		plyr->top_routine = dribble_animate;
	}

	if (plyr->control==0 || (ICCL_ROOKIE && !plyr->backdown) )
	{
		auto_crossover();
	}
	else
	{
	}

	if (!pass_flag)
	{
		if (icon_flag==ICON_OFF)
		{
			if (CTL_DOWN(current_ctrlr,CTRL_CROSSOVER))
			{
				int index;

				index = 0;
				//current_ctrlr->mctrlr = CTRL_DRIBBLE;
				if (plyr->last_speed > JOG_THRESHOLD)		index = 2;
				if (plyr->shuffle)							index = 4;

				special_start(plyr, index);
			}

			// Check for first step moves
			if (make_first_step(plyr))
				return;
		}
	}
}


//-----------------------------------------------------------------------------
//	Routine
//		which_side
//
//	Return Value
//		0: left
//		1: right
//
//	Description
//		Determines which side of the player a target player is on.  Left or
//		right is relative to the player and the direction he is facing, not a
//		global court left/right.
//-----------------------------------------------------------------------------
int	which_side(playert *plyr, playert *target)
{
	int	dx,dy;
	SW	angle;
	int	dir;

	dx=target->xco-plyr->xco;
	dy=target->yco-plyr->yco;
	angle=LFPAtn(dx,dy);
	//dir=((angle-player->angle)>=0)? 1 : 0;
	if (angle-plyr->angle>=0)
		dir=1;
	else
		dir=0;

	return dir;
}


//-----------------------------------------------------------------------------
//	Routine
//		first_step
//
//	Description
//		Main routine for handling a player in a first step maneuver.
//-----------------------------------------------------------------------------
void first_step(playert *plyr)
{
	int			ta,la;				// Top & Leg animatiosn
	int			tf,lf;				// Top & Leg frames
	void		(*lr)(playert *);	// Leg routine
	bool		loop=FALSE;
	int			chickie=-1;			// What would Chick say at a time like this?

	CallChainP(first_step);

	//move_by_anim(plyr);
	run_collision(plyr, plyr->xvel, plyr->yvel);
	plyr->angle += plyr->angle_vel;
	plyr->angle &= 0xffff;

	if (end_animation_test(plyr))	// Still executing maneuver?
	{
		//face_by_anim(plyr);


		switch(abs(plyr->top_anim))
		{
			case TOP_FIRSTSTR:
				ta=(plyr->top_anim>0)? TOP_JOG_DRIB : -TOP_JOG_DRIB;
				tf=61;
				la=LEG_JOG;
				lf=46;
				break;

			case TOP_FIRSTSTL:
				ta=(plyr->top_anim<0)? TOP_JOG_DRIB : -TOP_JOG_DRIB;
				tf=61;
				la=LEG_JOG;
				lf=11;
				break;

			case TOP_RCROSSR:
				ta=(plyr->top_anim>0)? TOP_JOG_DRIB : -TOP_JOG_DRIB;
				tf=31;
				la=LEG_JOG;
				lf=36;
				break;

			case TOP_FSTFRGOL:
				ta=(plyr->top_anim<0)? TOP_JOG_DRIB : -TOP_JOG_DRIB;
				tf=61;
				la=LEG_JOG;
				lf=51;
				break;

			case TOP_FSTFLGOR:
				ta=(plyr->top_anim>0)? TOP_JOG_DRIB : -TOP_JOG_DRIB;
				tf=21;
				la=LEG_JOG;
				lf=51;
				break;

			case TOP_FLGOR:
				ta=(plyr->top_anim>0)? TOP_JOG_DRIB : -TOP_JOG_DRIB;
				tf=61;
				la=LEG_JOG;
				lf=51;
				break;

			case TOP_FRGOL:
				ta=(plyr->top_anim<0)? TOP_JOG_DRIB : -TOP_JOG_DRIB;
				tf=51;
				la=LEG_JOG;
				lf=61;
				break;

			case TOP_BFRGOL:
				ta=(plyr->top_anim>0)? TOP_BSPINDRL: -TOP_BSPINDRL;
				tf=0;
				la=0;
				lf=0;
				loop=TRUE;
				break;

			case TOP_BSPINDRL:
				ta=(plyr->top_anim>0)? TOP_JOG_DRIB : -TOP_JOG_DRIB;
				tf=26;
				la=LEG_JOG;
				lf=46;
				break;

			case TOP_HARDAWAY:
				ta=(plyr->top_anim>0)? TOP_JOG_DRIB : -TOP_JOG_DRIB;
				tf=51;
				la=LEG_JOG;
				lf=11;
				break;

			case TOP_IVERSONA:
				ta=(plyr->top_anim>0)? TOP_JOG_DRIB : -TOP_JOG_DRIB;
				tf=11;
				la=LEG_JOG;
				lf=51;
				chickie=SFX_IVERSON2;
				break;

			case TOP_IVERSONB:
				ta=(plyr->top_anim<0)? TOP_JOG_DRIB : -TOP_JOG_DRIB;
				tf=31;
				la=LEG_JOG;
				lf=51;
				chickie=SFX_IVERSON2;
				break;

			case TOP_MARBURY:
				ta=(plyr->top_anim>0)? TOP_JOG_DRIB : -TOP_JOG_DRIB;
				tf=31;
				la=LEG_JOG;
				lf=11;
				break;

			case TOP_STDAMIRE:
				ta=(plyr->top_anim<0)? TOP_JOG_DRIB : -TOP_JOG_DRIB;
				tf=71;
				la=LEG_JOG;
				lf=11;
				chickie=SFX_STOUDAMIREWHATAMOVE;
				break;

			case TOP_VANEXCEL:
				ta=(plyr->top_anim>0)? TOP_JOG_DRIB : -TOP_JOG_DRIB;
				tf=11;
				la=LEG_JOG;
				lf=51;
				break;

			case TOP_VANHORN:
				ta=(plyr->top_anim<0)? TOP_JOG_DRIB : -TOP_JOG_DRIB;
				tf=61;
				la=LEG_JOG;
				lf=31;
				break;

			default:
				ta=(plyr->top_anim>0)? TOP_JOG_DRIB : -TOP_JOG_DRIB;
				tf=0;
				la=LEG_JOG;
				lf=0;
				break;
		}

		if (loop)
		{
			start_leg_anim(plyr,la);
			plyr->leg_frame=lf<<8;
			start_anim(plyr,ta);
			plyr->top_frame=tf<<8;
		}
		else
		{
			// If the top anim is a mirror, use opposite leg forward
			if (plyr->top_anim<0)
			{
				int	l;

				l=legAnims[la].a->numFrames;
				lf+=l/2;
				if (lf>=l)
					lf-=l;
			}

			plyr->last_speed = JOG_THRESHOLD-1;			

			start_blend_leg_anim(plyr,la);
			plyr->leg_frame=lf<<8;
			start_blend_anim(plyr,ta);
			plyr->top_frame=tf<<8;
			//plyr->leg_blend_speed = 0x20;
			//plyr->top_blend_speed = 0x20;


			SetMain(first_step,plyr,dribble);
			plyr->top_routine=dribble_animate;
			plyr->leg_routine=running;

			current_ctrlr->force=0x100;
			current_ctrlr->d_angle=plyr->angle;
			plyr->last_speed=0xa00;
			plyr->flags&=~MOVE_ROOT;

			if (first_step_flag && !plyr->control)
			{
				first_step_flag=FALSE;
				//if (blocked_basket_test(plyr)!=0xe)
					SetMain(first_step,plyr,cut_to_basket2);
			}

			if (!ArcadeMode && !project_flag && chickie>=0 && !Speech_IsBusy() && !Speech_IsQueued())
				Speech_PlayByPlay(chickie);

			if (!project_flag)
				ShowTrails=FALSE;
		}
	}
}

typedef struct fstepS{
	SW  anim;
	SW	leg;
	SW  angle;
	SW  av;
	int vel;
	
}fstepT;


fstepT fsTbl[]=
{
		TOP_FIRSTSTR,
		LEG_FIRSTSTR,
		-7618,
		-296,
		91,

		TOP_FIRSTSTL,
		LEG_FIRSTSTL,
		7594,
		240,
		89,

		TOP_RCROSSR,
		LEG_RCROSSR,
		1250,
		-446,
		92,

		TOP_FSTFRGOL,
		LEG_FSTFRGOL,
		1193,
		366,
		65,

		TOP_FSTFLGOR,
		LEG_FSTFLGOR,
		-4595,
		181,
		28,

		TOP_FLGOR,
		LEG_FLGOR,
		-3295,
		-266,
		56,

		TOP_FRGOL,
		LEG_FRGOL,
		3016,
		258,
		61,


		TOP_BFRGOL,
		LEG_BFRGOL,
		19027,
		-218,
		5,

		TOP_BSPINDRL,
		LEG_BSPINDRL,
		25014,
		2054,
		55,

		TOP_HARDAWAY,
		LEG_HARDAWAY,
		-1187,
		24,
		47,

		TOP_IVERSONA,
		LEG_IVERSONA,
		-4697,
		-193,
		48,

		TOP_IVERSONB,
		LEG_IVERSONB,
		2077,
		-1279,
		18,

		TOP_MARBURY,
		LEG_MARBURY,
		88,
		-143,
		14,

		TOP_STDAMIRE,
		LEG_STDAMIRE,
		2952,
		143,
		40,

		TOP_VANEXCEL,
		LEG_VANEXCEL,
		2887,
		1060,
		50,

		TOP_VANHORN,
		LEG_VANHORN,
		1368,
		68,
		8,

		TOP_KBHFLGOR,
		LEG_KBHFLGOR,
		-1777,
		-85,
		40,

		TOP_KBHFRGOL,
		LEG_KBHFRGOL,
		-3071,
		135,
		36,

		TOP_KSCROSS1,
		LEG_KSCROSS1,
		13142,
		11,
		0,

		TOP_KSPIN,
		LEG_KSPIN,
		218,
		-556,
		37,

		TOP_KWALKDRB,
		LEG_KWALKDRB,
		38,
		3,
		49,

		TOP_KHOPFLGOR,
		LEG_KHOPFLGOR,
		-651,
		-92,
		53,

		TOP_KSPNLGOR,
		LEG_KSPNLGOR,
		-3385,
		1776,
		66,

		0,0,0,0,
};


void start_first_step(playert *plyr, int an, int rate)
{
fstepT *fsPtr;
int a, v, av;

	fsPtr = fsTbl;

//	an=TOP_IVERSONB;

	while(abs(an) != fsPtr->anim)
	{
		if (fsPtr->anim == 0)	BRK;
		fsPtr++;
	}

	plyr->top_routine=NULL;
	plyr->leg_routine=NULL;


	a  = fsPtr->angle;
	v  = fsPtr->vel;
	av = (fsPtr->av*rate)>>8;

	start_blend_anim(plyr,an);

	if (an>0)
	{
		start_blend_leg_anim(plyr, fsPtr->leg);
	}
	else
	{
		start_blend_leg_anim(plyr, -fsPtr->leg);
		av = -av;
		a = -a;
	}

	plyr->angle_vel = av;
	plyr->leg_rate  = 
	plyr->top_rate  = (plyr->top_rate*rate)>>8;

	start_vels2(plyr, v, plyr->angle+a);

	plyr->flags&=~MOVE_ROOT;
}



bool standing_first_step(playert *plyr)
{
	bool	flag;
	int		dir;
	int		an;
	int		rate=0x100;
	int		dist;
	SW		angle;
	int		dx,dy;
	int		cone=0x8000-0x2000;
	playert	*dp;


	// This block only applies to Payton, so if more moves happen here, change this
	if (PLY(plyr))
		return FALSE;

	if (abs(plyr->angle-plyr->basket_angle)<0x6000)
		return FALSE;
	
	dp=&player[plyr->marker];
	dx=dp->xco-plyr->xco;
	dy=dp->yco-plyr->yco;
	dist=MANHATTAN(dx,dy);
	if (dist<(9*COL_DI)/8)
	{
		angle=LFPAtn(dx,dy);
		angle=plyr->angle-angle;
		if (angle>cone || angle<-cone)
		{
			dir=which_side(plyr,&player[plyr->marker]);
			an=(dir)? -TOP_PAYTON : TOP_PAYTON;


			start_first_step(plyr, an, rate);

			SetMain(standing_first_step,plyr,first_step);
			plyr->rlx=plyr->rly=0;
			CTL_RMASK(current_ctrlr,CTRL_SHUFFLE);

			return TRUE;
		}
	}

	return FALSE;
}



/* ************************************************************************ */
/* stand with ball														    */
/* ************************************************************************ */
/* main_routine for player standing with ball								    */
/* ************************************************************************ */
/* Inputs-  pointer to player data										    */
/* Output   -																*/
/* ************************************************************************ */

void stand_with_ball (playert *plyr)
{
SW	diff;
int top_anim;

	CallChainP(stand_with_ball);

	if (!project_flag)
	{
		if (!possession_flag)
		{
			BRK;
			set_default(plyr);
		}
		else
		{
			SetMain(stand_with_ball,&ball,follow_player);
			SetPossession(stand_with_ball,TRUE);
		}


		if (plyr->no != ball_handler)		BRK;
		if (dunk_flag)
		{
			//BRK;
			SetDunkFlag(stand_with_ball,FALSE);
		}

		if (pass_flag)
		{
			//BRK;
			pass_flag = FALSE;
		}
	}

	if (dribble_inbounds(plyr))	return;


	cur_team->main_plyr = plyr;

	SetPossession(stand_with_ball,TRUE);
	loose_flag		= FALSE;

	plyr->xvel	=
	plyr->yvel	=
	plyr->last_speed  = 0;

	plyr->top_routine = NULL;

	if (current_ctrlr->mctrlr & CTRL_SHOOT)
	{
		// Do a standing dunk if valid
		if (sdunk_test(plyr))
			return;

		if (postup_test(plyr))
			return;

		// Do a standard floor shot if no dunk available
		shoot(plyr,select_shot(plyr));
		return;
	}

	/*  make pass*/
	if ( ((current_ctrlr->mctrlr&(~current_ctrlr->last)&CTRL_PASS) && icon_flag==ICON_OFF) || CCTL_TAP(CTRL_PASS))
	{
// decide who to pass to and which pass sequence to follow
		start_pass(plyr);
		return;
	}

	if ((current_ctrlr->mctrlr & CTRL_POST_PASS) && (icon_flag == ICON_OFF))
	{
// decide who to pass to and which pass sequence to follow
		start_post_pass(plyr);
		return;
	}

	if (CTL_DOWN(current_ctrlr,CTRL_DRIBBLE))
		if (standing_first_step(plyr))
			return;

	// Check for brand-new fancy first-step moves
	if (make_first_step(plyr))
		return;

	if (dribble_flag && (current_ctrlr->ctrlr&CTRL_SHUFFLE))
	{
		current_ctrlr->d_angle = plyr->basket_angle^0x8000;
	}


	if (dribble_flag)		current_ctrlr->ctrlr &= ~CTRL_SHUFFLE;		  //don't shuffle

	if ((current_ctrlr->force > 0x70) || (current_ctrlr->ctrlr & CTRL_SHUFFLE))
	{
		if (dribble_flag)
		{
			diff = plyr->angle - current_ctrlr->d_angle;
			if (abs(diff) > 0x100)
				current_ctrlr->force = 0x10;	//face right way
			else
				current_ctrlr->force = 0;		//already facing right way
		}
		else
		{
			SetMain(stand_with_ball,plyr,dribble);
			plyr->top_routine  = dribble_animate;
		}
	}
	else if (current_ctrlr->force)
	{
		current_ctrlr->force = 0x10;	//turn and face d_angle only
	}




	//wait for bring ball down to finish
	if (plyr->top_anim == TOP_BALL_DOWN)
	{
		if (!end_animation_test(plyr))	return;
	}


	top_anim = TOP_STAND_BALL;

	switch(plyr->leg_anim)
	{
	case LEG_PVTB:
		top_anim = TOP_PVTB;
		break;

	case -LEG_PVTB:
		top_anim = -TOP_PVTB;
		break;

	case LEG_PVTF:
		top_anim = TOP_PVTF;
		break;

	case -LEG_PVTF:
		top_anim = -TOP_PVTF;
		break;
	}

	start_blend_anim(plyr,top_anim);
}



void stand_with_ball2 (playert *plyr)
{
int top_anim;

	CallChainP(stand_with_ball2);

	if (!project_flag)
	{
		if (!possession_flag)
		{
			BRK;
			set_default(plyr);
		}
		else
		{
			SetMain(stand_with_ball2,&ball,follow_player);
			SetPossession(stand_with_ball2,TRUE);
		}

		
		if (plyr->no != ball_handler)		BRK;
		if (dunk_flag)
		{
			SetDunkFlag(stand_with_ball2,FALSE);
			//BRK;
		}

		if (pass_flag)
		{
			//BRK;
			pass_flag = FALSE;
		}


	}

	cur_team->main_plyr = plyr;

	SetPossession(stand_with_ball2,TRUE);
	loose_flag		= FALSE;

	plyr->xvel	=
	plyr->yvel	=
	plyr->last_speed  = 0;

	plyr->top_routine = NULL;

	if (in_play_flag)
	{
		if (current_ctrlr->mctrlr & CTRL_SHOOT)
		{
			standing_j(plyr);
			return;
		}

		if (dribble_flag)
		{
			if (current_ctrlr->ctrlr & CTRL_SHUFFLE)
			{
				current_ctrlr->ctrlr &= ~CTRL_SHUFFLE;
				start_anim(plyr,TOP_BALL_DOWN);
				SetMain(stand_with_ball2,plyr,stand_with_ball);
				return;
			}
		}

		if (dribble_inbounds(plyr))	return;
	}
	else
	{
		SW	a_diff;

		if (player_inbounds_check(plyr))
		{
			//half_flag = FALSE;		/*no half-court violations*/

			a_diff = current_ctrlr->d_angle - inbound_angles[inbounds_flag];
			if (abs(a_diff) > 0x3fff)
			{
				current_ctrlr->d_angle	= (a_diff < 0) ? inbound_angles[inbounds_flag]-0x3fff:
														 inbound_angles[inbounds_flag]+0x3fff;
			}
		}

		if (current_ctrlr->force)	current_ctrlr->force=0x10;

		foul_flag = 0;

		current_ctrlr->ctrlr &= ~CTRL_SHUFFLE;
	}

/*  make pass*/
	if ( ((current_ctrlr->mctrlr&(~current_ctrlr->last)&CTRL_PASS) && icon_flag==ICON_OFF) || CCTL_TAP(CTRL_PASS))
	{
// decide who to pass to and which pass sequence to follow
		start_pass(plyr);
		return;
	}

	if ((current_ctrlr->mctrlr & CTRL_POST_PASS)	&& (icon_flag == ICON_OFF) && in_play_flag )
	{
// decide who to pass to and which pass sequence to follow
		start_post_pass(plyr);
		return;
	}

	if (CTL_DOWN(current_ctrlr,CTRL_DRIBBLE))
		if (standing_first_step(plyr))
			return;

	// Check for brand-new fancy first-step moves
	if (make_first_step(plyr))
		return;

	if (first_step_flag)
		return;

	if ((current_ctrlr->force > 0x70) || (current_ctrlr->ctrlr & CTRL_SHUFFLE))
	{
		SW a_diff;

		if (dribble_flag)
		{
			a_diff = plyr->angle - current_ctrlr->d_angle;
			if (abs(a_diff) > 0x100)
				current_ctrlr->force = 0x10;	//face right way
			else
				current_ctrlr->force = 0;		//already facing right way
		}
		else
		{
			//start top dribbling
			start_anim(plyr,TOP_BALL_DOWN);
			plyr->top_rate=0x200;
		}
	}
	else if (current_ctrlr->force)
	{
		current_ctrlr->force = 0x10;	//turn and face d_angle only
	}


	if (plyr->top_anim==TOP_BALL_DOWN)
	{
		if (end_animation_test(plyr))
		{
			plyr->top_routine = dribble_animate;
			SetMain(stand_with_ball2,plyr,dribble);
		}
		else
		{
			if (current_ctrlr->force)	current_ctrlr->force = 0x10;	//face right way
		}

		return;
	}


	top_anim = TOP_OVER_BALL;

	switch(plyr->leg_anim)
	{
	case LEG_PVTB:
		top_anim = TOP_PVT2B;
		break;

	case -LEG_PVTB:
		top_anim = -TOP_PVT2B;
		break;

	case LEG_PVTF:
		top_anim = TOP_PVT2F;
		break;

	case -LEG_PVTF:
		top_anim = -TOP_PVT2F;
		break;
	}

	start_blend_anim(plyr,top_anim);
}





static void ((*top_list[])(playert *plyr))=
{
	NULL,
	top_deflt,
	dribble_animate,
	top_in_place,
};

char *top_names[]={
	"NULL",
	"top_deflt",
	"dribble_animate", 			 //2
	"top_in_place",			 //3
};


static	void ((*leg_list[])(playert *plyr))=
{
	NULL,
	leg_deflt,			//standing
	running,			//running (walking jogging, turbo too)

	shuffle_stand,		 //standing pressing shuffle
	shuffling,			 //6
	shuffle_from_run,	 //8
	shuffle_from_run2,	 //8
	shuffle_from_run_init,

	turn_and_burn,		
	backward,

	steal_move,

	foul_move,
};

char *leg_names[]={
	"NULL",
	"leg_deflt",			
	"running",				 //2

	"shuffle_stand",		 //3
	"shuffling",			 //6
	"shuffle_from_run",		 //8
	"shuffle_from_run2",		 //8
	"shuffle_from_run_init",
	"turn_and_burn",
	//"turn180",

	"backward",
	"steal_move",

	"foul_move",
};



static	void ((*rou_list[])(playert *plyr))=
{
	NULL,

	intercept,						//intercepting pass routine
	intercept_recover,				//tween to dribble
	intercept_catch,				//pull ball in to stand with ball
	missed_intercept,				//intercept that's going to miss
	missed_intercept_recover,		//after miss
	jump_catch,						//make air catch
	jump_caught,					//after catch	
	
	nothing,						//as it says
	deflt,							//when not doing anything else
	stand_with_ball,				//stand with ball (@waist)
	stand_with_ball2,				//stand with ball (overhead)
	dribble,						//

	fake_shot_rou,					//fake shot (and start of jump shot)
	jump_shot_rou,					//in air now   to release of B button
	jump_shot_rou2,					//to release of ball
	jump_shot_rou3,					//to landing
	jump_shot_rou4,					//after landing

	shooting_foul_rou,
	shooting_foul_rou2,
	shooting_foul_rou3,
	shooting_foul_rou4,

	running_j_rou1,					//start of running j (goes to jump_shot_rou)

	finger_roll1,					//to take off
	finger_roll2,					//to release
	finger_roll3,					//to landing
	finger_roll4,					//to end of sequence

	dunk_take_off,					//to take off
	dunk_up_rou,					//to release
	dunk_down_rou,					//to landing
	landed,							//to end of seq

	rim_hang1,
	rim_hang2,
	rim_hang3,

	chest_pass,						//chest pass (used for other anims too)
	end_chest_pass,					//after release
	turn_chest_pass,				//turning to face receiver chest pass
	bounce_pass,					//
	turn_bounce_pass,
	end_turn_chest_pass,
	overhead_pass,
	base_pass,						//baseball pass
	base_pass2,

	jump_pass,						//pass out of J
	jump_pass2,						//to release
	jump_pass3,						//to landing

	down_first_pass,				//bring ball down (from overhead) before passing

	playback_pass_vals,				//replay pass values

	receive_pass,					//generate pass values
	hp_catch_wait,					//high post catch

	receive_alley1,					//to TO
	receive_alley2,					//to catch
	receive_alley3,					//to release

	jump_block_rou1,				//to TO
	jump_block_rou2,				//test for caught ball
	jump_block_rou3,				//bring arm down
	blocked_rou2,
	blocked_rou3,

	block_rou1,						//to takeoff
	block_rou2,						//to contact with ball - rebound_landed3

	run_block1,						//to takeoff
	run_block2,						//to landing
	run_block3,						//recover

	fall_routine,					//fall thru air
	fall_slide,						//slide on floor
	sat_down,						//pause
	get_up,							//get up

	start_pass,

	follow_player,					//ball routines
	pass_ball_move,		  
	loose_ball_move,
	shot_ball_move,
	made_ball_move,
	drop_bounce,		  

	run_screen,						//run round a screen set by another player not used in courside 1
	set_pick,						//set pick for another player
	picked,							//have set pick (and am waiting)

	turn180,						//turn on run using special animation

	rebound_rou1,					//on ground
	rebound_rou2,					//in the air
	rebound_rou3,					//come down (with or without ball)
	rebound_landed,					//wait for land sequence to be over

	tip_shoot,
	tip_rou2,

	spin_dribble,
	spin_wait,
	bb_dribble,
	bb_dribble_flip,
	crossover,
	crossover_wait,
	standing_crossover,
	standing_crossover_flip,

	std_x_left1,
	std_x_left2,
	std_x_right1,
	std_x_right2,
	std_wait,

	pick_up_ball,

	dribble_pickup_rou1,
	run_pickup_rou1,
	run_pickup_rou2,
	run_pickup_rou3,

	steal_rou,
	steal_react,
	steal_over,

	to_wait,
	to_waitc,

	to_to,
	to_up,
	to_down,
	to_land,

	baby_hook1,
	baby_hook2,
	baby_hook3,

	up_under1,
	up_under2,

	alley_pass0,
	alley_pass,
	cut_to_basket,
	cut_to_basket2,
	intercept_pass,

	foul_rou,
	foul_over,

	free_throw_pick_up,
	free_throw_wait,
	free_throw_shoot,
	free_throw_bounce,
	free_throw_recover,

	back_turn,

	grab_ball_rou,

	return_pass,

	first_step,

	fake_shot_return,

	missed_intercept2,
};


char *main_names[]={
	"NULL",								//NULL,                     									

	"intercept",			  			//intercept,              
	"intercept_recover", 	  			//bringBallDown,          
	"intercept_catch",	 	  			//bringBallDown,          
	"missed_intercept", 	  			//bringBallDown,          
	"missed_intercept_recover",			//bringBallDown,          
	"jump_catch",
	"jump_caught",

	"nothing",				  			//nothing,                
	"deflt",				  			//deflt,                  
	"stand_with_ball",		  			//stand_with_ball,        
	"stand_with_ball2",		  			//stand_with_ball2,       
	"dribble",			  				//dribble,			    
							  	    	
	"fake_shot_rou",		  			//fake_shot_rou,          
	"jump_shot_rou",		  			//jump_shot_rou,          
	"jump_shot_rou2",		  			//jump_shot_rou2,         
	"jump_shot_rou3",		  			//jump_shot_rou3,		    
	"jump_shot_rou4",		  			//jump_shot_rou4,         

	"shooting_foul_rou",
	"shooting_foul_rou2",
	"shooting_foul_rou3",
	"shooting_foul_rou4",

	"running_j_rou1",		  			//running_j_rou1,         

	"finger_roll1",			  			//finger_roll1,           
	"finger_roll2",			  			//finger_roll2,           
	"finger_roll3",			  			//finger_roll3,           
	"finger_roll4",			  			//finger_roll4,           
							  	    	                        
	"dunk_take_off",		  			//dunk_take_off,          
	"dunk_up_rou",			  			//dunk_up_rou,            
	"dunk_down_rou",		  			//dunk_down_rou,		    
	"landed",				  			//landed,                 
							  	    	                        
	"rim_hang1",			  			//rim_hang1,              
	"rim_hang2",			  			//rim_hang2,              
	"rim_hang3",			  			//rim_hang3,              
							  	    	//                        
	"chest_pass",			  			//chest_pass,             
	"end_chest_pass",		  			//end_chest_pass,         
	"turn_chest_pass",	 				//turn_chest_pass,	    
	"bounce_pass",			  			//bounce_pass,            
	"turn_bounce_pass",		  			//turn_bounce_pass,       
	"end_turn_chest_pass",	  			//end_turn_chest_pass,    
	"overhead_pass",		  			//overhead_pass,          
	"base_pass",			  			//base_pass,              
	"base_pass2",			  			//base_pass2,             
                        
	"jump_pass",			  			//jump_pass,              
	"jump_pass2",			  			//jump_pass2,             
	"jump_pass3",			  			//jump_pass3,             

	"down_first_pass",		  			//down_first_pass,        

	"playback_pass_vals",	  			//playback_pass_vals,     

	"receive_pass",			  			//receive_pass,           
	"hp_catch_wait",		  			//hp_catch_wait,          

	"receive_alley1",		  			//receive_alley1,         
	"receive_alley2",		  			//receive_alley2,         
	"receive_alley3",		  			//receive_alley3,         
							  	    	//                        
	"jump_block_rou1",		  			//jump_block_rou1,        
	"jump_block_rou2",		  			//jump_block_rou2,        
	"jump_block_rou3",		  			//jump_block_rou3,        
	"blocked_rou2",
	"blocked_rou3",
							  	    	//                        
	"block_rou1",			  			//block_rou1,             
	"block_rou2",			  			//block_rou2,             
							  	    	//                        
	"run_block1",			  			//run_block1,             
	"run_block2",			  			//run_block2,             
	"run_block3",			  			//run_block3,             
							  	    	//                        
	"fall_routine",			  			//fall_routine,           
	"fall_slide",			  			//fall_slide,             
	"sat_down",				  			//sat_down,			    
	"get_up",				  			//get_up,                 
							  	    	//                        
	"start_pass",			  			//start_pass,             
							  	    	//                        
	"follow_player",		  			//follow_player,          
	"pass_ball_move",		  			//pass_ball_move,		    
	"loose_ball_move",		  			//loose_ball_move,        
	"shot_ball_move",		  			//shot_ball_move,         
	"made_ball_move",		  			//made_ball_move,         
	"drop_bounce",			  			//drop_bounce,		    
							  	    	//                        
	"run_screen",			  			//run_screen,             
	"set_pick",				  	        //set_pick,                              
	"picked",				  			//picked,                 
							  			//                        
	"turn180",				  	    	//turn180,                
							  			//                        
	"rebound_rou1",			  	    	//rebound_rou1,           
	"rebound_rou2",			  			//rebound_rou2,           
	"rebound_rou3",			  			//rebound_rou3,           
	"rebound_landed",		  			//rebound_landed,         
							  			//                        
	"tip_shoot",			  	    	//tip_shoot,              
	"tip_rou2",				  			//tip_rou2,               
							  			//                        
	"spin_dribble",			  	    	//spin_dribble,           
	"spin_wait",			  			//spin_wait,              
	"bb_dribble",			  			//bb_dribble,             
	"bb_dribble_flip",		  			//bb_dribble_flip,        
	"crossover",			  			//crossover,              
	"crossover_wait",		  			//crossover_wait,         
	"standing_crossover",	  			//standing_crossover,     
	"standing_crossover_flip",			//standing_crossover_flip,
							  			//                        
	"std_x_left1",			  	    	//std_x_left1,            
	"std_x_left2",			  			//std_x_left2,            
	"std_x_right1",			  			//std_x_right1,           
	"std_x_right2",			  			//std_x_right2,           
	"std_wait",				  			//std_wait,               
							  			//                        
	"pick_up_ball",			  	    	//pick_up_ball,           
							  			//                        
	"dribble_pickup_rou1",	  	    	//dribble_pickup_rou1,    
	"run_pickup_rou1",		  			//run_pickup_rou1,        
	"run_pickup_rou2",		  			//run_pickup_rou2,        
	"run_pickup_rou3",		  			//run_pickup_rou3,        
							  			//                        
	"steal_rou",			  	    	//steal_rou,              
	"steal_react",			  			//steal_react,            
	"steal_over",			  			//steal_over,             
							  			//                        
	"to_wait",				  	    	//to_wait,                
	"to_waitc",				  			//to_waitc,               
							  			//                        
	"to_to",				  	    	//to_to,                  
	"to_up",				  			//to_up,                  
	"to_down",				  			//to_down,                
	"to_land",				  			//to_land,                
							  			//                        
	"baby_hook1",			  	    	//baby_hook1,             
	"baby_hook2",			  			//baby_hook2,             
	"baby_hook3",			  			//baby_hook3,             
							  			//                        
	"up_under1",			  	    	//up_under1,              
	"up_under2",			  			//up_under2,              
							  			//                        
	"alley_pass",			  	    	//alley_pass0,            
	"alley_pass0",			  			//alley_pass,             
	"cut_to_basket",		  			//cut_to_basket,          
	"cut_to_basket2",
	"intercept_pass",		  			//intercept_pass,         
							  			//                        
	"foul_rou",				  	    	//foul_rou,               
	"foul_over",			  			//foul_over,              
							  			//                        
	"free_throw_pick_up",	  	    	//free_throw_pick_up,     
	"free_throw_wait",		  			//free_throw_wait,        
	"free_throw_shoot",		  			//free_throw_shoot,       
	"free_throw_bounce",	  			//free_throw_bounce,      
	"free_throw_recover"	  			//free_throw_recover,     
							  			//                        
	"back_turn",			  	    	//back_turn,              

	"grab_ball_rou",

	"return_pass",

	"first_step",

	"fake_shot_return",

	"missed_intercept2",
	"error",							
};












/* *************************************************************************/
/* check_routines()*/
/* *************************************************************************/
/* check routine ptrs against list*/
/* save no in list for debugging purposes*/
/* if not in list print a warning*/
/* *************************************************************************/
/* Inputs   - ptr to plyr*/
/* Output   -*/
/* *************************************************************************/

void check_routines(playert *plyr)
{

bool flag;
int  i;

	plyr->mr_no = -1;
	plyr->top_no = -1;
	plyr->leg_no = -1;

	flag = TRUE;
	for (i=0 ;i<sizeof(rou_list)/sizeof(rou_list[0]); i++)
	{
		if (plyr->main_routine == rou_list[i])
		{
			plyr->mr_no = i;
			flag = FALSE;
			break;
		}
	}
	if (flag)
	{
		BRK;
	}


	flag = TRUE;
	for (i=0 ;i<sizeof(top_list)/4; i++)
	{
		if (plyr->top_routine == top_list[i])
		{
			plyr->top_no = i;
			flag = FALSE;
			break;
		}
	}
	if (flag)
	{
		BRK;
	}

	flag = TRUE;
	for (i=0 ;i<sizeof(leg_list)/4; i++)
	{
		if (plyr->leg_routine == leg_list[i])
		{
			plyr->leg_no = i;
			flag = FALSE;
			break;
		}
	}
	if (flag)
	{
		BRK;
	}

	//	if (flag)	printf("player %d leg routine %x\n", plyr->no, plyr->leg_routine);
}


extern void PlayWhistleSfx(void);

void process_timeout(void)
{
	if (free_throws)
	{
		timeout_called=0;
		return;
	}


	if (timeout_called==1)
	{
		PlayWhistleSfx();

		SetDunkFlag(process_timeout,FALSE);
		SetShootStage(process_timeout,0);
		inTimeOut = 1;
		timeout_called=2;
		last_timeout=time_left;

		DecNumberTimeOutsRemaining(bhp->team);	
//		pcl__gMatch->apcl_mTeamRam[bhp->team]->ub___tTimeOuts--;

		OverGfx_ShowTeamCard(bhp->team,CARD_TYPE_TIMEOUT,3*ONE_SEC);	// must be after dec

		// Update the momentum
		if (bhp->team^mom_team && ice)		// Icing other team?
		{
			momentum-=momentum>>2;
			ice=0;
		}

		if (ball_handler > 4)
		{
			if ((ball.yco<0) || ((time_left<30*ONE_SEC) && (!in_play_flag)))
			{
				init_players(away_halfcourt);
			}
			else
			{
				init_players(away_inbound);
			}
		}
		else
		{
			if ((ball.yco>0) || ((time_left<30*ONE_SEC) && (!in_play_flag)))
			{
				init_players(home_halfcourt);
			}
			else
			{
				init_players(home_inbound);
			}
		}

//		init_controls(); bug #224 - it just returned anyway if timeout_called

		five_sec_clock = 0;
		ten_sec_clock  = 0;
	}
}


void control_check(void)
{
int i;

#ifdef DEBUG
	for (i=0; i<4; i++)
	{
		if (controls[i]>=0)
		{
			if (player[controls[i]].control != i+1)		BRK;
		}
	}
#endif


	for (i=0;i<10;i++)
	{
		player[i].control = 0;
	}

	for (i=0; i<4; i++)
	{
		if (controls[i]>=0)
		{
			player[controls[i]].control = i+1;
		}
	}
}



/* *************************************************************************/
/* move()*/
/* *************************************************************************/
/* move both teams and ball*/
/* *************************************************************************/
/* Inputs   -*/
/* Output   -*/
/* *************************************************************************/

void move(void)
{
	control_check();

	if (possession_flag)
	{
		if (bhp->nearest_dist > 0x400000)
		{
			steal_ticks=0;
		}
		else
		{
			if (shoot_stage != 2)	steal_ticks++;
		}

		possession_ticks++;
	}
	else
		cut_flag=FALSE;

	// Determine whether the player will front his mark this frame
	check_fronting(&ai_team[(ball_handler<5)? 1 : 0]);

	get_positions();

	if ((ball_handler < 5) ^ (!in_play_flag) ^ (rebound_flag && possession_flag))
	{
		move_team(&ai_team[0]);
		move_team(&ai_team[1]);
	}
	else
	{
		move_team(&ai_team[1]);
		move_team(&ai_team[0]);
	}
	ball.main_routine(&ball);

	check_boards(&ball);
}


void end_quarter(void)
{

	if (pcl__gMatch->sb___mQuarter>=0)
	{
	}

	free_replay_buf();
}





void message(char *fname, int line)
{

char s[10];

#ifndef DEBUG
	strcpy(mikeStatusString, fname);
	strcpy(s, "       ");

	IntToDecStr(line,&s[1]);
	strcat(mikeStatusString, s);

 #ifdef PC
	strcat(mikeStatusString, __TIMESTAMP__);
 #else
	strcat(mikeStatusString, __TIME__);
	strcat(mikeStatusString, __DATE__);
 #endif

	string_flag = 1;
#endif

}




/* ***************************************************************************/
/* * StartGame ()                                                           **/
/* ***************************************************************************/
/* *                                                                        **/
/* ***************************************************************************/
/* * Inputs  -                                                              **/
/* *                                                                        **/
/* * Output  -                                                              **/
/* ***************************************************************************/

global void StartGame (void)
{
int team;
int	i;

	last_dunker = -1;

	mtempo=0x100+((0x21*pcl__gMatch->pcl__mOptions->sb___GameSpeed)>>7);
	reset_ai_flags();
//	ai_team[0].illegalD=ai_team[1].illegalD=0;
	demoMode=fl___gDemoFlag;

	
	if (PracticeMode)
	{
		pcl__gMatch->sb___mQuarter=-1;

	}

	CallChainInit();

#ifdef ML
	/*
	 * go to test positions for AI
	 */
#endif

#ifdef DUNK
	/*
	 * go to test positions for AI
	 */
	pcl__gMatch->sb___mQuarter = -1;
#endif

	start_quarter(pcl__gMatch->sb___mQuarter);

	if (pcl__gMatch->sb___mQuarter>0)
	{
		//wait for camera to get in place
		if ((ball.yco>0) ^ (switch_ends_flag))
		{
			freeze=ONE_SEC;
		}
		else
		{
			freeze=2*ONE_SEC;
		}
	}


#ifdef DEBUG
	if (pcl__gMatch->sb___mQuarter < 0)
	{
		pcl__gMatch->sb___mQuarter = 0;
	}

#endif

	reset_celebration();

	init_controls();

	init_camera();

	reset_play();

    InitRnd250();

	for(team=0; team < 2; team++)
	{
		if(ai_team[team].controllers[0] > 0)
		{	// put humans in manual substitution mode
			ai_team[team].manual_subs = 1;
		}
		else
		{
			ai_team[team].manual_subs = 0;
		}

		ai_team[team].illegalD = 0;

		ai_team[team].press = 0;

	}


	inTimeOut = 0;

	new_shot_clock();
	card_ctr  = ONE_SEC*3;	//get rid off score after 3 secs

	if (pcl__gMatch->sb___mQuarter == 0)
		Comment( COMMENT_WELCOME, NULL, 0 );

	for (i=0; i<10; i++)
	{
		fronts[i] = doubles[i]=0;
		pressures[i] = 1;	// start on "medium"	10/4/99
	}

	/* Now execute the main arcade loop.*/
    return;
}


/* ***************************************************************************/
/* * main_loop ()                                                           **/
/* ***************************************************************************/
/* *                                                                        **/
/* ***************************************************************************/
/* * Inputs  -                                                              **/
/* *                                                                        **/
/* * Output  -                                                              **/
/* ***************************************************************************/

global void main_loop (SI *v)
{
char string [80];
int leg_player;
int p;
int j;
int	i;

    /* Enter arcade game's main loop */

    get_dpad(v);

#if 0
	if (shoot_stage)
	{
		char text[128],numX[16],numY[16],numTime[16];

		IntToDecStr(lp_ctr,numTime);
		IntToHexStr(bhp->xvel,numX);
		IntToHexStr(bhp->yvel,numY);

		sprintf(text,"%s: %s,%s\n",numTime,numX,numY);
		PCwrite(-1, text, strlen(text));
	}
#endif

	if (menuScoreboardFlag)
	{
		for (i=1; i<=4; i++)
		{
			if (CTL_DOWN( &ctrlrs[i], CTRL_START ))
				menuScoreboardFlag = FALSE;
		}

		if (!menuScoreboardFlag)
		{
			PauseAll( FALSE );
			CamScoreBoard( FALSE );
			camFirstFrame = TRUE;
		}

		move_camera();
		return;
	}


	// Handle cruddy little slow down here
	if (slo_mo)
		if (slo_mo_skippie^=1)
			return;

	if ((PLY(bhp)<0 && ball.yco*((bhp->team)? -1:1)) || ball.main_routine==made_ball_move)
		Speech_PriorityGuy(Stu);
	else
		Speech_PriorityGuy(Chick);

	if (!possession_flag)
		first_step_flag=FALSE;

	// Crappy fix for blocking dunk shot
	if (!possession_flag && tempo!=mtempo)
		tempo=mtempo;

//#ifdef DEBUG

	if (CTL_DOWN(&ctrlrs[1],CTRL_C_RIGHT))
		ReadRnd250();

#if defined(NOAH) || defined(LOGGING)
	if (ctrlrs[4].ctrlr&CTRL_SHOULDER_L && !(ctrlrs[4].last&CTRL_SHOULDER_L))
		InfoFlag^=1;
#endif

#if defined(DEBUG) && 1
	if (ctrlrs[4].ctrlr&CTRL_SHOULDER_R && !(ctrlrs[4].last&CTRL_SHOULDER_R))
	{
		switch(time_rate)
		{
			case 0x100:
				time_rate=0x80;
				break;

			case 0x80:
				time_rate=0xc0;
				break;

			case 0xc0:
				time_rate=0x100;
				break;

			default:
				time_rate=0x100;
				break;
		}
	}
#endif

	if (!menuFlag && CTL_NEWPRESS(&ctrlrs[bhp->control],CTRL_SHOULDER_L))
	{
#if 0
		static int last_time=-100;

		if (lp_ctr-last_time<60)
			goto fuck_this_hack;
		else
			last_time=lp_ctr;
#endif
		ctrlrs[bhp->control].c_mask|=CTRL_SHOULDER_L;
		CTL_RMASK(&ctrlrs[bhp->control],CTRL_SHOULDER_L);

		if (PracticeMode)
		{
			if (!(ft_flag || free_throws))	// switch to free throws
			{
				bool	flag=TRUE;

				for (i=0; i<5; i++)
				{
					if (i==bhp->no)
					{
						if (player[i].main_routine!=dribble && player[i].main_routine!=stand_with_ball && player[i].main_routine!=stand_with_ball2)
							flag=FALSE;
					}
					else
					{
						if (player[i].main_routine!=deflt)
							flag=FALSE;
					}
				}

				if (flag)
				{
					if (ball.main_routine == pass_ball_move)
						set_default(player+int_recvr);

					in_play_flag = FALSE;
					time_flag    = FALSE;
					SetDunkFlag(dunk_flag,FALSE);
					pass_flag    = FALSE;
					fast_break_flag = FALSE;
					scored_flag=FALSE;
					free_thrower=bhp->no;

//					ft_flag=1;
					got_pos_flag = FALSE;
					if (possession_flag)
					{
						drop_ball(bhp);
						set_default(bhp);
					}

					start_drop_bounce(&ball);

					free_throws=300000;
					tempo=mtempo;
					last_bx  = ball.xco;
					last_by  = ball.yco;

					if (ball.zco<0x100000)	ball.zco = 0x100000;
					last_bz  = ball.zco;

					ball.target_x = 0;
					ball.target_y = FOUL_LINE+EDGE;

					ball.xvel = ball.yvel = ball.zvel = 0;
				}
			}
			else		// switch away from free throws
			{
				ShowFreeThrowHelp=FALSE;
				GiveBallToShooter();
				free_throws=0;
				ft_flag=0;
				FreeThrowReturn();
				FreeThrowStop();
				FreeThrowStopMotion();
			}
		}
	}
fuck_this_hack:


#ifdef ML
//#if 1
	if ((ctrlrs[2].mctrlr & CTRL_SHOULDER_L) && (!replay_flag))
		{
			end_quarter();
			ctrlrs[1].c_mask |= CTRL_SHOULDER_L;
			ctrlrs[2].c_mask |= CTRL_SHOULDER_L;

			reset_ai_flags();

			pcl__gMatch->sb___mQuarter = -1;

			start_quarter(-1);

			pcl__gMatch->sb___mQuarter = 0;

			reset_celebration();

			init_controls();

			init_camera();

			reset_play();

			new_shot_clock();

//old			AudioPlayCrowdSfx(AUDIO_CROWD_J1);

			lp_ctr = 0;
			status_var1=0;
			status_var4=0;
			status_var2=0;
			status_var3=0;

		}
#endif






#ifdef N64

#if defined(NOAH)
	if (ctrlrs[3].db_ctrlr & CTRL_SHOULDER_L)
	{
		#ifndef DEBUG
		string_flag ^= 1;
		#else
		time_left = 30*ONE_SEC;
		new_shot_clock();
		#endif
	}
#endif

	if(!menuFlag && !replay_flag && !demoMode && !celebration_flag && !gameOver)
	{
		int i;
		for(i=0;i<2;i++)
		{
			if(SubAutoMonitor(i))
			{
				OverGfx_ShowTeamCard(i,CARD_TYPE_DQ,ONE_SEC*3);
				GfxSubHack();
				SubDoSubstitution(i);
				Caption_Reset();
				break;
			}
			else if(foFlags[i] && SUBS_ALLOWED)
			{

				StartMenu(ai_team[i].controllers[0]-1,MENU_FORCESUB);
//				StartMenu(100+i,MENU_FORCESUB);
				break;
			}
		}
	}

	// consider quitting demo
	if(demoTimeout && demoMode && !replay_flag)
	{
		demoTimeout--;
		if(!demoTimeout || (ctrlrs[1].ctrlr || ctrlrs[2].ctrlr || ctrlrs[3].ctrlr || ctrlrs[4].ctrlr))
		{
			pcl__gMatch->sb___mQuarter=-1;	// signal player quit
			gameOver=1;
		}
	}


	if(gameOver && !menuFlag)
	{
		gameOver=0;
		end_quarter();
		SubProcessEndOfQuarter(pcl__gMatch->sb___mQuarter);
		if(pcl__gMatch->sb___mQuarter!=-1)
		{
			UpdateQuarterPts();
			XvertPlyrTimeOnCourt();
		}

		reset_ai_flags();
		start_quarter(++pcl__gMatch->sb___mQuarter);
		OverGfx_QuarterInit(pcl__gMatch->sb___mQuarter);
		last_timeout=quarter_length;
		time_left=quarter_length;
		reset_celebration();
		init_controls();
		init_camera();
		reset_play();
		new_shot_clock();
//old		AudioPlayCrowdSfx(AUDIO_CROWD_J1);
		lp_ctr = 0;

		#if 1
			switch(pcl__gMatch->sb___mQuarter)
			{
				case 0:		// player quit
					exitArcade=1;
					currentProcess->status = PROCESS_FREEING;
					break;
				case 1:
					//StartMenu(-1,MENU_QUARTER);
					break;
				case 2:
					//StartMenu(-1,MENU_HALFTIME);
					break;
				case 3:
					//StartMenu(-1,MENU_QUARTER);
					break;
				default:
					if(pcl__gMatch->apcl_mTeamRam[0]->uw___tPoints ==
					   pcl__gMatch->apcl_mTeamRam[1]->uw___tPoints)
					{
						if(pcl__gMatch->sb___mQuarter < 12)
						{
							// scores tied... keep going.
							//StartMenu(-1,MENU_QUARTER);
						}
						else
						{
							//StartMenu(-1,MENU_QUARTER);
							currentProcess->status = PROCESS_FREEING;
						}
					}
					else
					{
						// fulltime
						//StartMenu(-1,MENU_FULLTIME);
						currentProcess->status = PROCESS_FREEING;
					}
					break;
			}

			CallChainExit();
		#endif
	}
#endif

	// Check for action replay here
	if (!demoMode && !gameOver && !replay_flag)
	{
		if (AR_Time)
			if (!--AR_Time)
				if (lp_ctr-last_replay > (ONE_MIN/2))
				{
					last_replay = lp_ctr;

					switch(CAMERAS)
					{
					case 0:
						CamStartActionReplay(0);
						start_replay(-1);
						break;

					case 1:
						//CameraSpecialEnd();
						break;
					}
				}
	}



	if (!demoMode && !celebration_flag && !gameOver && !tip_off_flag)
	{
		int		l;
		int		c=FALSE;
		int		f[4];

		for (l=0; l<4; l++)
			f[l]=FALSE;

		for (l=0; l<10; l++)
			if (player[l].control)
				f[player[l].control-1]=c=TRUE;

		if (!c)
			f[0]=f[1]=f[2]=f[3]=TRUE;

		if (!f[menu_controller] && menuFlag)
			f[menu_controller]=TRUE;

		for (p=0;p<4;p++)
		{
			ctrlrT	*ctrl;

			if (!f[p])
				continue;

			ctrl=&ctrlrs[p+1];

			//if (test_and_mask(ctrlrs+p+1, CTRL_START))	break;

			if ((ctrlrs[p+1].ctrlr&CTRL_START) && !(ctrlrs[p+1].last&CTRL_START))
			{
				if (!menuFlag && !replay_flag)
				{
					stopAllMotors = TRUE;
					PauseAll( TRUE );

					if (PracticeMode)
						StartMenu( p, MENU_PRACTICE );	// this is now a subset of MENU_PAUSE (mjk  9/2/99)
					else
						StartMenu(p,MENU_PAUSE);
				}
				else if (manualReplayFlag)
				{
					EndMenu( p );
					end_replay( p );

					if (p == menu_controller)
					{
						PauseAll( FALSE );
						camFirstFrame = TRUE;
					}

					if (!replay_flag)
						manualReplayFlag = FALSE;
				}
				else if (!DumpGfxLoaded)
				{	// don't leave if no graphics 
	
				}
				else if(!ShellPauseMenuInited)	// ignore START if in shell pause menus (6/1/99 mjk)
				{
					if (p == menu_controller)
						PauseAll( FALSE );

					EndMenu(p);
				}

				break;
			}
		}

/*
#ifdef N64
		if((!freeThrowVisible || p==bhp->control-1) && !menuFlag)
		{
			StartMenu(p,MENU_PAUSE);
		}
#else
*/
	}


    if(menuFlag)
		ProcessMenu(v);

    if (replay_flag)
        process_replay();
	
//	if ( !(menuFlag || replay_flag) )
	if ( !(menuFlag || replay_flag || SubCard) )
    {
		manualReplayFlag=FALSE;

		if (possession_flag && !ft_flag && !timeout_called && !ArcadeMode)
		{
			for (i=0; i<2; i++)
			{
				bool call_it=FALSE;

				// Do not check auto-timeout if not valid
				if (bhp->team!=i)
					continue;

				if (timeout_called)
					continue;

				if (ai_team[i].controllers[0])	// Must be computer-controlled team
					continue;

//				if (!pcl__gMatch->apcl_mTeamRam[i]->ub___tTimeOuts)	// Need timeouts left
				if (!GetNumberTimeOutsRemaining(i))	// Need timeouts left
					continue;

				if(time_left < 30*ONE_SEC)
					continue;

				// Valid to call, but should the team call one?
				if (	SR_Team != bhp->team 
					&&	SR_Points>8
					&&	SCORET(bhp->team^1) - SCORET(bhp->team) < 20
					&& last_timeout - time_left > 150*ONE_SEC	  // - mjk (was 20 seconds)
					&& PLY(bhp)<0
				   )
					call_it=1;
#if	defined(DEBUG)
				if(testthisthing)	// modified in debugger
				{
					call_it = 1;
					testthisthing = 0;
				}				
#endif				
				// Call if so desired
				if (call_it)
				{
					timeout_called=1;
				}
			}
		}
		process_timeout();

		#ifdef N64
		if(!celebration_flag) SubProcessFatigue();
		#endif

		rep_frame2=rep_frame;
		save_replay();
		rep_frame=last_saved_frame;

//old        sfx = -1;

		advance_frame();
		if (!freeze)	//!freeze
		{
			get_angles_dist();

			if (cel_ctr)
				if (player[play_cel].control)
				{
					ctrlrs[player[play_cel].control].ctrlr&=~CTRL_TURBO;
					ctrlrs[player[play_cel].control].mctrlr&=~CTRL_TURBO;
				}

			move();

			process_celebration();

			if (glassScroll)  		glassScroll--;

			stats_update();

			clock_update();

			auto_set();

			manual_set();

			foul_check();

			defense_monitor();

			lp_ctr++;

			dunk_monitor();

			CheckFunkyTimeOutRules();

			//IntToDecStr(get_shot_percent(bhp, ((float)(pythag(bhp->xco, current_basket_y-bhp->yco))/0x100000)), statusString2);

			if (!replay_flag)	move_camera();
			else				process_replay();
		}
		else
		{
			//allow for start of quarter
			move_camera();
			freeze--;
		}
	}





#ifdef DEBUG
	status_var7 = player[9].plyrRAM->cl___pStatGame.uw___pBLK;
#endif


#ifdef PC

 #if 1
		if (rel_txt_cel1)
		{
			delete_text_cel( rel_txt_cel1);
			rel_txt_cel1 = NULL;
		}
		//rel_txt_cel1 = add_text_cel(mikeStatusString, 10, 20);

		if (rel_txt_cel2)
		{
			delete_text_cel( rel_txt_cel2);
			rel_txt_cel2 = NULL;
		}
		rel_txt_cel2 = add_text_cel(statusString, 10, 40);

		if (rel_txt_cel3)
		{
			delete_text_cel( rel_txt_cel3);
			rel_txt_cel3 = NULL;
		}
		rel_txt_cel3 = add_text_cel(statusString2, 10, 60);



 #endif
#endif

#ifdef SHOT_TEST
	edit_shot_data();
#endif

	//keep ticking over random #
#ifndef DEBUG
	ReadRnd250();
#endif

	/*
	if (!replay_flag)
	{
		status_var1 = bhp->leg_blend_ctr;
		status_var2 = bhp->leg_frame;
		status_var3 = bhp->last_leg_anim;
		status_var4 = bhp->last_leg_frame;

		status_var5 = bhp->top_blend_ctr;
		status_var6 = bhp->top_frame;
		status_var7 = bhp->last_top_anim;
		status_var8 = bhp->last_top_frame;
	}
	*/

}


void move_by_anim(playert *plyr)
{
	int			dx,dy;
	vector16	v,w;
	int			vx,vy;
	SW			angles[3];

	//evaluate root matrix 
	angles[0] = 0;
	angles[1] = plyr->pitch<<8;
	angles[2] = plyr->flip_angle+0x4000;
	AnglesToQuatPRH(&plyr->rootQuat, angles);
	QuatToMatrix(&plyr->rootMatrix, &plyr->rootQuat);


	v.x=plyr->aFrame.x;
	v.y=plyr->aFrame.y;
	v.z=plyr->aFrame.z;
	Vec16MulMat(&v, &plyr->rootMatrix, &w);

	dx=w.x<<10;
	dy=w.z<<10;

	vx=dx-plyr->rlx;
	vy=dy-plyr->rly;
	if (switch_ends_flag)
	{
		vx=-vx;
		vy=-vy;
	}
	if ( (vx>=plyr->xvel/2) || (vy>=plyr->yvel/2) || !end_animation_test(plyr))
	{
		plyr->xvel=vx;
		plyr->yvel=vy;
	}

	run_collision(plyr,plyr->xvel,plyr->yvel);

	plyr->rlx=dx;
	plyr->rly=dy;
}


void face_by_anim(playert *plyr)
{
	vector16	v,w;
	SW			a;
	int d1, d2;

	EvaluateAngles(plyr, &d1, &d2, 0);

	v.x=0x100;
	v.y=0;
	v.z=0;
	Vec16MulMat(&v, &plyr->skelMatrix[NODE_HIPS], &w);
	a=LFPAtn(w.x,w.z);
	plyr->angle=a-16384;
	if (switch_ends_flag)
		plyr->angle-=0x8000;
}

SW anim_angle(playert *plyr)
{
	vector16	v,w;
	SW			a;

	v.x=0x100;
	v.y=0;
	v.z=0;
	Vec16MulMat(&v, &plyr->skelMatrix[NODE_HIPS], &w);
	a=LFPAtn(w.x,w.z);
	a-=0x4000;
	if (switch_ends_flag)	a-=0x8000;
	return a;
}


bool is_pick_on(playert *plyr)
{
	playert	*p,*e;

	p=&player[plyr->base];
	e=p+5;
	do
	{
		if (p->main_routine==set_pick)
			break;

		if (p->main_routine==picked)
			break;

		if (p->pick_ctr>0)
			break;
	} while(++p<e);

	return (p!=e);
}






bool make_first_step(playert *plyr)
{
	bool	flag=FALSE;
	int		rate;
	int		an=0;
	int		rating;
	int		down,tap,hold;

	down=CCTL_DOWN(CTRL_DRIBBLE) & (~current_ctrlr->r_mask);
	tap=CCTL_TAP(CTRL_DRIBBLE) & (~current_ctrlr->r_mask);
	hold=CCTL_HOLD(CTRL_DRIBBLE) & (~current_ctrlr->r_mask);

	if (dribble_flag && 
		(plyr->main_routine==stand_with_ball || plyr->main_routine==stand_with_ball2) )
		return FALSE;

	// Check to see if computer player shouldn't perform move
	if (!plyr->control)
	{
		// Pick situations look like first step situations, but don't interrupt them
		if (is_pick_on(bhp))
			return FALSE;

		// Shitty dribblers aren't likely to make first step moves
		if (RANDOM(10000)>plyr->plyrROM->ub___pAttrDribble*plyr->plyrROM->ub___pAttrDribble/8)
			return FALSE;

		// Don't pull a move in the backcourt
		if (PLY(plyr)<0)
			return FALSE;
	}

	// All systems go, make that first step move
	rate=0x200;
	if (plyr->shuffle)		// Handle shuffle first steps here
	{
		if (tap)	// Move
		{
			// Check to see if turbo is available
			if (turbo_test(plyr, TURBO_DRIBBLE)==FALSE)
				return FALSE;

			an=(plyr->top_anim>0)? TOP_BSPINDRL : -TOP_BSPINDRL;
			flag=TRUE;
		}
		else if (hold) // Fake move
		{
			// Check to see if turbo is available
			if (turbo_test(plyr, TURBO_DRIBBLE)==FALSE)
				return FALSE;

			an=(plyr->top_anim>0)? -TOP_BFRGOL : TOP_BFRGOL;
			flag=TRUE;
		}
	}
	else	// Handle regular first steps here
	{
		switch(abs(plyr->leg_anim))
		{
			default:
			case LEG_RDY:
			case LEG_STAND:
				if (down)
				{
					int	dir;
					int	hand;

					// Check to see if turbo is available
					dir=which_side(plyr,&player[plyr->marker]);
					hand=(plyr->top_anim>0)?1:0;
					if (!(dir^hand))
					{
						int	pid;

						if (!dribble && IS_PLYR(STEPHON_MARBURY_NJ))
						{
							an=hand? TOP_MARBURY:-TOP_MARBURY;
							flag=TRUE;
							break;
						}

						pid=PID;
						if (ArcadeMode)
						{
							switch(rand()%4)
							{
							case 1:
								pid=PID_NICK_VANEXEL_DEN;
								break;

							case 2:
								pid=PID_STEPHON_MARBURY_NJ;
								break;

							case 3:
								pid=PID_ALLEN_IVERSON_PHI;
								break;
							}
						}

						switch(pid)
						{
							case PID_NICK_VANEXEL_DEN:
								an=hand? -TOP_VANEXCEL:TOP_VANEXCEL;
								flag=TRUE;
								break;

							case PID_STEPHON_MARBURY_NJ:
								an=hand? TOP_MARBURY:-TOP_MARBURY;
								break;

							case PID_ALLEN_IVERSON_PHI:
								if (rand()&1)
								{
									an=hand? -TOP_IVERSONA:TOP_IVERSONA;
									flag=TRUE;
								}
								else
								{
									an=hand? -TOP_IVERSONB:TOP_IVERSONB;
									flag=TRUE;
								}
								break;

							default:
								break;
						}

						if (flag)
							break;
					}
					else
					{
						if (IS_PLYR(DAMON_STOUDAMIRE_POR))
						{
							an=hand? TOP_STDAMIRE : -TOP_STDAMIRE;
							flag=TRUE;
							break;
						}
					}
				}

				if (an)
					break;

			case LEG_WALK:
				if (tap)
				{
					int	dir;
					int hand;

					// Check to see if turbo is available
					dir=which_side(plyr,&player[plyr->marker]);
					hand=(plyr->top_anim>0)?1:0;
					if (IS_PLYR_ONLY(KOBE_BRYANT_LAL))
						an=kobe_walk_anims[dir][hand];
					else
						an=first_step_anims[dir][hand];

					flag=TRUE;
				}
				else if (hold)
				{
					int	dir;
					int	hand;

					// Check to see if turbo is available
					if (turbo_test(plyr, TURBO_DRIBBLE)==FALSE)
						return FALSE;

					CCTL_RMASK(CTRL_DRIBBLE);

					dir=which_side(plyr,&player[plyr->marker]);
					hand=(plyr->top_anim>0)?1:0;
					if (IS_PLYR_ONLY(KOBE_BRYANT_LAL))
						an=kobe_fake_walk_anims[dir][hand];
					else
						an=fake_first_anims[dir][hand];
					flag=TRUE;

					if ( (dir^hand) && IS_PLYR(KEITH_VANHORN_NJ) && !dribble_flag)
						an=(dir)? TOP_VANHORN : -TOP_VANHORN;

					if (IS_PLYR_ONLY(KOBE_BRYANT_LAL))
						if (rand()%3==1)
							an=dir? TOP_KWALKDRB : -TOP_KWALKDRB;
				}
				break;

			case LEG_JOG:
			case LEG_RUN:
			case LEG_RUN2:
			case LEG_TURBO:
				if (down)
				{
					int	dir;
					int	hand;

					// Check to see if turbo is available
					CCTL_RMASK(CTRL_DRIBBLE);

					dir=which_side(plyr,&player[plyr->marker]);
					hand=(plyr->top_anim>0)?1:0;
					if (IS_PLYR_ONLY(KOBE_BRYANT_LAL))
						an=kobe_fake_run_anims[dir][hand];
					else
						an=fake_run_anims[dir][hand];
					flag=TRUE;

					if ( (dir&hand) && IS_PLYR(TIM_HARDAWAY_MIA) && ReadRnd250()<128)
						an=(dir)? TOP_HARDAWAY : -TOP_HARDAWAY;
				}
				break;
		}
	}

	switch(abs(an))
	{
		case TOP_BFRGOL:
			rate=0x150;
			break;

		case TOP_BSPINDRL:
			rate=0x150;
			break;

		case TOP_FIRSTSTR:
		case TOP_FIRSTSTL:
			rate=0x140;
			break;


		case TOP_FLGOR:
		case TOP_FRGOL:
			rate=0x199;
			break;

		case TOP_FSTFLGOR:
		case TOP_FSTFRGOL:
			rate=0x200;
			break;

		case TOP_HARDAWAY:
			rate=0x199;
			break;

		case TOP_IVERSONA:
			rate=0x180;
			break;

		case TOP_IVERSONB:
			break;

		case TOP_MARBURY:
			rate=0x199;
			break;

		case TOP_RCROSSR:
			rate=0x160;
			break;

		case TOP_STDAMIRE:
			rate=0x166;
			break;

		case TOP_VANEXCEL:
			rate=0x1cc;
			break;

		case TOP_VANHORN:
			rate=0x280;
			break;

		// New fancy-pants Kobe dribbles
		case TOP_KBHFLGOR:
		case TOP_KBHFRGOL:
		case TOP_KSCROSS1:
		case TOP_KSCROSS2:
		case TOP_KSPIN:
		case TOP_KWALKDRB:
		case TOP_KHOPFLGOR:
		case TOP_KSPNLGOR:
			rate=0x180;
			break;
	}

	// Start move if one is selected
	if (flag)
	{
		int v;
		int av;
		SW  a;

		// Ensure enough turbo juice
		if (turbo_test(plyr, TURBO_DRIBBLE)==FALSE)
			return FALSE;

		start_first_step(plyr, an, rate);

		SetMain(make_first_step,plyr,first_step);
		plyr->rlx=plyr->rly=0;
		CTL_RMASK(current_ctrlr,CTRL_SHUFFLE);
		if (!project_flag)
			SetDribbleFlag(make_first_step,1);

		if (!project_flag)
			if (ArcadeMode && MOM_MAX(plyr->team))
				ShowTrails=TRUE;
	}

	return flag;
}

#define	BCF		128			// Flag for fronting due to backcourt

void check_fronting(teamt *tm)
{
	int		i,e;
	playert	*p;

	for (i=0; i<5; i++)
		fronts[(tm->base^5)+i]&=~BCF;

	// If player is in the forecourt or a fast break is on, do not front
	if (PLY(bhp)>-FOUL_LINE || fast_break_flag)
	{
		for (i=0; i<5; i++)
			fronts[tm->base+i]&=~BCF;
		return;
	}

	// Player in back court, may front
	for (i=0; i<5; i++)
	{
		p=&player[tm->base+i];

#if 0
		if (p->markee==ball_handler)
			fronts[p->no]&=~BCF;
		else if (PLY(&player[p->markee])<0)
			fronts[p->no]&=~BCF;
		else
			fronts[p->no]|=BCF;
#else
		fronts[p->no]&=~BCF;
#endif
	}
}


bool should_i_backdown(playert *plyr, int dist)
{
	int		i;
	playert	*tgt;
	int		dp;
	SW		tpa,pta;

	if (fast_break_flag)
		return FALSE;

	if (blocked_basket_test(plyr)==0xe)
		return FALSE;

	for (i=0,tgt=&player[5-plyr->base]; i<5; i++,tgt++)
		if ((dp=MANHATTAN(plyr->xco-tgt->xco,plyr->yco-tgt->yco))<dist)
		{
			tpa=DA(PPA(tgt,plyr),plyr->d_angle);
			if (abs(tpa)<0x2000)
				if (abs(pta=PPRA(plyr,tgt))<0x3800)
					return TRUE;
		}

	return FALSE;
}

void check_intentional_foul(playert *plyr)
{
	int	dx,dy;
	int	dist;

	if (ArcadeMode)
		return;

	if (!ai_team[plyr->team].foul)
		return;

	// Foul time, head towards guy
	plyr->target_x=player[plyr->markee].xco+player[plyr->markee].xvel*4;
	plyr->target_y=player[plyr->markee].yco+player[plyr->markee].yvel*4;

	// Determine if ball handler can be fouled
	dx=bhp->xco-plyr->xco;
	dy=bhp->yco-plyr->yco;
	if ((dist=MANHATTAN(dx,dy))>DIST_FOUL)
		return;

	if (abs(LFPAtn(dx,dy)-plyr->angle)>0x2000)
		return;

	// Hit that sucker
	current_ctrlr->ctrlr|=CTRL_FOUL;
	current_ctrlr->mctrlr|=CTRL_FOUL;
}


#if defined(DEBUG)

static bool	CC_Flag[13]={ 0,0,0,0,0,0,0,0,0,0,0,0,1 };
//static bool	CC_Flag[13]={ 1,1,1,1,1,1,1,1,1,1,1,1,1 };
#define	IDX_BH		11
#define	IDX_HUMAN	12

#define	PRINT	1

int ccf=-1;

void _CallChainInit()
{
#if 0
	ccf=PCcreat("c:\\hockey\\bball2\\PlayLog.txt",0);
#endif
}

void _CallChainExit()
{
	PCclose(ccf);
}

void _CallChain
		(
		char	*routine,
		char	*file,
		int		line,
		playert	*plyr
		)
{
	int		i;
	char	txt[128];
	char	num[16];
	char	lineno[16];

#if !PRINT
	return;
#endif

	// Split if diagnostics are not to be printed out
	if (plyr)
	{
		if (!CC_Flag[plyr->no])
		{
			if (plyr==bhp)
			{
				if (!CC_Flag[IDX_BH])
					if (!plyr->control || (plyr->control && !CC_Flag[IDX_HUMAN]))
						return;
			}
			else if (plyr->control)
			{
				if (!CC_Flag[IDX_HUMAN])
					return;
			}
			else
				return;
		}
	}

	for (i=0; i<16; i++)
		num[i]=lineno[i]=0;

	IntToDecStr(lp_ctr,num);
	IntToDecStr(line,lineno);

	sprintf(txt,"%s: %d-%c%s [ %s:%s ]\n",num,plyr->no,project_flag? '*':' ',routine,file,lineno);
	PCwrite(ccf,txt,strlen(txt));
}

void _SetBallHandler
		(
		char	*routine,
		char	*file,
		int		line,
		int		player
		)
{
	int		i;
	char	txt[128];
	char	num[16];
	char	lineno[16];

#if PRINT
	for (i=0; i<16; i++)
		num[i]=lineno[i]=0;

	IntToDecStr(lp_ctr,num);
	IntToDecStr(line,lineno);
	sprintf(txt,"%s: ball_handler %d->%d [ %s (%s:%s)]\n",num,ball_handler,player,routine,file,lineno);
	PCwrite(-1,txt,strlen(txt));

	#if 1
		if (ccf!=-1)
			PCwrite(ccf,txt,strlen(txt));
	#endif

#endif

	ball_handler=player;
}

void _SetLastHandler
		(
		char	*routine,	// Name of calling routine
		char	*file,
		int		line,
		int		player		// New player as last handler
		)
{
	int		i;
	char	txt[128];
	char	num[16];
	char	lineno[16];

#if PRINT
	for (i=0; i<16; i++)
		num[i]=lineno[i]=0;

	IntToDecStr(lp_ctr,num);
	IntToDecStr(line,lineno);
	sprintf(txt,"%s: last_handler %d->%d [ %s (%s:%s)]\n",num,last_handler,player,routine,file,lineno);
	PCwrite(-1,txt,strlen(txt));

	#if 1
		if (ccf!=-1)
			PCwrite(ccf,txt,strlen(txt));
	#endif

#endif

	last_handler=player;
}


void _LogPointStats
		(
		char	*routine,
		char	*message,
		char	*file,
		int		line,
		playert	*p
		)
{
	int		i;
	char	txt[128];
	char	lp[16];
	char	lineno[16];

#if !PRINT
	return;
#endif

	for (i=0; i<16; i++)
		lineno[i]=lp[i]=0;

	IntToDecStr(lp_ctr,lp);
	IntToDecStr(line,lineno);

	sprintf(txt,"%s: %d - %s [ %s (%s:%s) ]\n",lp,p->no,message,routine,file,lineno);
	PCwrite(-1,txt,strlen(txt));

	if (ccf!=-1)
		PCwrite(ccf,txt,strlen(txt));
}


void _SetPossession
		(
		char	*routine,		// Name of routine
		char	*file,			// Source file of routine
		int		line,			// Line number of call
		int		state			// State to set possion_flag
		)
{
	int		i;
	char	txt[128];
	char	num[16];
	char	lineno[16];
	static char	*States[]={"Unpossessed","Possessed"};

	if (possession_flag!=state)
	{
#if PRINT
		for (i=0; i<16; i++)
			lineno[i]=num[i]=0;

		IntToDecStr(lp_ctr,num);
		IntToDecStr(line,lineno);

		sprintf(txt,"%s: %c%s [ %s (%s:%s) ]\n",num,project_flag? '*':' ',States[state],routine,file,lineno);
		PCwrite(-1,txt,strlen(txt));
	#if 1
		if (ccf!=-1)
			PCwrite(ccf,txt,strlen(txt));
	#endif

#endif
		possession_flag=state;
	}
}

void _SetMain
		(
		char	*caller,
		char	*file,
		int		line,
		playert	*plyr,
		void	(*rou)(playert *),
		char	*routine
		)
{
	int		i;
	char	txt[128];
	char	lp[16];
	char	lineno[16];
	char	idx;
	char	*omr;

#if PRINT
	if (!project_flag && rou!=plyr->main_routine)
	{
		for (i=0; i<16; i++)
			lp[i]=lineno[i]=0;

		IntToDecStr(lp_ctr,lp);
		IntToDecStr(line,lineno);

		if (plyr->no<10)
		{
			idx='0'+plyr->no;
			omr=main_names[plyr->mr_no];
		}
		else
		{
			idx='B';
			omr="***";
		}

		sprintf(txt,"%s: %c Set Main %s from %s [ %s (%s:%s) ]\n",lp,idx,routine,omr,caller,file,lineno);
		PCwrite(-1,txt,strlen(txt));
		if (ccf!=-1)
			PCwrite(ccf,txt,strlen(txt));
	}
#endif

	plyr->main_routine=rou;
}

void _SetIkBlendSpeed
		(
		char	*r,
		char	*f,
		int		line,
		playert	*plyr,
		int		speed
		)
{
	int		i;
	char	txt[128];
	char	lp[16];
	char	lineno[16];
	char	ss[16];

/*
#if PRINT
	for (i=0; i<16; i++)
		lp[i]=lineno[i]=ss[i]=0;

	IntToDecStr(lp_ctr,lp);
	IntToDecStr(line,lineno);
	IntToDecStr(speed,ss);

	sprintf(txt,"%s: %c%d IK Blend Speed: %s [ %s (%s:%s) ]\n",lp,project_flag? '*':' ',plyr->no,ss,r,f,lineno);
	PCwrite(-1,txt,strlen(txt));
	if (ccf!=-1)
		PCwrite(ccf,txt,strlen(txt));
#endif
*/

	plyr->ikBlendSpeed=speed;
}

void _SetHalfFlag
		(
		char	*r,
		char	*f,
		int		line,
		bool	state
		)
{
	char	txt[128];
	char	lp[16];
	char	lineno[16];

#if PRINT
	if (half_flag!=state)
	{
		memset(lineno,0,sizeof(lineno));
		memset(lp,0,sizeof(lineno));

		IntToDecStr(lp_ctr,lp);
		IntToDecStr(line,lineno);

		sprintf(txt,"%s: Set Halfcourt Flag %s [ %s (%s:%s) ]\n",lp,state? "On" : "Off",r,f,lineno);
		PCwrite(-1,txt,strlen(txt));
		if (ccf!=-1)
			PCwrite(ccf,txt,strlen(txt));
	}
#endif

	half_flag=state;
}


void _SetDunkFlag
		(
		char	*r,
		char	*f,
		int		line,
		bool	state
		)
{
	char	txt[128];
	char	lp[16];
	char	lineno[16];

#if PRINT
	if (dunk_flag!=state)
	{
		memset(lineno,0,sizeof(lineno));
		memset(lp,0,sizeof(lineno));

		IntToDecStr(lp_ctr,lp);
		IntToDecStr(line,lineno);

		sprintf(txt,"%s: Set Dunk Flag %d [ %s (%s:%s) ]\n",lp,state,r,f,lineno);
		PCwrite(-1,txt,strlen(txt));
		if (ccf!=-1)
			PCwrite(ccf,txt,strlen(txt));
	}
#endif

	dunk_flag=state;
}


void _SetShootStage
		(
		char	*r,
		char	*f,
		int		line,
		int		state
		)
{
	char	txt[128];
	char	lp[16];
	char	lineno[16];

#if PRINT
	if (shoot_stage!=state)
	{
		memset(lineno,0,sizeof(lineno));
		memset(lp,0,sizeof(lineno));

		IntToDecStr(lp_ctr,lp);
		IntToDecStr(line,lineno);

		sprintf(txt,"%s: Set Shoot Flag %d [ %s (%s:%s) ]\n",lp,state,r,f,lineno);
		PCwrite(-1,txt,strlen(txt));
		if (ccf!=-1)
			PCwrite(ccf,txt,strlen(txt));
	}
#endif

	shoot_stage=state;
}


void _SetPickedUpFlag
		(
		char	*r,
		char	*f,
		int		line,
		bool	state
		)
{
	char	txt[128];
	char	lp[16];
	char	lineno[16];

#if PRINT
	if (picked_up_flag!=state)
	{
		memset(lineno,0,sizeof(lineno));
		memset(lp,0,sizeof(lineno));

		IntToDecStr(lp_ctr,lp);
		IntToDecStr(line,lineno);

		sprintf(txt,"%s: Set Picked-Up Flag %d [ %s (%s:%s) ]\n",lp,state,r,f,lineno);
		PCwrite(-1,txt,strlen(txt));
		if (ccf!=-1)
			PCwrite(ccf,txt,strlen(txt));
	}
#endif

	picked_up_flag=state;
}

void _SetDribbleFlag
		(
		char	*r,
		char	*f,
		int		line,
		int		state
		)
{
	char	txt[128];
	char	lp[16];
	char	lineno[16];

#if PRINT
	if (dribble_flag!=state)
	{
		memset(lineno,0,sizeof(lineno));
		memset(lp,0,sizeof(lineno));

		IntToDecStr(lp_ctr,lp);
		IntToDecStr(line,lineno);

		sprintf(txt,"%s: Dribble Flag: %d [ %s (%s:%s) ]\n",lp,state,r,f,lineno);
		PCwrite(-1,txt,strlen(txt));
		if (ccf!=-1)
			PCwrite(ccf,txt,strlen(txt));
	}
#endif

	dribble_flag=state;
}

void _SetFreeThrowVisible
		(
		char	*r,
		char	*f,
		int		line,
		int		state
		)
{
	char	txt[128];
	char	lp[16];
	char	lineno[16];

#if PRINT
	{
		memset(lineno,0,sizeof(lineno));
		memset(lp,0,sizeof(lineno));

		IntToDecStr(lp_ctr,lp);
		IntToDecStr(line,lineno);

		sprintf(txt,"%s: Set Free Throw Visible %d [ %s (%s:%s) ]\n",lp,state,r,f,lineno);
		PCwrite(-1,txt,strlen(txt));
		if (ccf!=-1)
			PCwrite(ccf,txt,strlen(txt));
	}
#endif

	freeThrowVisible=state;
}

void _db_out
	(
	char	*r,
	char	*f,
	int		line,
	char	*msg
	)
{
	char	txt[128];
	char	lp[16];
	char	lineno[16];

	memset(lp,0,sizeof(lp));
	memset(lineno,0,sizeof(lineno));

	IntToDecStr(lp_ctr,lp);
	IntToDecStr(line,lineno);

	sprintf(txt,"%s: %s [ %s (%s:%s) ]\n",lp,msg,r,f,lineno);
	PCwrite(-1,txt,strlen(txt));
	if (ccf!=-1)
		PCwrite(ccf,txt,strlen(txt));
}

#endif
