//#define PHIL_TEST

#include "ult_64.h"
#include "generic.h"
#include "lfptypes.h"
#include "define.h"
#include "ml.h"

#define  FH	int
#include "stats.h"

#include "main.h"
#include "min.h"
#include "audio.h"
#include "track.h"
#include "speech.h"
#include "comment.h"

#include "playbyplay.h"
#include "colorguy.h"
#include "res/playerid.h"


#define	DIST_COVERED	0x140000

#define SUPER_DUNK	(45*TIME_FACTOR*3)

#define MAX_CHOICES 64

#define TIME_CHECK (3*ONE_MIN)
#define INIT_TIME -(30*ONE_MIN)


enum
{
	GRP_NONE = -1,
	GRP_OPENMAN = 0,
	GRP_RUN,
	GRP_MOM,
	GRP_COUNT
} EGroups;


typedef struct SPhrase
{
	u16		sample_id;			// Main commentary sample sound id
	s16		Group;
	u32		format;				// Audio format
	u16		TimeCheck;
	const char	*condition;			// Text string representing conditions for use
	int		LastPlayed;			// Time this sample was last played
} SPhrase;


typedef int		(*CPF)(const char *);
static bool		Parse(const char *,CPF parser);
static int		ParsePass(const char *);
static int		ParseShoot(const char *);
static int		ParseDunkScore(const char *);
static int		ParseLayup(const char *);
#define			ParseEndIsms	ParseShoot
#define			ParseDunkArc	ParseShoot
#define			ParseScore		ParseShoot
#define			ParseMadeFT		ParseShoot
#define			ParseMissFT		ParseShoot
#define			ParseMiss			ParseShoot
#define			ParseScoreArc		ParseShoot
#define			ParseDunk		ParseShoot
#define			ParseAlley		ParsePass
#define			ParseBlock		ParseShoot
#define			ParseFreeThrow	ParseShoot
#define			ParseTipIn		ParseShoot
#define			ParsePassSpecial		ParsePass

static int		ParseSlScore(const char *);
static int		ParseSlFoul(const char *);
#define	ParseSlRun			ParseSlScore
#define	ParseSlDiff			ParseSlScore
#define	ParseSlDunk			ParseSlScore
#define	ParseSlDunk1		ParseSlScore
#define	ParseSlDunk2		ParseSlScore
#define	ParseSlInbound	ParseSlScore
#define	ParseSlMiss			ParseSlScore
#define	ParseSlMadeFT		ParseSlFoul
#define	ParseSlMissFT		ParseSlFoul

static void		PlayBite(SPhrase *);
static void		PlayStu(SPhrase *);

#define	BALLER			1
#define	RECEIVER		2
#define	TORECEIVER	3
#define	AUDIO				4
#define	XBALLER			5
#define	LASTH				6
#define	FOULER			7
#define XRECEIVER		8
#define ASSISTER		9			// Helper
#define	TEAM				10
#define	OPPOSING		11

#define	COBITS		4
#define	COMASK		((1<<COBITS)-1)
#define	CO2(x,y)	( ((y)<<(COBITS))+(x) )
#define	CO3(x,y,z)	( ((z)<<(COBITS*2))+((y)<<(COBITS))+(x) )
#define	CO4(x,y,z,p)	( ((p)<<(COBITS*3))+((z)<<(COBITS*2))+((y)<<(COBITS))+(x) )
#define	CO5(x,y,z,p,q)	( ((q)<<(COBITS*4))+((p)<<(COBITS*3))+((z)<<(COBITS*2))+((y)<<(COBITS))+(x) )
#define	BAT			CO3(BALLER,AUDIO,TORECEIVER)
#define	BA			CO2(BALLER,AUDIO)
#define	BAA			CO3(BALLER,AUDIO,AUDIO)
#define	AT			CO2(AUDIO,TORECEIVER)
#define	RA			CO2(RECEIVER,AUDIO)
#define	XA			CO2(XBALLER,AUDIO)	/* Excited mention of ballhandler */
#define	LA			CO2(LASTH,AUDIO)
#define	AF			CO2(AUDIO,FOULER)
#define	FA			CO2(FOULER,AUDIO)
#define	Xr			XRECEIVER
#define	Xp			XBALLER
#define AB			CO2(AUDIO,BALLER)
#define ABA			CO3(AUDIO,BALLER,AUDIO)
#define	A				AUDIO
#define AA			CO2(AUDIO,AUDIO)
#define AAA			CO3(AUDIO,AUDIO,AUDIO)

#define	OA			CO2(OPPOSING,AUDIO)
#define	OAA			CO3(OPPOSING,AUDIO,AUDIO)
#define	HAB			CO3(ASSISTER,AUDIO,BALLER)
#define	TA			CO2(TEAM,AUDIO)
#define TAA			CO3(TEAM,AUDIO,AUDIO)
#define TAAA		CO4(TEAM,AUDIO,AUDIO,AUDIO)
#define TAAAA		CO5(TEAM,AUDIO,AUDIO,AUDIO,AUDIO)
#define	tA			CO2(TEAM,AUDIO)

#define PHRASE_COUNT(x) (sizeof(x)/sizeof(SPhrase))


// Chick phrases...


static SPhrase
	ClHi[] =
	{
		{ SFX_HIEVERYBODY1,	GRP_NONE,	A, 0, "" },
		{ SFX_HIEVERYBODY2,	GRP_NONE,	A, 0, "" },
		{ SFX_HIEVERYBODY3,	GRP_NONE,	A, 0, "" },
		{ SFX_HIEVERYBODY4,	GRP_NONE,	A, 0, "" },
	};

#define	NumClHi PHRASE_COUNT(ClHi)


static SPhrase
	ClPly[] =
	{
		{ SFX_WEREHEREFOR,		GRP_NONE,	   A,	0,	"" },
		{ SFX_WEREHERETOSEE,	GRP_NONE,	   A,	0,	"" },
	};

#define	NumClPly PHRASE_COUNT(ClPly)


static SPhrase
	Exhib = { SFX_WEREHEREFORTHEGAMEBETWEEN,	GRP_NONE,	   A,	0,	"" };

static SPhrase
	ClGame[] =
	{
		{ SFX_GAME1OF,	GRP_NONE,	   A,	0,	"" },
		{ SFX_GAME2OF,	GRP_NONE,	   A,	0,	"" },
		{ SFX_GAME3OF,	GRP_NONE,	   A,	0,	"" },
		{ SFX_GAME4OF,	GRP_NONE,	   A,	0,	"" },
		{ SFX_GAME5OF,	GRP_NONE,	   A,	0,	"" },
		{ SFX_GAME6OF,	GRP_NONE,	   A,	0,	"" },
		{ SFX_GAME7OF,	GRP_NONE,	   A,	0,	"" },
	};

static SPhrase
	ClPlyGame[][2] =
	{
		{
			{ SFX_WESTQUARTERS,	GRP_NONE,	   A,	0,	"" },
			{ SFX_EASTQUARTERS,	GRP_NONE,	   A,	0,	"" },
		},
		{
			{ SFX_WESTSEMIS,	GRP_NONE,	   A,	0,	"" },
			{ SFX_EASTSEMIS,	GRP_NONE,	   A,	0,	"" },
		},
		{
			{ SFX_WESTFINALS,	GRP_NONE,	   A,	0,	"" },
			{ SFX_EASTFINALS,	GRP_NONE,	   A,	0,	"" },
		},
		{
			{ SFX_NBAFINALS,	GRP_NONE,	   A,	0,	"" },
			{ SFX_NBAFINALS,	GRP_NONE,	   A,	0,	"" }
		}
	};

#define	NumClPlyGame PHRASE_COUNT(ClPlyGame)


static SPhrase Foul_3						= { SFX_3INTHEKEY,			GRP_NONE,	   A,	0,	"" };
static SPhrase Foul_5						= { SFX_5SECVIOL,				GRP_NONE,	   A,	0,	"" };
static SPhrase Foul_10					= { SFX_10SECVIOL,			GRP_NONE,	   A,	0,	"" };
static SPhrase Foul_24					= { SFX_24SECVIOL,			GRP_NONE,	   A,	0,	"" };
static SPhrase Foul_Backcourt		= { SFX_BACKCOURTVIOL,	GRP_NONE,	   A,	0,	"" };
static SPhrase Foul_IllegalD		= { SFX_ILLEGALDEFENSE,	GRP_NONE,	   A,	0,	"" };
static SPhrase Foul_Technical		= { SFX_ATTECHNICAL,		GRP_NONE,	   A,	0,	"" };
static SPhrase Foul_Charging		= { SFX_CHARGING2,			GRP_NONE,	   A,	0,	"" };
static SPhrase Foul_ReachingIn	= { SFX_REACHINGIN2,		GRP_NONE,	   A,	0,	"" };
static SPhrase Foul_Flagrant		=	{ SFX_FLAGRANTFOUL,		GRP_NONE,	   A,	0,	"" };


static SPhrase
	ClFoulOut[] =
	{
		{ SFX_HESFOULEDOUT,			GRP_NONE,	   A,	0,	"" },
		{ SFX_HESOUTTATHEGAME2,	GRP_NONE,	   A,	0,	"" },
	};

#define	NumClFoulOut PHRASE_COUNT(ClFoulOut)

static SPhrase
	ClFoulDunk[]=
	{
		{ SFX_OOHHEGOTHAMMERED,	GRP_NONE,	   A,	0,	 },
		{ SFX_HEGETSBUTCHERED,	GRP_NONE,	   A,	0,	 },
	};

#define	NumClFoulDunk PHRASE_COUNT(ClFoulDunk)

static SPhrase
	ClFoulShot[] =
	{
		{ SFX_THERESAWHISTLE,		GRP_NONE,	   A,	0,	 },
		{ SFX_WHISTLEONTHEPLAY,	GRP_NONE,	   A,	0,	 },
	};

#define	NumClFoulShot PHRASE_COUNT(ClFoulShot)

static SPhrase
	ClFoulOn[] =
	{
		{ SFX_ITSON,					GRP_NONE,	   AF,	0,	 },
		{ SFX_PICKSUPTHEFOUL,	GRP_NONE,	   FA,	0,	 },
		{ SFX_FOULON3,				GRP_NONE,	   AF,	0,	 },
	};

#define	NumClFoulOn PHRASE_COUNT(ClFoulOn)

static SPhrase
	ClFoulCount[] =
	{
		{ SFX_THATSHISFIRST,		GRP_NONE,	   A,	0,	"" },
		{ SFX_THATSHISSECOND2,	GRP_NONE,	   A,	0,	"" },
		{ SFX_THATSHISTHIRD,		GRP_NONE,	   A,	0,	"" },
		{ SFX_THATSHISFOURTH,		GRP_NONE,	   A,	0,	"" },
		{ SFX_THATSHISFIFTH,		GRP_NONE,	   A,	0,	"" },
		{ SFX_THATSHISSIXTH,		GRP_NONE,	   A,	0,	"" },
	};

#define	NumClFoulCount PHRASE_COUNT(ClFoulCount)


static SPhrase
	ClIllDef[] =
	{
//		{ SFX_COLLEGEBALL,	GRP_NONE,	AF,	0, "" },
//		{ SFX_NEED2LEARN,		GRP_NONE,	FA,	0, "" },
//		{ SFX_NOZONED,			GRP_NONE,	AF,	0, "" },
	};

#define	NumClIllDef PHRASE_COUNT(ClIllDef)


//SigRebound
#if 0
		{ SFX_BARKERLY,	GRP_NONE,	A, 5*60, "" },
#endif


//sig ft				{ SFX_HORNACEKRITUAL,	GRP_NONE,	A, 1*60, "" },


//sig dribble		{ SFX_IVERSON2,	GRP_NONE,	A, 1*60, "" },
//sig dribble		{ SFX_MARBURYMUSTARD,		PID_STEPHON_MARBURY_NJ,		A, 5*60, NULL },
//sig dribble		{ SFX_STOUDAMIREWHATAMOVE,	GRP_NONE,	A, 1*60, "" },
//sig dribble		{ SFX_VANEXELQUICK,	GRP_NONE,	A, 1*60, "" },

//block		{ SFX_MUTUMBOHOUSE,	GRP_NONE,	A, 1*60, "" },

//sig pass		{ SFX_STRICKLANDTRAFFIC,	GRP_NONE,	A, 1*60, "" },


#if 0
//hotspot 10 appears
				{ SFX_10PTOPEN,	GRP_NONE,	A, 1*60, "" },
				{ SFX_10PTOPEN2,	GRP_NONE,	A, 1*60, "" },
				{ SFX_10PTOPEN3,	GRP_NONE,	A, 1*60, "" },
				{ SFX_10PTOPEN4,	GRP_NONE,	A, 1*60, "" },

//hotspot 15 appears
				{ SFX_15PTOPEN,	GRP_NONE,	A, 1*60, "" },
				{ SFX_15PTOPEN2,	GRP_NONE,	A, 1*60, "" },
				{ SFX_15PTOPEN3,	GRP_NONE,	A, 1*60, "" },
				{ SFX_15PTOPEN4,	GRP_NONE,	A, 1*60, "" },
				{ SFX_15PTOPEN5,	GRP_NONE,	A, 1*60, "" },
				{ SFX_15PTOPEN6,	GRP_NONE,	A, 1*60, "" },

//hotspot 5 appears
				{ SFX_5PTOPEN,	GRP_NONE,	A, 1*60, "" },
				{ SFX_5PTOPEN2,	GRP_NONE,	A, 1*60, "" },
				{ SFX_5PTOPEN3,	GRP_NONE,	A, 1*60, "" },
				{ SFX_5PTOPEN4,	GRP_NONE,	A, 1*60, "" },
				{ SFX_5PTOPEN5,	GRP_NONE,	A, 1*60, "" },

//hotspot appears after above
				{ SFX_BEHIND3PT,	GRP_NONE,	A, 1*60, "" },
				{ SFX_BYKEY,	GRP_NONE,	A, 1*60, "" },
				{ SFX_INKEY,	GRP_NONE,	A, 1*60, "" },
				{ SFX_INSIDE3PTLINE,	GRP_NONE,	A, 1*60, "" },
				{ SFX_NEARHALFCOURTLINE,	GRP_NONE,	A, 1*60, "" },
				{ SFX_UNDERNEATHBASKET,	GRP_NONE,	A, 1*60, "" },

//				{ SFX_PASSITTOPLAYER1A,	GRP_NONE,	A, 1*60, "" },
//				{ SFX_PASSITTOPLAYER1B,	GRP_NONE,	A, 1*60, "" },
//				{ SFX_PASSITTOPLAYER2A,	GRP_NONE,	A, 1*60, "" },
//				{ SFX_PASSITTOPLAYER2B,	GRP_NONE,	A, 1*60, "" },
//				{ SFX_PASSITTOPLAYER3A,	GRP_NONE,	A, 1*60, "" },
//				{ SFX_PASSITTOPLAYER3B,	GRP_NONE,	A, 1*60, "" },

				{ SFX_SHOULDGETINZONE,	GRP_NONE,	BA, 1*60, "" },		// hotspot up for 3sec

//				{ SFX_PLAYERSHOULDSHOOT,	GRP_NONE,	A, 1*60, "" },
//				{ SFX_HOLESGONNACLOSESHOOT,	GRP_NONE,	A, 1*60, "" },
				{ SFX_SHOOTSHOOT,	GRP_NONE,	A, 1*60, "" },			// on a hotspot

				{ SFX_HEAD4THEZONE,	GRP_NONE,	A, 1*60, "" },		// not on a hotspot, hs on for 3, 10 feet away
				{ SFX_HEAD4THEZONE2,	GRP_NONE,	A, 1*60, "" },
				{ SFX_HEAD4THEZONE3,	GRP_NONE,	A, 1*60, "" },
				{ SFX_HEAD4THEZONE4,	GRP_NONE,	A, 1*60, "" },

//				{ SFX_10PTSHOOTER,	GRP_NONE,	A, 1*60, "" },
//				{ SFX_10PTSHOOTER2,	GRP_NONE,	A, 1*60, "" },
//				{ SFX_5PTSHOOTER,	GRP_NONE,	A, 1*60, "" },
//				{ SFX_15PTSHOOTER,	GRP_NONE,	A, 1*60, "" },
//				{ SFX_15PTSHOOTER2,	GRP_NONE,	A, 1*60, "" },

				{ SFX_BETTERMOVEFAST,	GRP_NONE,	A, 1*60, "" },			// hs on for 3sec
				{ SFX_BETTERMOVEFAST2,	GRP_NONE,	A, 1*60, "" },
				{ SFX_BETTERMOVEFAST3,	GRP_NONE,	A, 1*60, "" },
				{ SFX_BETTERMOVEFAST4,	GRP_NONE,	A, 1*60, "" },
				{ SFX_15POINTSGONNACLOSE,	GRP_NONE,	A, 1*60, "" },
				{ SFX_10POINTSGONNACLOSE,	GRP_NONE,	A, 1*60, "" },

				{ SFX_KOBEAMAZING,	GRP_NONE,	A, 1*60, "" },			// special dribble/ or dunk level 90+

#endif


// Chickisms
#if 0

				{ SFX_PLAYERCOOKIEJAR,	GRP_NONE,	A, 5*60, "" },			// reach in foul

//				{ SFX_GAMEPOPCORNMACHINE,	GRP_NONE,	A, 1*60, "" },


				{ SFX_WINTHETIP,	GRP_NONE,	A, 1*60, "" },
				{ SFX_WINTHETIP2,	GRP_NONE,	A, 1*60, "" },
#endif


// 5min
static SPhrase
	CLSigShot[] =
	{
		{ SFX_BAKERSHAKENBAKE,	GRP_NONE,	A, 5*60, "Ls" },			// low post
		{ SFX_DUNCUN3,					GRP_NONE,	A, 5*60, "" },			// fade away jumper
		{ SFX_EWINGVINTAGE,			GRP_NONE,	A, 5*60, "" },
		{ SFX_OLAJUWONDREAM,		GRP_NONE,	A, 5*60, "" },
	};



static SPhrase
	ClDunkArc[] =
	{
		{ SFX_FLYSLIKEANEAGLE,	GRP_NONE,	A, 5*60, "Th" },		// super dunk up
		{ SFX_BIGLEAP,					GRP_NONE,	A, 5*60, "Th" },
		{ SFX_BIGLEAP2,					GRP_NONE,	A, 5*60, "Th" },
		{ SFX_BIGLEAP3,					GRP_NONE,	A, 5*60, "Th" },
		{ SFX_BIGLEAP5,					GRP_NONE,	A, 5*60, "Th" },
		{ SFX_BIGLEAP6,					GRP_NONE,	A, 5*60, "Th" },
		{ SFX_BIGLEAP7,					GRP_NONE,	A, 5*60, "Th" },
		{ SFX_BIGLEAP8,					GRP_NONE,	A, 5*60, "Th" },
		{ SFX_BIGLEAP9,					GRP_NONE,	A, 5*60, "Th" },
		{ SFX_BIGLEAP10,				GRP_NONE,	A, 5*60, "Th" },
		{ SFX_BIGLEAP11,				GRP_NONE,	A, 5*60, "Th" },
		{ SFX_BIGLEAP12,				GRP_NONE,	A, 5*60, "Th" },
		{ SFX_WHATALEAP,				GRP_NONE,	A, 5*60, "Th" },
		{ SFX_TWIGHLIGHTZONE,		GRP_NONE,	A, 5*60, "Th" },
		{ SFX_PLAYERLEAP,				GRP_NONE,	A, 5*60, "Th" },
		{ SFX_PLAYERLEAP2,			GRP_NONE,	A, 5*60, "Th" },
		{ SFX_PLAYERTAKESOFF,		GRP_NONE,	A, 5*60, "Th" },
		{ SFX_SKYHIGH,					GRP_NONE,	A, 5*60, "Th" },
		{ SFX_GROUNDCONTROL1A,	GRP_NONE,	A, 5*60, "Th" },
		{ SFX_GROUNDCONTROL1B,	GRP_NONE,	A, 5*60, "Th" },
		{ SFX_GROUNDCONTROL2,		GRP_NONE,	A, 5*60, "Th" },
	};

#define NumClDunkArc PHRASE_COUNT(ClDunkArc)


// 1min
static SPhrase
	ClShoot[]=
	{
		{ 0xffff,	GRP_NONE,	   Xp,	1*60,	"" },

		{ SFX_10PTSHOT,	GRP_NONE,	A, 1*60, "Ty" },		// shoots from hs
		{ SFX_15PTSHOT,	GRP_NONE,	A, 1*60, "Tz" },

		{ SFX_2POINTS,	GRP_NONE,				A,	1*60,	"T2" },
		{ SFX_FOR22,	GRP_NONE,				BA,	1*60,	"T2" },
		{ SFX_HEFIRES,	GRP_NONE,				A,	1*60,	"" },
		{ SFX_HELETSITFLY2,	GRP_NONE,			A,	1*60,	"" },
		{ SFX_HESETSHEFIRES2,	GRP_NONE,		A,	1*60,	"" },
		{ SFX_HESHOOTS,	GRP_NONE,				A,	1*60,	"" },
		{ SFX_HESHOOTS3,	GRP_NONE,			A,	1*60,	"" },
//		{ SFX_HETAKESTHEJUMPER4,	GRP_NONE,	A, 1*60, "Tj" },
		{ SFX_HETAKESTHESHOT,	GRP_NONE,		A,	1*60,	"Tj" },
		{ SFX_HEUNLOADS,	GRP_NONE,			A,	1*60,	"" },
		{ SFX_POPSTHEJAY,	GRP_NONE,			BA,	1*60,	"Tj" },
		{ SFX_PULLSUP,	GRP_NONE,				BA,	1*60,	"" },
		{ SFX_PULLSUPINTHELANE,	GRP_NONE,		BA,	1*60,	"Ll" },
		{ SFX_PUTSUPTHESHOT,	GRP_NONE,		BA,	1*60,	"" },
		{ SFX_SHOOTS,	GRP_NONE,				BA,	1*60,	"" },
		{ SFX_STOPEINTHELANE,	GRP_NONE,		BA,	1*60,	"Ll" },
		{ SFX_TAKESTHEJUMPER2,	GRP_NONE,		A,	1*60,	"" },
		{ SFX_UNLOADS,	GRP_NONE,				BA,	1*60,	"" },
		{ SFX_WITHTHEJUMPER,	GRP_NONE,		BA,	1*60,	"Tj" },
		{ SFX_WITHTHESHOT,	GRP_NONE,			BA,	1*60,	"" },
		{ SFX_HEPUTSUPTHEJAY,	GRP_NONE,		A,	1,	"Tj" },
		{ SFX_WIDEOPEN,	GRP_NONE,				A,	1,	"So" },

		{ SFX_3POINTCORNER2,	GRP_NONE,	A, 1*60, "T3 Lc &" },
		{ SFX_3POINTER,	GRP_NONE,	A, 1*60, "T3" },
		{ SFX_FORTHREE3,	GRP_NONE,	A, 1*60, "T3" },
		{ SFX_FORTHREE4,	GRP_NONE,	A, 1*60, "T3" },
		{ SFX_FROMBEHINDTHEARC,	GRP_NONE,	A, 1*60, "T3" },
		{ SFX_FROMOUTSIDE,	GRP_NONE,	A, 1*60, "T3" },

		{ SFX_FROMWAYOUTSIDE2,	GRP_NONE,	A, 1*60, "Lf" },
		{ SFX_HEGOESFORTHREE,	GRP_NONE,	A, 1*60, "T3" },
		{ SFX_PUTSUPTHETREY,	GRP_NONE,	A, 1*60, "T3" },
		{ SFX_WITHALONGHOIST,	GRP_NONE,	A, 1*60, "T3" },
		{ SFX_WITHTHELONGRANGESHOT,	GRP_NONE,	A, 1*60, "T3" },

		{ SFX_THROWSUPAPRAYER,	GRP_NONE,		A,	1*60,	"Lf Sb |" },
	};

#define	NumClShoot PHRASE_COUNT(ClShoot)


static SPhrase
	ClSigDunk[] =
	{
		{ SFX_BARRYFATHER,			PID_BRENT_BARRY_SEA,			A, 5*60, NULL },
		{ SFX_CARTERFLAIR,			PID_VINCE_CARTER_TOR,			A, 5*60, NULL },
		{ SFX_FINLEYCHINA,			PID_MICHAEL_FINLEY_DAL,		A, 5*60, NULL },
		{ SFX_KOBEPHENOMENAL,		PID_KOBE_BRYANT_LAL,			A, 5*60, NULL },
		{ SFX_KOBESHOWSTOPPER,	PID_KOBE_BRYANT_LAL,			A, 5*60, NULL },
		{ SFX_MALONEDELIVERS,		PID_KARL_MALONE_UTA,			A, 5*60, NULL },
		{ SFX_MCDYESS2,					PID_ANTONIO_MCDYESS_DEN,	A, 5*60, NULL },
		{ SFX_SHAQHOUSE,				PID_SHAQUILLE_ONEAL_LAL,	A, 5*60, NULL },
		{ SFX_SPREEWELLHAMMER,	PID_LATRELL_SPREWELL_NY,	A, 5*60, NULL },
		{ SFX_STARKSHANGAIR,		PID_JOHN_STARKS_GS,				A, 5*60, NULL },
		{ SFX_WEBBERBREAK,			PID_CHRIS_WEBBER_SAC,			A, 5*60, NULL },
		{ SFX_WILLIAMSREALDEAL,	PID_JASON_WILLIAMS_SAC,		A, 5*60, NULL },
//		{ SFX_PIPPENLEANSINFORTHESLAM,	GRP_NONE,	A, 1*60, "" },
	};

#define	NumClSigDunk PHRASE_COUNT(ClSigDunk)


// 5min
static SPhrase
	ClScoreArc[] =
	{
		{ SFX_PLAYERISONFIRE,		GRP_NONE,	BA, 1*60, "@" },		// team on fire
		{ SFX_PLAYERISONFIRE2,	GRP_NONE,	BA, 1*60, "@" },
		{ SFX_HEISONFIRE,				GRP_NONE,	 A, 1*60, "@" },

		{ SFX_5PTSCOREDA,				GRP_NONE,	 A, 1*60, "Tx" },
		{ SFX_5PTSCORED2,				GRP_NONE,	 A, 1*60, "Tx" },
		{ SFX_5PTSCORED3,				GRP_NONE,	 A, 1*60, "Tx" },
		{ SFX_5PTSCORED4,				GRP_NONE,	 A, 1*60, "Tx" },

		{ SFX_10PTSCOREDA,			GRP_NONE,	 A, 1*60, "Ty" },
		{ SFX_10PTSCORED2A,			GRP_NONE,	 A, 1*60, "Ty" },
		{ SFX_10PTSCORED3,			GRP_NONE,	 A, 1*60, "Ty" },
		{ SFX_10PTSCORED4,			GRP_NONE,	 A, 1*60, "Ty" },
		{ SFX_10PTSCORED5A,			GRP_NONE,	 A, 1*60, "Ty" },
		{ SFX_10PTSCORED6,			GRP_NONE,	 A, 1*60, "Ty" },
		{ SFX_10PTSCORED7,			GRP_NONE,	 A, 1*60, "Ty" },
		{ SFX_10PTSCORED8A,			GRP_NONE,	 A, 1*60, "Ty" },

		{ SFX_15PTSCOREDA,			GRP_NONE,	 A, 1*60, "Tz" },
		{ SFX_15PTSCORED2A,			GRP_NONE,	 A, 1*60, "Tz" },
		{ SFX_15PTSCORED3,			GRP_NONE,	 A, 1*60, "Tz" },
		{ SFX_15PTSCORED4A,			GRP_NONE,	 A, 1*60, "Tz" },
		{ SFX_15PTSCORED5,			GRP_NONE,	 A, 1*60, "Tz" },
		{ SFX_15PTSCORED6A,			GRP_NONE,	 A, 1*60, "Tz" },
		{ SFX_15PTSCORED7A,			GRP_NONE,	 A, 1*60, "Tz Do>10 &" },

		{ SFX_PLAYER5PTS,				GRP_NONE,	BA, 1*60, "Tx" },
		{ SFX_PLAYER5PTS2,			GRP_NONE,	BA, 1*60, "Tx" },
		{ SFX_PLAYER5PTS3,			GRP_NONE,	BA, 1*60, "Tx" },
		{ SFX_PLAYER5PTS4A,			GRP_NONE,	BA, 1*60, "Tx" },
		{ SFX_PLAYER5PTS5,			GRP_NONE,	BA, 1*60, "Tx" },

		{ SFX_PLAYER10PTS,			GRP_NONE,	BA, 1*60, "Ty" },
		{ SFX_PLAYER10PTS2A,		GRP_NONE,	BA, 1*60, "Ty" },
		{ SFX_PLAYER10PTS3A,		GRP_NONE,	BA, 1*60, "Ty" },
		{ SFX_PLAYER10PTS4A,		GRP_NONE,	BA, 1*60, "Ty" },
		{ SFX_PLAYER10PTS5,			GRP_NONE,	BA, 1*60, "Ty" },
		{ SFX_PLAYER10PTS6,			GRP_NONE,	BA, 1*60, "Ty" },

		{ SFX_PLAYER15PTS,			GRP_NONE,	BA, 1*60, "Tz" },
		{ SFX_PLAYER15PTS2A,		GRP_NONE,	BA, 1*60, "Tz" },
		{ SFX_PLAYER15PTS3A,		GRP_NONE,	BA, 1*60, "Tz" },
		{ SFX_PLAYER15PTS4,			GRP_NONE,	BA, 1*60, "Tz" },
		{ SFX_PLAYER15PTS5,			GRP_NONE,	BA, 1*60, "Tz" },
	};

#define NumClScoreArc PHRASE_COUNT(ClScoreArc)


static SPhrase
	ClEndIsms[] =
	{
//		{ SFX_NERVOUSTIME,			GRP_NONE,	 A, 2*60, "Dt<03 Do<03 | E2 &" },			// 2min left, score diff <3
		{ SFX_GARBAGETIME,			GRP_NONE,	 A, 5*60, "E2 Dt>10 & E1 Dt>05 & | $ ! &" },			// 2min left, team up by 10, not arcade
		{ SFX_GARBAGETIME,			GRP_NONE,	 A, 5*60, "E2 Dt>30 & $ &" },			// 2min left, team up by 30 arcade
		{ SFX_REFRIGERATOR2,		GRP_NONE,	 A, 5*60, "E2 Dt>10 & E1 Dt>05 & | $ ! &" },			// 2min left, team up by 10, not arcade
		{ SFX_REFRIGERATOR2,		GRP_NONE,	 A, 5*60, "E2 Dt>30 & $ &" },			// 2min left, team up by 10, arcade
	};

#define NumClEndIsms PHRASE_COUNT(ClEndIsms)


static SPhrase
	ClScore[] =
	{
// Not arcade...
		{ SFX_DEFENSEVACATION,	GRP_NONE,	tA, 5*60, "Dt>06" },		// ahead by 6+

		{ SFX_PARKINGLOT,				GRP_NONE,	 A, 5*60, "Lf" },			// shot from far out

		{ SFX_GOODSHOT2,				GRP_NONE,	 A, 5*60, "" },
		{ SFX_GOODSHOT3,				GRP_NONE,	 A, 5*60, "" },
		{ SFX_GOODSHOT4,				GRP_NONE,	 A, 5*60, "" },
		{ SFX_GOODSHOT6,				GRP_NONE,	 A, 5*60, "" },
		{ SFX_GOODSHOT7,				GRP_NONE,	 A, 5*60, "" },
		{ SFX_GOODSHOT9,				GRP_NONE,	 A, 5*60, "" },

		{ SFX_ADEUCE,						GRP_NONE,	 A,	5*60,	"T2" },

		{ SFX_ANDHEHITSIT,			GRP_NONE,	 A,	5*60,	"" },
		{ SFX_ANDITGOESIN,			GRP_NONE,	 A,	5*60,	"" },
		{ SFX_ANEASYDEUCE,			GRP_NONE,	 A,	5*60,	"T2" },
		{ SFX_DOWNITGOES2,			GRP_NONE,	 A,	5*60,	"" },
		{ SFX_FINELOOK,					GRP_NONE,	 A,	5*60,	"" },

		{ SFX_ITSANSWERED,			GRP_NONE,	 A,	5*60,	"Sp" },

		{ SFX_SWISH,						GRP_NONE,	 A,	5*60,	"Rs" },
		{ SFX_HOHEHITTHESHOT,		GRP_NONE,	 A,	5*60,	"" },
		{ SFX_HESCORES,					GRP_NONE,	 A,	5*60,	"" },
		{ SFX_GOOD2,						GRP_NONE,	 A,	5*60,	"" },
		{ SFX_HEHITTHESHOT,			GRP_NONE,	 A,	5*60,	"" },
		{ SFX_HEMADEIT,					GRP_NONE,	 A,	5*60,	"" },
		{ SFX_HEPUTSITIN,				GRP_NONE,	 A,	5*60,	"" },
		{ SFX_ITSGOOD,					GRP_NONE,	 A,	5*60,	"" },
		{ SFX_NICEOUTSIDESHOT,	GRP_NONE,	 A,	5*60,	"T3" },
		{ SFX_NOTHINGBUTNET,		GRP_NONE,	 A,	5*60,	"Rs" },
	};

#define NumClScore PHRASE_COUNT(ClScore)


static SPhrase
	ClMiss[] =
	{
		{ SFX_HEARTBREAKSHOT,	GRP_NONE,	 A, 5*60, "Rs !" },			// bounced out
//		{ SFX_SISTERSOFMERCY,	GRP_NONE,	TA, 5*60, "Do>10" },			// team down by 10+
		{ SFX_AIRBALL,				GRP_NONE,	 A, 5*60, "Rs" },
		{ SFX_ANDITSNOGOOD,		GRP_NONE,	 A, 5*60, "" },
		{ SFX_NO4,						GRP_NONE,	 A, 5*60, "" },
		{ SFX_NOGOOD,					GRP_NONE,	 A, 5*60, "" },
		{ SFX_OFFGLASSNOGOOD,	GRP_NONE,	 A, 5*60, "Rb" },
	};

#define NumClMiss PHRASE_COUNT(ClMiss)


// 1min
static SPhrase
	ClMadeFT[] =
	{
		{ SFX_NICESHOT,			GRP_NONE,	A,	1*60,	"" },
		{ SFX_ITGOESIN4,		GRP_NONE,	A,	1*60,	"" },
		{ SFX_DOWNITGOES2,	GRP_NONE,	A,	1*60,	"" },
		{ SFX_HEGOTIT,			GRP_NONE,	A,	1*60,	"" },
		{ SFX_HESCORES,			GRP_NONE,	A,	1*60,	"" },
		{ SFX_YES,					GRP_NONE,	A,	1*60,	"" },
		{ SFX_ITSGOOD4,			GRP_NONE,	A,	1*60,	"" },
	};

#define	NumClMadeFT PHRASE_COUNT(ClMadeFT)


static SPhrase
	ClMissFT[] =
	{
		{ SFX_AIRBALL,				GRP_NONE,	A, 1*60, "Rs" },
		{ SFX_ANDITSNOGOOD,		GRP_NONE,	A, 1*60, "" },
		{ SFX_NO4,						GRP_NONE,	A, 1*60, "" },
		{ SFX_NOGOOD,					GRP_NONE,	A, 1*60, "" },
		{ SFX_OFFGLASSNOGOOD,	GRP_NONE,	A, 1*60, "Rb" },
	};

#define NumClMissFT PHRASE_COUNT(ClMissFT)


static SPhrase
	ClDunk[] =
	{
		{ SFX_TAKESITUPSTRONG,			GRP_NONE,	BA,	5*60,	"" },
		{ SFX_TAKESITTOTHEHOLE,			GRP_NONE,	BA,	5*60,	"" },
		{ SFX_SLASHESTHRUTHELANE,		GRP_NONE,	BA,	5*60,	"" },
		{ SFX_HETAKESOFF,						GRP_NONE,	 A,	5*60,	"" },
		{ SFX_HEGOESUP2,						GRP_NONE,	 A,	5*60,	"" },
		{ SFX_HEGOESUP6,						GRP_NONE,	 A,	5*60,	"" },
		{ SFX_HEGOESINSIDE,					GRP_NONE,	 A,	5*60,	"" },
		{ SFX_HEGOESIN,							GRP_NONE,	 A,	5*60,	"" },
		{ SFX_HEDRIVESTOTHEBASKET,	GRP_NONE,	 A,	5*60,	"" },
		{ SFX_GOESUP,								GRP_NONE,	BA,	5*60,	"" },
		{ SFX_GOESINSTRONG2,				GRP_NONE,	BA,	5*60,	"" },
		{ SFX_FORTHEJAM2,						GRP_NONE,	BA,	5*60,	"" },
		{ SFX_ELEVATES,							GRP_NONE,	BA,	5*60,	"" },
		{ SFX_ELEVATES1HANDED,			GRP_NONE,	BA,	5*60,	"To" },
		{ SFX_ELEVATES2HANDED,			GRP_NONE,	BA,	5*60,	"Tt" },
	};

#define	NumClDunk	PHRASE_COUNT(ClDunk)


static SPhrase
	ClDunkScore[] =
	{
		{ SFX_BIGDUNK1,	GRP_NONE,	A, 5*60, "Ts" },			// sonic boom dunks
		{ SFX_BIGDUNK2,	GRP_NONE,	A, 5*60, "Ts" },
		{ SFX_EARTHQUAKE,	GRP_NONE,	A, 5*60, "Ts" },
		{ SFX_SONICBOOM,	GRP_NONE,	A, 5*60, "Ts" },

		{ SFX_JAMSITIN,												GRP_NONE,	 A, 5*60, "" },
		{ SFX_SLAMSITHOME,										GRP_NONE,	 A, 5*60, "" },
		{ SFX_HEJAMSITIN,											GRP_NONE,	 A, 5*60, "" },
		{ SFX_FINISHESWITHATHUNDEROUS,				GRP_NONE,	XA,	5*60,	"" },
		{ SFX_POUNDSITDOWN,										GRP_NONE,	XA,	5*60,	"" },
		{ SFX_SLAMDUNK,												GRP_NONE,	 A,	5*60,	"" },
		{ SFX_SLAMDUNK3,											GRP_NONE,	 A,	5*60,	"" },
		{ SFX_SLAMSITWITHAUTHORITY,						GRP_NONE,	XA,	5*60,	"" },
		{ SFX_SLAMSITWITHAUTHORITY2,					GRP_NONE,	XA,	5*60,	"" },
		{ SFX_WITHAMONSTERJAM,								GRP_NONE,	XA,	5*60,	"" },
		{ SFX_WITHAMONSTERJAM2,								GRP_NONE,	XA,	5*60,	"" },
		{ SFX_WITHAUTHORITY,									GRP_NONE,	XA,	5*60,	"" },

		{ SFX_2HANDEDREVERSE,									GRP_NONE,	 A,	5*60,	"T2" },
		{ SFX_ANDFINISHESWITHATHUNDEROUSJAM2,	GRP_NONE,	 A,	5*60,	"" },
		{ SFX_ANDSTUFFSIT,										GRP_NONE,	 A,	5*60,	"" },
		{ SFX_ANDHAMMERSITHOME,								GRP_NONE,	 A,	5*60,	"" },
		{ SFX_AREVERSEJAM,										GRP_NONE,	 A,	5*60,	"Tr" },
		{ SFX_HESLAMSITHOME,									GRP_NONE,	 A,	5*60,	"" },
		{ SFX_PUSHESITDOWN,										GRP_NONE,	XA,	5*60,	"" },
		{ SFX_SLAMSITDOWN,										GRP_NONE,	XA,	5*60,	"" },
		{ SFX_WHOAHELOWERS,										GRP_NONE,	 A,	5*60,	"" },
	};

#define NumClDunkScore PHRASE_COUNT(ClDunkScore)


// 1min
static SPhrase
	ClLayup[] =
	{
		{ SFX_KISSESITOFFTHEGLASS,	GRP_NONE,	BA,	1*60,	"G" },
		{ SFX_LAYITUPFORTWO,				GRP_NONE,	BA,	1*60,	"" },
		{ SFX_LAYSITUPOFFTHEGLASS,	GRP_NONE,	BA,	1*60,	"G" },
		{ SFX_PUTSITOFFTHEGLASS,		GRP_NONE,	BA,	1*60,	"G" },
		{ SFX_LAYSITUP2,						GRP_NONE,	BA,	1*60,	"" },
	};

#define	NumClLayup PHRASE_COUNT(ClLayup)


// 1min
static SPhrase
	ClTipIn[] =
	{
		{ SFX_BACKUPANDIN,			GRP_NONE,	XA,	1*60,	"" },
		{ SFX_TIPSITIN2,				GRP_NONE,	XA,	1*60,	"" },
		{ SFX_WITHTHEPUTBACK,		GRP_NONE,	XA,	1*60,	"" },
		{ SFX_WITHTHETOUCHSHOT,	GRP_NONE,	XA,	1*60,	"" },
	};

#define	NumClTipIn PHRASE_COUNT(ClTipIn)


// 1min
static SPhrase
	ClBlock[] =
	{
		{ SFX_GETTHATSHOTOUTTAHERESHORTY,	GRP_NONE,	 A,	1*60,	"Ll Hb6 &" },
		{ SFX_ITSDENIED,									GRP_NONE,	 A,	1*60,	"" },
		{ SFX_WITHTHEBLOCK,								GRP_NONE,	BA,	1*60,	"" },
		{ SFX_SENDITBACKAIRMAIL,					GRP_NONE,	BA,	1*60,	"Td !" },
	};

#define NumClBlock PHRASE_COUNT(ClBlock)


// 1min
static SPhrase
	ClFreeThrow[] =
	{
		{ SFX_ATTHELINEFORTHEFIRSTTIME,	GRP_NONE,	BA,	1*60,	"Fa" },
		{ SFX_STEPSTOTHELINE,						GRP_NONE,	BA,	1*60,	"" },
		{ SFX_GOESTOTHECHARITY,					GRP_NONE,	BA,	1*60,	"" },
		{ SFX_SHOOTINGONE2,							GRP_NONE,	BA,	1*60,	"Fc1" },
		{ SFX_SHOOTING2,								GRP_NONE,	BA,	1*60,	"Fc2" },
		{ SFX_SHOOTINGTHREE,						GRP_NONE,	BA,	1*60,	"Fc3" },
	};

#define	NumClFreeThrow PHRASE_COUNT(ClFreeThrow)


// 1min
SPhrase	ClAlley[]=
			{
				{ SFX_GOESFORTHEALLEYOOP2,	GRP_NONE,	BA,	1*60,	"" },
				{ SFX_HEPUTSITUP,	GRP_NONE,			A,	1*60,	"" },
				{ SFX_PERFECTLOB,	GRP_NONE,			A,	1*60,	"" },
				{ SFX_THROWSTHEALLEYOOP2,	GRP_NONE,	BA,	1*60,	"" },
			};

#define NumClAlley PHRASE_COUNT(ClAlley)


// 30sec
static SPhrase
	ClPass[] =
	{
		{ SFX_DISHESIT2,			GRP_NONE,	BAT, 30,	"" },
		{ SFX_PASSES,					GRP_NONE,	 AT, 30,	"" },
		{ SFX_PASSESTHEBALL,	GRP_NONE,	BAT, 30,	"" },
		{ SFX_SENDSIT,				GRP_NONE,	BAT, 30,	"" },
	};

#define	NumClPass PHRASE_COUNT(ClPass)


//rebound 1min

// 30sec
static SPhrase
	ClPassSpecial[] =
	{
		{ 0xffff,										GRP_NONE,			 Xr, 30,	"Lrk Lrl |" },
		{ SFX_BACK3,								GRP_NONE,			BAT, 30,	"Srh" },
//crosscourt	a cross court pass
		{ SFX_BASSLINEPASS,					GRP_NONE,			 AT, 30,	"Lrl Lpe &" },
		{ SFX_DOWNCOURT,						GRP_NONE,			 AT, 30,	"Lpb Lru & Dm Dl | &"	},
		{ SFX_DOWNLOW,							GRP_NONE,			 AT, 30,	"Lpl ! Lrl &" },
		{ SFX_DOWNTHELANE,					GRP_NONE,			 AT, 30,	"Lrk Lpt &" },
		{ SFX_FEEDSIT,							GRP_NONE,			BAT, 30,	"Dc" },
		{ SFX_FINDSTHEOPENMAN,			GRP_OPENMAN,	 BA, 30,	"Sro Lru & Dc ! &" },
		{ SFX_FROMTHETOPOFTHEKEY,		GRP_NONE,			BAT, 30,	"Lrt ! Lpt &" },
		{ SFX_GIVESIT,							GRP_NONE,			BAT, 30,	"Dc" },
		{ SFX_GIVESITBACK,					GRP_NONE,			BAT, 30,	"Srh Dc &" },
		{ SFX_GIVESITDOWNLOW,				GRP_NONE,			BAT, 30,	"Lrt Lpt ! &" },
		{ SFX_GOODENTRYPASS,				GRP_NONE,			 AT, 30,	"Lrk Lpk ! &" },
		{ SFX_GREATPASSUPTHEFLOOR,	GRP_NONE,			 AT, 30,	"Lpb Lru & Dl &" },
		{ SFX_HANDSIT,							GRP_NONE,			BAT, 30,	"Dc" },
		{ SFX_HANDSOFF,							GRP_NONE,			BAT, 30,	"Dc" },
		{ SFX_INBOUNDSIT,						GRP_NONE,			BAT, 30,	"Spi" },
		{ SFX_INTOTHELANE,					GRP_NONE,			 AT, 30,	"Lpk ! Lrk &" },
		{ SFX_KICKSITOUT,						GRP_NONE,			BAT, 30,	"Lpl Lrl ! &" },
		{ SFX_LOBSIT,								GRP_NONE,			BAT, 30,	"Tl" },
		{ SFX_LONGPASS,							GRP_NONE,			 AT, 30,	"Dl" },
		{ SFX_NOLOOKPASS,						GRP_NONE,			BAT, 30,	"Tn" },
		{ SFX_OUT,									GRP_NONE,			 AT, 30,	"Lpk Lrk ! &" },
		{ SFX_OVER,									GRP_NONE,			 AT, 30,	"Tl" },
		{ SFX_PASSESITOUT,					GRP_NONE,			BAT, 30,	"Lpk Lrk ! &" },
		{ SFX_PASSESTHRUTRAFFIC,		GRP_NONE,			BAT, 30,	"Lrk Spf ! &" },
		{ SFX_PASSITOUTOFTHEDOUBLE,	GRP_NONE,			BAT, 30,	"Spd" },
		{ SFX_RECEIVESTHEENTRYPASS,	GRP_NONE,			 RA, 30,	"Lrk Lpk ! &" },
		{ SFX_RIFLESIT,							GRP_NONE,			BAT, 30,	"Dl Tl ! &" },
		{ SFX_SENDSITBACK,					GRP_NONE,			BAT, 30,	"Srh" },
		{ SFX_SKIPPASS,							GRP_NONE,			 AT, 30,	"Tb" },
		{ SFX_SNAPSOFFACHESTPASS,		GRP_NONE,			BAT, 30,	"Tc" },
		{ SFX_SWINGSITOUTSIDE,			GRP_NONE,			BAT, 30,	"Lpk Lrk ! &" },
		{ SFX_THENOLOOK,						GRP_NONE,			 AT, 30,	"Tn" },
		{ SFX_THROWSITAHEAD,				GRP_NONE,			BAT, 30,	"Lpb Lru &" },
		{ SFX_THROWSITINSIDE,				GRP_NONE,			BAT, 30,	"Lpk ! Lrk &" },
		{ SFX_TOTHEOPENMAN,					GRP_OPENMAN,	 BA, 30,	"Sro Lru & Dc ! &" },
		{ SFX_UPTOP,								GRP_NONE,			BAT, 30,	"Lpt ! Lrt &" },
		{ SFX_WHIRLSIT,							GRP_NONE,			BAT, 30,	"Dl Tl ! &" },
		{ SFX_WITHTHEINBOUNDS,			GRP_NONE,			BAT, 30,	"Spi" },
		{ SFX_WITHTHENOLOOK,				GRP_NONE,			BAT, 30,	"Tn" },
		{ SFX_WRAPAROUNDBOUNCEPASS,	GRP_NONE,			 AT, 30,	"Tw" },
	};

#define	NumClPassSpecial PHRASE_COUNT(ClPassSpecial)


static SPhrase
	ClQuarter[] =
	{
		{ SFX_FIRSTQ,	GRP_NONE,				A,		1,	"" },
		{ SFX_HALF,	GRP_NONE,					A,		1,	"" },
		{ SFX_THIRDQ,	GRP_NONE,				A,		1,	"" },
		{ SFX_REGULATIONPLAY,	GRP_NONE,		A,		1,	"" },
		{ SFX_1STOT,	GRP_NONE,				A,		1,	"" },
		{ SFX_2NDOT,	GRP_NONE,				A,		1,	"" },
		{ SFX_ANYOT,	GRP_NONE,				A,		1,	"" },
	};

#define	NumClQuarter PHRASE_COUNT(ClQuarter)

static SPhrase
	ClSi[] =
	{
		{ SFX_THESCOREIS,	GRP_NONE,			A,		1,	"" },
		{ SFX_FINALSCOREIS,	GRP_NONE,			A,		1,	"" },
	};

#define	NumClSi PHRASE_COUNT(ClSi)



// Stu phrases...


static SPhrase
	SlRun[] =
	{
		{ SFX_NOPOINTSFROM3PLAYS,					GRP_RUN,     TA,	5*60,	"Zfn3t3r" },			// Team missed last 3 plays.
		{ SFX_DONENOTHINGLAST3,						GRP_RUN,     TA,	5*60,	"Zfn3t3r" },			// Team missed last 3 plays.
		{ SFX_MADENOTHINGLAST3,						GRP_RUN,     TA,	5*60,	"Zfn3t3r" },			// Team missed last 3 plays.
		{ SFX_NOTSCOREDLAST4,							GRP_RUN,     TA,	2*60,	"Zfn4t4r" },			// Team missed last 4 plays.
		{ SFX_HAVEGIVENUP,								GRP_RUN,     OA,	2*60,	"Zfy3t3r" },			// Team scored last 3 plays.
		{ SFX_HAVEMADE,										GRP_RUN,     TA,	2*60,	"Zfy5t5r" },			// Team has made last 5 shots.

		{ SFX_HAVEASTRANGLEHOLD,					GRP_RUN,     TA,	2*60,	"Rg St>20 & $ ! &" },			// Team has >20 point lead.
		{ SFX_HAVEGOT2FIND,								GRP_RUN,     TA,	2*60,	"Q>4 So>10 & $ ! &" },			// Team is down by >10 in 4th Q.
		{ SFX_HAVEGOTANUPHILLBATTLE,			GRP_RUN,     TA,	2*60,	"So>10 $ ! &" },			// Team is down by >10.
		{ SFX_HAVETHIERWORKCUTOUT,				GRP_RUN,     TA,	2*60,	"So=20 $ ! &" },			// Team goes down by 20 points.
		{ SFX_LETTINITSLIP,								GRP_RUN,     TA,	2*60,	"So>10 $ ! &" },			// Team goes down by 10+ points.
		{ SFX_LOOKSET2WIN,								GRP_RUN,     TA,	2*60,	"Rg St>21 & $ ! &" },			// Team lead by >21 points.
		{ SFX_NEED2FIND,									GRP_RUN,     TA,	2*60,	"So=15 Q<2 & $ ! &" },			// Team go down by 15 in first half.
		{ SFX_NEED2GETBACK,								GRP_RUN,     OA,	2*60,	"Rg St=15 & $ ! &" },			// Team go down by 15 points.
		{ SFX_RDOMINATING,								GRP_RUN,     TA,	2*60,	"Rg St>15 & $ ! &" },			// Team lead by >15.
		{ SFX_RLOOKINREALSTRONG,					GRP_RUN,     TA,	2*60,	"Rg St=10 & $ ! &" },			// Team lead by 10.
		{ SFX_RPUSHINGAHEAD,							GRP_RUN,     TA,	2*60,	"Rg St>11 & $ ! &" },			// Team lead by >11
		{ SFX_RSTARTIN2PULL,							GRP_RUN,     TA,	2*60,	"Rg St>11 & $ ! &" },			// Team lead by >11
		{ SFX_RSTARTINTODOMINATE,					GRP_RUN,     TA,	2*60,	"Rg St>20 & $ ! &" },			// Team lead by >20.

// Arcade...
		{ SFX_HAVEGOT2FIND,								GRP_RUN,     TA,	2*60,	"Q>4 So>30 & $ &" },			// Team is down by >10 in 4th Q.
		{ SFX_HAVEGOTANUPHILLBATTLE,			GRP_RUN,     TA,	2*60,	"So>30 $ &" },			// Team is down by >10.
		{ SFX_LETTINITSLIP,								GRP_RUN,     TA,	2*60,	"So>30 $ &" },			// Team goes down by 10 points.
		{ SFX_NEED2FIND,									GRP_RUN,     TA,	2*60,	"So=45 Q<2 & $ &" },			// Team go down by 15 in first half.
		{ SFX_NEED2GETBACK,								GRP_RUN,     OA,	2*60,	"Rg St=45 & $ &" },			// Team go down by 15 points.
		{ SFX_RDOMINATING,								GRP_RUN,     TA,	2*60,	"Rg St>45 & $ &" },			// Team lead by >15.
	};

#define	NumSlRun PHRASE_COUNT(SlRun)


// Scoring difference should only be called after a score by the team...

static SPhrase
	SlDiff[] =
	{
		{ SFX_EVENTHESCORE,				GRP_NONE, TA,	10*60,	"St=00 Q>2 &" },			// Equal score & >2nd Q
		{ SFX_TIETHESCORE,				GRP_NONE, TA,	10*60,	"St=00 Q>2 &" },			// Equal score & >2nd Q
//		{ SFX_LEADTHEGAME,					GRP_NONE,     TA,	10*60,	"" },
//		{ SFX_TAKETHELEAD,					GRP_NONE,     TA,	10*60,	"" },
//		{ SFX_GOINFRONT,					GRP_NONE,     TA,	10*60,	"" },
//		{ SFX_TAKETHELEADFIRSTTIME,					GRP_NONE,     TA,	10*60,	"" },
//		{ SFX_GOINFRONTFIRSTTIME,					GRP_NONE,     TA,	10*60,	"" },
//		{ SFX_HAVENEVERLEAD,					GRP_NONE,     TA,	10*60,	"" },
		{ SFX_HAVEA1POINTLEAD,		GRP_NONE, TA,	10*60,	"St=01 Q>4 &" },			// 1 point lead & >4th Q
		{ SFX_RAHEADBY1,					GRP_NONE, TA,	10*60,	"St=01 Q>2 &" },			// 1 point lead & >2nd Q
		{ SFX_RINFRONTBY2,				GRP_NONE, TA,	10*60,	"St=02 Q>2 &" },			// 2 point lead & >2nd Q
		{ SFX_LEADBY2,						GRP_NONE, TA,	10*60,	"St=02 Q>3 &" },			// 2 point lead & >3rd Q
		{ SFX_LEADBY3,						GRP_NONE, TA,	10*60,	"St=03 Q>2 &" },			// 3 point lead & >2nd Q
		{ SFX_R3POINTSAHEAD,			GRP_NONE, TA,	10*60,	"St=03 Q>2 &" },			// 3 point lead & >2nd Q
		{ SFX_NOWHAVEA4POINTLEAD,	GRP_NONE, TA,	10*60,	"St=04 Q>2 &" },			// 4 point lead & >2nd Q
	};

#define	NumSlDiff PHRASE_COUNT(SlDiff)


// Alley-oop should only be called after a dunk level 80...

static SPhrase
	SlAlley[] =
	{
		{ SFX_DOESNTDUNK1,											GRP_NONE,	  BAA, 5*60,	"L5" },			// Level 50
//		{ SFX_DELIVEREDASWEETPASS2,	GRP_NONE,	HAB,	5*60,	"" },
//		{ SFX_GOODDUNKFINEPASSFROM,	GRP_NONE,			AH,	5*60,	"" },
//		{ SFX_OHYEAH1,						GRP_NONE,			A,	5*60,	"" },
//		{ SFX_GREATPASSBY,						GRP_NONE,			A,	5*60,	"" },
	};

#define	NumSlAlley PHRASE_COUNT(SlAlley)


static SPhrase
	SlInbound[] =
	{
		{ SFX_OURGHTTOSTART,				GRP_NONE, TA,	2*60,	"" },
		{ SFX_SHOULDSTART,					GRP_NONE, TA,	2*60,	"" },
		{ SFX_SHOULDSTARTTHINKING,	GRP_NONE, TA,	2*60,	"" },
		{ SFX_TIMETOMILK,						GRP_NONE,  A,	2*60,	"" },
	};

#define	NumSlInbound PHRASE_COUNT(SlInbound)


static SPhrase
	SlTurnOver[] =
	{
//		{ SFX_AREGETTINGSTRIPPED1,	GRP_NONE, AAA,	2*60,	"" },
//		{ SFX_ARETURNING1,					GRP_NONE, AAA,	2*60,	"" },
	};

#define	NumSlTurnOver PHRASE_COUNT(SlTurnOver)


static SPhrase
	SlScore[] =
	{
// Team...
		{ SFX_AREMAKINGTHIER3S,						GRP_NONE,	  TA,	5*60,	"Z3y3t3r P3t5 & $ ! &" },			// Team made last 3 3pt, 3pt% > 50
		{ SFX_ARENOTSHOWING,							GRP_NONE,	  OA,	5*60,	"St>10 Aft>20 & Pft6 &" },			// Team lead by >10, fg attempt > 20, fg%>65
		{ SFX_ARETOUGHTONIGHT,						GRP_NONE,	  TA,	5*60,	"St>10 Aft>20 & Pft6 &" },			// Team lead by >10, fg attempt > 20, fg%>65
		{ SFX_GETTHIERHEADS2,							GRP_NONE,	  OA,	5*60,	"St>10 Aft>20 & Pft6 &" },			// Team lead by >10, fg attempt > 20, fg%>65
		{ SFX_KNOCKINGDOWN2,							GRP_NONE,	  TA,	5*60,	"St>10 Aft>20 & Pft6 &" },			// Team lead by >10, fg attempt > 20, fg%>65
		{ SFX_LOOKLIKEA,									GRP_NONE,	  OA,	5*60,	"St>10 Aft>20 & Pft6 &" },			// Team lead by >10, fg attempt > 20, fg%>65
		{ SFX_MAKINGLIFEDIFFICULT,				GRP_NONE,	  OA,	5*60,	"St>10 Aft>20 & Pft6 &" },			// Team lead by >10, fg attempt > 20, fg%>65
		{ SFX_NEEDTOSTEP,									GRP_NONE,	  OA,	5*60,	"St>10 Aft>20 & Pft6 &" },			// Team lead by >10, fg attempt > 20, fg%>65
		{ SFX_NEEDTOSTOP,									GRP_NONE,	  OA,	5*60,	"St>10 Aft>20 & Pft6 &" },			// Team lead by >10, fg attempt > 20, fg%>65
		{ SFX_NEEDTOTURNUP2,							GRP_NONE,	  OA,	5*60,	"St>10 Aft>20 & Pft6 &" },			// Team lead by >10, fg attempt > 20, fg%>65
//		{ SFX_ARERUNNINGAWAY,							GRP_NONE, TA,	5*60,	"St=15" },			// Team up by 15, 40 for arcade
		{ SFX_SLACKINGONDEFENSE2,					GRP_NONE,	  OA,	5*60,	"St>10 Aft>20 & Pft6 &" },			// Team lead by >10, fg attempt > 20, fg%>65
//		{ SFX_BETTERMAKESOMEADJUSTMENTS,	GRP_NONE, OA,	5*60,	"St=08" },			// Team up by 8, 20 for arcade
		{ SFX_AREKNOCKINGIN1,							GRP_NONE,	TAAA,	5*60,	"A3t>08 P3t5 & T3 &" },			// Team tried 3pt 8+, 3pt% > 50, 3pt
		{ SFX_PUTTINGONACLINIC,						GRP_NONE,	  TA,	5*60,	"St>10 Aft>20 & Pft6 &" },			// Team lead by >10, fg attempt > 20, fg%>65
		{ SFX_REALLYPLAYING,							GRP_NONE,	  TA,	5*60,	"St>10 Aft>20 & Pft6 &" },			// Team lead by >10, fg attempt > 20, fg%>65
		{ SFX_PICKUPDEFENSE,							GRP_NONE,	   A,	5*60,	"Zfy3t3r St>10 &" },			// Team made last 3 fg, up by 10+
		{ SFX_LOOKLIKETHEYREGLUED1,				GRP_NONE,	 OAA,	5*60,	"Zfy3t3r Pft6 &" },			// Team made last 3 fg, fg% 60+
		{ SFX_ARESHOOTING1,								GRP_NONE,	 TAA,	5*60,	"Zfy3t3r Pft6 &" },			// Team made last 3 fg, fg% 60+
		{ SFX_JUSTCANTMISS1,							GRP_NONE,	 TAA,	5*60,	"Z3y3t3r P3t5 &" },			// Team made last 3 3pt, 3pt% 50+
		{ SFX_YOUCANTGIVEAWAY,						GRP_NONE,	   A,	5*60,	"Zfy3t3r Pft6 &" },			// Team made last 3 fg, fg% 60+

// Player...
		{ SFX_HESLIGHTINGTHEMUP,					GRP_NONE, A,	5*60,	"Zfy3s3r Ss>15 & Pfs7 &" },			// Made last 3 fg, 15+ points, fg% 70+
		{ SFX_ANOTHER2,					GRP_NONE, BA,	5*60,	"A2s>03 P2s7 & T2 &" },			// Tried 3+ 2pt, 2pt% 70+
		{ SFX_ANOTHER2POINTS,					GRP_NONE, AB,	5*60,	"A2s>03 P2s7 & T2 &" },			// Tried 3+ 2pt, 2pt% 70+
		{ SFX_ANOTHER3POINTER,					GRP_NONE, AB,	5*60,	"A3s>03 P3s5 & T3 &" },			// Tried 3+ 3pt, 3pt% 50+
		{ SFX_BASKET3FEETWIDE,					GRP_NONE, A,	5*60,	"Zfy3s3r Afs>06 & Pfs7 &" },			// Made last 3 fg, tried fg 6+, fg% 70+
		{ SFX_CLEANSHOTFROM,					GRP_NONE, AB,	5*60,	"Afs>03 Pfs7 &" },			// Tried 3+ fg, fg% 70+
//		{ SFX_DOUBLEFIGURES,					GRP_NONE, A,	5*60,	"" },			// 
//		{ SFX_DRAINSHIGHESTSCORINGTONIGHT,					GRP_NONE, A,	5*60,	"" },			// 
		{ SFX_DRAINSTHESHOTGOODPLAY,					GRP_NONE, BA,	5*60,	"Afs>03 Pfs7 &" },			// Tried 3+ fg, fg% 70+
		{ SFX_GETSANOTHERBASKET,					GRP_NONE, BA,	5*60,	"Afs>03 Pfs7 &" },			// Tried 3+ fg, fg% 70+
		{ SFX_GETSHISFIRSTPOINTS,					GRP_NONE, BA,	5*60,	"Q>2 Afs=01 &" },			// First shot
//		{ SFX_GETSTHEBASKET,					GRP_NONE, A,	5*60,	"" },			// 
//		{ SFX_GETSTHEBASKETNICESHOT,					GRP_NONE, A,	5*60,	"" },			// 
//		{ SFX_GOODMOVEBY,					GRP_NONE, A,	5*60,	"" },			// Dunk level 80
		{ SFX_GOODSHOTBY,					GRP_NONE, AB,	5*60,	"" },			// -
		{ SFX_GUYAMAZING,					GRP_NONE, A,	5*60,	"Zfy3s3r Pfs7 & Afs>05 &" },			// Made last 3 fg, fg% 70+, tried 5+ fg
		{ SFX_GUYONFIRE,					GRP_NONE, A,	5*60,	"Zfy3s3r Pfs7 & Afs>05 &" },			// Made last 3 fg, fg% 70+, tried 5+ fg
		{ SFX_IFYOULOOKUPAUTOMATIC,					GRP_NONE, AB,	5*60,	"Zfy3s3r Afs>03 & Pfs7 &" },			// Made last 3 fg, tried 6+ fg, fg% 70+
		{ SFX_KEEPSMAKINGTTHOSES3,					GRP_NONE, BA,	5*60,	"Z3y3s3r P3s5 & T3 &" },			// Made last 3 3pt, 3pt% 50+
		{ SFX_MAKESITLOOKEASY,					GRP_NONE, BA,	5*60,	"Zfy3s3r Afs>06 & Pfs7 &" },			// Made last 3 fg, tried 6+ fg, fg% 70+
		{ SFX_MAKESSHOTANOTHER2POINTS,					GRP_NONE, BA,	5*60,	"T2 Afs>03 & Pfs6 &" },			// Tried 3+ fg, fg% 60+
		{ SFX_MAKESTHE3POINT,					GRP_NONE, BA,	10*60,	"T3" },			// 3pt
		{ SFX_NICESHOTFROM,					GRP_NONE, AB,	5*60,	"Afs>03 Pfs6 &" },			// Tried 3+ fg, fg% 60+
		{ SFX_PICKSUP2POINTS,					GRP_NONE, BA,	5*60,	"T2 A2s>03 & P2s6 &" },			// Tried 3+ 2pt, 2pt% 60+
		{ SFX_PICKSUPANOTHER2POINTS,					GRP_NONE, BA,	5*60,	"T2 A2s>03 & P2s6 &" },			// Tried 3+ 2pt, 2pt% 60+
		{ SFX_PICKSUPANOTHER3,					GRP_NONE, BA,	5*60,	"T3 A3s>03 & P3s5 &" },			// Tried 3+ 3pt, 3pt% 50+
//		{ SFX_SCOREDMOREANYONE,					GRP_NONE, A,	5*60,	"" },			// 
//		{ SFX_SCOREDMORETEAM,					GRP_NONE, A,	5*60,	"" },			// 
//		{ SFX_SCOREDMORETEAMB,					GRP_NONE, A,	5*60,	"" },			// 
		{ SFX_SCORESANOTHER2POINTER,					GRP_NONE, BA,	5*60,	"T2 Afs>03 & Pfs6 &" },			// Tried 3+ fg, fg% 60+
		{ SFX_SCORESFORTHEFIRSTTIME,					GRP_NONE, A,	5*60,	"Q>2 Afs=01 &" },			// 
		{ SFX_SHOTSOSWEET,					GRP_NONE, A,	5*60,	"Z3y3s3r P3s5 &" },			// Made last 3 3pt, 3pt% 50+
		{ SFX_THATGUYSDRAININGTHEM,					GRP_NONE, A,	5*60,	"Zfy3s3r Afs>06 & Pfs7 &" },			// Made last 3 fg, tried 6+ fg, fg% 70+
		{ SFX_THATSTHEFIRSTTIME,					GRP_NONE, A,	5*60,	"Q>2 Afs=01 &" },			// First shot
		{ SFX_YOUCANTSTOP,					GRP_NONE, A,	5*60,	"Zfy3s3r Ss>15 & Pfs7 &" },			// Made last 3 fg, 15+ points, fg% 70+
		{ SFX_HESJUSTPLAYINGGREAT,					GRP_NONE, A,	5*60,	"Ss>15 Pfs7 &" },			// 15+ points, fg% 70+
		{ SFX_HESPUTTINGONACLINIC,					GRP_NONE, A,	5*60,	"Zfy3s3r Ss>15 & Pfs7 &" },			// Made last 3 fg, 15+ points, fg% 70+
		{ SFX_ISABIGTIMEPLAYER,					GRP_NONE, BA,	5*60,	"Ss>15 Pfs7 &" },			// 15+ points, fg% 70+
		{ SFX_ISCARRYINGTHELOAD,					GRP_NONE, BA,	5*60,	"Ss>15 Pfs7 &" },			// 15+ points, fg% 70+
		{ SFX_ISKNOCKINGTHEMDOWN,					GRP_NONE, BA,	5*60,	"Zfy3s3r Ss>15 & Pfs7 &" },			// Made last 3 fg, 15+ points, fg% 70+
		{ SFX_ISLIGHTINGTHEMUP,					GRP_NONE, BA,	5*60,	"Zfy3s3r Ss>15 & Pfs7 &" },			// Made last 3 fg, 15+ points, fg% 70+
		{ SFX_ISPUTTINGON,					GRP_NONE, BA,	5*60,	"Zfy3s3r Ss>15 & Pfs7 &" },			// Made last 3 fg, 15+ points, fg% 70+
		{ SFX_SOMEBODYSGOTTOGET,					GRP_NONE, A,	5*60,	"Ss>15 Pfs7 &" },			// 15+ points, fg% 70+
		{ SFX_HEDEFINEITELYGOT,				GRP_NONE,	     A,	5*60,	"Afs>03 Pfs6 & Rs ! &" },			// Tried 3+ fg, fg% 60+, rim bounce
//		{ SFX_HESONFIRE,							GRP_NONE,	     A,	5*60,	"Qfy05s05r" },			// made 5 in a row
//		{ SFX_HESREALLYKNOCKINGTHEM,					GRP_NONE, A,	5*60,	"" },			// 
//		{ SFX_HEWASNTGOINGTO,					GRP_NONE, A,	5*60,	"" },			// 
		{ SFX_ISKNOCKINGTHEM,					GRP_NONE, BA,	5*60,	"Afs>08 Pfs7 &" },			// Tried 8+ fg, fg% 70+
		{ SFX_ISREALLYSTEPPING,					GRP_NONE, BA,	5*60,	"Afs>08 Pfs7 &" },			// Tried 8+ fg, fg% 70+
		{ SFX_ISSHOOTINGTHELIGHTS,					GRP_NONE, A,	5*60,	"Afs>08 Pfs7 &" },			// Tried 8+ fg, fg% 70+
		{ SFX_ISSHOOTINGWELLDOWNTOWN,					GRP_NONE, A,	5*60,	"Z3y3s3r P3s5 &" },			// Made last 3 3pt, 3pt% 50+
		{ SFX_ONFIRE1,					GRP_NONE, BA,	5*60,	"Zfy3s3r Afs>08 & Pfs7 &" },			// Made last 3 fg, tried 8+ fg, fg% 70+
		{ SFX_SOMETIMESYOUJUSTKNOW,					GRP_NONE, A,	5*60,	"Z3y3s3r Pfs7 &" },			// Made last 3 fg, fg% 70+
		{ SFX_THATSHOTSGONNA,					GRP_NONE, A,	5*60,	"Zfy1s4r" },			// Made 1 of last 4 fg
		{ SFX_WHENYOUHAVE,					GRP_NONE, A,	5*60,	"Afs>03 Pfs6 & Rs ! &" },			// Tried 3+ fg, fg% 60+, rim bounce
//		{ SFX_YOUJUSTCANT,					GRP_NONE, A,	5*60,	"" },			// 
	};

#define	NumSlScore PHRASE_COUNT(SlScore)


static SPhrase
	SlMiss[] =
	{
// Team...
		{ SFX_WHATWASTHAT1,						GRP_NONE,			AA,	5*60,	"Dh Eq ! & $ ! &" },			// From back court & not last 5 secs
		{ SFX_CHICKITHINK1,						GRP_NONE,			AA,	5*60,	"Dh Eq ! & $ ! &" },			// From back court & not last 5 secs
		{ SFX_ARESHOOTINGPOORLY,						GRP_NONE,	     TA,	5*60,	"Zfn3t3r Pft4 ! &" },			// Missed last 3, fg% < 40
		{ SFX_AREINTROUBLE,						GRP_NONE,	     TA,	5*60,	"Zfn3t3r Pft4 ! &" },			// Missed last 3, fg% < 40
		{ SFX_COULDNTHITWATER,						GRP_NONE,	    TA,	5*60,	"Zfn3t3r Pft4 ! & St<00 &" },			// Missed last 3, fg% < 40
		{ SFX_HAVEMISSED,						GRP_NONE,	     TA,	5*60,	"T3 A3t>06 & P3t2 ! &" },			// 3pt, tried 6+ 3pt, 3pt% < 23
//		{ SFX_FIRINGAWAY,						GRP_NONE,	     A,	5*60,	"" },

// Player...
		{ SFX_1BRICKATATIME,				GRP_NONE,	  A,	5*60,	"Zfn3s3r Pfs4 ! &" },			// Missed last 3, fg% < 40
//		{ SFX_AGEHIGHERTHAN,				GRP_NONE,	  A,	5*60,	"Afs>05 Pfs4 ! &" },			// Tried 5+, fg% < 40
		{ SFX_HASMISSEDTOOMANY,			GRP_NONE,	 BA,	5*60,	"Zfn3s3r Pfs4 ! &" },			// Missed last 3, fg% < 40
		{ SFX_ISNOTSHOOTINGWELL,		GRP_NONE,	 BA,	5*60,	"Zfn3s3r Pfs4 ! &" },			// Missed last 3, fg% < 40
		{ SFX_FORCINGTOOMANYSHOTS,	GRP_NONE,	  A,	5*60,	"Afs>08 Pfs3 ! &" },			// Tried 8+, fg% < 30
		{ SFX_IFITWASNTFOR,					GRP_NONE,	  A,	5*60,	"Afs>08 Pfs3 ! &" },			// Tried 8+, fg% < 30
		{ SFX_TROUBLEFINDINGRANGE,	GRP_NONE,	  A,	5*60,	"Afs>08 Pfs3 ! &" },			// Tried 8+, fg% < 30
		{ SFX_HASNTFOUND1,					GRP_NONE,	BAA,	5*60,	"Afs>06 Pfs2 ! &" },			// Tried 6+, fg% < 20
		{ SFX_HECOULDNTHIT,					GRP_NONE,	  A,	5*60,	"Afs>06 Pfs2 ! &" },			// Tried 6+, fg% < 20
		{ SFX_HESFORCINGTOOMANY1,		GRP_NONE,	AAA,	5*60,	"Afs>08 Pfs2 ! &" },			// Tried 8+, fg% < 20
		{ SFX_MAYBEHENEEDS,					GRP_NONE,	  A, 10*60,	"Rs" },			// Airball
		{ SFX_THATMUSTVE,						GRP_NONE,	  A,	5*60,	"Zfn3s3r Pfs4 ! &" },			// Missed last 3, fg% < 40
		{ SFX_IVEHEARDOF1,					GRP_NONE,	ABA,	5*60,	"Zfn3s3r Pfs4 ! &" },			// Missed last 3, fg% < 40
	};

#define	NumSlMiss PHRASE_COUNT(SlMiss)


// Dunk should only be called after when it goes in...

static SPhrase
	SlDunk[] =
	{
		{ SFX_ENJOYSDUNKING,										GRP_NONE,	   BA, 5*60,	"L8" },			// Level 80
//		{ SFX_IHOPENONEOFHISFRIENDSAREWATCHING,	GRP_NONE,	    A, 5*60,	"" },
		{ SFX_ITHOURGHTTHEBACKBOARD,						GRP_NONE,	    A, 5*60,	"L8" },			// Level 80
		{ SFX_KINDOFATHELETE1,									GRP_NONE,	  BAA, 5*60,	"L8" },			// Level 80
//		{ SFX_MONEYMONEY2,											GRP_NONE,	    A, 5*60,	"" },
		{ SFX_THATSONEFORTHEHIGHLIGHTS,					GRP_NONE,	    A, 5*60,	"L7" },			// Level 70
		{ SFX_WHOAHPRICEOFADMISSION2,						GRP_NONE,	    A, 5*60,	"L9" },			// Level 90
//		{ SFX_360OHMY,	GRP_NONE, A, 5*60, "" ),
		{ SFX_10CHICK2,													GRP_NONE,			A, 5*60,	"L8" },			// Level 80
		{ SFX_95CHICK,													GRP_NONE,			A, 5*60,	"L8" },			// Level 80
//		{ SFX_180A,															GRP_NONE,			A, 5*60,	"" },
//		{ SFX_1HANDREVERSE,											GRP_NONE,			A, 5*60,	"" },
		{ SFX_69RICHTER3,												GRP_NONE,			A, 5*60,	"L8" },			// Level 80
		{ SFX_HECAMETHRU,												GRP_NONE,			A, 5*60,	"L8" },			// Level 80
		{ SFX_BROUGHTDOWNTHEHOUSE,							GRP_NONE,			A, 5*60,	"L8" },			// Level 80
//		{ SFX_HESJUMPINGOUTTHEBUILDING,					GRP_NONE,			A, 5*60,	"" },
		{ SFX_CROWDLOVEDTHAT,										GRP_NONE,			A, 5*60,	"L8" },			// Level 80
//		{ SFX_CUTEFINGERROLL,										GRP_NONE,			A, 5*60,	"" },
//		{ SFX_HETHREWITDOWNINTRAFFIC,						GRP_NONE,			A, 5*60,	"" },
		{ SFX_IHOPEHEHASHISVCRON,								GRP_NONE,			A, 5*60,	"L8" },			// Level 80
//		{ SFX_KOBEDUNKS,												GRP_NONE,			A, 5*60,	"" },
		{ SFX_LOOKATTHATJAM,										GRP_NONE,			A, 5*60,	"L8" },			// Level 80
		{ SFX_MONSTERDUNK,											GRP_NONE,			A, 5*60,	"L8" },			// Level 80
		{ SFX_MONSTERJAM2,											GRP_NONE,			A, 5*60,	"L8" },			// Level 80
//		{ SFX_NEXTZIPCODE,											GRP_NONE,			A, 5*60,	"" },
		{ SFX_NOTEVERYPLAYERCANDOTHAT2,					GRP_NONE,			A, 5*60,	"L8" },			// Level 80
//		{ SFX_ONEHANDFLYBYDUNK,									GRP_NONE,			A, 5*60,	"" },
//		{ SFX_ONESMALLSTEPFORMAN,								GRP_NONE,    AB, 5*60,	"" },
//		{ SFX_POORGUY4,													GRP_NONE,			A, 5*60,	"" },
//		{ SFX_PRETTYBOYDUNK,										GRP_NONE,			A, 5*60,	"" },
//		{ SFX_REVERSE2,													GRP_NONE,			A, 5*60,	"" },
		{ SFX_THATWASPRETTY,										GRP_NONE,			A, 5*60,	"L8" },			// Level 80
		{ SFX_THATWASSOMEDUNK,									GRP_NONE,			A, 5*60,	"L8" },			// Level 80
//		{ SFX_THETOMAHAWK,											GRP_NONE,			A, 5*60,	"" },
		{ SFX_THATSTHEKINDOFPLAY,								GRP_NONE,			A, 5*60,	"Wh So>10 &" },			// Team down by 10+
//		{ SFX_TWOHANDEDSLAM,										GRP_NONE,			A, 5*60,	"" },
//		{ SFX_TWOHANDREVERSE,										GRP_NONE,			A, 5*60,	"" },
//		{ SFX_WINDMILLDUNK,											GRP_NONE,			A, 5*60,	"" },
		{ SFX_YOUDONTSEETHATEVERYDAY,						GRP_NONE,			A, 5*60,	"L9" },			// Level 90
	};

#define	NumSlDunk PHRASE_COUNT(SlDunk)


// Only called if dunk level is 80+

static SPhrase
	SlDunk1[] =
	{
		{ SFX_CHECKITOUT,	GRP_NONE,	A, 1*60,	"" },
		{ SFX_OHMY,				GRP_NONE,	A, 1*60,	"" },
		{ SFX_BOY,				GRP_NONE,	A, 1*60,	"" },
		{ SFX_WOW,				GRP_NONE,	A, 1*60,	"" },
		{ SFX_WHOAH,			GRP_NONE,	A, 1*60,	"" },
	};

#define	NumSlDunk1 PHRASE_COUNT(SlDunk1)


// Only called if dunk level is 80+

static SPhrase
	SlDunk2[] =
	{
		{ SFX_THATWASSOCOOL2,						GRP_NONE, A, 5*60,	"" },
		{ SFX_THATKIDISONFIRE,					GRP_NONE, A, 5*60,	"K Afs>08 & Pfs7 &" },			// Kid, tried 8+ fg, fg% 70+
		{ SFX_THATKIDISAMAZING,					GRP_NONE, A, 5*60,	"K" },			// Kid
		{ SFX_NOSTOPPINGTHATKINDADUNK,	GRP_NONE, A, 5*60,	"" },
		{ SFX_YOUCANTSTOPTHERAIN,				GRP_NONE, A, 5*60,	"K Afs>08 & Pfs7 &" },			// Kid, tried 8+ fg, fg% 70+
		{ SFX_SHOWTIME,									GRP_NONE, A, 5*60,	"" },
	};

#define	NumSlDunk2 PHRASE_COUNT(SlDunk2)


static SPhrase
	SlFoul[] =
	{
		{ SFX_AREGETTING,						GRP_NONE,	TA,	5*60,	"Ctl" },
		{ SFX_AREGIVIGUP,						GRP_NONE,	TA,	5*60,	"Ctl" },
		{ SFX_HESPICKEDUP,					GRP_NONE,	 A,	5*60,	"Q<1 Cph & Cpo ! &" },
		{ SFX_HENEEDSTOPLAYSMARTER,	GRP_NONE,	 A,	5*60,	"Cph Cpo ! &" },
		{ SFX_ISGETTING,						GRP_NONE,	FA,	5*60,	"Q<1 Cph & Cpo ! &" },
		{ SFX_HESSTILLGOT,					GRP_NONE,	 A,	5*60,	"Q>3 Cp3 & Cpo ! &" },
		{ SFX_ONEMOREAND,						GRP_NONE,	 A,	5*60,	"Cpn Cpo ! &" },
		{ SFX_THATWASNOT,						GRP_NONE,	 A,	5*60,	"" },
//		{ SFX_HETOOKTHECHARGE,	GRP_NONE,			A,		5*60,	"" },
	};

#define	NumSlFoul PHRASE_COUNT(SlFoul)


static SPhrase
	SlMadeFT[] =
	{
//		{ SFX_GAMESHAVEBEEN,	GRP_NONE, A, 5*60, "Q>4 " },			// 4th quarter, after 1st ft
		{ SFX_HASBEENAUTOMATIC,			GRP_NONE, BA, 5*60, "As>08 Ps8 &" },			// attempted > 8 ft, ft % > 80
		{ SFX_AREGETTINGTHEJOB,			GRP_NONE, TA, 5*60, "At>14 Pt8 &" },			// attempted > 14 ft, ft % > 80
		{ SFX_ARETAKINGADVANTAGE,		GRP_NONE, TA, 5*60, "At>15 Pt8 &" },			// made ft, team attempted > 15, team ft %> 80
		{ SFX_BEENIMPRESSIVE,				GRP_NONE, TA, 5*60, "At>15 Pt8 &" },			// made ft, team attempted > 15, team ft %> 80
		{ SFX_HAVEBEENSHOOTING,			GRP_NONE, TA, 5*60, "At>10 Pt8 &" },			// made ft, team attempted > 10, team ft %> 80
		{ SFX_HAVEBEENSHOOTINGWELL,	GRP_NONE, TA, 5*60, "At>10 Pt8 &" },			// made ft, team attempted > 10, team ft %> 80
		{ SFX_KNOCKINGDOWNF,				GRP_NONE, TA, 5*60, "At>10 Pt8 &" },	// made ft, team attempted > 10, team ft %> 80
		{ SFX_KNOWALLABOUT,					GRP_NONE,	TA, 5*60, "At>10 Pt8 & Q>3 &" },			// made ft, team attempted > 10, team ft %> 80, second half
		{ SFX_MAKINGFREE,						GRP_NONE, TA, 5*60, "At>15 Pt8 &" },			// made ft, team attempted > 15, team ft %> 80
	};
			
#define	NumSlMadeFT PHRASE_COUNT(SlMadeFT)


static SPhrase
	SlMissFT[] =
	{
		{ SFX_FREETHROWSHOOTING,		GRP_NONE,	 A, 5*60, "Ps5 ! Pt5 ! & At>10 &" },			// player and team ft% < 50
//		{ SFX_GAMESHAVEBEEN,	GRP_NONE, A, 5*60, "Q>4 " },			// 4th quarter, after 1st ft
		{ SFX_CONSISTENT,						GRP_NONE,	TA, 5*60, "At>10 Pt5 ! &" },			// team attempted > 10, team ft % < 50
		{ SFX_COULDDOBETTER,				GRP_NONE,	TA, 5*60, "At>10 Pt5 ! &" },			// team attempted > 10, team ft % < 50
		{ SFX_IDONTKNOW,						GRP_NONE,	 A, 5*60, "As>06 Ps5 ! &" },			// attempted >6, ft %<50
		{ SFX_KNOWHOWTOSHOOT,				GRP_NONE,	TA, 5*60, "At>10 Pt5 ! &" },			// team attempted > 10, team ft % < 50
		{ SFX_MISSEDOPPORTUNITIES,	GRP_NONE,	TA, 5*60, "At>10 Pt5 ! &" },			// team attempted > 10, team ft % < 50
		{ SFX_NEED2IMPROVE,					GRP_NONE,	TA, 5*60, "At>10 Pt5 ! &" },			// team attempted > 10, team ft % < 50
		{ SFX_NEEDTOWORK,						GRP_NONE,	TA, 5*60, "At>10 Pt5 ! &" },			// team attempted > 10, team ft % < 50
	};

#define	NumSlMissFT PHRASE_COUNT(SlMissFT)



#define	RANDOM_COLOR(block)									\
			j = FindPhrases( Sl##block, NumSl##block, ParseSl##block );			\
			c=&Sl##block[Choices[random(j)]]

#define	RANDOM_BITE(block)								\
			j = FindPhrases( Cl##block, NumCl##block, Parse##block );			\
			c=&Cl##block[Choices[random(j)]];	

#define	COMMENT_VARS						\
			int		i,j;						\
			SPhrase	*c;


static bool
	prayer,
	Scored = FALSE;

static playert
	*Player = NULL,
	*Fouler = NULL;

static int
	PassToTime,
	GroupTimes[GRP_COUNT];

static u16
	FTshots,
	Choices[MAX_CHOICES];


#ifdef PHIL_TEST

static void OutInfo( const char *name, playert *plyr )
{
	char
		text[128];

	memset( text, 0, 16 );
	IntToDecStr( lp_ctr, text );

	strcat( text, " " );
	strcat( text, name );
	strcat( text, " " );
	strcat( text, plyr->plyrROM->pcz__pSName );
	strcat( text, "\n" );

	PCwrite( -1, text, strlen( text ) );
}


#define SFXDEF(sfx) { sfx, #sfx, }


static void OutChick( int id )
{
	static struct
	{
		int
			id;
		char
			*name;
	} list[] =
		{
// Score...
			SFXDEF( SFX_PLAYERISONFIRE ),
			SFXDEF( SFX_PLAYERISONFIRE2 ),
			SFXDEF( SFX_HEISONFIRE ),

			SFXDEF( SFX_5PTSCOREDA ),
			SFXDEF( SFX_5PTSCORED2 ),
			SFXDEF( SFX_5PTSCORED3 ),
			SFXDEF( SFX_5PTSCORED4 ),

			SFXDEF( SFX_10PTSCOREDA ),
			SFXDEF( SFX_10PTSCORED2A ),
			SFXDEF( SFX_10PTSCORED3 ),
			SFXDEF( SFX_10PTSCORED4 ),
			SFXDEF( SFX_10PTSCORED5A ),
			SFXDEF( SFX_10PTSCORED6 ),
			SFXDEF( SFX_10PTSCORED7 ),
			SFXDEF( SFX_10PTSCORED8A ),

			SFXDEF( SFX_15PTSCOREDA ),
			SFXDEF( SFX_15PTSCORED2A ),
			SFXDEF( SFX_15PTSCORED3 ),
			SFXDEF( SFX_15PTSCORED4A ),
			SFXDEF( SFX_15PTSCORED5 ),
			SFXDEF( SFX_15PTSCORED6A ),
			SFXDEF( SFX_15PTSCORED7A ),

			SFXDEF( SFX_PLAYER5PTS ),
			SFXDEF( SFX_PLAYER5PTS2 ),
			SFXDEF( SFX_PLAYER5PTS3 ),
			SFXDEF( SFX_PLAYER5PTS4A ),
			SFXDEF( SFX_PLAYER5PTS5 ),

			SFXDEF( SFX_PLAYER10PTS ),
			SFXDEF( SFX_PLAYER10PTS2A ),
			SFXDEF( SFX_PLAYER10PTS3A ),
			SFXDEF( SFX_PLAYER10PTS4A ),
			SFXDEF( SFX_PLAYER10PTS5 ),
			SFXDEF( SFX_PLAYER10PTS6 ),

			SFXDEF( SFX_PLAYER15PTS ),
			SFXDEF( SFX_PLAYER15PTS2A ),
			SFXDEF( SFX_PLAYER15PTS3A ),
			SFXDEF( SFX_PLAYER15PTS4 ),
			SFXDEF( SFX_PLAYER15PTS5 ),

			SFXDEF( SFX_DEFENSEVACATION ),
			SFXDEF( SFX_GARBAGETIME ),
			SFXDEF( SFX_REFRIGERATOR2 ),
			SFXDEF( SFX_PARKINGLOT ),

			SFXDEF( SFX_GOODSHOT2 ),
			SFXDEF( SFX_GOODSHOT3 ),
			SFXDEF( SFX_GOODSHOT4 ),
			SFXDEF( SFX_GOODSHOT6 ),
			SFXDEF( SFX_GOODSHOT7 ),
			SFXDEF( SFX_GOODSHOT9 ),

			SFXDEF( SFX_ADEUCE ),
			SFXDEF( SFX_AIRBALL ),

			SFXDEF( SFX_ANDHEHITSIT ),
			SFXDEF( SFX_ANDITGOESIN ),
			SFXDEF( SFX_ANDITSNOGOOD ),
			SFXDEF( SFX_ANEASYDEUCE ),
			SFXDEF( SFX_DOWNITGOES2 ),
			SFXDEF( SFX_FINELOOK ),
			SFXDEF( SFX_NO4 ),
			SFXDEF( SFX_NOGOOD ),
			SFXDEF( SFX_OFFGLASSNOGOOD ),

			SFXDEF( SFX_ITSANSWERED ),

			SFXDEF( SFX_SWISH ),
			SFXDEF( SFX_HOHEHITTHESHOT ),
			SFXDEF( SFX_HESCORES ),
			SFXDEF( SFX_GOOD2 ),
			SFXDEF( SFX_HEHITTHESHOT ),
			SFXDEF( SFX_HEMADEIT ),
			SFXDEF( SFX_HEPUTSITIN ),
			SFXDEF( SFX_ITSGOOD ),
			SFXDEF( SFX_NICEOUTSIDESHOT ),
			SFXDEF( SFX_NOTHINGBUTNET ),

// SigDunk...
			SFXDEF( SFX_BARRYFATHER ),
			SFXDEF( SFX_CARTERFLAIR ),
			SFXDEF( SFX_FINLEYCHINA ),
			SFXDEF( SFX_KOBEPHENOMENAL ),
			SFXDEF( SFX_KOBESHOWSTOPPER ),
			SFXDEF( SFX_MALONEDELIVERS ),
			SFXDEF( SFX_MCDYESS2 ),
			SFXDEF( SFX_SHAQHOUSE ),
			SFXDEF( SFX_SPREEWELLHAMMER ),
			SFXDEF( SFX_STARKSHANGAIR ),
			SFXDEF( SFX_WEBBERBREAK ),
			SFXDEF( SFX_WILLIAMSREALDEAL ),

// DunkScore...
			SFXDEF( SFX_BIGDUNK1 ),
			SFXDEF( SFX_BIGDUNK2 ),
			SFXDEF( SFX_EARTHQUAKE ),
			SFXDEF( SFX_SONICBOOM ),

			SFXDEF( SFX_FINISHESWITHATHUNDEROUS ),
			SFXDEF( SFX_POUNDSITDOWN ),
			SFXDEF( SFX_SLAMDUNK ),
			SFXDEF( SFX_SLAMDUNK3 ),
			SFXDEF( SFX_SLAMSITWITHAUTHORITY ),
			SFXDEF( SFX_SLAMSITWITHAUTHORITY2 ),
			SFXDEF( SFX_WITHAMONSTERJAM ),
			SFXDEF( SFX_WITHAMONSTERJAM2 ),
			SFXDEF( SFX_WITHAUTHORITY ),

			SFXDEF( SFX_2HANDEDREVERSE ),
			SFXDEF( SFX_ANDFINISHESWITHATHUNDEROUSJAM2 ),
			SFXDEF( SFX_ANDSTUFFSIT ),
			SFXDEF( SFX_ANDHAMMERSITHOME ),
			SFXDEF( SFX_AREVERSEJAM ),
			SFXDEF( SFX_HESLAMSITHOME ),
			SFXDEF( SFX_PUSHESITDOWN ),
			SFXDEF( SFX_SLAMSITDOWN ),
			SFXDEF( SFX_WHOAHELOWERS ),

// SHoot...
			SFXDEF( SFX_FLYSLIKEANEAGLE ),
			SFXDEF( SFX_BIGLEAP ),
			SFXDEF( SFX_BIGLEAP2 ),
			SFXDEF( SFX_BIGLEAP3 ),
			SFXDEF( SFX_BIGLEAP5 ),
			SFXDEF( SFX_BIGLEAP6 ),
			SFXDEF( SFX_BIGLEAP7 ),
			SFXDEF( SFX_BIGLEAP8 ),
			SFXDEF( SFX_BIGLEAP9 ),
			SFXDEF( SFX_BIGLEAP10 ),
			SFXDEF( SFX_BIGLEAP11 ),
			SFXDEF( SFX_BIGLEAP12 ),
			SFXDEF( SFX_WHATALEAP ),
			SFXDEF( SFX_TWIGHLIGHTZONE ),
			SFXDEF( SFX_PLAYERLEAP ),
			SFXDEF( SFX_PLAYERLEAP2 ),
			SFXDEF( SFX_PLAYERTAKESOFF ),
			SFXDEF( SFX_SKYHIGH ),
			SFXDEF( SFX_GROUNDCONTROL1A ),
			SFXDEF( SFX_GROUNDCONTROL1B ),
			SFXDEF( SFX_GROUNDCONTROL2 ),

			SFXDEF( SFX_10PTSHOT ),
			SFXDEF( SFX_15PTSHOT ),
			SFXDEF( SFX_2POINTS ),
			SFXDEF( SFX_FOR22 ),
			SFXDEF( SFX_HEFIRES ),
			SFXDEF( SFX_HELETSITFLY2 ),
			SFXDEF( SFX_HESETSHEFIRES2 ),
			SFXDEF( SFX_HESHOOTS ),
			SFXDEF( SFX_HESHOOTS3 ),
			SFXDEF( SFX_HETAKESTHESHOT ),
			SFXDEF( SFX_HEUNLOADS ),
			SFXDEF( SFX_POPSTHEJAY ),
			SFXDEF( SFX_PULLSUP ),
			SFXDEF( SFX_PULLSUPINTHELANE ),
			SFXDEF( SFX_PUTSUPTHESHOT ),
			SFXDEF( SFX_SHOOTS ),
			SFXDEF( SFX_STOPEINTHELANE ),
			SFXDEF( SFX_TAKESTHEJUMPER2 ),
			SFXDEF( SFX_UNLOADS ),
			SFXDEF( SFX_WITHTHEJUMPER ),
			SFXDEF( SFX_WITHTHESHOT ),
			SFXDEF( SFX_HEPUTSUPTHEJAY ),
			SFXDEF( SFX_WIDEOPEN ),
			SFXDEF( SFX_3POINTCORNER2 ),
			SFXDEF( SFX_3POINTER ),
			SFXDEF( SFX_FORTHREE3 ),
			SFXDEF( SFX_FORTHREE4 ),
			SFXDEF( SFX_FROMBEHINDTHEARC ),
			SFXDEF( SFX_FROMOUTSIDE ),
			SFXDEF( SFX_FROMWAYOUTSIDE2 ),
			SFXDEF( SFX_HEGOESFORTHREE ),
			SFXDEF( SFX_PUTSUPTHETREY ),
			SFXDEF( SFX_WITHALONGHOIST ),
			SFXDEF( SFX_WITHTHELONGRANGESHOT ),
			SFXDEF( SFX_THROWSUPAPRAYER ),

			{ 0, NULL }
		};
	int
		i = 0;

	while (list[i].name)
	{
		if (list[i].id == id)
		{
			PCwrite( -1, list[i].name, strlen( list[i].name ) );
			PCwrite( -1, "\n", 1 );
			return;
		}

		i++;
	}

	PCwrite( -1, "<unknown>\n", 10 );
}


static void OutStu( int id )
{
	static struct
	{
		int
			id;
		char
			*name;
	} list[] =
		{
// Run...
			SFXDEF( SFX_NOPOINTSFROM3PLAYS ),
			SFXDEF( SFX_DONENOTHINGLAST3 ),
			SFXDEF( SFX_MADENOTHINGLAST3 ),
			SFXDEF( SFX_NOTSCOREDLAST4 ),

			SFXDEF( SFX_HAVEASTRANGLEHOLD ),
			SFXDEF( SFX_HAVEGIVENUP ),
			SFXDEF( SFX_HAVEGOT2FIND ),
			SFXDEF( SFX_HAVEGOTANUPHILLBATTLE ),
			SFXDEF( SFX_HAVEMADE ),

			SFXDEF( SFX_HAVETHIERWORKCUTOUT ),
			SFXDEF( SFX_LETTINITSLIP ),
			SFXDEF( SFX_LOOKSET2WIN ),

			SFXDEF( SFX_NEED2FIND ),
			SFXDEF( SFX_NEED2GETBACK ),
			SFXDEF( SFX_RDOMINATING ),
			SFXDEF( SFX_RLOOKINREALSTRONG ),
			SFXDEF( SFX_RPUSHINGAHEAD ),
			SFXDEF( SFX_RSTARTIN2PULL ),
			SFXDEF( SFX_RSTARTINTODOMINATE ),

// Diff...
			SFXDEF( SFX_EVENTHESCORE ),
			SFXDEF( SFX_TIETHESCORE ),

			SFXDEF( SFX_HAVEA1POINTLEAD ),
			SFXDEF( SFX_RAHEADBY1 ),
			SFXDEF( SFX_RINFRONTBY2 ),
			SFXDEF( SFX_LEADBY2 ),
			SFXDEF( SFX_LEADBY3 ),
			SFXDEF( SFX_R3POINTSAHEAD ),
			SFXDEF( SFX_NOWHAVEA4POINTLEAD ),

// Alley-oop...

// Inbound...
			SFXDEF( SFX_OURGHTTOSTART ),
			SFXDEF( SFX_SHOULDSTART ),
			SFXDEF( SFX_SHOULDSTARTTHINKING ),
			SFXDEF( SFX_TIMETOMILK ),

// TurnOver...

// Score...
			SFXDEF( SFX_AREMAKINGTHIER3S ),
			SFXDEF( SFX_ARENOTSHOWING ),
			SFXDEF( SFX_ARETOUGHTONIGHT ),
			SFXDEF( SFX_GETTHIERHEADS2 ),
			SFXDEF( SFX_KNOCKINGDOWN2 ),
			SFXDEF( SFX_LOOKLIKEA ),
			SFXDEF( SFX_MAKINGLIFEDIFFICULT ),
			SFXDEF( SFX_NEEDTOSTEP ),
			SFXDEF( SFX_NEEDTOSTOP ),
			SFXDEF( SFX_NEEDTOTURNUP2 ),
			SFXDEF( SFX_ARERUNNINGAWAY ),
			SFXDEF( SFX_SLACKINGONDEFENSE2 ),
			SFXDEF( SFX_BETTERMAKESOMEADJUSTMENTS ),
			SFXDEF( SFX_AREKNOCKINGIN1 ),
			SFXDEF( SFX_PUTTINGONACLINIC ),
			SFXDEF( SFX_REALLYPLAYING ),
			SFXDEF( SFX_PICKUPDEFENSE ),
			SFXDEF( SFX_YOUCANTGIVE ),
			SFXDEF( SFX_LOOKLIKETHEYREGLUED1 ),
			SFXDEF( SFX_ARESHOOTING1 ),
			SFXDEF( SFX_JUSTCANTMISS1 ),
			SFXDEF( SFX_YOUCANTGIVEAWAY ),
			SFXDEF( SFX_HESLIGHTINGTHEMUP ),
			SFXDEF( SFX_ANOTHER2 ),
			SFXDEF( SFX_ANOTHER2POINTS ),
			SFXDEF( SFX_ANOTHER3POINTER ),
			SFXDEF( SFX_BASKET3FEETWIDE ),
			SFXDEF( SFX_CLEANSHOTFROM ),
			SFXDEF( SFX_DRAINSTHESHOTGOODPLAY ),
			SFXDEF( SFX_GETSANOTHERBASKET ),
			SFXDEF( SFX_GETSHISFIRSTPOINTS ),
			SFXDEF( SFX_GETSTHEBASKET ),
			SFXDEF( SFX_GOODSHOTBY ),
			SFXDEF( SFX_GUYAMAZING ),
			SFXDEF( SFX_GUYONFIRE ),
			SFXDEF( SFX_IFYOULOOKUPAUTOMATIC ),
			SFXDEF( SFX_KEEPSMAKINGTTHOSES3 ),
			SFXDEF( SFX_MAKESITLOOKEASY ),
			SFXDEF( SFX_MAKESSHOTANOTHER2POINTS ),
			SFXDEF( SFX_MAKESTHE3POINT ),
			SFXDEF( SFX_NICESHOTFROM ),
			SFXDEF( SFX_PICKSUP2POINTS ),
			SFXDEF( SFX_PICKSUPANOTHER2POINTS ),
			SFXDEF( SFX_PICKSUPANOTHER3 ),
			SFXDEF( SFX_SCORESANOTHER2POINTER ),
			SFXDEF( SFX_SCORESFORTHEFIRSTTIME ),
			SFXDEF( SFX_SHOTSOSWEET ),
			SFXDEF( SFX_THATGUYSDRAININGTHEM ),
			SFXDEF( SFX_THATSTHEFIRSTTIME ),
			SFXDEF( SFX_YOUCANTSTOP ),
			SFXDEF( SFX_HESJUSTPLAYINGGREAT ),
			SFXDEF( SFX_HESPUTTINGONACLINIC ),
			SFXDEF( SFX_ISABIGTIMEPLAYER ),
			SFXDEF( SFX_ISCARRYINGTHELOAD ),
			SFXDEF( SFX_ISKNOCKINGTHEMDOWN ),
			SFXDEF( SFX_ISLIGHTINGTHEMUP ),
			SFXDEF( SFX_ISPUTTINGON ),
			SFXDEF( SFX_SOMEBODYSGOTTOGET ),
			SFXDEF( SFX_HEDEFINEITELYGOT ),
			SFXDEF( SFX_HESREALLYKNOCKINGTHEM ),
			SFXDEF( SFX_ISKNOCKINGTHEM ),
			SFXDEF( SFX_ISREALLYSTEPPING ),
			SFXDEF( SFX_ISSHOOTINGTHELIGHTS ),
			SFXDEF( SFX_ISSHOOTINGWELLDOWNTOWN ),
			SFXDEF( SFX_ONFIRE1 ),
			SFXDEF( SFX_SOMETIMESYOUJUSTKNOW ),
			SFXDEF( SFX_THATSHOTSGONNA ),
			SFXDEF( SFX_WHENYOUHAVE ),
//			SFXDEF( SFX_YOUJUSTCANT ),

// Miss...
			SFXDEF( SFX_WHATWASTHAT1 ),
			SFXDEF( SFX_CHICKITHINK1 ),
			SFXDEF( SFX_ARESHOOTINGPOORLY ),
			SFXDEF( SFX_AREINTROUBLE ),
			SFXDEF( SFX_COULDNTHITWATER ),
			SFXDEF( SFX_HAVEMISSED ),
//			SFXDEF( SFX_FIRINGAWAY ),
			SFXDEF( SFX_1BRICKATATIME ),
//			SFXDEF( SFX_AGEHIGHERTHAN ),
			SFXDEF( SFX_HASMISSEDTOOMANY ),
			SFXDEF( SFX_ISNOTSHOOTINGWELL ),
			SFXDEF( SFX_FORCINGTOOMANYSHOTS ),
			SFXDEF( SFX_IFITWASNTFOR ),
			SFXDEF( SFX_TROUBLEFINDINGRANGE ),
			SFXDEF( SFX_HASNTFOUND1 ),
			SFXDEF( SFX_HECOULDNTHIT ),
			SFXDEF( SFX_HESFORCINGTOOMANY1 ),
			SFXDEF( SFX_MAYBEHENEEDS ),
			SFXDEF( SFX_THATMUSTVE ),
			SFXDEF( SFX_IVEHEARDOF1 ),

// Dunk...
			SFXDEF( SFX_DOESNTDUNK1 ),
			SFXDEF( SFX_ENJOYSDUNKING ),
//			SFXDEF( SFX_IHOPENONEOFHISFRIENDSAREWATCHING ),
			SFXDEF( SFX_ITHOURGHTTHEBACKBOARD ),
			SFXDEF( SFX_KINDOFATHELETE1 ),
			SFXDEF( SFX_MONEYMONEY2 ),
			SFXDEF( SFX_THATSONEFORTHEHIGHLIGHTS ),
			SFXDEF( SFX_WHOAHPRICEOFADMISSION2 ),
			SFXDEF( SFX_10CHICK2 ),
			SFXDEF( SFX_95CHICK ),
#if 0
			SFXDEF( SFX_360OHMY ),
			SFXDEF( SFX_180A ),
			SFXDEF( SFX_1HANDREVERSE ),
			SFXDEF( SFX_HESJUMPINGOUTTHEBUILDING ),
			SFXDEF( SFX_ONEHANDFLYBYDUNK ),
#endif
			SFXDEF( SFX_69RICHTER3 ),
			SFXDEF( SFX_HECAMETHRU ),
			SFXDEF( SFX_BROUGHTDOWNTHEHOUSE ),
			SFXDEF( SFX_CROWDLOVEDTHAT ),
			SFXDEF( SFX_CUTEFINGERROLL ),
			SFXDEF( SFX_IHOPEHEHASHISVCRON ),
//			SFXDEF( SFX_KOBEDUNKS ),
			SFXDEF( SFX_LOOKATTHATJAM ),
			SFXDEF( SFX_MONSTERDUNK ),
			SFXDEF( SFX_MONSTERJAM2 ),
			SFXDEF( SFX_NEXTZIPCODE ),
			SFXDEF( SFX_NOTEVERYPLAYERCANDOTHAT2 ),
//			SFXDEF( SFX_ONESMALLSTEPFORMAN ),
//			SFXDEF( SFX_POORGUY4 ),
//			SFXDEF( SFX_PRETTYBOYDUNK ),
//			SFXDEF( SFX_REVERSE2 ),
			SFXDEF( SFX_THATWASPRETTY ),
			SFXDEF( SFX_THATWASSOMEDUNK ),
//			SFXDEF( SFX_THETOMAHAWK ),
			SFXDEF( SFX_THATSTHEKINDOFPLAY ),
//			SFXDEF( SFX_TWOHANDEDSLAM ),
//			SFXDEF( SFX_TWOHANDREVERSE ),
//			SFXDEF( SFX_WINDMILLDUNK ),
			SFXDEF( SFX_YOUDONTSEETHATEVERYDAY ),

// Dunk1...
			SFXDEF( SFX_CHECKITOUT ),
			SFXDEF( SFX_OHMY ),
			SFXDEF( SFX_BOY ),
			SFXDEF( SFX_WOW ),
			SFXDEF( SFX_WHOAH ),

// Dunk2...
			SFXDEF( SFX_THATWASSOCOOL2 ),
			SFXDEF( SFX_THATKIDISONFIRE ),
			SFXDEF( SFX_THATKIDISAMAZING ),
			SFXDEF( SFX_NOSTOPPINGTHATKINDADUNK ),
			SFXDEF( SFX_YOUCANTSTOPTHERAIN ),
			SFXDEF( SFX_SHOWTIME ),

// Foul...
			SFXDEF( SFX_AREGETTING ),
			SFXDEF( SFX_AREGIVIGUP ),
			SFXDEF( SFX_HESPICKEDUP ),
			SFXDEF( SFX_HENEEDSTOPLAYSMARTER ),
			SFXDEF( SFX_ISGETTING ),
			SFXDEF( SFX_HESSTILLGOT ),
			SFXDEF( SFX_ONEMOREAND ),
			SFXDEF( SFX_THATWASNOT ),
//			SFXDEF( SFX_HETOOKTHECHARGE ),

// MadeFT...
//			SFXDEF( SFX_GAMESHAVEBEEN ),
			SFXDEF( SFX_HASBEENAUTOMATIC ),
			SFXDEF( SFX_AREGETTINGTHEJOB ),
			SFXDEF( SFX_ARETAKINGADVANTAGE ),
			SFXDEF( SFX_BEENIMPRESSIVE ),
			SFXDEF( SFX_HAVEBEENSHOOTING ),
			SFXDEF( SFX_HAVEBEENSHOOTINGWELL ),
			SFXDEF( SFX_KNOCKINGDOWNF ),
			SFXDEF( SFX_KNOWALLABOUT ),
			SFXDEF( SFX_MAKINGFREE ),

// MissFT...
			SFXDEF( SFX_FREETHROWSHOOTING ),
//			SFXDEF( SFX_GAMESHAVEBEEN ),
			SFXDEF( SFX_CONSISTENT ),
			SFXDEF( SFX_COULDDOBETTER ),
			SFXDEF( SFX_IDONTKNOW ),
			SFXDEF( SFX_KNOWHOWTOSHOOT ),
			SFXDEF( SFX_MISSEDOPPORTUNITIES ),
			SFXDEF( SFX_NEED2IMPROVE ),
			SFXDEF( SFX_NEEDTOWORK ),

			{ 0, NULL }
		};
	int
		i = 0;

	while (list[i].name)
	{
		if (list[i].id == id)
		{
			PCwrite( -1, list[i].name, strlen( list[i].name ) );
			PCwrite( -1, "\n", 1 );
			return;
		}

		i++;
	}

	PCwrite( -1, "<unknown>\n", 10 );
}

#endif


static int FindPhrases( SPhrase *phrase, const u32 total, CPF parser )
{
	s32
		ok,
		group;
	u32
		i,
		count = 0;

	for (i=0; i<total; i++)
	{
		ok = TRUE;

		group = phrase->Group;
		if (group != GRP_NONE)
		{
			if (lp_ctr < (GroupTimes[group] + (phrase->TimeCheck * ONE_SEC)))
				ok = FALSE;
		}

		if (ok)
		{
			if (lp_ctr >= (phrase->LastPlayed + (phrase->TimeCheck * ONE_SEC)))
			{
				if (Parse( phrase->condition, parser ))
				{
if (count > MAX_CHOICES)
	FatalError( "Choice list too small!", __FILE__, __LINE__ );
					Choices[count] = i;
					count++;
				}
			}
#if 0
			else
			{
				if (Parse( phrase->condition, parser ))
				{
					PCwrite( -1, "time ", 5 );
					OutStu( phrase->sample_id );
				}
			}
#endif
		}

		phrase++;
	}

	return( count );
}


static void ResetPhrases( SPhrase *phrase, u32 count )
{
	while (count)
	{
		phrase->LastPlayed = INIT_TIME;

		phrase++;
		count--;
	}
}


void reset_commentary()
{
	Set32s( GroupTimes, INIT_TIME, GRP_COUNT );

	// Chick...

	ResetPhrases( ClShoot,				NumClShoot				);
	ResetPhrases( ClSigDunk,			NumClSigDunk			);
	ResetPhrases( ClScoreArc,			NumClScoreArc			);
	ResetPhrases( ClScore,				NumClScore				);
	ResetPhrases( ClMiss,					NumClMiss					);
	ResetPhrases( ClMadeFT,				NumClMadeFT				);
	ResetPhrases( ClMissFT,				NumClMissFT				);
	ResetPhrases( ClDunk,					NumClDunk					);
	ResetPhrases( ClDunkScore,		NumClDunkScore		);
	ResetPhrases( ClLayup,				NumClLayup				);
	ResetPhrases( ClTipIn,				NumClTipIn				);
	ResetPhrases( ClBlock,				NumClBlock				);
	ResetPhrases( ClFreeThrow,		NumClFreeThrow		);
	ResetPhrases( ClAlley,				NumClAlley				);
	ResetPhrases( ClPass,					NumClPass					);
	ResetPhrases( ClPassSpecial,	NumClPassSpecial	);
	ResetPhrases( ClDunkArc,			NumClDunkArc			);
	ResetPhrases( ClEndIsms,			NumClEndIsms			);
	ResetPhrases( ClIllDef,				NumClIllDef				);

	// Stu...

	ResetPhrases( SlRun,			NumSlRun			);
	ResetPhrases( SlDiff,			NumSlDiff			);
	ResetPhrases( SlAlley,		NumSlAlley		);
	ResetPhrases( SlInbound,	NumSlInbound	);
	ResetPhrases( SlTurnOver,	NumSlTurnOver	);
	ResetPhrases( SlScore,		NumSlScore		);
	ResetPhrases( SlMiss,			NumSlMiss			);
	ResetPhrases( SlDunk,			NumSlDunk			);
	ResetPhrases( SlDunk1,		NumSlDunk1		);
	ResetPhrases( SlDunk2,		NumSlDunk2		);
	ResetPhrases( SlFoul,			NumSlFoul			);
	ResetPhrases( SlMadeFT,		NumSlMadeFT		);
	ResetPhrases( SlMissFT,		NumSlMissFT		);

	FTshots = 0;
	PassToTime = INIT_TIME;
}


void quarter_commentary(void)
{
	int		i;
	int		q;
	bool	end;

	// Indicate quarter
	end=FALSE;
	q=pcl__gMatch->sb___mQuarter;
	if (q>=NumClQuarter)
		q=NumClQuarter-1;

	PlayBite(&ClQuarter[q]);

	if (q < 4)
		i = 0;
	else
	{
		// "the score is..."
		if (SCORET(0)==SCORET(1))	// score or final score?
			i = 0;
		else
		{
			i = 1;
			end = TRUE;
		}
	}

	PlayBite(&ClSi[i]);

	if (SCORET(0) < SCORET(1))
		i = 1;
	else
		i = 0;

	// Teams & scores
	Speech_PlayByPlay_Team(i,SPEECH_TEAM_LONG);
	Speech_PlayByPlay_Number(SCORET(i));
	i = (1 - i);
	Speech_PlayByPlay_Team(i,SPEECH_TEAM_LONG);
	Speech_PlayByPlay_Number(SCORET(i));
}


void welcome_commentary(void)
{
	s32
		and,
		game;

#if defined(DEBUG)
	return;
#endif

	if (AttractMode)
		return;

	// Hi everybody...
	PlayBite(&ClHi[random(NumClHi)]);

	// Kick off queued speech now...
	Speech_Process();
	Audio_Process();

	// We're here...
	if (pcl__gOptions->sw___PlayoffIndx)	// Handle a playoff game
	{
		game = asb__gPlayoffTree[sb___gPlyIndex + 32] +
					 asb__gPlayoffTree[sb___gPlyIndex + 33];

		PlayBite(&ClPly[random(NumClPly)]);	// We're here to see...
		PlayBite(&ClGame[game]);	// Game X of...
		PlayBite(&ClPlyGame[sb___gPlyRound][sb___gPlyConfr]);			// the Y Z
		and = FALSE;
	}
	else	// Regular season or exhibition game here
	{
		PlayBite(&Exhib);
		and = TRUE;
	}

	// Speaketh the team names
	Speech_PlayByPlay_Team(1,SPEECH_TEAM_LONG);
	Speech_PlayByPlay( and ? SFX_AND : SFX_VERSES );
	Speech_PlayByPlay_Team(0,SPEECH_TEAM_LONG);
}


static void foul_commentary(playert *plyr, int foul)
{
	int			i,j;
	SPhrase		*c=0;
	const int	delay=8;
	bool		pf=FALSE;

#ifdef PHIL_TEST
	OutInfo( "chick foul", plyr );
	if (foul == REACHING_IN)
		OutInfo( "reaching in", plyr );
#endif

	switch(foul)
	{
		case THREE_SECOND:
			c=&Foul_3;
			pf=FALSE;
			break;

		case FIVE_SECOND:
			c=&Foul_5;
			pf=FALSE;
			break;

		case TEN_SECOND:
			c=&Foul_10;
			pf=FALSE;
			break;

		case SHOT_CLOCK:
			c=&Foul_24;
			pf=FALSE;
			break;

		case HALF_COURT:
			c=&Foul_Backcourt;
			pf=FALSE;
			break;

		case FLAGRANT:
			c=&Foul_Flagrant;
			pf=TRUE;
			break;

		case ILLEGAL_DEFENSE:
			c=&Foul_IllegalD;
			pf=FALSE;
			break;

		case TECHNICAL:
			c=&Foul_Technical;
			pf=FALSE;
			break;

		case CHARGING:
			c=&Foul_Charging;
			pf=FALSE;
			break;

		case REACHING_IN:
			c=&Foul_ReachingIn;
			pf=FALSE;
			break;

		default:
#ifdef PHIL_TEST
	{
		char
			numstr[8];

		memset( numstr, 0 , 8 );
		IntToDecStr( foul, numstr );
		OutInfo( numstr, plyr );
	}
#endif
			break;
	}

	// Handle simple foul call
	if (c)
	{
		Speech_Delay(delay);
		PlayBite(c);

		if (foul == FLAGRANT)
		{
//			if (plyr->plyrRAM->cl___pStatGame.uw___pPF == pcl__gMatch->sb___mMaxPlyrFouls)
			if (plyr->plyrRAM->cl___pStatGame.uw___pDQ)			// Fouled out?
			{
				c = &ClFoulOn[0];			// "It's on xxx"
				PlayBite( c );

				c = &ClFoulOut[random( NumClFoulOut )];		// Fouled out.
				PlayBite( c );
				return;
			}

			c = &ClFoulDunk[random( NumClFoulDunk )];
			PlayBite( c );
		}
		else if (foul == ILLEGAL_DEFENSE)
		{
#if 0
			RANDOM_BITE(IllDef);

			if (j)
				PlayBite(c);
#endif
		}

		return;
	}
	else
	{
		// Only call out shooting fouls beyond this point
		if (!(foul_flag2 || free_throws))
			return;

		// Handle commenting a funky shooting foul
		if (dunk_flag)	// Do dunk & layup intro
			c=&ClFoulDunk[random( NumClFoulDunk )];
		else	// Do intro for the rest
			c=&ClFoulShot[random( NumClFoulShot )];

//		Speech_Delay(delay);
		PlayBite(c);
		pf=TRUE;
	}

	if (pf)			// Check for more than 6 fouls!
	{
		if (plyr->plyrRAM->cl___pStatGame.uw___pPF == pcl__gMatch->sb___mMaxPlyrFouls)
			pf = TRUE;
		else
			pf = random( 2 );

		if (pf)
		{
			Speech_Delay(30);
			PlayBite(&ClFoulOn[random( NumClFoulOn )]);
			PlayBite(&ClFoulCount[plyr->plyrRAM->cl___pStatGame.uw___pPF-1]);
		}

		if (plyr->plyrRAM->cl___pStatGame.uw___pDQ)//PF == pcl__gMatch->sb___mMaxPlyrFouls)
		{
			PlayBite(&ClFoulOut[random( NumClFoulOut )]);
		}
		else if (free_throws && !pf)
		{
			RANDOM_BITE(FreeThrow);
			if (j)
				PlayBite(c);
		}
	}
}


void tip_in_commentary(void)
{
	COMMENT_VARS;

	if (ft_flag || free_throws)
		return;

#ifdef PHIL_TEST
	OutInfo( "chick tip-in", bhp );
#endif

	RANDOM_BITE(TipIn);

	if (j)
		PlayBite(c);
}


void block_commentary(void)
{
	COMMENT_VARS;

#ifdef PHIL_TEST
	OutInfo( "chick block", bhp );
#endif

	RANDOM_BITE(Block);

	if (j)
		PlayBite(c);
}


void layup_commentary(void)
{
	COMMENT_VARS;

	/* Don't play audio if projecting */
	if (ft_flag || free_throws)
		return;

#ifdef PHIL_TEST
	OutInfo( "chick layup", bhp );
#endif

	RANDOM_BITE(Layup);

	if (j)
		PlayBite(c);
}


#define	PO_PCT_TARGET	1
#define	PO_PCT_TYPE		2
#define	PO_PCT_RANGE	3

int ParseSlFoul( const char *src )
{
const char *text = src;
	playert			*plyr;
	bool			result=0;
	PlyrRamStat_T	*stats;	// Works also for team since they are identical in the fields that matter
	int				c, l, num;
	int				sm, sa, sp;

	plyr = Fouler;
	Player = plyr;

	switch(*src)
	{
		case 'C':	// Count
			switch(src[1])	// Which entity to check
			{
				case 'p':	// fouler
					stats=&plyr->plyrRAM->cl___pStatGame;
					l=pcl__gMatch->sb___mMaxPlyrFouls;
					break;

				case 't':	// shooter's team
					stats=(PlyrRamStat_T *)&plyr->teamRAM->cl___tStatGame;
					l=pcl__gMatch->sb___mMaxTeamFouls;
					break;

				case 'o':	// other team
					stats=(PlyrRamStat_T *) &TRAM(plyr->team^1)->cl___tStatGame;
					l=pcl__gMatch->sb___mMaxTeamFouls;
					break;

				default:
					BRK;
			}

			c=stats->uw___pPF;

			switch(src[2])	// Number of fouls to check
			{
				case 'l':
					if (c>=l)
						result=1;
					break;

				case 'h':
					if (c>=(l+1)/2)
						result=1;
					break;

				case 'n':
					if (c==l-1)
						result=1;
					break;

				case '3':			// 3 left?
					if (c <= (l-3))
						result = 1;
					break;

				case 'o':			// fouled out?
					if (stats->uw___pDQ)
						result = 1;
					break;

				default:
					BRK;
			}

			return 3*2+result;


		case 'P':	// Free throw percentage?
			switch (src[1])	// Get pointer to appropriate stats
			{
				case 's':	// shooter
					stats = &plyr->plyrRAM->cl___pStatGame;
					break;

				case 't':	// shooter's team
					stats = (PlyrRamStat_T *)&plyr->teamRAM->cl___tStatGame;
					break;

				case 'o':	// other team
					stats = (PlyrRamStat_T *)&TRAM(plyr->team^1)->cl___tStatGame;
					break;

				default:
					BRK;
			}

			sm = stats->uw___pFTM;
			sa = stats->uw___pFTA;

			// If no attempts, must be false
			if (!sa)
				return 3*2;

			sp=sm*10/sa;

			num = (src[2] - '0');

			if (num < 0 || num > 9)
				BRK;

			if (sp >= num)
				result = 1;

			return 3*2+result;


		case 'A':			// Attempts
			switch (src[1])	// Get pointer to appropriate stats
			{
				case 's':	// shooter
					stats = &plyr->plyrRAM->cl___pStatGame;
					break;

				case 't':	// shooter's team
					stats = (PlyrRamStat_T *)&plyr->teamRAM->cl___tStatGame;
					break;

				case 'o':	// other team
					stats = (PlyrRamStat_T *)&TRAM(plyr->team^1)->cl___tStatGame;
					break;

				default:
					BRK;
			}

			c = stats->uw___pFTA;

			num = (src[3] - '0') * 10;
			num += (src[4] - '0');

			switch (src[2])
			{
				case '>':
					if (c >= num)
						result = 1;
					break;

				case '<':
					if (c <= num)
						result = 1;
					break;

				case '=':
					if (c == num)
						result = 1;
					break;

				default:
					BRK;
			}

			return 5*2+result;


		case 'Q':
			num = (src[2] - '0');

			switch (src[1])
			{
				case '>':
					if (pcl__gMatch->sb___mQuarter >= num)
						result = 1;
					break;

				case '<':
					if (pcl__gMatch->sb___mQuarter <= num)
						result = 1;
					break;

				default:
					BRK;
			}
			return 3*2+result;


		default:
			FatalError( text, __FILE__, __LINE__ );
//			BRK;
	}
}


static bool CheckScoreDiff( playert *plyr, const char *src )
{
	s32
		ds,
		num;

	switch (src[0])
	{
		case 't':
			ds = SCORET(plyr->team) - SCORET(plyr->team^1);
			break;

		case 'o':
			ds = SCORET(plyr->team^1) - SCORET(plyr->team);
			break;

		case 's':
			ds = plyr->plyrRAM->uw___pPoints;
			break;

		default:
			BRK;
	}

	num = (src[2] - '0') * 10;
	num += (src[3] - '0');

	switch (src[1])
	{
		case '<':
			if (ds <= num)
				return( TRUE );
			break;

		case '>':
			if (ds >= num)
				return( TRUE );
			break;

		case '=':
			if (ds == num)
				return( TRUE );
			break;

		default:
			BRK;
	}

	return( FALSE );
}


int ParseSlScore( const char *src )
{
	int		sm,sa,sp;		// Stats: made, attempted, percentage
	int		pl,ph;			// Low and high percentage marks
	int		te;				// Time elapsed
	int		ds;				// Score differential
	int		who;
	int		num;
	playert	*plyr;
	bool	result=0;
	PlyrRamStat_T	*stats;	// Works also for team since they are identical in the fields that matter
	ExtraGameStats_T *extra;

	plyr=&player[last_shooter];	// Default player pointer to the shooter

	switch(*src)
	{
#if 0
		case 'C':	// Count
			switch(src[PO_PCT_TARGET])	// Get pointer to appropriate stats
			{
				case 's':	// shooter
//					stats=&bhp->plyrRAM->cl___pStatGame;
					stats = &bhp->plyrROM->cl___pStatNBA;
					break;

				case 't':	// shooter's team
					stats=(PlyrRamStat_T *)&bhp->teamRAM->cl___tStatGame;
					break;

				case 'o':	// other team
					stats=(PlyrRamStat_T *) &TRAM(bhp->team^1)->cl___tStatGame;
					break;

				default:
					BRK;
			}

			switch(src[PO_PCT_TYPE])		// Type of shot
			{
				case '2':				// 2 pointer
					sm=stats->uw___pFGM;
					break;

				case '3':				// 3 pointer
					sm=stats->uw___p3PM;
					break;

				case 'f':				// All field goals
					sm=stats->uw___pFGM+stats->uw___p3PM;
					break;

				case 'p':
					sm=stats->uw___pFGM*2+stats->uw___p3PM*3;
					break;
						

				default:
					BRK;
			}
			pl=src[4]*10+src[5];
			result=((src[3]=='>')? 1 : 0)^((pl<sm)? 1 : 0);
			return 6*2+result;
#endif

		case 'D':		// Distance
			switch(src[1])
			{
				case 'h':		// Beyond half-court
					if (PLY(Player) < 0)
						result = 1;
					break;

				default:
					BRK;
			}
			return 2*2+result;

#if 0
		case 'F':		// Frequency
			switch(src[1])	// Shot type
			{
				case '2':	// 2 pointers
					sa=TRAM(bhp->team)->cl___tStatGame.uw___tFGA;
					pl=20;
					ph=50;
					break;

				case '3':	// 3 pointers
					sa=TRAM(bhp->team)->cl___tStatGame.uw___t3PA;
					pl=10;
					ph=20;
					break;

				case 'f':	// All field goals
					sa=TRAM(bhp->team)->cl___tStatGame.uw___t3PA+TRAM(bhp->team)->cl___tStatGame.uw___tFGA;
					pl=30;
					ph=70;
					break;

				default:
					BRK;
			}

			te=pcl__gMatch->sb___mQuarter*(QUARTER_LENGTH/ONE_MIN);
			te+=(quarter_length-time_left)/ONE_MIN;
			if (!te)		// If not long enough, don't comment
				return 3*2;
			sa=sa*48/te;

			switch(src[2])	// Frequency band
			{
				case 'h':		// high
					if (sa>=ph)
						result=1;
					break;

				case 'l':		// low
					if (sa<=pl)
						result=1;
					break;
			}
			return 3*2+result;
#endif


		case 'L':	// Dunk level
			pl = (src[1] - '0') * 10;
			result = (current_dunk->level >= pl) ? 1 : 0;
			return 2*2+result;


		case 'P':	// Shooting percentage?
			switch (src[2])	// Get pointer to appropriate stats
			{
				case 's':	// shooter
					stats = &Player->plyrRAM->cl___pStatGame;
					extra = &Player->plyrRAM->ExtraPlayerGameStats;
					break;

				case 't':	// shooter's team
					stats = (PlyrRamStat_T *)&Player->teamRAM->cl___tStatGame;
					extra = &Player->teamRAM->ExtraTeamGameStats;
					break;

				case 'o':	// other team
					stats = (PlyrRamStat_T *)&TRAM(Player->team^1)->cl___tStatGame;
					extra = &TRAM(Player->team^1)->ExtraTeamGameStats;
					break;

				default:
					BRK;
			}

			switch (src[1])		// Type of shot
			{
				case '2':				// 2 pointer
					sm=stats->uw___pFGM;
					sa=stats->uw___pFGA;
					break;

				case '3':				// 3 pointer
					sm=stats->uw___p3PM;
					sa=stats->uw___p3PA;
					break;

				case 'f':				// All field goals
					sm = (stats->uw___pFGM + stats->uw___p3PM +
								extra->Num5PM + extra->Num10PM + extra->Num15PM);
					sa = (stats->uw___pFGA + stats->uw___p3PA +
								extra->Num5PA + extra->Num10PA + extra->Num15PA);
					break;

				default:
					BRK;
			}

			// If no attempts, must be false
			if (!sa)
				return 4*2;

			sp=sm*10/sa;

			num = (src[3] - '0');

			if (num < 0 || num > 9)
				BRK;

			if (sp >= num)
				result = 1;

			return 4*2+result;


		case 'R':	//Result
			switch(src[1])
			{
				case 'b':		// Bank off glass
					if (ball.no2)
						result=1;
					break;

				case 'g':		// Shot good
					if (ball.main_routine==made_ball_move)
						result=1;
					break;

				case 's':		// Swish (could also be airball)
					if (!ball.rim_bounce_count)
						result=1;
					break;

				default:
					BRK;
			}
			return 2*2+result;


		case 'S': // Scoring differential
			result = CheckScoreDiff( Player, &src[1] );
			return 5*2+result;


		case 'T':		// Type
			switch(src[1])
			{
				case '2':		// 2-point
					if (!pt3_flag && !BigPoints)
						result = 1;
					break;

				case '3':		// 3-point range
					if (pt3_flag && !BigPoints)
						result = 1;
					break;

				case 'x':
					if (BigPoints == 5)
						result = 1;
					break;

				case 'y':
					if (BigPoints == 10)
						result = 1;
					break;

				case 'z':
					if (BigPoints == 15)
						result = 1;
					break;

// Put checks for other special dunks/shots here...

				default:
					BRK;
			}
			return 2*2+result;


		case 'E':			// End of time
			result = time_left < (5*ONE_SEC) ? 1 : 0;
			return 2*2+result;


		case 'K':			// Kid
			result = Player->plyrROM->ub___pAge < 25 ? 1 : 0;
			return 1*2+result;


		case 'Z':			// Tracking
			result = Track_Check( &src[1], Player );
			return 7*2+result;


		case 'A':			// Attempts
			switch (src[2])	// Get pointer to appropriate stats
			{
				case 's':	// shooter
					stats = &Player->plyrRAM->cl___pStatGame;
					extra = &Player->plyrRAM->ExtraPlayerGameStats;
					break;

				case 't':	// shooter's team
					stats = (PlyrRamStat_T *)&Player->teamRAM->cl___tStatGame;
					extra = &Player->teamRAM->ExtraTeamGameStats;
					break;

				case 'o':	// other team
					stats = (PlyrRamStat_T *)&TRAM(Player->team^1)->cl___tStatGame;
					extra = &TRAM(Player->team^1)->ExtraTeamGameStats;
					break;

				default:
					BRK;
			}

			switch (src[1])
			{
				case '2':
					sa = stats->uw___pFGA;
					break;

				case '3':
					sa = stats->uw___p3PA;
					break;

				case 'f':
					sa = (stats->uw___pFGA + stats->uw___p3PA +
								extra->Num5PA + extra->Num10PA + extra->Num15PA);
					break;
			}

			num = (src[4] - '0') * 10;
			num += (src[5] - '0');

			switch (src[3])
			{
				case '>':
					if (sa >= num)
						result = 1;
					break;

				case '<':
					if (sa <= num)
						result = 1;
					break;

				case '=':
					if (sa == num)
						result = 1;
					break;

				default:
					BRK;
			}

			return 6*2+result;


		case 'Q':
			num = (src[2] - '0');

			switch (src[1])
			{
				case '>':
					if (pcl__gMatch->sb___mQuarter >= num)
						result = 1;
					break;

				case '<':
					if (pcl__gMatch->sb___mQuarter <= num)
						result = 1;
					break;

				default:
					BRK;
			}
			return 3*2+result;


		case '$':
			if (ArcadeMode)
				result = 1;
			return 1*2+result;


		case 'W':		// Which team
			switch (src[1])
			{
				case 'h':		// home
					if (Player->team == HOME_TEAM)
						result = 1;
					break;

				default:
					BRK;
			}
			return 2*2+result;


		default:
			BRK;
	}
}


int ParseLayup( const char *src )
{
	bool	result=0;
	int		an;

	switch(*src)
	{
		case 'G':	// Type of shot
			if (off_glass)
				result=1;
			break;

		default:	// Illegal Op
			BRK;
			break;
	}

	return 2+result;
}


void alley_commentary(void)
{
	COMMENT_VARS;

	/* Don't play audio if projecting */
	if (ft_flag || free_throws)
		return;

#ifdef PHIL_TEST
	OutInfo( "chick alley", bhp );
#endif

	RANDOM_BITE(Alley);

	if (j)
		PlayBite(c);
}


void dunk_commentary(void)
{
	COMMENT_VARS;

	/* Is it OK for us to play this audio? */
	if (ft_flag || free_throws)
		return;

//	Player = &player[last_shooter];

	if (ArcadeMode)
	{
		RANDOM_BITE(DunkArc);

		if (j)
		{
			PlayBite(c);
			return;
		}
	}

	RANDOM_BITE(Dunk);

	if (j)
		PlayBite(c);
}


void dunk_score_commentary(void)
{
	COMMENT_VARS;

	/* Is it OK for us to play this audio? */
	if (ft_flag || free_throws || foul_flag2)
		return;


j = 0;
if (time_left <= (2*ONE_MIN))
{
	RANDOM_BITE(EndIsms);

	if (j)
	{
#ifdef PHIL_TEST
		OutInfo( "chick end isms", bhp );
		for (i=0; i<j; i++)
			OutChick( ClEndIsms[Choices[i]].sample_id );
#endif
		PlayBite(c);
		return;
	}
}


#ifdef PHIL_TEST
	OutInfo( "chick dunk score", bhp );
#endif

	// Check for signature dunk commentary
	if (random( 2 ))			// 50% of the time.
	{
		j = 0;
		c = ClSigDunk;
		for (i=0; i<NumClSigDunk; i++)
		{
			if (c->Group == bhp->plyrROM->uw___pIndx &&
					lp_ctr >= (c->LastPlayed + (c->TimeCheck * ONE_SEC)))
			{
				Choices[j++] = i;
#ifdef PHIL_TEST
				OutChick( c->sample_id );
#endif
			}

			c++;
		}

		if (j)
		{
			i = random( j );
			c = &ClSigDunk[Choices[i]];
#ifdef PHIL_TEST
	OutChick( c->sample_id );
#endif

			c->LastPlayed = lp_ctr;

			Speech_PlayByPlay( c->sample_id );
			return;
		}
	}

	RANDOM_BITE(DunkScore);
	if (j)
	{
#ifdef PHIL_TEST
		for (i=0; i<j; i++)
			OutChick( ClDunkScore[Choices[i]].sample_id );
#endif
		PlayBite(c);
	}
}


int ParseDunkScore( const char *src )
{
	const char *text = src;
	bool	result=0;
	int		an;

	switch(*src)
	{
		case 'T':	// Type of shot
			switch(src[1])
			{
				case 's':
					if (ShakeScreen)
						result = 1;
					break;

				case '2':	// 2-handed Reverse
					switch(abs(bhp->top_anim))
					{
						case TOP_2HRD1:
							result=1;
							break;
					}
					break;

				case 'r':	// Reverse dunk
					switch(abs(bhp->top_anim))
					{
						case TOP_1HRD1:
							result=1;
							break;
					}
					break;

				default:	// Need a specifier
					BRK;
					break;
			}

			return 2*2+result;

		default:	// Illegal Op
			FatalError( text, __FILE__, __LINE__ );
//			BRK;
			break;
	}

	return 2*2+result;
}


static void foul_color( const s32 foul )
{
	COMMENT_VARS;

	if (FTshots &&
		  !ai_team[Fouler->team].foul &&
			(foul == FLAGRANT || foul == CHARGING || foul == REACHING_IN))
	{
#ifdef PHIL_TEST
		OutInfo( "stu foul", Player );
#endif

		RANDOM_COLOR(Foul);

		if (j)
		{
#ifdef PHIL_TEST
			for (i=0; i<j; i++)
				OutStu( SlFoul[Choices[i]].sample_id );
#endif
			PlayStu( c );
		}
	}
}


static void freethrow_color()
{
	COMMENT_VARS;

	if (Scored)
	{
#ifdef PHIL_TEST
	PCwrite( -1, "stu made ft\n", 12 );
#endif

		RANDOM_COLOR(MadeFT);

		if (j)
		{
#ifdef PHIL_TEST
			for (i=0; i<j; i++)
				OutStu( SlMadeFT[Choices[i]].sample_id );
#endif
			PlayStu( c );
		}
	}
	else
	{
#ifdef PHIL_TEST
	PCwrite( -1, "stu miss ft\n", 12 );
#endif

		RANDOM_COLOR(MissFT);

		if (j)
		{
#ifdef PHIL_TEST
			for (i=0; i<j; i++)
				OutStu( SlMissFT[Choices[i]].sample_id );
#endif
			PlayStu( c );
		}
	}
}


static s32 run_color()
{
	COMMENT_VARS;

	RANDOM_COLOR(Run);

	if (j)
	{
#ifdef PHIL_TEST
		char
			num[4],
			text[64];

		strcpy( text, "run " );

		*(u32 *)num = 0;
		IntToDecStr( SCORET( Player->team ), num );
		strcat( text, num );

		strcat( text, " " );

		*(u32 *)num = 0;
		IntToDecStr( SCORET( Player->team^1 ), num );
		strcat( text, num );

		strcat( text, "\n" );
		PCwrite( -1, text, strlen( text ) );

		for (i=0; i<j; i++)
			OutStu( SlRun[Choices[i]].sample_id );
#endif

		PlayStu(c);
		return( TRUE );
	}

	return( FALSE );
}


static s32 diff_color()
{
	COMMENT_VARS;

	// Only do scoring difference if just scored...

	RANDOM_COLOR(Diff);

	if (j)
	{
#ifdef PHIL_TEST
		char
			num[4],
			text[64];

		strcpy( text, "diff " );

		*(u32 *)num = 0;
		IntToDecStr( SCORET( Player->team ), num );
		strcat( text, num );

		strcat( text, " " );

		*(u32 *)num = 0;
		IntToDecStr( SCORET( Player->team^1 ), num );
		strcat( text, num );

		strcat( text, "\n" );
		PCwrite( -1, text, strlen( text ) );

		for (i=0; i<j; i++)
			OutStu( SlRun[Choices[i]].sample_id );
#endif

		PlayStu(c);
		return( TRUE );
	}

	return( FALSE );
}


static void score_color()
{
	COMMENT_VARS;

#ifdef PHIL_TEST
	if (ball.rim_bounce_count)
	{
		char
			str[16];

		*(u32 *)str = 0;
		IntToDecStr( ball.rim_bounce_count, str );
		strcat( str, " bounce\n" );
		PCwrite( -1, str, strlen( str ) );
	}

	if (dunk_flag)
		PCwrite( -1, "dunk\n", 5 );
#endif

	// Determine all of the valid comments
#ifdef PHIL_TEST
	OutInfo( "stu score", Player );
#endif

	if (!run_color())
	{
		if (!diff_color())
		{
			RANDOM_COLOR(Score);

			if (j)
			{
#ifdef PHIL_TEST
				for (i=0; i<j; i++)
					OutStu( SlScore[Choices[i]].sample_id );
#endif
				PlayStu(c);
			}
		}
	}
}


static void miss_color()
{
	COMMENT_VARS;

	// Determine all of the valid comments
#ifdef PHIL_TEST
	OutInfo( "stu miss", Player );
#endif

	if (!run_color())
	{
		RANDOM_COLOR(Miss);

		if (j)
		{
#ifdef PHIL_TEST
			for (i=0; i<j; i++)
				OutStu( SlMiss[Choices[i]].sample_id );
#endif

			PlayStu(c);
		}
	}
}


void dunk_score_color(void)
{
	COMMENT_VARS;

	if (ft_flag || free_throws || foul_flag2)
		return;

//	Player = &player[last_shooter];

#ifdef PHIL_TEST
	OutInfo( "stu dunk", Player );
#endif

	j = random( 2 );

	if (j)
	{
		RANDOM_COLOR(Dunk);

		if (j)
		{
#ifdef PHIL_TEST
			for (i=0; i<j; i++)
				OutStu( SlDunk[Choices[i]].sample_id );
#endif
			PlayStu(c);
		}
		else if (current_dunk->level >= 80)
		{
			RANDOM_COLOR(Dunk1);
			if (j)
			{
#ifdef PHIL_TEST
				for (i=0; i<j; i++)
					OutStu( SlDunk1[Choices[i]].sample_id );
#endif
				PlayStu(c);

				RANDOM_COLOR(Dunk2);
				if (j)
				{
#ifdef PHIL_TEST
					for (i=0; i<j; i++)
						OutStu( SlDunk2[Choices[i]].sample_id );
#endif
					PlayStu(c);
				}
			}
		}
	}
	else
	{
		j = 0;
		if (current_dunk->level >= 80)
		{
			RANDOM_COLOR(Dunk1);
			if (j)
			{
#ifdef PHIL_TEST
				for (i=0; i<j; i++)
					OutStu( SlDunk1[Choices[i]].sample_id );
#endif
				PlayStu(c);

				RANDOM_COLOR(Dunk2);
				if (j)
				{
#ifdef PHIL_TEST
					for (i=0; i<j; i++)
						OutStu( SlDunk2[Choices[i]].sample_id );
#endif
					PlayStu(c);
					return;
				}
			}
		}

		if (!j)
		{
			RANDOM_COLOR(Dunk);

			if (j)
			{
#ifdef PHIL_TEST
				for (i=0; i<j; i++)
					OutStu( SlDunk[Choices[i]].sample_id );
#endif
				PlayStu(c);
			}
		}
	}
}


void inbound_color()
{
	s32
		lead;

	COMMENT_VARS;

#ifdef PHIL_TEST
	PCwrite( -1, "stu inbound\n", 12 );
#endif

	if (Speech_IsAnnouncing( Stu ))
		return;

	if (time_left <= ONE_MIN)
	{
		lead = SCORET( bhp->team ) - SCORET( bhp->team^1 );

		if (lead >= 3 && lead <= 8)
		{
//			Player = bhp;

			RANDOM_COLOR(Inbound);

			if (j)
			{
#ifdef PHIL_TEST
				for (i=0; i<j; i++)
					OutStu( SlInbound[Choices[i]].sample_id );
#endif
				PlayStu(c);
			}
		}
	}
}


static void miss_commentary()
{
	COMMENT_VARS;

	if (FTshots)
	{
#ifdef PHIL_TEST
		OutInfo( "chick miss ft", Player );
#endif

		RANDOM_BITE(MissFT);

#ifdef PHIL_TEST
		if (j)
		{
			for (i=0; i<j; i++)
				OutChick( ClMissFT[Choices[i]].sample_id );
		}
#endif
	}
	else
	{
#ifdef PHIL_TEST
		OutInfo( "chick miss", Player );
#endif

		RANDOM_BITE(Miss);

#ifdef PHIL_TEST
		if (j)
		{
			for (i=0; i<j; i++)
				OutChick( ClMiss[Choices[i]].sample_id );
		}
#endif
	}

	if (j)
		PlayBite(c);
}


static void score_commentary()
{
	COMMENT_VARS;

	if (shot_at_time < 0)
		return;

	// Determine all of the valid comments
	if (FTshots)
	{
		RANDOM_BITE(MadeFT);
	}
	else
	{
if (time_left <= (2*ONE_MIN))
{
			RANDOM_BITE(EndIsms);

			if (j)
			{
		#ifdef PHIL_TEST
				OutInfo( "chick end isms", bhp );
				for (i=0; i<j; i++)
					OutChick( ClEndIsms[Choices[i]].sample_id );
		#endif
				PlayBite(c);
				return;
			}
}

			j = 0;
			if (ArcadeMode)
			{
				RANDOM_BITE(ScoreArc);
#ifdef PHIL_TEST
				if (j)
				{
					for (i=0; i<j; i++)
						OutChick( ClScoreArc[Choices[i]].sample_id );
				}
#endif
			}

			if (!j)
			{
				RANDOM_BITE(Score);
#ifdef PHIL_TEST
				if (j)
				{
					for (i=0; i<j; i++)
						OutChick( ClScore[Choices[i]].sample_id );
				}
#endif
			}
		}

		if (j)
		{
			PlayBite( c );
		}
}


static void shoot_commentary()
{
	COMMENT_VARS;

#ifdef PHIL_TEST
	OutInfo( "chick shoot", Player );
#endif

	prayer=0;

	// Check for signature shot commentary
	if (ArcadeMode)
	{
	}
	else
	{
		int	sfx=-1;

		switch(Player->plyrROM->uw___pIndx)
		{
			case PID_PATRICK_EWING_NY:
				switch(abs(Player->top_anim))
				{
					case TOP_EWING1:
					case TOP_EWING2:
					case TOP_EWING3:
					case TOP_EWING4:
						sfx=SFX_EWINGVINTAGE;
						break;

				default:
					break;
				}
				break;
		}

		if (sfx>=0)
		{
			Speech_PlayByPlay(sfx);
			return;
		}

	}

	RANDOM_BITE(Shoot);
	if (j)
	{
		PlayBite(c);

		// Damn prayer line
		if (c->sample_id==SFX_THROWSUPAPRAYER)
			prayer=1;
	}
}


static int ParseShoot( const char *src )
{
	bool	result=0;
	int		an;
	playert	*p,*e;
	int		dh;

	switch(*src)
	{
		case 'F':	// Free throw crap
			p=bhp;
			switch(src[1])
			{
				case 'a':	// Appearences
					if (!p->plyrRAM->cl___pStatGame.uw___pFTA)
						result=1;
					return 2*2+result;

				case 'c':	// Count of free throws
					if (free_throws==src[2]-'0')
						result=1;
					break;
			}
			return 3*2+result;

		case 'T':	// Type of shot
			switch(src[1])
			{
				case 's':
					if (ShakeScreen)
						result = 1;
					break;

				case 'h':
					if (current_dunk->max_time == SUPER_DUNK)
						result = 1;
					break;

				case 'x':
					if (BigPoints == 5)
						result = 1;
					break;

				case 'y':
					if (BigPoints == 10)
						result = 1;
					break;

				case 'z':
					if (BigPoints == 15)
						result = 1;
					break;

				case '2':	// 2-point shot
					if (!pt3_flag && !BigPoints)
						result=1;
					break;

				case '3':	// 3-point shot
					if (pt3_flag && !BigPoints)
						result=1;
					break;

				case 'd':
					if (bhp->main_routine==dunk_up_rou || bhp->main_routine==dunk_take_off)
						result=1;
					break;

				case 'j':	// Jump shot
					switch(abs(bhp->top_anim))
					{
						case TOP_JSHOT3:
						case TOP_3PTSHOT13:
						case TOP_JSHOTR3:
						case TOP_SJSHOT3:
						case TOP_SJSPIV3:
							result=1;
							break;

						default:
							result=0;
							break;
					}
					break;

				case 'o':	// One-handed dunk
					switch(abs(bhp->top_anim))
					{
						case TOP_1H3601:
						case TOP_1HTOMJR1:
						case TOP_1HRD1:
						case TOP_1HFLYBY1:
						case TOP_1HBB2S1:
						case TOP_S1HRD1:
						case TOP_1HHAM1:
						case TOP_1H1801:
						case TOP_1HJORDAN1:
						case TOP_1HSTUFF3:
						case TOP_1HTOM1:
						case TOP_1HUL1801:
						case TOP_1HWINDM2:
							result=1;
							break;
					}
					break;

				case 't':	// Two-handed dunk
					switch(abs(bhp->top_anim))
					{
						case TOP_2HD1:
						case TOP_2HRD4:
						case TOP_S2HD1:
						case TOP_S2HDUNK1:
							result=1;
							break;
					}
					break;

				default:	// Need a specifier
					BRK;
					break;
			}

			return 2*2+result;

		case 'H':	// Height check (1st taller than second)
			switch(src[1])
			{
				case 'b':	// Blocker
					p=&player[last_blocker];
					e=bhp;
					break;

				case 's':	// Shooter
					p=bhp;
					e=&player[last_blocker];
					break;

				default:
					BRK;
			}

			dh=(78*(p->scale-e->scale))>>8;
			if (dh>=src[2]-'0')
				result=1;

			return 3*2+result;

		case 'L':	// Player Location
			switch(src[1])
			{
				case 'c':		// Corner
					if (PLY(bhp)>BASE_LINE-0xC0000)
						result=1;
					break;

				case 'f':		// Far away
					if (bhp->basket_dist>0x600000)
						result=1;
					break;

				case 'l':	// Lane
					if (IN_KEY(bhp))
						result=1;
					break;

				default:
					BRK;
			}
			return 2*2+result;

		case 'R':	//Result
			switch(src[1])
			{
				case 'b':		// Bank off glass
					if (ball.no2)
						result=1;
					break;

				case 'g':		// Shot good
					if (ball.main_routine==made_ball_move)
						result=1;
					break;

				case 's':		// Swish (could also be airball)
					if (!ball.rim_bounce_count)
						result=1;
					break;

				default:
					BRK;
					break;
			}
			return 2*2+result;

		case 'S':	// Situation
			switch(src[1])
			{
				case 'b':	// Buzzer
					if (time_left<ONE_SEC)
						result=1;
					break;

				case 'o':	// Shooter open
					p=&player[bhp->base^5];
					e=p+5;
					do
					{
						if (MANHATTAN(p->xco-bhp->xco,p->yco-bhp->yco)<DIST_COVERED)
							break;
					} while (++p<e);
					if (p==e)
						result=1;
					break;

				case 'p':	// Said prayer line when the shot was lofted
						result=prayer;
					break;
			}
			return 2*2+result;


		case 'D':
			result = CheckScoreDiff( bhp, &src[1] );
			return 5*2+result;


		case 'E':
			if (time_left <= (src[1] - '0')*ONE_MIN &&
					pcl__gMatch->sb___mQuarter >= 3)
				result = 1;
			return 2*2+result;


		case '$':
			if (ArcadeMode)
				result = 1;
			return 1*2+result;


		case '@':
			if (ArcadeMode && MOM_MAX(bhp->team))
				result = 1;
			return 1*2+result;


		default:	// Illegal Op
			BRK;
			break;
	}

	return 3*2+result;
}


void loseball_commentary( playert *plost, playert *pgain )
{
	static u16
		ids[] =
		{
			SFX_LOSESCONTROL,
			SFX_THEBALLSKNOCKEDLOOSE,
			SFX_KNOCKSTHEBALLLOOSE,
		};
	static int
		time[3] =
		{
			-TIME_CHECK,
			-TIME_CHECK,
			-TIME_CHECK,
		};
	u16
		id,
		list[3];
	s32
		i,
		count = 0;

	if (project_flag || Speech_IsAnnouncing( Stu ))
		return;

	for (i=0; i<3; i++)
	{
		if (lp_ctr > (time[i] - TIME_CHECK))
			list[count++] = i;
	}

	if (!count)
		return;

	i = random( count );
	time[i] = lp_ctr;
	id = ids[i];

	if (id == SFX_LOSESCONTROL)
		Speech_PlayByPlay_Player( plost, SPEECH_NORMAL );

	if (id == SFX_KNOCKSTHEBALLLOOSE)
		Speech_PlayByPlay_Player( pgain, SPEECH_NORMAL );

	Speech_PlayByPlay( id );
}


void steal_commentary( playert *plost, playert *pgain )
{
	static u16
		ids[] =
		{
			SFX_STEAL,
			SFX_ITSSTOLEN,
			SFX_ITSSTOLENBY,
		};
	static int
		time[3] =
		{
			-TIME_CHECK,
			-TIME_CHECK,
			-TIME_CHECK,
		};
	u16
		id,
		list[3];
	s32
		i,
		count = 0;

	if (project_flag || Speech_IsAnnouncing( Stu ))
		return;

	for (i=0; i<3; i++)
	{
		if (lp_ctr > (time[i] - TIME_CHECK))
			list[count++] = i;
	}

	if (!count)
		return;

	i = random( count );
	time[i] = lp_ctr;
	id = ids[i];

	Speech_PlayByPlay( id );

	if (id == SFX_ITSSTOLENBY)
		Speech_PlayByPlay_Player( pgain, SPEECH_NORMAL );
}


void intercept_commentary( playert *plost, playert *pgain )
{
	static u16
		ids[] =
		{
			SFX_INTERCEPTED,
			SFX_INTERCEPTION,
			SFX_TURNOVER,
		};
	static int
		time[6] =
		{
			-TIME_CHECK,
			-TIME_CHECK,
			-TIME_CHECK,
		};
	u16
		id,
		list[6];
	s32
		i,
		num,
		base,
		count = 0;

	if (project_flag || Speech_IsAnnouncing( Stu ))
		return;


	{
		base = 3;
		num = 3;
	}

	for (i=0; i<num; i++)
	{
		if (lp_ctr > (time[base] - TIME_CHECK))
			list[count++] = base;

		base++;
	}

	if (!count)
		return;

	i = random( count );
	time[i] = lp_ctr;
	id = ids[i];

	Speech_PlayByPlay( id );
}


static void pass_commentary()
{
	int		id,ids;

	COMMENT_VARS;

	if (inbounds_flag)
		inbound_color();

	if (Speech_IsBusy() || Speech_IsQueued() || random( 2 ))
		return;

	j = 0;
	if (random( 5 ))
	{
		RANDOM_BITE( PassSpecial );
	}

	if (!j)
	{
		RANDOM_BITE( Pass );
	}

	// Determine whether or not to play the 'to player' passing commentary
	if (!j || !random( 4 ))
	{
		if (lp_ctr > (PassToTime + (10 * ONE_SEC)))
		{
			if (!inbounds_flag)
				Speech_PlayByPlay_Player( &player[int_recvr], SPEECH_TO );

			Speech_PlayByPlay_Player( &player[int_recvr], SPEECH_NORMAL );
		}
		return;
	}

	// Play the sound bite
	PlayBite(c);
}


playert *PassPlyr
		(
		char	src
		)
{
	playert	*plyr;

	switch(src)
	{
		case 'p':	// Passer
			plyr=bhp;
			break;

		case 'r':	// Receiver
			plyr=&player[int_recvr];
			break;
	}

	return plyr;
}

#define	PASS_DIST_CLOSE			0x180000
//#define	PASS_DIST_MEDIUM	 0x500000
#define	PASS_DIST_MEDIUM		0x7d0000
#define	PASS_DIST_LONG			0x1fff0000

static int ParsePass( const char *src )
{
	playert	*plyr;
	playert	*p,*e;
	bool	result=0;
	int		dist;
	int		d_max;
	int		d_min;
	int		an;

	switch(*src)
	{
		case 'D':	// Distance (passer to receiver)
			switch(src[1])
			{
				case 'c':	//	Close
					d_min=0;
					d_max=PASS_DIST_CLOSE;
					break;

				case 'l':	// Long
					d_min=PASS_DIST_MEDIUM;
					d_max=PASS_DIST_LONG;
					break;

				case 'm':	// Medium
					d_min=PASS_DIST_CLOSE;
					d_max=PASS_DIST_MEDIUM;
					break;

				default:	// Need a specifier
					BRK;
					break;
			}

			dist=MANHATTAN(player[int_recvr].xco-bhp->xco,player[int_recvr].yco-bhp->yco);
			if (dist>=d_min && dist<=d_max)
				result=1;
			return 2*2+result;

		case 'L':	// Player Location
			plyr=PassPlyr(src[1]);
			switch(src[2])
			{
				case 'b':	// Backcourt
					if (PLY(plyr)<0)
						result=1;
					break;

				case 'u':	// Upcourt
					if (PLY(plyr)>0)
						result=1;
					break;

				case 'l':	// Low post
					if (abs(plyr->xco)<LANE_X*5/4 && PLY(plyr)>(FOUL_LINE+BASE_LINE)/2)
						result=1;
					break;

				case 'k':	// Key
					if (IN_KEY(plyr))
						result=1;
					break;

				case 't':	// Top of the key
					if (abs(plyr->xco)<LANE_X*5/4 && PLY(plyr)>FOUL_LINE && PLY(plyr)<FOUL_LINE/2)
						result=1;
					break;

				case 'e':	// Base line
					if (PLY(plyr) > (BASE_LINE-0x1f4000))
						result=1;
					break;
			}
			break;

		case 'T':	// Pass Type
			switch(src[1])
			{
				case 'b':	// Bounce pass
					if (bounce_flag)
						result=1;
					break;

				case 'c':	// Chest pass
					an=abs(bhp->top_anim);
					switch(an)
					{
						case TOP_OPR1:
						case TOP_SHOV1:
//						case TOP_DISHR1:
//						case TOP_DISHL1:
							result=1;
							break;
					}
					break;

				case 'l':	// Lob pass
					an=abs(bhp->top_anim);
					switch(an)
					{
						case TOP_BASEP1:
						case TOP_HOOKP1:
						case TOP_OHP0:
						case TOP_OPR1:
							result=1;
							break;
					}
					break;

				case 'n':	// No-look pass
					an=abs(bhp->top_anim);
					break;

				case 'w':	// Wrap-around pass
					an=abs(bhp->top_anim);
					break;
			}
			return 2*2+result;

		case 'S':	// Situation
			plyr=PassPlyr(src[1]);
			switch(src[2])
			{
				case 'd':	// Double team
					if (plyr==bhp && ai_team[bhp->team].dt)
						result=1;
					break;

				case 'f':	// Fast break
					if (fast_break_flag)
						result=1;
					break;
					
				case 'h':	// Player is last ball handler (give 'n go type thingie)
					if (plyr->no == last_handler)
						result=1;
					break;

				case 'i':	// Check for inbounds
					if (inbounds_flag && !in_play_flag)
						result=1;
					break;

				case 'o':
					plyr=&player[int_recvr];
					p=&player[plyr->base^5];
					e=p+5;
					do
					{
						if (MANHATTAN(p->xco-plyr->xco,p->yco-plyr->yco)<DIST_COVERED)
							break;
					} while (++p<e);
					if (p==e)
						result=1;
					break;
			}
			return 3*2+result;

		default:	// Illegal Op
			BRK;
			break;
	}

	return 3*2+result;
}


void PlayStu(SPhrase *c)
{
	int		id;
	int		ids;
	int sfx, group;
	playert	*plyr;

	group = c->Group;
	if (group != GRP_NONE)
		GroupTimes[group] = lp_ctr;

	c->LastPlayed = lp_ctr;

	sfx = c->sample_id;
	ids=c->format;

	while((id=ids&COMASK))
	{
		ids>>=COBITS;
		switch(id)
		{
			case BALLER:
			case FOULER:
				Speech_ColorGuy_Player( Player->plyrROM->uw___pIndx );
				break;

			case OPPOSING:
				Speech_ColorGuy_Team( Player->team^1 );
				break;

			case TEAM:
				Speech_ColorGuy_Team( Player->team );
				break;

			case AUDIO:
				Speech_ColorGuy( sfx );
				sfx++;
				break;

			default:
				BRK;
		}
	}
}

void PlayBite(SPhrase *c)
{
	int		id;
	int		ids;
	int		i, index;
	playert	*plyr;

	plyr = Player;

	c->LastPlayed = lp_ctr;

	ids=c->format;
	i=0;

	while((id=ids&COMASK))
	{
		ids>>=COBITS;
		switch(id)
		{
			case XBALLER:
				if (!i)	// Don't play initial player name if same as last player
					if (Speech_IsBusy() || Speech_IsQueued())
						if (Speech_LastPlayer()==plyr->plyrROM->uw___pIndx)
							break;

				Speech_PlayByPlay_Player( plyr, SPEECH_EXCITED );
				break;

			case BALLER:
				if (!i)	// Don't play initial player name if same as last player
				{
//					if (Speech_IsBusy() || Speech_IsQueued())
						if (Speech_LastPlayer()==plyr->plyrROM->uw___pIndx)
						{
#if 0//def PHIL_TEST
							int
								j;
							char
								text[64];

							plyr = NULL;
							for (j=0; j<10; j++)
							{
								if (player[j].plyrROM->uw___pIndx == Speech_LastPlayer())
									plyr = &player[j];
							}

							if (plyr)
							{
								sprintf( text, "cut %s %s\n",
												 plyr->plyrROM->pcz__pSName,
												 bhp->plyrROM->pcz__pSName );
							}
							else
							{
								sprintf( text, "cut ? %s\n", bhp->plyrROM->pcz__pSName );
							}

							PCwrite( -1, text, strlen( text ) );
#endif
							break;
						}
				}

				Speech_PlayByPlay_Player( plyr, SPEECH_NORMAL );
				break;

			case FOULER:
				plyr = Fouler;
				if (!i)	// Don't play initial player name if same as last player
					if (Speech_IsBusy() || Speech_IsQueued())
						if (Speech_LastPlayer()==plyr->plyrROM->uw___pIndx)
							break;

				Speech_PlayByPlay_Player( plyr, SPEECH_NORMAL );
				break;

			case LASTH:
				plyr=&player[last_handler];
				if (!i)	// Don't play initial player name if same as last player
					if (Speech_IsBusy() || Speech_IsQueued())
						if (Speech_LastPlayer()==plyr->plyrROM->uw___pIndx)
							break;

				Speech_PlayByPlay_Player( plyr, SPEECH_NORMAL );
				break;

			case RECEIVER:
				if (!i)	// Don't play initial player name if same as last player
					if (Speech_IsBusy() || Speech_IsQueued())
						if (Speech_LastPlayer()==player[int_recvr].plyrROM->uw___pIndx)
							break;

				Speech_PlayByPlay_Player( &player[int_recvr], SPEECH_NORMAL );
				break;

			case TORECEIVER:
				plyr = &player[int_recvr];
				index = plyr->plyrROM->uw___pIndx;

				Speech_PlayByPlay_Player( plyr, SPEECH_TO );
				Speech_PlayByPlay_Player( plyr, SPEECH_NORMAL );
				break;

			case AUDIO:
				Speech_PlayByPlay(c->sample_id);
				break;

			case XRECEIVER:
				Speech_PlayByPlay_Player( &player[int_recvr], SPEECH_EXCITED );
				break;

			case TEAM:
				Speech_PlayByPlay_Team( plyr->team, SPEECH_TEAM_NAME );
				break;

			default:
#ifdef PHIL_TEST
				{
					char
						numstr[8];

					IntToHexStr( c->format, numstr );
					strcat( numstr, "\n" );
					PCwrite( -1, numstr, strlen( numstr ) );
				}
#endif
				BRK;
				break;
		}

		i++;
	}
}


static bool Parse( const char *src, CPF parser )
{
	const char *text = src;
	u32		stack;
	int		level;
	int		rv;

	// If no text string, always true
	if (!(*src))
		return TRUE;

	// Run through the function
	stack=0;	// No truth values on stack yet
	level=0;	// Haven't pushed anything on the stack yet
	do
	{
		switch(*src)
		{
			case '&':
				if (level<2)
					FatalError( text, __FILE__, __LINE__ );
//					BRK;

				stack=(stack>>1)&(stack|~1);	// Pop & AND with the bottom bit only
				src+=1;
				level--;
				break;

			case '|':
				if (level<2)
					BRK;

				stack=(stack>>1)|(stack&1);		// Pop & OR with bottom bit only
				src+=1;
				level--;
				break;

			case '^':
				if (level<2)
					BRK;

				stack=(stack>>1)^(stack&1);		// Pop & XOR with bottom bit only
				src+=1;
				level--;
				break;

			case '!':
				if (!level)
					BRK;

				stack^=1;	// Flip the top of the stack
				src+=1;		// Skip this character plus the trailing space
				break;

			default:
				rv=parser(src);
				src+=rv>>1;
				stack=(stack<<1)+(rv&1);
				level++;
				break;
		}

	} while(*src++);	// Skips space after specifier, but accepts final null

	if (level!=1)
		FatalError( text, __FILE__, __LINE__ );

	return (stack&1);	// Result is top of stack
}


static void DoStu( const u32 type, const s32 extra )
{
	if (time_left > (3*ONE_SEC))
	{
		switch (type)
		{
			case COMMENT_FOUL:
				foul_color( extra );
				break;

			case COMMENT_SHOT_MISS:
				if (FTshots)
					freethrow_color();
				else
					miss_color();
				break;

			case COMMENT_SHOT_SCORE:
				if (FTshots)
					freethrow_color();
				else
					score_color();
				break;

			case COMMENT_DUNK_SCORE:
				dunk_score_color();
				break;
		}
	}
}


static void DoChick( const u32 type, const s32 extra )
{
		switch (type)
		{
			case COMMENT_FOUL:
				foul_commentary( Fouler, extra );
				break;

			case COMMENT_SHOT_MISS:
				Scored = FALSE;
				miss_commentary();
				break;

			case COMMENT_SHOT_SCORE:
				Scored = TRUE;
				score_commentary();
				break;

			case COMMENT_DUNK_SCORE:
				Scored = TRUE;
				dunk_score_commentary();
				break;

			case COMMENT_PASS:
				pass_commentary();
				break;

			case COMMENT_SHOOT:
				shoot_commentary();
				break;

			case COMMENT_DUNK:
				dunk_commentary();
				break;

			case COMMENT_LAYUP:
				layup_commentary();
				break;

			case COMMENT_TIP_IN:
				tip_in_commentary();
				break;

			case COMMENT_ALLEY_OOP:
				alley_commentary();
				break;

			case COMMENT_BLOCK:
				block_commentary();
				break;

			case COMMENT_WELCOME:
				welcome_commentary();
				break;

			case COMMENT_QUARTER:
				quarter_commentary();
				break;
		}
}


void Comment( const u32 type, playert *plyr, const s32 extra )
{
	if (project_flag || C3PT)
		return;

	if (type == COMMENT_FOUL)
	{
		FTshots = free_throws;
		Player = bhp;
		Fouler = plyr;
	}
	else
		Player = plyr;

#ifdef PHIL_TEST
	if (Speech_IsAnnouncing( Stu ))
		PCwrite( -1, "stu busy!\n", 10 );
#endif

	if (!Speech_IsAnnouncing( Stu ))
	{
		DoChick( type, extra );
		DoStu( type, extra );
	}


	if (type != COMMENT_FOUL)
	{
		if (FTshots)
			FTshots--;
	}
}
