// This version of a Scrabble analysis program uses an Optimal Universal Directed Acyclic Word Graph and a Parallel Algorithm sequentially.

#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <time.h>
#include <assert.h>

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define MIN 2
#define MAX 15
#define MAXTILES 7
#define NUMBEROFENGLISHLETTERS 26
#define NUMBEROFPARENTNODES 28
#define TOTAL 178691
#define TOTALARRAYNODES 1625324
#define LOWERIT 32
#define BINGO 7
#define BINGOBONUS 50
#define INVALID 999
#define LEFT 0
#define RIGHT 1

// This data file containing the optimal UDawg required 21 hours, 34 minutes, 31 seconds to compile on an AMD 2000+ cpu ASUS K8V-X 1GB 400Mhz ddr RAM.
#define OUDAWG_DATA "OptimalUDawgForLexicon.dat"

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

enum { MAX_ROW = 15, MAX_COL = 15, MIN_ROW = 1, MIN_COL = 1 };

typedef enum { SPACE = 32, EMPTY = 63, Aa = 65, Bb = 66, Cc = 67, Dd = 68, Ee = 69, Ff = 70, Gg = 71, 
Hh = 72, Ii = 73, Jj = 74, Kk = 75, Ll = 76, Mm = 77, Nn = 78, Oo = 79, Pp = 80, Qq = 81, 
Rr = 82, Ss = 83, Tt = 84, Uu = 85, Vv = 86, Ww = 87, Xx = 88, Yy = 89, Zz = 90} Letter;

typedef enum { CLEAR = 0, LIGHTBLUE = 1, DARKBLUE = 2, PINK = 3, RED = 4 } Colour;

typedef enum { NOBODY = 0, PLAYERONE = 1, PLAYERTWO = 2, PLAYERTHREE = 3, PLAYERFOUR = 4 } Player;

typedef enum { ZERO =0, ONEE =1, TWOO =2, THREEE =3, FOURR =4, FIVEE =5, EIGHTT =8, TENN =10 } Value;

typedef enum { TRUE = 1, FALSE = 0} Bool;
typedef Bool* BoolPtr;

typedef enum { ACROSS = 0, DOWN = 1 } Direction;

typedef enum { VACANT = 0, FILLED = 1, CONDITIONAL = 2 } SquareState;

typedef enum { ONLINE = 0, TWOPLAYER = 1, THREEPLAYER = 2, FOURPLAYER = 3, TWOPLAYERGENERATERACK = 4,
							 THREEPLAYERGENERATERACK = 5, FOURPLAYERGENERATERACK = 4} GameType;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

const Value TileValues[28] = { ZERO, ZERO, ONEE, THREEE, THREEE, TWOO, ONEE, FOURR, TWOO, FOURR, ONEE, EIGHTT, 
FIVEE, ONEE, THREEE, ONEE, ONEE, THREEE, TENN, ONEE, ONEE, ONEE, ONEE, FOURR, FOURR, EIGHTT, FOURR, TENN };

const int NumberOfNodesBelowParent[NUMBEROFPARENTNODES][NUMBEROFENGLISHLETTERS] 
={{ 24755, 20788, 35007, 22389, 16259, 14958, 12202, 14621, 16195, 3043, 3737, 10963, 21966, 12517, 13889, 33932, 1721, 22285, 41965, 19066, 16032, 6107, 8027,  363,  1097, 1300 },
	{ 10183,   568, 12960, 42636, 51869,   890, 33966,  5564,  2901,   16, 4207, 17211,  9281, 23031,  3290,  2935,   11, 25286,197185, 24648,   611,   67, 1073, 1143, 40367,  255 },
	{ 49219,  2388,  6620,  2373, 60564,  1217,  1333, 15415, 38080,  117, 1018, 16968,  6427, 34185, 54762,  7997, 1069, 31657,  4532,  7555, 31583, 5342, 1833, 3924,  8673,  330 },
	{ 32578,  1409, 11606, 10945,130612,  2231,  8592,  4879, 31024,   98, 6624, 39855, 10925, 65936, 23640,  5198,   16, 34985, 31835, 34533, 13327, 3806, 1667,  282,  2365, 3184 },
	{ 31415, 10975, 21560, 13043, 29619,  6551, 10027,  4130, 22038, 1056, 1918, 24197, 16455, 33139, 25498, 17522,  836, 34920, 26806, 31285, 14951, 5509, 3830, 1865,  4656, 1479 },
	{ 35944, 10332, 13220, 11628, 56549,  3429,  9629,  9973,114557,  398, 4888, 25351,  9908, 30974, 43261,  6896,  322, 22443, 34782, 36535, 12694, 3698, 2198, 1899,  3138, 7413 },
	{ 28355,  8672, 18908, 14185, 43617,  6824, 10468, 10299, 33536,  861, 7750, 21661, 12845, 21065, 29054, 15230, 1048, 31493, 19288, 31321, 13982, 4648, 3674, 1092,  3843, 1858 },
	{ 51811,  8556, 17299, 13198, 34797,  6208, 11537, 13517, 63653,  634, 6078, 33619, 13158, 36996, 32730, 11572,  541, 34769, 30721, 49074, 17568, 4903, 5584, 1345,  6721, 5338 },
	{ 32180,  8314, 14641, 10428, 43321,  6085,  8595, 12672, 42523,  401, 4996, 25546, 12110, 22372, 34421, 11223,  619, 33138, 19447, 26136, 13591, 3006, 3787,  942,  4280, 1443 },
	{ 54075, 10397, 23757, 14050, 52123,  6714, 12542, 15091, 51893,  653, 4818, 31000, 15775, 29707, 38143, 15048,  852, 38148, 24317, 39203, 16782, 4176, 5814, 1434,  5957, 2190 },
	{ 32368,  7766, 15819,  9483, 46154,  6011,  9084, 10198, 47563,  445, 2769, 25459, 11344, 29018, 28904,  9770,  501, 28976, 19482, 28028, 11575, 3907, 3816, 1203,  4270, 1449 },
	{ 50052, 11745, 21491, 12596, 50027,  6724, 11475, 14660, 43573,  791, 4696, 33276, 15964, 35824, 41848, 16284,  860, 43635, 24849, 33667, 23468, 6082, 4348, 1787,  6190, 2726 },
	{ 34580,  5686, 12122,  8121, 49985,  3103,  7920,  7349, 50888,  204, 3675, 23541,  8815, 27882, 27152,  6563,  254, 26403, 21052, 28346, 12116, 2513, 1877, 1134,  4094, 2258 },
	{ 44541, 10847, 21949, 12736, 49862,  6294, 11399, 14831, 44906,  786, 4049, 28613, 15920, 30377, 45721, 16591, 1189, 44584, 23901, 33055, 22674, 5857, 4152, 2253,  6028, 2124 },
	{ 25236,  4965, 10718,  7788, 46138,  2491,  6670,  6211, 45003,  102, 3608, 21288,  8086, 30475, 18412,  5156,  163, 21870, 20787, 27446,  8701, 2672, 1384,  768,  2636, 2857 },
	{ 38036,  8917, 19383, 10599, 48430,  5401,  8244, 12714, 35460,  669, 2901, 23981, 13885, 29842, 41718, 15576, 1170, 41515, 22301, 29558, 21675, 5429, 2634, 2409,  5996,  810 },
	{ 18456,  3598,  8162,  5667, 42801,  1231,  4838,  4652, 40394,   78, 2400, 15995,  6056, 28279, 12684,  3366,  127, 16040, 16748, 21250,  6493, 2134,  565,  418,  1438, 2532 },
	{ 31417,  6157, 15890,  8086, 41991,  4174,  5447, 10147, 28693,  488, 1776, 17540, 11064, 25574, 34348, 12895,  966, 34497, 16155, 22096, 17773, 4171, 1369, 2348,  5090,  471 },
	{ 13375,  2403,  6125,  3246, 33973,   515,  3184,  2855, 30190,    0,  994, 13788,  4173, 23806, 10026,  1846,   13, 10084, 13201, 16424,  4409, 1638,  300,  226,   674, 1863 },
	{ 22582,  4305, 11779,  5753, 33300,  2877,  3499,  7848, 21107,  343,  843, 12678,  9136, 21356, 26714,  9921,  753, 26274, 12087, 17187, 13146, 3680,  936, 1694,  4084,  359 },
	{  9657,  1406,  4261,  1731, 24057,   358,  2155,  1685, 22756,   15,  456, 11177,  2510, 18531,  6921,  1105,   36,  6956, 10683, 11868,  2356, 1088,  147,   69,   397,  930 },
	{ 14931,  2659,  8986,  4003, 24353,  1958,  2476,  5970, 14043,  218,  400,  8289,  6134, 17811, 19944,  7132,  484, 20170,  8039, 13040,  9322, 2756,  374, 1462,  3425,  263 },
	{  5655,   755,  1879,   931, 16617,   121,  1332,   712, 14620,    0,  220,  8493,  1530, 12327,  4808,   602,   15,  3720,  9267,  8448,  1530,  773,   44,   40,   286,  863 },
	{  9366,  1626,  5951,  2517, 17604,  1176,  1627,  3890,  9508,   86,  223,  5363,  3827, 13322, 13402,  4818,  307, 12496,  5471,  8168,  6567, 1997,  263, 1227,  2690,   53 },
	{  2500,   325,  1184,   433, 12010,    29,   696,   367,  9528,    0,   62,  5199,  1040,  6945,  3168,   516,   15,  1911,  6632,  4108,   702,  489,    0,   29,    80,  250 },
	{  5361,   706,  3144,  1378, 10230,   677,   768,  2373,  5071,  105,  131,  3297,  2357,  8382,  8681,  3161,  106,  6298,  3406,  4001,  4263, 1600,  170,  748,  2069,   28 },
	{  1635,     0,   372,   142,  6975,     0,   361,   178,  1305,    0,   29,  2492,   609,  4321,  1727,   216,    0,   781,  2309,  2327,   334,  268,    0,    0,     0,  122 },
	{  2023,   176,   435,   211,  5488,   108,   165,  1558,  2906,    0,    0,  1141,   793,  4453,  4714,   544,   65,  2477,   488,   511,  1810,  943,   15,  658,  1100,   15 } };

const int ExactParentNodeIndexPosition[NUMBEROFPARENTNODES][NUMBEROFENGLISHLETTERS] 	
={{   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26 },
	{ 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379 },
	{  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52 },
	{ 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405 },
	{  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78 },
	{ 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431 },
	{  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99, 100, 101, 102, 103, 104 },
	{ 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457 },
	{ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130 },
	{ 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483 },
	{ 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156 },
	{ 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509 },
	{ 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182 },
	{ 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535 },
	{ 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208 },
	{ 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561 },
	{ 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234 },
	{ 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587 },
	{ 235, 236, 237, 238, 239, 240, 241, 242, 243,   0, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259 },
	{ 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613 },
	{ 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285 },
	{ 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639 },
	{ 286, 287, 288, 289, 290, 291, 292, 293, 294,   0, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310 },
	{ 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665 },
	{ 311, 312, 313, 314, 315, 316, 317, 318, 319,   0, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,   0, 332, 333, 334 },
	{ 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691 },
	{ 335,   0, 336, 337, 338,   0, 339, 340, 341,   0, 342, 343, 344, 345, 346, 347,   0, 348, 349, 350, 351, 352,   0,   0,   0, 353 },
	{ 692, 693, 694, 695, 696, 697, 698, 699, 700,   0,   0, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715 } };
	
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// String Manipulation functions.

// When ThisChar is a lower case letter the function returns its capital counterpart.  Otherwise, the function returns the upper case letter entered.  This function is never to be used on anything but Alphabetical letters.
char CapitalChar( char ThisChar ) {
	if ( ThisChar <= Zz ) return ThisChar;
	else return (ThisChar - LOWERIT);
}

void StringsHaveInCommon( char *First, char *Second, char *Resultant ) {
	int X;
	int Y;
	int NumberIntersect = 0;
	for ( X = 0; X < (signed int)(signed int)strlen( First ); X++ ) {
		for ( Y = 0; Y < (signed int)(signed int)strlen( Second ); Y++ ) {
			if ( First[X] == Second[Y] ){
				Resultant[NumberIntersect] = First[X];
				NumberIntersect += 1;
				break;
			}
		}
	}
	Resultant[NumberIntersect] = '\0';
}

int StringToInt( char* TheNumberNotYet	) {
	int result = 0;
	int X;
	int Y;
	for ( X = ((signed int)(signed int)strlen( TheNumberNotYet ) - 1); X >=0; X-- ) {
		Y = (signed int)(signed int)strlen( TheNumberNotYet ) - 1 - X;
		if ( !(TheNumberNotYet[X] >= '0' && TheNumberNotYet[X] <= '9') ) return 0;
		result += (int)(TheNumberNotYet[X] - '0')*pow( 10, Y );
	}
	return result;
}

void StringClearMe( char *ThisString ) {
	int X;
	for( X = 0; X <= (signed int)(signed int)strlen( ThisString ); X++ ) {
		ThisString[X] = '\0';
	}
}

// Used when placing a tile on a conditional square when a conditional square takes only 1 potential tile in a rack.
void StringRemoveChar( char *ThisString, int Place ) {
	int X;
	int Last = (signed int)(signed int)strlen( ThisString );
	for ( X = Place; X < Last; X++ ) {
		ThisString[X] = ThisString[X + 1];
	} 
}

/*This Function converts any lower case letters in the string "RawWord," into all capitals, so that the whole string is made of capital letters. */
void MakeMeAllCapital( char* RawWord ) {
	int Count;
	for( Count = 0; Count < (signed int)(signed int)strlen( RawWord ); Count++ ) {
		if( RawWord[Count] >= 97 && RawWord[Count] <= 122 ) RawWord[Count] = RawWord[Count] -LOWERIT;
	}
}

/* Let's use a simple bubble sort,. The is no need for a q-sort or anything that snazzy for alphabetizing the simple string "Word" that will be 21 chars long at most.	*/
void Alphabetize( char* Word ) {
	int X;
	int Y;
	char WorkingChar;
	int WordSize = (signed int)(signed int)strlen(Word);
	/* This nested "for" loop structure ensures that the highest letter filters to the back of the string each time that we	increment X in the outer loop. */
	for( X = 1; X < WordSize; X++ ) {
		for( Y = 0; Y <= (WordSize - X - 1); Y++) {
			if (Word[Y] > Word[Y + 1]){
				WorkingChar = Word[Y + 1];
				Word[Y + 1] = Word[Y];
				Word[Y] = WorkingChar;
			}
		}
	}
}

char *StringAllocateMe( char *DataString ) {
	char *Result = malloc( (signed int)(signed int)strlen( DataString + 1 ) );
	strcpy ( Result, DataString );
	return Result;
}

// This function could use some clean up.
int BoolMakeValidLetterString( BoolPtr Vector, char* ThisRack, int RackSize, char *Intersect ) {
	int X;
	int Y;
	int StartY = (ThisRack[1] == EMPTY)? 1: 0;
	int NumberOfValid = 0;
	// Proper decision for the ? must be made
	for( X = 0; X < NUMBEROFENGLISHLETTERS; X++ ) {
		if ( Vector[X] == TRUE) {
			for ( Y = StartY; Y < RackSize; Y++ ) {
				if ( ThisRack[Y] == EMPTY ) {
					Intersect[NumberOfValid] = (X + Aa + LOWERIT);
					NumberOfValid += 1;
				}
				else if ( ThisRack[Y] < (X + Aa) ) continue;
				else if ( ThisRack[Y] == (X + Aa) ) {
					Intersect[NumberOfValid] = (X + 'A');
					NumberOfValid += 1;
					break;
				}
				else if ( ThisRack[Y] > (X + Aa) ) break;
			}
		}
	}
	Intersect[NumberOfValid] = '\0';
	return NumberOfValid;
}

// This function could use some clean up.
int BoolHowManyValid( BoolPtr Vector, char* ThisRack, int RackSize ) {
	int X;
	int Y;
	int StartY = (ThisRack[1] == EMPTY)? 1: 0;
	int NumberOfValid = 0;
	// Proper decision for the ? must be made
	for( X = 0; X < NUMBEROFENGLISHLETTERS; X++ ) {
		if ( Vector[X] == TRUE) {
			for ( Y = StartY; Y < RackSize; Y++ ) {
				if ( ThisRack[Y] == EMPTY ) {
					NumberOfValid += 1;
				}
				else if ( ThisRack[Y] < (X + Aa) ) continue;
				else if ( ThisRack[Y] == (X + Aa) ) {
					NumberOfValid += 1;
					break;
				}
				else if ( ThisRack[Y] > (X + Aa) ) break;
			}
		}
	}
	return NumberOfValid;
}

// returns -1 if the char is not in the string, otherwise returns the index of the first ThisChar in the word.
int StringFindChar( char *ThisString, int StringSize, char ThisChar ) {
	int X;
	for ( X = 0; X < StringSize; X++ ) {
		if ( ThisString[X] == ThisChar ) return X;
	}
	return -1;
}

// Used to add words to a list that keeps track of valid plays to be made in a PlaySpace.
char *AllocateAndReorderWord( char *ThisRawWord, int ReorderTolken ) {
	char *Result = malloc( (signed int)(signed int)strlen( ThisRawWord ) + 1 );
	int WordLength = (signed int)(signed int)strlen( ThisRawWord );
	int Direction;
	int Position;
	int Y;
	char Temp;
	strcpy ( Result, ThisRawWord  );
	if ( div( ReorderTolken, 2 ).rem == 0 ) Direction = LEFT;
	else Direction = RIGHT;
	Position = div( ReorderTolken, 2).quot + 1;
	// re-arrange the letters based on positional variance.
	for ( Y = 0; Y < div( Position, 2 ).quot; Y++ ) {
		Temp = Result[Y];
		Result[Y] = Result[Position - 1 - Y];
		Result[Position - 1 - Y] = Temp;
	}
	// Re-Reverse the word only if necessary.
	if ( Direction == RIGHT ) {
		for ( Y = 0; Y < div( WordLength, 2 ).quot; Y++ ) {
			Temp = Result[Y];
			Result[Y] = Result[WordLength - 1 - Y];
			Result[WordLength - 1 - Y] = Temp;
		}
	}
	return Result;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// This is where the linked list type definitions are located for a WordList.

/*WordList TypeDefs*/
struct wordnode {
	char* Word;
	struct wordnode* Next;
};

typedef struct wordnode WordNode;
typedef WordNode* WordNodePtr;

struct wordlist {
	WordNodePtr Front;
	int Size;
};

typedef struct wordlist WordList;
typedef WordList* WordListPtr;

/*WordList functions*/
WordListPtr WordListInit( void ) {
	WordListPtr Result = malloc( sizeof( WordList ) );
	assert(Result != NULL);
	Result->Front = NULL;
	Result->Size = 0;
	return Result;
}

/* Returns the size of the given wordlist wl. */
int WordListSize( const WordListPtr ThisWordList ) {
	assert(ThisWordList != NULL);
	return ThisWordList->Size;
}

/* Returns the element at index i in wordlist wl. The given index must be
	 between 0 and n-1 inclusive, where n is the size of the wordlist. */
char* WordListGetWord( const WordListPtr ThisWordList, int Count ) {
	int X;
	WordNodePtr Current;
	assert(ThisWordList != NULL);
	assert( Count >= 0  && Count < ThisWordList->Size );
	for ( X = 0, Current = ThisWordList->Front; X != Count && Current != NULL; X++, Current = Current->Next );
	return Current->Word;
}

/*Take Note that this function does not make a new word, it only makes a new WordNode., hence W must be allocated elsewhere.  Insert the word at the beginning of the list, this process will get reversed with the plat appending function for alphabetical order concerns.*/
void WordListAppend( WordListPtr ThisWordList, char* ThisWord ) {
	WordNodePtr NewWordNode;
	assert(ThisWordList != NULL);
	NewWordNode = (WordNodePtr)malloc( sizeof( WordNode ) );
	assert( NewWordNode != NULL );
	NewWordNode->Word = ThisWord;
	NewWordNode->Next = ThisWordList->Front;
	ThisWordList->Front = NewWordNode;
	ThisWordList->Size += 1;
}

void WordListOutput( WordListPtr ThisWordList ){
	WordNodePtr Current;
	assert(ThisWordList != NULL);
	if (ThisWordList->Front == NULL) {
		printf("The List is empty, better luck next time!\n");
	}
	else {
		printf("|%ld| Words In List.\n", ThisWordList->Size);
		Current = ThisWordList->Front;
		while ( Current->Next != NULL ) {
			printf( "|%s|\n", Current->Word );
			Current = Current->Next;
		}
		printf( "|%s|\n",Current->Word );
		printf( "|%d| words printed\n", ThisWordList->Size );
	}
}

// The words contained inside of a word list should not be refered to anywhere else in the program.
void ClearWordList( WordListPtr ThisWordList ) {
	WordNodePtr RunningWordNode, Current;
	if (ThisWordList->Front != NULL) {
		RunningWordNode = ThisWordList->Front;
		while (RunningWordNode->Next != NULL) {
			Current = RunningWordNode->Next;
			free( RunningWordNode->Word );
			free( RunningWordNode );
			RunningWordNode = Current;
		}
		free( RunningWordNode->Word );
		free( RunningWordNode );
	}
	ThisWordList->Front = NULL;
	ThisWordList->Size = 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Bool ArrayUnodeEndOfWordFlag( unsigned int ThisArrayUnode ) {
	if ( (ThisArrayUnode & 2147483648) == 2147483648 ) return TRUE;
	else return FALSE;
}

Bool ArrayUnodeEndOfChildListFlag( unsigned int ThisArrayUnode ) {
	if ( (ThisArrayUnode & 1073741824) ==  1073741824 )  return TRUE;
	else return FALSE;
}

int ArrayUnodeChild( unsigned int ThisArrayUnode ) {
	return ( ThisArrayUnode & 4194303);
}

int ArrayUnodeNext( unsigned int *ThisArray, int CurrentIndex ) {
	if ( ((ThisArray[CurrentIndex]) & 1073741824) == 1073741824 ) return 0;
	else return (CurrentIndex + 1);
}

char ArrayUnodeLetter( unsigned int ThisArrayUnode ) {
	return ((ThisArrayUnode & 532676608) >> 22);
}



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct arrayudawg {
	// This pointer will hold the fabled ArrayOUDAWG but it is actually an array of unsigned integers.
	unsigned int *TheBigOUDAWGArray;
};

typedef struct arrayudawg ArrayUDawg;
typedef ArrayUDawg* ArrayUDawgPtr;

// This function simply copies pre-processed array pointers into the parent data structure because all of the 21 hours of OUDAWG processing has already taken place in another program.
ArrayUDawgPtr ArrayUDawgInit( unsigned int *StaticUnit ) {
	ArrayUDawgPtr Result = (ArrayUDawgPtr)malloc( sizeof( ArrayUDawg ) );
	Result->TheBigOUDAWGArray = StaticUnit;
	return Result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct playbucket {
	SquareState Variant;
	BoolPtr Vector;
	char TheLook;
};

typedef struct playbucket PlayBucket;
typedef PlayBucket* PlayBucketPtr;

void PlayBucketInit( PlayBucketPtr ThisPlayBucket ) {
	ThisPlayBucket->Variant = VACANT;
	ThisPlayBucket->TheLook = '\0';
	ThisPlayBucket->Vector = NULL;
}

void PlayBucketSet( PlayBucketPtr ThisPlayBucket, char LookLikeMe, Bool *Vectrix, SquareState WhoAmI ) {
	ThisPlayBucket->Variant = WhoAmI;
	ThisPlayBucket->TheLook = LookLikeMe;
	ThisPlayBucket->Vector = Vectrix;
}

void PlayBucketCopy( PlayBucketPtr Destination, PlayBucketPtr Source) {
	Destination->TheLook = Source->TheLook;
	Destination->Vector = Source->Vector;
	Destination->Variant = Source->Variant;
}

struct playspace {
	int Length;
	PlayBucket StateSpace[MAX];
};

typedef struct playspace PlaySpace;
typedef PlaySpace* PlaySpacePtr;

PlaySpacePtr PlaySpaceInit( void ) {
	int X;
	PlaySpacePtr Result = malloc( sizeof( PlaySpace ) );
	Result->Length = 0;
	for ( X = 0; X < MAX; X++ ) {
		PlayBucketInit( &((Result->StateSpace)[X]) );
	}
	return Result;
}

void FreePlaySpace( PlaySpacePtr ThisPlaySpace ){
	free( ThisPlaySpace );
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct play {
	int Row;
	int Col;
	int MainWordLength;
	int TilesRequired;
	Bool BlankRequired;
	Direction Move;
	// Dynamically Allocated so that we can free the string when done with it.
	char *MainWord;
	int PointValue;
};

typedef struct play Play;
typedef Play* PlayPtr;

PlayPtr PlayInit(void) {
	PlayPtr ThisPlay = malloc(sizeof(Play));
	ThisPlay->Row = INVALID;
	ThisPlay->Col = INVALID;
	ThisPlay->MainWordLength = 0;
	ThisPlay->TilesRequired = 0;
	ThisPlay->BlankRequired = FALSE;
	ThisPlay->Move = ACROSS;
	ThisPlay->MainWord = NULL;
	return ThisPlay;
}

void PlaySet(PlayPtr ThisPlay, int row, int col, int ExactWordLength, int TilesNeeded, char *ExactWord, Direction ExactMove ) {
	int X;
	char *Resultant = StringAllocateMe( ExactWord );
	for ( X = 0; X < ExactWordLength; X++ ) {
		if ( ExactWord[X] > Zz ) {
			ThisPlay->BlankRequired = TRUE;
			break;
		}
	}
	ThisPlay->Row = row;
	ThisPlay->Col = col;
	ThisPlay->MainWordLength = ExactWordLength;
	ThisPlay->TilesRequired = TilesNeeded;
	ThisPlay->Move = ExactMove;
	ThisPlay->MainWord = Resultant;
	ThisPlay->PointValue = 0;
}

void PlayCopy ( PlayPtr NewPlay, PlayPtr OldPlay ) {
	char *Resultant = (char*)malloc( (OldPlay->MainWordLength) + 1 );
	strcpy( Resultant, OldPlay->MainWord );
	NewPlay->Row = OldPlay->Row;
	NewPlay->Col = OldPlay->Col;
	NewPlay->BlankRequired = OldPlay->BlankRequired;
	NewPlay->MainWordLength = OldPlay->MainWordLength;
	NewPlay->TilesRequired = OldPlay->TilesRequired;
	NewPlay->Move = OldPlay->Move;
	NewPlay->MainWord = Resultant;
	NewPlay->PointValue = OldPlay->PointValue;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

int PlayRow (PlayPtr ThisPlay) {
	return ThisPlay->Row;
}

int PlayCol (PlayPtr ThisPlay) {
	return ThisPlay->Col;
}

Direction PlayMove (PlayPtr ThisPlay) {
	return ThisPlay->Move;
}

int PlayMainWordLength(PlayPtr ThisPlay) {
	return ThisPlay->MainWordLength;
}

int PlayTilesRequired(PlayPtr ThisPlay) {
	return ThisPlay->TilesRequired;
}

char *PlayMainWord(PlayPtr ThisPlay) {
	return ThisPlay->MainWord;
}

int PlayPointValue( PlayPtr ThisPlay ) {
	return ThisPlay->PointValue;
}

Bool PlayBlankRequired( PlayPtr ThisPlay ) {
	return ThisPlay->BlankRequired;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void PlaySetPointValue( PlayPtr ThisPlay, int PointAnalysis ) {
	ThisPlay->PointValue = PointAnalysis;
}

void PlayOutput ( PlayPtr ThisPlay, int PlayPosition ) {
	int countyer;
	printf( "||p#%5d|| ", PlayPosition );
	if ( ThisPlay->BlankRequired == TRUE ) printf( "?it|" );
	else printf( "   |" );
	printf( " %s", ThisPlay->MainWord );
	for ( countyer = 0; countyer < ( 16 - ThisPlay->MainWordLength) ; countyer++, printf(" ") );
	printf( " |%d| Tiles",ThisPlay->TilesRequired );
	printf( " |%2d| Word Length",ThisPlay->MainWordLength );
	printf("  ||Row|%c||-||Col|%2d|| ", (char)ThisPlay->Row + 65, ThisPlay->Col + 1);
	printf("Worth |%3d| Points |", ThisPlay->PointValue );
	if ( ThisPlay->Move == ACROSS ) printf("Across||\n");
	else printf("  Down||\n");
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/*PlayList TypeDefs*/
struct playnode {
	PlayPtr ThePlay;
	struct playnode* Next;
};

typedef struct playnode PlayNode;
typedef PlayNode* PlayNodePtr;

PlayNodePtr PlayNodeInit( PlayPtr ThisPlay ) {
	PlayNodePtr NewPlayNode = malloc( sizeof( PlayNode ) );
	assert( NewPlayNode != NULL );
	NewPlayNode->ThePlay = ThisPlay;
	NewPlayNode->Next = NULL;
	return NewPlayNode;
}

struct playlist {
	PlayNodePtr Front;
	int Size;
};

typedef struct playlist PlayList;
typedef PlayList* PlayListPtr;

/*PlayList functions*/
PlayListPtr PlayListInit( void ) {
	PlayListPtr Result = malloc( sizeof( PlayList ) );
	assert( Result != NULL );
	Result->Front = NULL;
	Result->Size = 0;
	return Result;
}

/* Returns the size of the given PlayList pl. */
int PlayListSize( const PlayListPtr ThisPlayList ) {
	assert( ThisPlayList != NULL );
	return ThisPlayList->Size;
}

/* Returns the element at index i in PlayList ThisPlayList. The given index must be
	 between 1 and n inclusive, where n is the size of the PlayList ThisPlayList. */
PlayPtr PlayListGetPlay(const PlayListPtr ThisPlayList, int Count) {
	int X;
	PlayNodePtr Current;
	assert( ThisPlayList != NULL );
	assert( Count >= 1 && Count <= ThisPlayList->Size );
	for (X = 1, Current = ThisPlayList->Front; X != Count && Current != NULL; X++, Current = Current->Next);
	return Current->ThePlay;
}

/*Take Note that this function does not make a new Play, it only makes a new PlayNode., hence P must be dynamically allocated elsewhere*/
void PlayListAppend(PlayListPtr ThisPlayList, PlayPtr ThisPlay) {
	PlayNodePtr NewPlayNode;
	assert( ThisPlayList != NULL );
	NewPlayNode = PlayNodeInit( ThisPlay );
	NewPlayNode->Next = ThisPlayList->Front;
	ThisPlayList->Front = NewPlayNode;
	ThisPlayList->Size += 1;
}

int PlayPointValueCompare( const void *p, const void *q ) {
	return (*((PlayPtr*)p))->PointValue - (*((PlayPtr*)q))->PointValue;
}

// As a result of experimentation, the inclusion of blank tiles with the UDawg algorithm can generate well over 50,000 plays and this takes a while with the basic Bubble Sort algorithm,  maybe an array structure and a Q-Sort are a better idea for sure.  Butt fuck the array structure for now, but use it as a holder of the play pointers during the standard qsort stdlib function.
void PlayListQSortByPointValue( PlayListPtr ThisPlayList ) {
	if ( ThisPlayList->Front != NULL ) {
		int X;
		PlayNodePtr Current = ThisPlayList->Front;
		// We need to allocate an array of the right size, then we dump all of the Play pointers into it associated with each successive node in the list, and we are going to have to write a compare function.
		PlayPtr *PlayListConvertedToArray = (PlayPtr*)malloc( (ThisPlayList->Size)*sizeof( PlayPtr ) );
		// Copy all of the PlayPtrs into the array.
		for ( X = 0; X < ThisPlayList->Size; X++) {
			PlayListConvertedToArray[X] = Current->ThePlay;
			Current = Current->Next;
		}
		qsort( PlayListConvertedToArray, ThisPlayList->Size, sizeof( PlayPtr ), PlayPointValueCompare );
		// Finally, we are required to copy all of the play pointers back into the list in the correct sorted order.
		Current = ThisPlayList->Front;
		for ( X = 0; X < ThisPlayList->Size; X++) {
			Current->ThePlay = PlayListConvertedToArray[X];
			Current = Current->Next;
		}
		// Free the temporary array because its use has expired, though we did appreciate it.
		free ( PlayListConvertedToArray );
	}
}

void PlayListOutput( const PlayListPtr ThisPlayList ){
	int PlayRank = 1;
	if ( ThisPlayList->Front == NULL ) {
		printf("The PlayList is empty, better luck next time!\n");
	}
	else {
		PlayNodePtr Current = ThisPlayList->Front;
		printf( "||                                |   It is time to begin printing a list of     |%7d| plays             ||\n", ThisPlayList->Size );
		while ( Current->Next != NULL ) {
			PlayOutput( Current->ThePlay, PlayRank );
			Current = Current->Next;
			PlayRank += 1;
		}
		PlayOutput( Current->ThePlay, PlayRank );
		printf( "||                                |   Now we will finish printing the list of    |%7d| plays             ||\n\n", ThisPlayList->Size );
	}
}

// This function is used when clearing a PlayList, it destroys the malloced play and the malloced string inside of it.
void FreeMePlay( PlayPtr MallocedPlay ) {
	free( MallocedPlay->MainWord );
	free( MallocedPlay );
}

// empty out the contents of the list only but keep the list structure itself.
void ClearPlayList( PlayListPtr ThisPlayList ) {
	PlayNodePtr RunningPlayNode, Current;
	if ( ThisPlayList->Front != NULL ) {
		RunningPlayNode = ThisPlayList->Front;
		while ( RunningPlayNode->Next != NULL ) {
			Current = RunningPlayNode->Next;
			FreeMePlay( RunningPlayNode->ThePlay );
			free ( RunningPlayNode );
			RunningPlayNode = Current;
		}
		FreeMePlay( RunningPlayNode->ThePlay );
		free ( RunningPlayNode );
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


/* define the "square" struct with all of the information needed to define a spot on a Scrabble Board */ 
struct square {
	Bool Used;
	Player UsedBy;
	Colour TypeOfSquare;
	Bool ValidAcrossPivot;
	Bool ValidDownPivot;
	Bool AcrossPivotLetters[NUMBEROFENGLISHLETTERS];
	Bool DownPivotLetters[NUMBEROFENGLISHLETTERS];
	char Placed;
	struct square *UpSquare;
	struct square *DownSquare;
	struct square *LeftSquare;
	struct square *RightSquare;
};

/* define the "Square" type */ 
typedef struct square Square;
typedef Square* SquarePtr;

void SquareInit( SquarePtr ThisSquare, Colour Type ) {
	int Country;
	ThisSquare->Used = FALSE;
	ThisSquare->UsedBy = NOBODY;
	ThisSquare->TypeOfSquare = Type;
	ThisSquare->ValidAcrossPivot = FALSE;
	ThisSquare->ValidDownPivot = FALSE;
	ThisSquare->Placed = SPACE;
	for ( Country = 0; Country < NUMBEROFENGLISHLETTERS; Country++ ) {
		ThisSquare->AcrossPivotLetters[Country] = FALSE;
		ThisSquare->DownPivotLetters[Country] = FALSE;
	}
	ThisSquare->UpSquare = NULL;
	ThisSquare->DownSquare = NULL;
	ThisSquare->LeftSquare = NULL;
	ThisSquare->RightSquare = NULL;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// returns TRUE if "ThisSquare" has been used, false otherwise.	When the function is passed a NULL pointer, the return vale becomes FALSE.
Bool SquareUsed( const SquarePtr ThisSquare ) {
	if ( ThisSquare != NULL ) return ThisSquare->Used;
	else return FALSE;
}

Player SquareUsedBy( const SquarePtr ThisSquare ) {
	return ThisSquare->UsedBy;
}

Colour SquareTypeOfSquare( const SquarePtr ThisSquare ) {
	return ThisSquare->TypeOfSquare;
}

/* returns TRUE if "ThisSquare" is a valid across pivot point, false otherwise */
Bool SquareValidAcrossPivot( const SquarePtr ThisSquare ) {
	return ThisSquare->ValidAcrossPivot;
}

/* returns TRUE if "ThisSquare" is a valid down pivot point, false otherwise */
Bool SquareValidDownPivot( const SquarePtr ThisSquare ) {
	return ThisSquare->ValidDownPivot;
}

/* returns TRUE if "ThisSquare" is a valid pivot point, false otherwise */
Bool SquareValidPivot( const SquarePtr ThisSquare ){
	if ( ThisSquare->ValidDownPivot == TRUE || ThisSquare->ValidAcrossPivot == TRUE ) return TRUE;
	else return FALSE;
}

Bool *SquareAcrossPivotLetters( Square *ThisSquare ) {
	return (ThisSquare->AcrossPivotLetters);
}

Bool *SquareDownPivotLetters( Square *ThisSquare ) {
	return (ThisSquare->DownPivotLetters);
}

char SquarePlaced( const SquarePtr ThisSquare ) {
	return ThisSquare->Placed;
}

SquarePtr SquareUp( const SquarePtr ThisSquare ) {
	return ThisSquare->UpSquare;
}

SquarePtr SquareDown( const SquarePtr ThisSquare ) {
	return ThisSquare->DownSquare;
}

SquarePtr SquareLeft( const SquarePtr ThisSquare ) {
	return ThisSquare->LeftSquare;
}

SquarePtr SquareRight( const SquarePtr ThisSquare ) {
	return ThisSquare->RightSquare;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void SquareCopy( SquarePtr CarbonCopy, const SquarePtr Original ) {
	CarbonCopy->Used = Original->Used;
	CarbonCopy->UsedBy = Original->UsedBy;
	CarbonCopy->TypeOfSquare = Original->TypeOfSquare;
	CarbonCopy->ValidAcrossPivot = Original->ValidAcrossPivot;
	CarbonCopy->ValidDownPivot = Original->ValidDownPivot;
	CarbonCopy->Placed = Original->Placed;
}

void SquareMakeValidAcrossPivot( SquarePtr ThisSquare ) {
	if ( ThisSquare !=NULL ) {
		if ( ThisSquare->Used == FALSE ) ThisSquare->ValidAcrossPivot = TRUE;
	}
}

void SquareMakeValidDownPivot( SquarePtr ThisSquare ) {
	if ( ThisSquare != NULL ) {
		if ( ThisSquare->Used == FALSE ) ThisSquare->ValidDownPivot = TRUE;
	}
}

void SquarePlaceChar( SquarePtr ThisSquare, Player ThisPlayer, char Plinko ) {
	ThisSquare->Used = TRUE;
	ThisSquare->UsedBy = ThisPlayer;
	ThisSquare->ValidAcrossPivot = FALSE;
	ThisSquare->ValidDownPivot = FALSE;
	ThisSquare->Placed = Plinko;
}

void SquareSetAcrossPivotLetters( SquarePtr ThisSquare, Bool *AnalysisResult ) {
	int Countery;
	for ( Countery = 0; Countery < NUMBEROFENGLISHLETTERS; Countery++ ) {
		ThisSquare->AcrossPivotLetters[Countery] = AnalysisResult[Countery];
	}
}

void SquareSetDownPivotLetters( SquarePtr ThisSquare, Bool *AnalysisResult ) {
	int Countery;
	for ( Countery = 0; Countery < NUMBEROFENGLISHLETTERS; Countery++ ) {
		(ThisSquare->DownPivotLetters)[Countery] = AnalysisResult[Countery];
	}
}

void SquareSetNeighbours( SquarePtr ThisSquare, SquarePtr uper, SquarePtr downer, SquarePtr lefter, SquarePtr righter ) {
	ThisSquare->UpSquare = uper;
	ThisSquare->DownSquare = downer;
	ThisSquare->LeftSquare = lefter;
	ThisSquare->RightSquare = righter;
}

Bool SquareCanWePutThisLetterDown ( SquarePtr ThisSquare, char ThisLetter, Direction ThisWay ) {
	if ( ThisWay == ACROSS ) return (SquareAcrossPivotLetters( ThisSquare ))[ThisLetter - Aa];
	else return (SquareDownPivotLetters( ThisSquare ))[ThisLetter - Aa];
}

Bool BoolAvailable( BoolPtr Vector, char *Rack, int RackSize ) {
	int X;
	int Y;
	for ( X = 0; X < NUMBEROFENGLISHLETTERS; X++ ) {
		if ( Vector[X] == TRUE) {
			for (Y = 0; Y < RackSize; Y++) {
				if ( Rack[Y] == EMPTY ) return TRUE;
				if ( Rack[Y] == (Aa + X) ) return TRUE;
			}
		}
	}
	return FALSE;
}

Bool SquareValidAcrossPlayHook( SquarePtr Squared, char *Rack, int RackSize ){
	if ( Squared->Used == TRUE ) return FALSE;
	if ( Squared->ValidDownPivot == TRUE ) {
		if ( Squared->ValidAcrossPivot == FALSE ) return TRUE;
		else{
			int X, Y = 0;
			for ( X = 0; X < NUMBEROFENGLISHLETTERS; X++ ) {
				if ( (Squared->AcrossPivotLetters)[X] == TRUE ) {
					if ( Rack[Y] == EMPTY ) return TRUE;
					for (Y = 0; Y < RackSize; Y++){
						if ( Rack[Y] == (Letter)(Aa + X) ) return TRUE;
					}
				}
			}
		}
	}
	else if ( Squared->ValidAcrossPivot == FALSE ) return FALSE;
	else {
		int X, Y = 0;
		for ( X = 0; X < NUMBEROFENGLISHLETTERS; X++ ) {
			if ( Squared->AcrossPivotLetters[X] == TRUE) {
				if ( Rack[Y] == EMPTY ) return TRUE;
				for (Y = 0; Y < RackSize; Y++) {
					if ( Rack[Y] == (Aa + X) ) return TRUE;
				}
			}
		}
	}
	return FALSE;
}

Bool SquareValidDownPlayHook( SquarePtr Squared, char *Rack, int RackSize ) {
	if ( Squared->Used == TRUE ) return FALSE;
	if ( Squared->ValidAcrossPivot == TRUE ) {
		if ( Squared->ValidDownPivot == FALSE ) return TRUE;
		else{
			int X, Y = 0;
			for ( X = 0; X < NUMBEROFENGLISHLETTERS; X++ ) {
				if ( Squared->DownPivotLetters[X] == TRUE) {
					if ( Rack[Y] == EMPTY ) return TRUE;
					for (Y = 0; Y < RackSize; Y++){
						if ( Rack[Y] == (Aa + X) ) return TRUE;
					}
				}
			}
		}
	}
	else if ( Squared->ValidDownPivot == FALSE ) return FALSE;
	else {
		int X, Y = 0;
		for ( X = 0; X < NUMBEROFENGLISHLETTERS; X++ ) {
			if ( Squared->DownPivotLetters[X] == TRUE) {
				if ( Rack[Y] == EMPTY ) return TRUE;
				for ( Y = 0; Y < RackSize; Y++ ) {
					if ( Rack[Y] == (Aa + X) ) return TRUE;
				}
			}
		}
	}
	return FALSE;
}

void SquareMakeValidLetterString( SquarePtr ThisSquare, char* ThisRack, int RackSize, char *Intersect, Direction ThisWay ) {
	int X;
	int Y;
	int NumberOfValid = 0;
	char Previous;
	Bool *Pivotal;
	if ( ThisWay == ACROSS ) Pivotal = SquareAcrossPivotLetters( ThisSquare );
	else Pivotal = SquareDownPivotLetters( ThisSquare );
	// Proper decision for the ? must be made
	for( X = 0; X < NUMBEROFENGLISHLETTERS; X++ ) {
		// The X'th letter is allowable in the vector.
		if ( Pivotal[X] == TRUE){
			Previous = '*';
			// Traverse each tile in the rack from where we left off to see if it is the X'th tile, get out ASAP, and the ? means keep going.
			for (Y = 0; Y < RackSize; Y++) {
				if ( ThisRack[Y] > (X + Aa) ) break;
				if ( ThisRack[Y] == EMPTY ) {
					if ( Previous !=  EMPTY ) {
						Intersect[NumberOfValid] = (char)(X + Aa + LOWERIT);
						NumberOfValid += 1;
					}
					Previous = EMPTY;
				}
				else if ( ThisRack[Y] == (X + Aa) ) {
					Intersect[NumberOfValid] = (char)(X + Aa);
					NumberOfValid += 1;
					break;
				}
			}
		}
	}
	Intersect[NumberOfValid] = '\0';
}

void SquareOutput ( const SquarePtr ThisSquare, int Cut ) {
	if ( ThisSquare->Used == FALSE ) {
		if ( Cut == 0 ) {
			if ( ThisSquare->TypeOfSquare == CLEAR ) printf ( "    " );
			if ( ThisSquare->TypeOfSquare == LIGHTBLUE ) printf ( "2xl " );
			if ( ThisSquare->TypeOfSquare == DARKBLUE ) printf ( "3xl " );
			if ( ThisSquare->TypeOfSquare == PINK ) printf ( "2xw " );
			if ( ThisSquare->TypeOfSquare == RED ) printf ( "3xw " );
		}
		if ( Cut == 1 ) {
			if ( ThisSquare->ValidAcrossPivot == TRUE) printf ( "->" );
			if ( ThisSquare->ValidAcrossPivot == FALSE) printf ( "  " );
			if ( ThisSquare->ValidDownPivot == TRUE) printf ( "\\/" );
			if ( ThisSquare->ValidDownPivot == FALSE) printf ( "  " );
		}
	}
	else {
		if ( Cut == 0 ) {
			printf( " %c  ", ThisSquare->Placed );
		}
		if ( Cut == 1) {
			printf( "%d %2d", ((ThisSquare->UsedBy == PLAYERONE )? 1: 2), (ThisSquare->Placed <= Zz)? (TileValues[ThisSquare->Placed - EMPTY]): 0 );
		}
	}
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// This function should use recursion less and iteration a lot more, there is more overhead when calling a function.  The only advantage that recursion has is that it look better.
Bool ArrayUnodeWordSearchRecurse( unsigned int *DoggieDog, int Index, char *PotWord ) {
	if ( Index == 0 ) return FALSE;
	if ( ArrayUnodeLetter( DoggieDog[Index] ) == PotWord[0] ) {
		if ( PotWord[1] == '\0' && ArrayUnodeEndOfWordFlag( DoggieDog[Index] ) == TRUE ) return TRUE;
		else return ArrayUnodeWordSearchRecurse( DoggieDog, ArrayUnodeChild( DoggieDog[Index] ), &(PotWord[1]) );
	}
	else {
		if ( ArrayUnodeLetter( DoggieDog[Index] ) > PotWord[0] ) return FALSE;
		else return ArrayUnodeWordSearchRecurse( DoggieDog, ArrayUnodeNext( DoggieDog, Index ), PotWord );
	}
}

Bool ArrayUDawgWordSearch( ArrayUDawgPtr ThisArrayUDawg, char *PotWord ){
	return ArrayUnodeWordSearchRecurse( ThisArrayUDawg->TheBigOUDAWGArray, 1, PotWord );
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct board {
	Square Block[MAX_ROW][MAX_COL];
	int NumberOfPlayers;
	int NumberOfPlays;
	int StartRow;
	int StartCol;
	int EndRow;
	int EndCol;
};

typedef struct board Board;
typedef Board* BoardPtr;

void BoardInit ( BoardPtr ThisBoard, int NumberofPlayers ){
	int row, col;
	Colour CurrentType = CLEAR;
	Bool AnyLetterGoes[NUMBEROFENGLISHLETTERS] = {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, 
	TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE};
	ThisBoard->NumberOfPlayers = NumberofPlayers;
	ThisBoard->NumberOfPlays = 0;
	ThisBoard->StartRow = 7;
	ThisBoard->StartCol = 7;
	ThisBoard->EndRow = 7;
	ThisBoard->EndCol = 7;
	for ( row = 0; row < MAX_ROW; row++ ) {
		for ( col = 0; col < MAX_COL; col++ ) {
			CurrentType = CLEAR;
			if ( row == 0 || row == 14 ) {
				if ( col == 0 || col == 7 || col == 14 ) CurrentType = RED;
				if ( col == 3 || col == 11 ) CurrentType = LIGHTBLUE;
			}
			if ( row == 1 || row == 13 ) {
				if ( col == 1 || col == 13 ) CurrentType = PINK;
				if ( col == 5 || col == 9 ) CurrentType = DARKBLUE;
			}
			if ( row == 2 || row == 12 ) {
				if ( col == 2 || col == 12 ) CurrentType = PINK;
				if ( col == 6 || col == 8 ) CurrentType = LIGHTBLUE;
			}
			if ( row == 3 || row == 11 ) {
				if ( col == 3 || col == 11 ) CurrentType = PINK;
				if ( col == 0 || col == 7 || col == 14) CurrentType = LIGHTBLUE;
			}
			if ( row == 4 || row == 10 ) {
				if ( col == 4 || col == 10 ) CurrentType = PINK;
			}
			if ( row == 5 || row == 9 ) {
				if ( col == 1 || col == 5 || col == 9 || col == 13 ) CurrentType = DARKBLUE;
			}
			if ( row == 6 || row == 8 ) {
				if ( col == 2 || col == 6 || col == 8 || col == 12 ) CurrentType = LIGHTBLUE;
			}
			if ( row == 7 ) {
				if ( col == 0 || col == 14 ) CurrentType = RED;
				if ( col == 3 || col == 11 ) CurrentType = LIGHTBLUE;
				if ( col == 7 ) CurrentType = PINK;
			}
			SquareInit( &ThisBoard->Block[row][col], CurrentType );
			if ( row == 0) {
				if ( col == 0) SquareSetNeighbours( &(ThisBoard->Block[row][col]), NULL, &(ThisBoard->Block[row+1][col]), NULL, &(ThisBoard->Block[row][col+1]) );
				if ( col == 14) SquareSetNeighbours( &(ThisBoard->Block[row][col]), NULL, &(ThisBoard->Block[row+1][col]), &(ThisBoard->Block[row][col-1]), NULL );
				if ( col >= 1 && col <= 13) SquareSetNeighbours( &(ThisBoard->Block[row][col]), NULL, &(ThisBoard->Block[row+1][col]), &(ThisBoard->Block[row][col-1]), &(ThisBoard->Block[row][col+1]) );
			}
			if ( row == 14) {
				if ( col == 0) SquareSetNeighbours( &(ThisBoard->Block[row][col]), &(ThisBoard->Block[row-1][col]), NULL, NULL, &(ThisBoard->Block[row][col+1]) );
				if ( col == 14) SquareSetNeighbours( &(ThisBoard->Block[row][col]), &(ThisBoard->Block[row-1][col]), NULL, &(ThisBoard->Block[row][col-1]), NULL );
				if ( col >= 1 && col <= 13) SquareSetNeighbours( &(ThisBoard->Block[row][col]), &(ThisBoard->Block[row-1][col]), NULL, &(ThisBoard->Block[row][col-1]), &(ThisBoard->Block[row][col+1]) );
			}
			if ( col == 0) {
				if ( row == 0) SquareSetNeighbours( &(ThisBoard->Block[row][col]), NULL, &(ThisBoard->Block[row+1][col]), NULL, &(ThisBoard->Block[row][col+1]) );
				if ( row == 14) SquareSetNeighbours( &(ThisBoard->Block[row][col]), &(ThisBoard->Block[row-1][col]), NULL, NULL, &(ThisBoard->Block[row][col+1]) );
				if ( row >= 1 && row <= 13) SquareSetNeighbours( &(ThisBoard->Block[row][col]), &(ThisBoard->Block[row-1][col]), &(ThisBoard->Block[row+1][col]), NULL, &(ThisBoard->Block[row][col+1]) );
			}
			if ( col == 14) {
				if ( row == 0) SquareSetNeighbours( &(ThisBoard->Block[row][col]), NULL, &(ThisBoard->Block[row+1][col]), &(ThisBoard->Block[row][col-1]), NULL );
				if ( row == 14) SquareSetNeighbours( &(ThisBoard->Block[row][col]), &(ThisBoard->Block[row-1][col]), NULL, &(ThisBoard->Block[row][col-1]), NULL );
				if ( row >= 1 && row <= 13) SquareSetNeighbours( &(ThisBoard->Block[row][col]), &(ThisBoard->Block[row-1][col]), &(ThisBoard->Block[row+1][col]), &(ThisBoard->Block[row][col-1]), NULL );
			}
			if ( row >= 1 && row <= 13 && col >= 1 && col <= 13 ) {
				SquareSetNeighbours( &(ThisBoard->Block[row][col]), &(ThisBoard->Block[row-1][col]), &(ThisBoard->Block[row+1][col]), &(ThisBoard->Block[row][col-1]), &(ThisBoard->Block[row][col+1]));
			}
			if ( row == 7 && col == 7 ) {
				SquareMakeValidAcrossPivot( &(ThisBoard->Block[row][col]) );
				SquareSetAcrossPivotLetters( &(ThisBoard->Block[row][col]), AnyLetterGoes );
				SquareMakeValidDownPivot( &(ThisBoard->Block[row][col]) );
				SquareSetDownPivotLetters( &(ThisBoard->Block[row][col]), AnyLetterGoes );
			}
		}	
	}
}

/* this function prints "ThisBoard" to the standard output	*/
void BoardOutput ( const BoardPtr ThisBoard ) {
	int row, col, Split;
	char ColLet = Aa;
	printf( "  |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |\n" );
	printf( "  | 1  | 2  | 3  | 4  | 5  | 6  | 7  | 8  | 9  | 10 | 11 | 12 | 13 | 14 | 15 |\n" );
	printf( "--------------------------------------------------------------------------------\n" );
	for ( row = 0; row < MAX_ROW; row++ ) {
		for ( Split = 0; Split < 2; Split++ ) {
			if ( Split == 1 ) {
				printf( " %c", ColLet );
				ColLet += 1;
			}
			else printf( "  " );
			for ( col = 0; col < MAX_COL; col++ ) {
				printf( "|" );
				SquareOutput( &ThisBoard->Block[row][col], Split );
			}
		printf( "|\n" );
		}
		printf( "--|--------------------------------------------------------------------------|--\n" );
	}
	printf( "  |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |\n" );
	printf( "  |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |\n\n" );
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// These are the new functions that discover the valid plays using the UDawg, the PlayBucket, and the PlaySpace data structures .

// This function fills an across  PlaySpace using the board associated with the starting square.  VACANT and CONDITIONAL squares translate into having a PlayBucket with TheLook equal to SPACE.
// It is critical that when populating a filled bucket we convert all letters into capital letters so that the plays come out labeled properly.  ie, when we are placing a blank, as opposed to using one on the board.
void PlaySpaceFromSquarePopulateAcross( PlaySpacePtr ThisPlaySpace, SquarePtr ThisSquare, int ThisLength ) {
	int X;
	PlayBucketPtr CurrentBucket;
	SquarePtr CurrentSquare = ThisSquare;
	ThisPlaySpace->Length = ThisLength;
	for ( X = 0; X < ThisLength; X++ ) {
		CurrentBucket = &((ThisPlaySpace->StateSpace)[X]);
		// The Square is Filled.
		if ( CurrentSquare->Used == TRUE ) PlayBucketSet( CurrentBucket, CapitalChar( CurrentSquare->Placed ), NULL, FILLED );
		// The square is Vacant.
		else if ( CurrentSquare->ValidAcrossPivot == FALSE ) PlayBucketSet( CurrentBucket, SPACE, NULL, VACANT );
		// The square is Conditional.
		else PlayBucketSet( CurrentBucket, SPACE, CurrentSquare->AcrossPivotLetters, CONDITIONAL );
		CurrentSquare = CurrentSquare->RightSquare;
	}
}

// This function fills a down  PlaySpace using the board associated with the starting square.  VACANT and CONDITIONAL squares translate into having a PlayBucket with TheLook equal to SPACE.
// It is critical that when populating a filled bucket we convert all letters into capital letters so that the plays come out labeled properly.  ie, when we are placing a blank, as opposed to using one on the board.
void PlaySpaceFromSquarePopulateDown( PlaySpacePtr ThisPlaySpace, SquarePtr ThisSquare, int ThisLength ) {
	int X;
	PlayBucketPtr CurrentBucket;
	SquarePtr CurrentSquare = ThisSquare;
	ThisPlaySpace->Length = ThisLength;
	for ( X = 0; X < ThisLength; X++ ) {
		CurrentBucket = &((ThisPlaySpace->StateSpace)[X]);
		// The Square is Filled.
		if ( CurrentSquare->Used == TRUE ) PlayBucketSet( CurrentBucket, CapitalChar( CurrentSquare->Placed ), NULL, FILLED );
		// The square is Vacant.
		else if ( CurrentSquare->ValidDownPivot == FALSE ) PlayBucketSet( CurrentBucket, SPACE, NULL, VACANT );
		// The square is Conditional.
		else PlayBucketSet( CurrentBucket, SPACE, CurrentSquare->DownPivotLetters, CONDITIONAL );
		CurrentSquare = CurrentSquare->DownSquare;
	}
}

// This function returns the number of total function calls that result from the initial call.  This will allow us to keep track of the amount of work needed to fill a given playspace.
// I am able to say with confidence that this function is complete to my knowledge, and ready to be tested.  Worked without any mods to my knowledge.  Derivitive of an anagram function designed for the UDawg structure.
// ParentIndexValue will inevitably use to rearrange the words found to fit inside the PlaySpace.
int WordListPlayBucketArrayUnodeRackPopulateRecurse( WordListPtr ThisWordList, PlayBucketPtr ThisPlayBucketArray, int NumberOfTotalPlayBuckets, int WorkThisBucket, unsigned int *DoggieDog, int Index, char *TilesLeft, int NumberTilesLeft, char *RunnerWord, int ParentIndexValue ) {
	int TroubleTab = 1;
	int Current = Index;
	// When we are treating a filled bucket, start at the index given to us and attempt to find the letter in the UDawg.  Take the next action based on the UDawg structure.
	if ( (ThisPlayBucketArray[WorkThisBucket]).Variant == FILLED ) {
		char CapitalLetter = ( (ThisPlayBucketArray[WorkThisBucket]).TheLook <= Zz )? (ThisPlayBucketArray[WorkThisBucket]).TheLook: ((ThisPlayBucketArray[WorkThisBucket]).TheLook - LOWERIT);
		while ( Current != 0 ) {
		  if ( CapitalLetter > ArrayUnodeLetter( DoggieDog[Current] ) ) Current = ArrayUnodeNext( DoggieDog, Current );
			else if ( CapitalLetter == ArrayUnodeLetter( DoggieDog[Current] ) ) {
				// Place the letter contained in the bucket into the RunnerWord.
				RunnerWord[WorkThisBucket] = (ThisPlayBucketArray[WorkThisBucket]).TheLook;
				// We are at the end of the playspace, check for end of word flag.
				if ( NumberOfTotalPlayBuckets == (WorkThisBucket + 1) ) {
					if ( ArrayUnodeEndOfWordFlag( DoggieDog[Current] ) == TRUE ) {
						RunnerWord[NumberOfTotalPlayBuckets] = '\0';
						// Undo the ordering of the word now, so that later on down the line, we don't have to worry about it.
						WordListAppend ( ThisWordList, AllocateAndReorderWord( RunnerWord, ParentIndexValue ) );
					}
				}
				else{
				  // If the NextChild line exists, then recurse using the same tile rack.
					if ( ArrayUnodeChild( DoggieDog[Current] ) != 0 ) TroubleTab += WordListPlayBucketArrayUnodeRackPopulateRecurse( ThisWordList, ThisPlayBucketArray, NumberOfTotalPlayBuckets, (WorkThisBucket + 1), DoggieDog, ArrayUnodeChild( DoggieDog[Current] ), TilesLeft, NumberTilesLeft, RunnerWord, ParentIndexValue );
			  }
				break;
			}
			else break;
		}
	}
	else {
		int X;
		char CutUpRack[MAXTILES + 1] = "\0\0\0\0\0\0\0\0";
		char Previous = '*';
		// The PlayBucket is conditional so treat it like a vacant, only check before confirmation that the letter in question is located inside of the Vector.  Also maybe get out of the for loop ASAP for non-blank tiles.
		if ( (ThisPlayBucketArray[WorkThisBucket]).Variant == CONDITIONAL ) {
			for ( X = 0; X < NumberTilesLeft; X++ ) {
				// This condition resets the start position when we have finished placing a blank tile.
				if ( Previous == EMPTY ) Current = Index;
				//  If for whatever reason we are pointing to a NULL value, get out.  i.e. we were looking for a late letter but ran into the end of the list first.
				if ( Current == 0 ) break;
				// We have already tried to place an identical tile in this bucket so move on to the next immediately.
				if ( TilesLeft[X] == Previous ) continue;
				// This condition makes sure that we are not looking for nodes that are disallowed due to the conditional vector.
				if ( TilesLeft[X] != EMPTY ){
					if ( ((ThisPlayBucketArray[WorkThisBucket]).Vector)[TilesLeft[X] - Aa] == FALSE ) {
						Previous = TilesLeft[X];
						continue;
					}
				}
				while ( Current != 0){
				  // When running with an empty tile, move to the next node if the bucket vector disallows the current one.
					if ( TilesLeft[X] == EMPTY ){
						if ( ((ThisPlayBucketArray[WorkThisBucket]).Vector)[ArrayUnodeLetter( DoggieDog[Current] ) - Aa] == FALSE ){
							Current = ArrayUnodeNext( DoggieDog, Current );
							continue;
						}
					}
					// We have landed on the node that we are looking for.  If we are dealing with a blank tile, we are going to have to check the conditional vector. but that has already been done.
					if ( TilesLeft[X] == ArrayUnodeLetter( DoggieDog[Current] ) || TilesLeft[X] == EMPTY ) {
						RunnerWord[WorkThisBucket] = (TilesLeft[X] == EMPTY)? (ArrayUnodeLetter( DoggieDog[Current] ) + LOWERIT): ArrayUnodeLetter( DoggieDog[Current] ) ;
						RunnerWord[WorkThisBucket + 1] = '\0';
						if ( NumberOfTotalPlayBuckets == (WorkThisBucket + 1) ) {
							if ( ArrayUnodeEndOfWordFlag( DoggieDog[Current] ) == TRUE ) {
								RunnerWord[NumberOfTotalPlayBuckets] = '\0';
								WordListAppend ( ThisWordList, AllocateAndReorderWord( RunnerWord, ParentIndexValue ) );
							}
						}
						// The else must be inserted because we are only looking for words of an exact length, as opposed to the anagram function.
						else if ( ArrayUnodeChild( DoggieDog[Current] ) != 0 ) {
							strcpy( CutUpRack, TilesLeft );
							StringRemoveChar( CutUpRack, X);
							// Remove the tile we used and recurse.
							TroubleTab += WordListPlayBucketArrayUnodeRackPopulateRecurse( ThisWordList, ThisPlayBucketArray, NumberOfTotalPlayBuckets, (WorkThisBucket + 1), DoggieDog, ArrayUnodeChild( DoggieDog[Current] ), CutUpRack, (NumberTilesLeft - 1), RunnerWord, ParentIndexValue );
						}
						// Get out of the while loop only when we do not try to place a question mark, because we have found what we are looking for and need to move on to the next letter.  EMPTIES can be placed in the same bucket with different representation, so keep going with them.
						if ( TilesLeft[X] != EMPTY ) break;
					}
					// The node that we are looking for does not exist, but some of the rest might.
					else if ( ArrayUnodeLetter( DoggieDog[Current] ) > TilesLeft[X] ) break;
					// If we have not broken yet, keep looking for the node that we want, or the tile is a question mark so use all options.	We have exhausted all easy outs.
					Current = ArrayUnodeNext( DoggieDog, Current );
				}
				Previous = TilesLeft[X];
			}
		}
		// The PlayBucket that we are now filling is VACANT so attempt to place any letter inside of it, we never have to check the conditional vector, ever.  This is a lot like the anagram function but the length is fixed.
		else {
			for ( X = 0; X < NumberTilesLeft; X++ ) {
				if ( Previous == EMPTY ) Current = Index;
				if ( Current == 0 ) break;
				if ( TilesLeft[X] == Previous ) continue;
				while ( Current != 0) {
					// We have landed on the node that we are looking for.
					if ( TilesLeft[X] == ArrayUnodeLetter( DoggieDog[Current] ) || TilesLeft[X] == EMPTY ) {
						RunnerWord[WorkThisBucket] = (TilesLeft[X] == EMPTY)? (ArrayUnodeLetter( DoggieDog[Current] ) + LOWERIT): ArrayUnodeLetter( DoggieDog[Current] ) ;
						if ( NumberOfTotalPlayBuckets == (WorkThisBucket + 1) ) {
							if ( ArrayUnodeEndOfWordFlag( DoggieDog[Current] ) == TRUE ){
								RunnerWord[NumberOfTotalPlayBuckets] = '\0';
								WordListAppend ( ThisWordList, AllocateAndReorderWord( RunnerWord, ParentIndexValue ) );
							}
						}
						else if ( ArrayUnodeChild( DoggieDog[Current] ) != 0 ) {
							strcpy( CutUpRack, TilesLeft );
							StringRemoveChar( CutUpRack, X);
							// Remove the tile we used and recurse.
							TroubleTab += WordListPlayBucketArrayUnodeRackPopulateRecurse( ThisWordList, ThisPlayBucketArray, NumberOfTotalPlayBuckets, (WorkThisBucket + 1), DoggieDog, ArrayUnodeChild( DoggieDog[Current] ), CutUpRack, (NumberTilesLeft - 1), RunnerWord, ParentIndexValue );
						}
						// Get out of the while loop only when we do not try to place a question mark, because we have found what we are looking for and need to move on to the next letter.
						if ( TilesLeft[X] != EMPTY ) break;
					}
					// The node that we are looking for does not exist, but some of the rest might so leave but keep Current what it is.  Since a question mark is below all letters, we never break at this point when we are placing one.  Current == 0 will be our break point every time.
					else if ( ArrayUnodeLetter( DoggieDog[Current] ) > TilesLeft[X] ) break;
					// If we have not broken yet, keep looking for the node that we want, or the tile is a question mark so use all options.  We have exhausted all easy outs.
					Current = ArrayUnodeNext( DoggieDog, Current );
				}
				// Set Previous to the tile that we just finished treating so we can jump over any identical tiles.
				Previous = TilesLeft[X];
			}
		}
	}
	return TroubleTab;
}

// This function rearranges a PlaySpace by ordering PlayBuckets so that they correspond to the given ParentNodeIndex.
void PlayBucketArrayReorder( PlayBucketPtr ThisPlayBucketArray, int ArraySize, int ParentNodeIndex ) {
	int Y;
	PlayBucketPtr TempHolder = (PlayBucketPtr)malloc( sizeof( PlayBucket ) );
	int Position;
	// Reverse the PlayBucket order if necessary.
	if ( div( ParentNodeIndex, 2 ).rem == 1) {
		for ( Y = 0; Y < div( ArraySize, 2 ).quot; Y++ ) {
			PlayBucketCopy( TempHolder, &(ThisPlayBucketArray[Y]) );
			PlayBucketCopy( &(ThisPlayBucketArray[Y]), &(ThisPlayBucketArray[ArraySize - 1 - Y]) );
			PlayBucketCopy( &(ThisPlayBucketArray[ArraySize - 1 - Y]), TempHolder );
		}
	}
	// Start from the correct character.
	Position = div( ParentNodeIndex, 2 ).quot + 1;
	for ( Y = 0; Y < div( Position, 2 ).quot; Y++ ){
			PlayBucketCopy( TempHolder, &(ThisPlayBucketArray[Y]) );
			PlayBucketCopy( &(ThisPlayBucketArray[Y]), &(ThisPlayBucketArray[Position - 1 - Y]) );
			PlayBucketCopy( &(ThisPlayBucketArray[Position - 1 - Y]), TempHolder );
	}
}

// This function sets all of the relevant variables needed to determine the parent node that we should start at in the ArrayUDawg, for buckets with the state:  ThisSquareState.
void PlayBucketArrayDetermineOptimalValues( PlayBucketPtr ThisPlayBucketArray, int NumberOfBuckets, int *ConsecutiveCurrentState, int *StartOfCurrentStateBlock, int *ConsecutiveMaxState, int *StartOfMaxStateBlock, int *NumberOfOptimalStateBlocks, SquareState ThisSquareState ) {
	int X;
	for ( X = 0; X < NumberOfBuckets; X++) {
		if ( (ThisPlayBucketArray[X]).Variant == ThisSquareState ) {
			*ConsecutiveCurrentState += 1;
			// We have hit the beginning of a new ThisSquareState block.
			if ( *StartOfCurrentStateBlock == -1 ) *StartOfCurrentStateBlock = X;
			// We have reached the end of the current ThisSquareState block on the last bucket, so set it to the Max if it is the Max.
			if ( X == (NumberOfBuckets - 1) ) {
				// We are going to have to favour filled blocks of the same size that are closer to the end of the word, because those graphs have less words in them.	Not true due to reference point selection, but run with it for now.	The condition first has to do with max distance from a reference point, then if equal based on the existance of conditional squares, then statistics.
				if ( *ConsecutiveCurrentState == *ConsecutiveMaxState ) {
					*NumberOfOptimalStateBlocks += 1;
				}
				else if ( *ConsecutiveCurrentState > *ConsecutiveMaxState ) {
					*ConsecutiveMaxState = *ConsecutiveCurrentState;
					*StartOfMaxStateBlock = *StartOfCurrentStateBlock;
					*NumberOfOptimalStateBlocks = 1;
				}
			}
			// We have reached the end of the current filled block on an internal bucket, so set it to the Max if it is the Max.
			else if ( (ThisPlayBucketArray[X + 1]).Variant != ThisSquareState ) {
				// We are going to have to favour filled blocks of the same size that are closer to the end of the word, because those graphs have less words in them.  * not true.  Base this on stats but later.
				if ( *ConsecutiveCurrentState == *ConsecutiveMaxState ) {
					*NumberOfOptimalStateBlocks += 1;
				}
				else if ( *ConsecutiveCurrentState > *ConsecutiveMaxState ) {
					*ConsecutiveMaxState = *ConsecutiveCurrentState;
					*StartOfMaxStateBlock = *StartOfCurrentStateBlock;
					*NumberOfOptimalStateBlocks = 1;
				}
			}
		}
		else {
			// Reset the Current tracking values to non existant.
			*ConsecutiveCurrentState = 0;
			*StartOfCurrentStateBlock = -1;
		}
	}
}

// This function is truely the heart of this treatment of the UDawg Scrabble algorithm as this is where the path of highest constraint is determined.
Bool WordListPlaySpaceArrayUDawgRackPopulate( WordListPtr ThisWordList, PlaySpacePtr ThisPlaySpace , ArrayUDawgPtr Lexicon, const char * ThisRack, int RackSize, int *Tally ) {
	// we have to allow for filled buckets to contain lower case letters, note that this does not mean that the square itself is filled, though sometimes it will be.  Only when calculating point values, this becomes essential.  Used Squares hold lower case letters, but when a PlaySpace is filled, the letter is cast as upper case.
	// If given a choice, we should pretty much logically start from as far into a word from a reference point as possible,	This eliminates many of the short words in the lexicon right away.  This is not applicable using statistical node analysis, which handles all cases.
	// A special case is when a conditional bucket has only one value that will fit inside of it.  In this case it is much like a filled bucket, in that the one fitting tile MUST be placed there every time in this play space.  This case is clearly handled in the first code structure of this function.
	// We are going to need a tile rack that we can fuck with for each play space, without effecting the tile rack for the other play spaces.  Since TheRack is inherited, we can not modify it in any way.
	// This rack will definitely be fucked up along the way, thus localize it, so that the rack that this function inherits will be a const. 
	char PlasticRack[MAXTILES + 1] = "\0\0\0\0\0\0\0\0";
	int PlasticSize = RackSize;
	// Make note that there are certainly faster ways to analyze a board if we constrain ourselves to sequential programming.  But that should go without saying.  The need for independant play spaces does not exist.
	int SpaceSize = ThisPlaySpace->Length;
	PlayBucketPtr Represent = ThisPlaySpace->StateSpace;
	char PlaceAbles[NUMBEROFENGLISHLETTERS + MAXTILES + 1] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
	int X;
	Bool FirstConditional = TRUE;
	// These variables will allow us to know what to do to find the optimal parental index.
	int FilledCount = 0;
	int ConsecutiveMaxFilled = 0;
	int ConsecutiveCurrentFilled = 0;
	int StartOfMaxFilledBlock = 0;
	int StartOfCurrentFilledBlock = -1;
	int NumberOfOptimalFilledBlocks = 0;
	int ConditionalCount = 0;
	int ConsecutiveMaxConditional = 0;
	int ConsecutiveCurrentConditional = 0;
	int StartOfMaxConditionalBlock = 0;
	int StartOfCurrentConditionalBlock = -1;
	int NumberOfOptimalConditionalBlocks = 0;
	int ParentIndex = 0;
	int CorrespondingParentNodeLeft;
	int CorrespondingParentNodeRight;
	int CurrentStatisticHolder;
	Bool IsConditionalThere = FALSE;
	int DistanceFromReferencePoint;
	int CurrentNumberOfAllowableLetters;
	int MaxNumberOfAllowableLetters;
	int LeftValidLetters;
	int RightValidLetters;
	int RightPIV;
	char MegaWordHolder[MAX +1] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
	
	strcpy( PlasticRack, ThisRack );
	// If there is only 1 tile that can be placed in a conditional bucket place it first and fill the bucket.	Now if that tile is required in another bucket, likely a question mark, return the empty list.
	// Note that we can fuck with the play space as much as we need to because it is recalibrated each time.
	// Keep in mind that this analysis is cumulative in that if 1 letter that we have is needed in 2 squares, this construct will bail us out of the function.
	// This string must be large enough to hold 26 lower case letters and 7 upper case letters and the EOS character of course, that is 34 Bytes.
	// When a questoin mark is used on the first play a segmentation fault.  Problem corrected.  The PlaceAbles string was too small.
	// In this structure we are filling all buckets that must be filled due to having only 1 tile that can fit in that bucket.
	
	// There exists a special case here that needs to be handled.  Whenever a Bucket is virtually filled, unless it is the first conditional bucket, start from the beginning of the PlaySpace again looking for fillable buckets because the rack has changed, this should surly reduce process time.
	for ( X = 0; X < SpaceSize; X++) {
		if ( Represent[X].Variant == CONDITIONAL ) {
			// We don't have any tiles left that will fit into the condition, so get the fuck out...	NOW.  This case is suppose to be taken care of in the BoardArrayUDawgDiscoverValidPlays function, but it clearly leaves out the case where the same tile needs to be in 2 different buckets, so we will check for that case here..
			if ( BoolAvailable( Represent[X].Vector, PlasticRack, PlasticSize ) == FALSE ) {
				return FALSE;
			}
			// We have only 1 type of normal tile that can fit into the condition and no question mark. So go ahead and place that tile in the bucket.
			if ( PlasticRack[0] != EMPTY ){
				if ( BoolMakeValidLetterString( Represent[X].Vector, PlasticRack, PlasticSize, PlaceAbles ) == 1 ) {
					Represent[X].Variant = FILLED;
					Represent[X].TheLook = PlaceAbles[0];
					Represent[X].Vector = NULL;
					StringRemoveChar( PlasticRack, StringFindChar( PlasticRack, PlasticSize, PlaceAbles[0] ) );
					PlasticSize--;
					if ( FirstConditional == FALSE ) X = -1, FirstConditional = TRUE;
				}
				else FirstConditional = FALSE;
			}
			// There is at least 1 question mark in our rack, but the conditional bucket only has 1 valid letter and we don't have this face tile. Place the question Mark.  Be careful, the rest of the program thinks all filled buckets contain upper case letters, but change this, it makes little to no sense.  Lower case letters being virtually placed in buckets must be lower case.
			else if ( PlasticRack[0] == EMPTY ) {
				if ( BoolMakeValidLetterString( Represent[X].Vector, PlasticRack, PlasticSize, PlaceAbles ) == 1 ) {
					Represent[X].Variant = FILLED;
					// TheLook will be a lower case letter and hence have an implied point value of zero.  This is bullshit or no but there is a problem, statistics require upper case letters only.  Use the CapitalChar function for this case!  Solved.
					Represent[X].TheLook = PlaceAbles[0];
					Represent[X].Vector = NULL;
					// If we have a question mark, it will be in position 0 of our rack.
					StringRemoveChar( PlasticRack, 0 );
					PlasticSize--;
					if ( FirstConditional == FALSE ) X = -1, FirstConditional = TRUE;
				}
				else FirstConditional = FALSE;
			}
		}
	}
	// We need a very simple loop to count the number of filled and conditional buckets so that we know which analysis to perform.
	for ( X = 0; X < SpaceSize; X++ ) {
		if ( (Represent[X]).Variant == FILLED ) FilledCount += 1;
		else if ( (Represent[X]).Variant == CONDITIONAL ) ConditionalCount += 1;
	}
	// Use the new tally function to set the values required for filled buckets or if none filled than for conditional buckets, take care of the most common cases first.
	if ( FilledCount != 0 ) PlayBucketArrayDetermineOptimalValues( Represent, SpaceSize, &ConsecutiveCurrentFilled, &StartOfCurrentFilledBlock, &ConsecutiveMaxFilled, &StartOfMaxFilledBlock, &NumberOfOptimalFilledBlocks, FILLED );
	else PlayBucketArrayDetermineOptimalValues( Represent, SpaceSize, &ConsecutiveCurrentConditional, &StartOfCurrentConditionalBlock, &ConsecutiveMaxConditional, &StartOfMaxConditionalBlock, &NumberOfOptimalConditionalBlocks, CONDITIONAL );	
	// The primary analysis is complete, there are several scenarios that can play out here. 0 filled buckets, 1 filled bucket, filled buckets that touch the reference point (Any of the Buckets may start based on statistics only or fuck it due to the extreme being more constrained) deal with the esay ones first.
	// Further filling analysis requires recursion, hence a new function that will play with the MegaWordHolder and fill the wordlist with every play possible in an optimised anagram style.
	
	// To my knowledge, all we have to do to complete this function is to deal with the cases where there are multiple optimal blocks and they are of length greater than 1, they are a pain in the ass but very rare, at the same time, they are entirely possible.
	
	// This operation is one that a human being would have an easy time figuring out, it requires a more broad scope than a computer has the luxury of posessing.  Even the above structure would be overkill for the human intellect.  It seems as though we do multiple operations at once, just by looking at something.  We also just tend to know things from experience.
	// A simple and common case - the single filled square block.  First and Last is a special case because there is only one way to go for now.  Might want to check where conditional is at a later time, or now.  Now it is done.
	// Adjustment is required for this case, it is a fact that even when the ConsecutiveMaxFilled is one, there can be multiple filled buckets, so we need to find the best one...  Have a FilledCount.
	// The only time that further analysis is required is when, NumberOfOptimalFilledBlocks is found to be greater than 1, this causes us to choose between several blocks based on 2 or more conditions.
	
	// There is only one filled bucket, and we know exactly where it is, so simply choose a direction, and we are through.
	if ( FilledCount == 1 ) {
		Tally[0] += 1;
		// The single filled bucket is at the front of the PlaySpace set ParentIndex to 0 and get out.  This will be changed in version 2.
		if ( StartOfMaxFilledBlock == 0 ) {
			ParentIndex = 0;
		}
		else if ( StartOfMaxFilledBlock == (SpaceSize - 1) ) {
			ParentIndex = 1;
		}
		else {
			CorrespondingParentNodeLeft = 2*(StartOfMaxFilledBlock);
			CorrespondingParentNodeRight = 2*(SpaceSize - StartOfMaxFilledBlock - 1) + RIGHT;
			// This structure takes care of a potential CONDITIONAL bucket adjacent to one side of the FILLED bucket.
			if ( (Represent[StartOfMaxFilledBlock - 1]).Variant == CONDITIONAL ) {
				if ( (Represent[StartOfMaxFilledBlock + 1]).Variant != CONDITIONAL ) {
					ParentIndex = CorrespondingParentNodeLeft;
					goto GetMeOutOfHere;
				}
			}
			else {
				if ( (Represent[StartOfMaxFilledBlock + 1]).Variant == CONDITIONAL ) {
					ParentIndex = CorrespondingParentNodeRight;
					goto GetMeOutOfHere;
				}
			}
			// If the two statistical values are equal than use the start as our reference to reduce order and reorder time.  Also if we get to here, the buckets to either side of the filled bucket are of the same Variant.
			if ( NumberOfNodesBelowParent[CorrespondingParentNodeLeft][CapitalChar( (Represent[StartOfMaxFilledBlock]).TheLook ) - Aa] <=  NumberOfNodesBelowParent[CorrespondingParentNodeRight][CapitalChar( (Represent[StartOfMaxFilledBlock]).TheLook ) - Aa] ) {
				ParentIndex = CorrespondingParentNodeLeft;
			}
			else {
				ParentIndex = CorrespondingParentNodeRight;
			}
		}
	}
	// This is the case where we have to use the variable set by the conditional alalysis.
	else if ( FilledCount == 0 ) {
		// Simply choose the direction to travel
		if ( ConditionalCount == 1 ) {
			Tally[4] += 1;
			if ( StartOfMaxConditionalBlock == 0 ) {		
				ParentIndex = 0;
			}
			else if ( StartOfMaxConditionalBlock == (SpaceSize - 1) ) {
				ParentIndex = 1;
			}
			else {
				CorrespondingParentNodeLeft = 2*(StartOfMaxConditionalBlock);
				CorrespondingParentNodeRight = 2*(SpaceSize - StartOfMaxConditionalBlock - 1) + RIGHT;
				if ( StartOfMaxConditionalBlock >=  (SpaceSize - StartOfMaxConditionalBlock - 1) ) {
					ParentIndex = CorrespondingParentNodeLeft;
				}
				else {
					ParentIndex = CorrespondingParentNodeRight;
				}
			}
		}
		// Determine the start and direction based on conditional squares instead of filled ones.  Note that it is impossible to have zero filled and zero conditional squares in a play space, one must be present.
		// Note that every bucket in a play space may be conditional but not filled.  This will be tricky to find the path of highest constraint.  But just use the ends.  Also we can measure the length of the allowable string from our rack, that should produce better results.
		else {
			// This case is extremely rare, but entirely possible.
			if ( ConsecutiveMaxConditional == 1 ) {
				Tally[5] += 1;
				DistanceFromReferencePoint = -1;
				MaxNumberOfAllowableLetters = 50;
				for ( X = 0; X < SpaceSize; X++ ) {
					if ( (Represent[X]).Variant == CONDITIONAL ) {
						CurrentNumberOfAllowableLetters = BoolHowManyValid( (Represent[X]).Vector, PlasticRack, PlasticSize );
						if ( X == 0 ) {
							DistanceFromReferencePoint = 0;
							MaxNumberOfAllowableLetters = CurrentNumberOfAllowableLetters;
							ParentIndex = 0;
						}
						else if ( X == (SpaceSize - 1) ) {
							if ( CurrentNumberOfAllowableLetters <  MaxNumberOfAllowableLetters ) {
								DistanceFromReferencePoint = 0;
								MaxNumberOfAllowableLetters = CurrentNumberOfAllowableLetters;
								ParentIndex = 1;
							}
						}
						// We have hit the case where there is an internal CONDITIONAL bucket so we have two ways to go, so we are going to have to check them both.
						else{
							if ( CurrentNumberOfAllowableLetters < MaxNumberOfAllowableLetters ){
								DistanceFromReferencePoint = (X > (SpaceSize - X - 1))? X: (SpaceSize - X -1);
								MaxNumberOfAllowableLetters = CurrentNumberOfAllowableLetters;
								ParentIndex = (X > (SpaceSize - X - 1))? 2*X: (2*(SpaceSize - X - 1) + RIGHT);
							}
							else if ( CurrentNumberOfAllowableLetters ==  MaxNumberOfAllowableLetters ) {
								if ( X > DistanceFromReferencePoint ) {
									DistanceFromReferencePoint = X;
									ParentIndex = 2*X;
								}
								if ( (SpaceSize - X - 1) > DistanceFromReferencePoint ) {
									DistanceFromReferencePoint = (SpaceSize - X - 1);
									ParentIndex = 2*(SpaceSize - X - 1) + RIGHT;
								}
							}
					 }
				 }
			 }
			}
			else if ( NumberOfOptimalConditionalBlocks == 1 ) {
				Tally[6] += 1;
				ConditionalCopOut:;
				LeftValidLetters = BoolHowManyValid( (Represent[StartOfMaxConditionalBlock]).Vector, PlasticRack, PlasticSize );
				RightValidLetters = BoolHowManyValid( (Represent[StartOfMaxConditionalBlock + ConsecutiveMaxConditional - 1]).Vector, PlasticRack, PlasticSize );
				// Remember that all of the buckets in a PlaySpace can be conditional.  Then, if not first, then last.
				if ( StartOfMaxConditionalBlock == 0 ) {
					if ( LeftValidLetters < RightValidLetters ) {
						ParentIndex = 0;
					}
					// Even when the two ValidLetters are equal, this is going to deal with a smaller lexicon, unless the PlaySpace is entirely conditional.
					else {
						if ( ConsecutiveMaxConditional == SpaceSize ) {
							ParentIndex = 1;
						}
						else ParentIndex = 2*(ConsecutiveMaxConditional - 1);
					}
				}
				// The block is located at the end of the PlaySpace.  Our only reference will be the end of the PlaySpace.
				else if ( (StartOfMaxConditionalBlock + ConsecutiveMaxConditional) == SpaceSize ) {
					if ( RightValidLetters < LeftValidLetters ) {
						ParentIndex = 1;
					}
					else {
						ParentIndex = 2*(SpaceSize - StartOfMaxConditionalBlock - 1) + RIGHT;
					}
				}
				// The block is internal to the PlaySpace.
				else {
					if ( LeftValidLetters < RightValidLetters  ) {
						ParentIndex = 2*(SpaceSize - StartOfMaxConditionalBlock - 1) + RIGHT;
					}
					else if ( LeftValidLetters > RightValidLetters  ) {
						ParentIndex = 2*(StartOfMaxConditionalBlock + ConsecutiveMaxConditional - 1);
					}
					else {
						if ( (StartOfMaxConditionalBlock + ConsecutiveMaxConditional - 1) <= (SpaceSize - StartOfMaxConditionalBlock - 1)) ParentIndex = 2*(StartOfMaxConditionalBlock + ConsecutiveMaxConditional - 1);
						else ParentIndex = 2*(SpaceSize - StartOfMaxConditionalBlock - 1) + RIGHT;;
					}
				}
			}
			else {
				Tally[7] += 1;
				goto ConditionalCopOut;
			}
		}
	}
	else{
		if ( ConsecutiveMaxFilled == 1 ) {
			Tally[1] += 1;
			CurrentStatisticHolder = 5000000;
			IsConditionalThere = FALSE;
			// When testing for the optimal ParentIndex, first check if we are dealing with conditionals, based on this do only the analysis that we require.
			for ( X = 0; X < SpaceSize; X++ ) {
				if ( (Represent[X]).Variant == FILLED ) {
					if ( X == 0 ) {
						if ( (Represent[1]).Variant == CONDITIONAL ) IsConditionalThere = TRUE;
						CurrentStatisticHolder = NumberOfNodesBelowParent[0][CapitalChar( (Represent[0]).TheLook ) - Aa];
						ParentIndex = 0;
					}
					else if ( X == (SpaceSize - 1) ) {
						if ( IsConditionalThere == TRUE ) {
							if ( (Represent[SpaceSize - 2]).Variant == CONDITIONAL ) {
								if ( NumberOfNodesBelowParent[1][CapitalChar( (Represent[X]).TheLook ) - Aa] < CurrentStatisticHolder ) {
									ParentIndex = 1;
								}
							}
						}
						else {
							if ( (Represent[SpaceSize - 2]).Variant == CONDITIONAL ){
								ParentIndex = 1;
							}
							else {
								if ( NumberOfNodesBelowParent[1][CapitalChar( (Represent[X]).TheLook ) - Aa] < CurrentStatisticHolder ) {
									ParentIndex = 1;
								}
							}
						}
					}
					// We have hit the case where there is an internal FILLED bucket so we have two ways to go, so we are going to have to check them both.
					else{
						// Run a check on the left side.
						int LeftPIV = 2*X;
						if ( IsConditionalThere == TRUE ) {
							if ( (Represent[X - 1]).Variant == CONDITIONAL ) {
								if ( NumberOfNodesBelowParent[LeftPIV][CapitalChar( (Represent[X]).TheLook ) - Aa] < CurrentStatisticHolder ) {
									CurrentStatisticHolder = NumberOfNodesBelowParent[LeftPIV][CapitalChar( (Represent[X]).TheLook ) - Aa];
									ParentIndex = LeftPIV;
								}
							}
						}
						else {
							if ( (Represent[X - 1]).Variant == CONDITIONAL ){
								IsConditionalThere = TRUE;
								CurrentStatisticHolder = NumberOfNodesBelowParent[LeftPIV][CapitalChar( (Represent[X]).TheLook ) - Aa];
								ParentIndex = LeftPIV;
							}
							else {
								if ( NumberOfNodesBelowParent[LeftPIV][CapitalChar( (Represent[X]).TheLook ) - Aa] < CurrentStatisticHolder ) {
									CurrentStatisticHolder = NumberOfNodesBelowParent[LeftPIV][CapitalChar( (Represent[X]).TheLook ) - Aa];
									ParentIndex = LeftPIV;
								}
							}
						}
						// Run a check on the right side.  I must admit that this looks like a mess and I should clean it up by introducing a new variable.
						RightPIV = 2*(SpaceSize - X - 1) + RIGHT;
						if ( IsConditionalThere == TRUE ) {
							if ( (Represent[X + 1]).Variant == CONDITIONAL ) {
								if ( NumberOfNodesBelowParent[RightPIV][CapitalChar( (Represent[X]).TheLook ) - Aa] < CurrentStatisticHolder ) {
									CurrentStatisticHolder = NumberOfNodesBelowParent[RightPIV][CapitalChar( (Represent[X]).TheLook ) - Aa];
									ParentIndex = RightPIV;
								}
							}
						}
						else {
							if ( (Represent[X + 1]).Variant == CONDITIONAL ){
								IsConditionalThere = TRUE;
								CurrentStatisticHolder = NumberOfNodesBelowParent[RightPIV][CapitalChar( (Represent[X]).TheLook ) - Aa];
								ParentIndex = RightPIV;
							}
							else {
								if ( NumberOfNodesBelowParent[RightPIV][CapitalChar( (Represent[X]).TheLook ) - Aa] < CurrentStatisticHolder ) {
									CurrentStatisticHolder = NumberOfNodesBelowParent[RightPIV][CapitalChar( (Represent[X]).TheLook ) - Aa];
									ParentIndex = RightPIV;
								}
							}
						}
					}
				}
			}
		}
		else {
			if ( NumberOfOptimalFilledBlocks == 1 ) {
				Tally[2] += 1;
				FilledCopOut:;
				// The single big block is located at the beginning of the PlaySpace.  In this case, the reference point will always be the beginning of the word.
				// Remember that all of the buckets in a PlaySpace can be Filled Because Conditionals are allowed to be virtually Filled.  Take care of this case right here.
				if ( StartOfMaxFilledBlock == 0 ) {
					if ( ConsecutiveMaxFilled != SpaceSize  ) {
						if ( NumberOfNodesBelowParent[0][CapitalChar( (Represent[0]).TheLook ) - Aa] <= NumberOfNodesBelowParent[2*(ConsecutiveMaxFilled - 1)][CapitalChar( (Represent[ConsecutiveMaxFilled - 1]).TheLook ) - Aa] ) {
							ParentIndex = 0;
						}
						else {
							ParentIndex = 2*(ConsecutiveMaxFilled - 1);
						}
					}
					else {
						if ( NumberOfNodesBelowParent[0][CapitalChar( (Represent[0]).TheLook ) - Aa] <= NumberOfNodesBelowParent[1][CapitalChar( (Represent[SpaceSize - 1]).TheLook ) - Aa] ) {
							ParentIndex = 0;
						}
						else {
							ParentIndex = 1;
						}
					}
				}
				// The block is located at the end of the PlaySpace.  Our only reference will be the end of the PlaySpace.
				else if ( (StartOfMaxFilledBlock + ConsecutiveMaxFilled) == SpaceSize ) {
					if ( NumberOfNodesBelowParent[1][CapitalChar( (Represent[SpaceSize - 1]).TheLook ) - Aa] < NumberOfNodesBelowParent[2*(SpaceSize - StartOfMaxFilledBlock - 1) + RIGHT][CapitalChar( (Represent[StartOfMaxFilledBlock]).TheLook ) - Aa] ) {
						ParentIndex = 1;
					}
					else {
						ParentIndex = 2*(SpaceSize - StartOfMaxFilledBlock - 1) + RIGHT;
					}
				}
				// The block is internal to the PlaySpace.
				else {
					if (   NumberOfNodesBelowParent[2*(SpaceSize - StartOfMaxFilledBlock - 1) + RIGHT][CapitalChar( (Represent[StartOfMaxFilledBlock]).TheLook ) - Aa] < NumberOfNodesBelowParent[2*(StartOfMaxFilledBlock + ConsecutiveMaxFilled - 1)][CapitalChar( (Represent[StartOfMaxFilledBlock + ConsecutiveMaxFilled - 1]).TheLook ) - Aa]   ) {
						ParentIndex = 2*(SpaceSize - StartOfMaxFilledBlock - 1) + RIGHT;
					}
					else {
						ParentIndex = 2*(StartOfMaxFilledBlock + ConsecutiveMaxFilled - 1);
					}
				}	
			}
			else {
				Tally[3] += 1;
				goto FilledCopOut;
			}
		}
	}
	GetMeOutOfHere:;
	//it is absolutely critical that we re-arrange the playspace buckets so as to match the filling order with start position and direction, that way we will discover words with ease, and then rearrange them before we generate Plays with them.
	PlayBucketArrayReorder( Represent, SpaceSize, ParentIndex );
	WordListPlayBucketArrayUnodeRackPopulateRecurse( ThisWordList, Represent , SpaceSize, 0, Lexicon->TheBigOUDAWGArray, ExactParentNodeIndexPosition[ParentIndex][( FilledCount != 0 ) ? (CapitalChar( (Represent[0]).TheLook ) - Aa): 0], PlasticRack, PlasticSize, MegaWordHolder, ParentIndex );
	return TRUE;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Older function central in scope to the play of the game.

//"ThisPlay" must be validated, and in this game it has to be because the computer generates all plays to speed things up.
int BoardPlayCalculatePointValue(BoardPtr ThisBoard, PlayPtr ThisPlay ) {
	int X, Y;
	int StartCol, StartRow;
	int PerpSum = 0;
	int PerpMult = 1;
	int ParaMult = 1;
	int ParaSum = 0;
	int result = 0;
	int WordLength = PlayMainWordLength( ThisPlay );
	char *WordChars = PlayMainWord( ThisPlay );
	SquarePtr CurrentSquare;
	if ( ( PlayMove( ThisPlay ) == ACROSS) ) {
		X = PlayRow( ThisPlay );
		StartCol = PlayCol( ThisPlay );
		for ( Y = StartCol; Y < (StartCol + WordLength); Y++ ) {
			CurrentSquare = &(ThisBoard->Block[X][Y]);
			if ( SquareUsed( CurrentSquare ) == TRUE ) {
				ParaSum += TileValues[(CurrentSquare->Placed > Zz)? 0: (CurrentSquare->Placed - EMPTY)];
			}
			else{
				// We have found a word that is perpinduclar to the main word that we must add to the total.	Note that the central pivot is used only on the first play, and has no perp word associated with it.
				if ( SquareValidAcrossPivot( CurrentSquare ) == TRUE && !(X == 7 && Y == 7) ) {
					if ( SquareTypeOfSquare( CurrentSquare ) == RED ) {
						PerpMult *= 3;
						ParaMult *= 3;
						PerpSum += TileValues[(WordChars[Y - StartCol] > Zz)? 0: (WordChars[Y - StartCol] - EMPTY)];
						ParaSum += TileValues[(WordChars[Y - StartCol] > Zz)? 0: (WordChars[Y - StartCol] - EMPTY)];
					}
					if ( SquareTypeOfSquare( CurrentSquare ) == PINK ) {
						PerpMult *= 2;
						ParaMult *= 2;
						PerpSum += TileValues[(WordChars[Y - StartCol] > Zz)? 0: (WordChars[Y - StartCol] - EMPTY)];
						ParaSum += TileValues[(WordChars[Y - StartCol] > Zz)? 0: (WordChars[Y - StartCol] - EMPTY)];
					}
					if ( SquareTypeOfSquare( CurrentSquare ) == DARKBLUE ) {
						PerpSum += 3 * TileValues[(WordChars[Y - StartCol] > Zz)? 0: (WordChars[Y - StartCol] - EMPTY)];
						ParaSum += 3 * TileValues[(WordChars[Y - StartCol] > Zz)? 0: (WordChars[Y - StartCol] - EMPTY)];
					}
					if ( SquareTypeOfSquare( CurrentSquare ) == LIGHTBLUE ) {
						PerpSum += 2 * TileValues[(WordChars[Y - StartCol] > Zz)? 0: (WordChars[Y - StartCol] - EMPTY)];
						ParaSum += 2 * TileValues[(WordChars[Y - StartCol] > Zz)? 0: (WordChars[Y - StartCol] - EMPTY)];
					}
					if ( SquareTypeOfSquare( CurrentSquare ) == CLEAR ) {
						PerpSum += TileValues[(WordChars[Y - StartCol] > Zz)? 0: (WordChars[Y - StartCol] - EMPTY)];
						ParaSum += TileValues[(WordChars[Y - StartCol] > Zz)? 0: (WordChars[Y - StartCol] - EMPTY)];
					}
					CurrentSquare = SquareUp( CurrentSquare );
					// Add above tile values to the perp.
					while ( SquareUsed( CurrentSquare ) == TRUE) {
						PerpSum += TileValues[(CurrentSquare->Placed > Zz)? 0: (CurrentSquare->Placed - EMPTY)];
						CurrentSquare = SquareUp( CurrentSquare );
					}
					CurrentSquare = &(ThisBoard->Block[X][Y]);
					CurrentSquare = SquareDown( CurrentSquare );
					// Add Below tile values.
					while ( SquareUsed( CurrentSquare ) == TRUE) {
						PerpSum += TileValues[(CurrentSquare->Placed > Zz)? 0: (CurrentSquare->Placed - EMPTY)];
						CurrentSquare = SquareDown( CurrentSquare );
					}
					PerpSum *= PerpMult;
					result += PerpSum;
					PerpSum = 0;
					PerpMult = 1;
				}
				// The square must be unused but it is not a pivot so it only effects the para word.
				else{
					if ( SquareTypeOfSquare( CurrentSquare ) == RED ) {
						ParaMult *= 3;
						ParaSum += TileValues[(WordChars[Y - StartCol] > Zz)? 0: (WordChars[Y - StartCol] - EMPTY)];
					}
					if ( SquareTypeOfSquare( CurrentSquare ) == PINK ) {
						ParaMult *= 2;
						ParaSum += TileValues[(WordChars[Y - StartCol] > Zz)? 0: (WordChars[Y - StartCol] - EMPTY)];
					}
					if ( SquareTypeOfSquare( CurrentSquare ) == DARKBLUE ) ParaSum += 3*TileValues[(WordChars[Y - StartCol] > Zz)? 0: (WordChars[Y - StartCol] - EMPTY)];
					if ( SquareTypeOfSquare( CurrentSquare ) == LIGHTBLUE ) ParaSum += 2*TileValues[(WordChars[Y - StartCol] > Zz)? 0: (WordChars[Y - StartCol] - EMPTY)];
					if ( SquareTypeOfSquare( CurrentSquare ) == CLEAR ) ParaSum += TileValues[(WordChars[Y - StartCol] > Zz)? 0: (WordChars[Y - StartCol] - EMPTY)];
				}
			}
		}
		ParaSum *= ParaMult;
		result += ParaSum;
	}
	else{
		Y = PlayCol( ThisPlay );
		StartRow = PlayRow( ThisPlay );
		for ( X = StartRow; X < (StartRow + WordLength); X++ ) {
			CurrentSquare = &(ThisBoard->Block[X][Y]);
			if ( SquareUsed( CurrentSquare ) == TRUE ) {
				ParaSum += TileValues[(CurrentSquare->Placed > Zz)? 0: (CurrentSquare->Placed - EMPTY)];
			}
			else{
				// We have found a word that is perpinduclar to the main word that we must add to the total. note that the central pivot is used only on the first play, and has no perp word associated with it.
				if ( SquareValidDownPivot( CurrentSquare ) == TRUE && !(X == 7 && Y == 7) ){
					if ( SquareTypeOfSquare( CurrentSquare ) == RED ) {
						PerpMult *= 3;
						ParaMult *= 3;
						PerpSum += TileValues[(WordChars[X - StartRow] > Zz)? 0: (WordChars[X - StartRow] - EMPTY)];
						ParaSum += TileValues[(WordChars[X - StartRow] > Zz)? 0: (WordChars[X - StartRow] - EMPTY)];
					}
					if ( SquareTypeOfSquare( CurrentSquare ) == PINK ) {
						PerpMult *= 2;
						ParaMult *= 2;
						PerpSum += TileValues[(WordChars[X - StartRow] > Zz)? 0: (WordChars[X - StartRow] - EMPTY)];
						ParaSum += TileValues[(WordChars[X - StartRow] > Zz)? 0: (WordChars[X - StartRow] - EMPTY)];
					}
					if ( SquareTypeOfSquare( CurrentSquare ) == DARKBLUE ) {
						PerpSum += 3*TileValues[(WordChars[X - StartRow] > Zz)? 0: (WordChars[X - StartRow] - '?')];
						ParaSum += 3*TileValues[(WordChars[X - StartRow] > Zz)? 0: (WordChars[X - StartRow] - '?')];
					}
					if ( SquareTypeOfSquare( CurrentSquare ) == LIGHTBLUE ) {
						PerpSum += 2*TileValues[(WordChars[X - StartRow] > Zz)? 0: (WordChars[X - StartRow] - EMPTY)];
						ParaSum += 2*TileValues[(WordChars[X - StartRow] > Zz)? 0: (WordChars[X - StartRow] - EMPTY)];
					}
					if ( SquareTypeOfSquare( CurrentSquare ) == CLEAR ){
						PerpSum += TileValues[(WordChars[X - StartRow] > Zz)? 0: (WordChars[X - StartRow] - EMPTY)];
						ParaSum += TileValues[(WordChars[X - StartRow] > Zz)? 0: (WordChars[X - StartRow] - EMPTY)];
					}
					CurrentSquare = SquareLeft( CurrentSquare );
					// Add above tile values to the perp.
					while ( SquareUsed( CurrentSquare ) == TRUE){
						PerpSum += TileValues[(CurrentSquare->Placed > Zz)? 0: (CurrentSquare->Placed - EMPTY)];
						CurrentSquare = SquareLeft( CurrentSquare );
					}
					CurrentSquare = &(ThisBoard->Block[X][Y]);
					CurrentSquare = SquareRight( CurrentSquare );
					// Add Below tile values.
					while ( SquareUsed( CurrentSquare ) == TRUE) {
						PerpSum += TileValues[(CurrentSquare->Placed > Zz)? 0: (CurrentSquare->Placed - EMPTY)];
						CurrentSquare = SquareRight( CurrentSquare );
					}
					PerpSum *= PerpMult;
					result += PerpSum;
					/// reset the counting variables for the next potential perp
					PerpSum = 0;
					PerpMult = 1;
				}
				// The square must be unused but it is not a pivot so it only effects the para word.
				else{
					if ( SquareTypeOfSquare( CurrentSquare ) == RED ) {
						ParaMult *= 3;
						ParaSum += TileValues[(WordChars[X - StartRow] > Zz)? 0: (WordChars[X - StartRow] - EMPTY)];
					}
					if ( SquareTypeOfSquare( CurrentSquare ) == PINK ) {
						ParaMult *= 2;
						ParaSum += TileValues[(WordChars[X - StartRow] > Zz)? 0: (WordChars[X - StartRow] - EMPTY)];
					}
					if ( SquareTypeOfSquare( CurrentSquare ) == DARKBLUE ) ParaSum += 3*TileValues[(WordChars[X - StartRow] > Zz)? 0: (WordChars[X - StartRow] - EMPTY)];
					if ( SquareTypeOfSquare( CurrentSquare ) == LIGHTBLUE ) ParaSum += 2*TileValues[(WordChars[X - StartRow] > Zz)? 0: (WordChars[X - StartRow] - EMPTY)];
					if ( SquareTypeOfSquare( CurrentSquare ) == CLEAR ) ParaSum += TileValues[(WordChars[X - StartRow] > Zz)? 0: (WordChars[X - StartRow] - EMPTY)];
				}
			}
		}
		ParaSum *= ParaMult;
		result += ParaSum;
	}
	if ( PlayTilesRequired( ThisPlay ) == BINGO ) result += BINGOBONUS;
	return result;
}

// This function cuts up a board into PlaySpaces and gets them processed using the new functions above.
void BoardArrayUDawgDiscoverValidPlays( BoardPtr ThisBoard, PlayListPtr Options, char *Hord, int HordSize, ArrayUDawgPtr ThisArrayUDawg, Player Who ) { 
	// PlaySpaces need to be analysed immediately if they are valid in the case where 1 tile needs to be in 2 spaces, this PlaySpace is invalid.  - This fix is for future consideration.  It has been taken care of when we try to fill buckets for an individual PlaySpace in the WordListPlaySpaceArrayUDawgRackPopulate.
	// The easiest cases have been accounted for.
	int X, Y, V, TilesToPlay, ScrollTab, CountDown;
	int startcol, endcol = 0;
	int startrow, endrow = 0;
	int LeastTiles;
	int DownCounter, UpCounter;
	int CurrentSize;
	SquarePtr CurrentSquare;
	WordListPtr CurrentFittingWords = WordListInit();
	PlaySpacePtr Shuffler = PlaySpaceInit();
	PlayPtr PlaceHolderPlay;
	int PlaySpaceTypeTally[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
	char CurrentWord[MAX + 1] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
	char Intersector[MAXTILES + NUMBEROFENGLISHLETTERS + 1] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
	char IntersectorTwo[MAXTILES + NUMBEROFENGLISHLETTERS + 1] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
	char IntersectorTotal[MAXTILES + NUMBEROFENGLISHLETTERS + 1] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
	int wordcounter;
	int c;
	int rower;
	int rowtwo;
	int coler;
	int coltwo;
	int PotentialWordLength;
	// When the nemesis is playing, we know exactly how many tiles they will play so limit the analysis to the entire hord entered only.  This drastically speeds up the game play.
	LeastTiles = (Who == PLAYERTWO) ?	HordSize : 2;
	if ( HordSize == 1 ) goto OneTilePlaysOnly;
	// This structure finds only ACROSS plays which can hook on Across or Down Pivots which have no inherant restrictions, in other words, there is at least 1 tile in the hord that can be placed on the pivot square.
	// Be careful because it is a fact that the further conditional squares that are encountered may easily render the chosen playspace to be invalid.  Taken Care of I believe.
	for ( X = ThisBoard->StartRow; X <= ThisBoard->EndRow; X++) {
		for ( Y = ThisBoard->StartCol; Y <= ThisBoard->EndCol; Y++) {
			// Enter only if the square is a ValidDownPivot or if a ValidAcrossPivot, then only if we have a placeable tile in our rack.	The "SquareValidAcrossPlayHook" function tests for this condition well.
			if ( SquareValidAcrossPlayHook(	&(ThisBoard->Block[X][Y]), Hord, HordSize ) == TRUE ) {
				for ( TilesToPlay = HordSize; TilesToPlay >= LeastTiles ; TilesToPlay-- ) {
					// X,Y represents the CountDown'th tile.
					for( CountDown = TilesToPlay; CountDown >= 1; CountDown-- ) {
						// Given TilesToPlay and CountDown, Discover firt Square then last Square (Make sure to check for the impossible condition); conclude on total word length.
						// Discover first Square.
						CurrentSquare = &(ThisBoard->Block[X][Y]);
						// This variable represents the number of tiles that must be placed before X,Y.
						DownCounter = CountDown - 1;
						for ( ScrollTab = Y; ScrollTab >= 0; ScrollTab-- ) {
							// End of the line, we can start the word right here.	Note that we will never arrive on a pivot that has been used before.	Play == Valid.
							if ( DownCounter == 0 && SquareUsed( SquareLeft( CurrentSquare ) ) == FALSE ) {
								startcol = ScrollTab;
								break;
							}
							// Don't waste time looking for the ending column if the play, as stated, is impossible. We have reached the end of the board, and still need to place more tiles.
							if ( DownCounter != 0 && SquareLeft( CurrentSquare ) == NULL ) goto ImpossibleAcrossCase;
							// It is a fact that we have already tried to put a word in this space on the previous pass.	Hence, the impossible dream.	Only in the "left" direction.	The selected pivot will be the leftmost.
							if ( DownCounter != 0 && SquareValidPivot( SquareLeft( CurrentSquare ) ) == TRUE) goto ImpossibleAcrossCase;
							// We have found a place where a tile can go.
							if ( DownCounter != 0 && SquareUsed( SquareLeft( CurrentSquare ) ) == FALSE ) DownCounter--;
							//	Even when DownCounter is found to be zero, we still need to find a filled square with nothing to the left of it.
							CurrentSquare = SquareLeft( CurrentSquare );
						}
						// Discover last Square.	Hence reset the current square to the leftmost hook.
						CurrentSquare = &(ThisBoard->Block[X][Y]);
						// This variable represents the number of tiles that must be placed after X,Y.
						UpCounter = TilesToPlay - CountDown;
						for ( ScrollTab = Y; ScrollTab < MAX; ScrollTab++ ) {
							// We have successfully found the end of the play space that we are trying to fill.
							if (UpCounter == 0 && SquareUsed( SquareRight( CurrentSquare ) ) == FALSE ) {
								endcol = ScrollTab;
								break;
							}
							// We have reached the end of the board and run out of space.
							if ( UpCounter != 0 && SquareRight( CurrentSquare ) == NULL ) goto ImpossibleAcrossCase;
							// We do not have any of the conditional tiles for this pivot square.	Go to the impossible case and hault the countdown.	Move on to the next number of tiles.
							if ( UpCounter != 0 && SquareValidAcrossPivot( SquareRight( CurrentSquare ) ) == TRUE ) {
								if ( SquareValidAcrossPlayHook( SquareRight( CurrentSquare ), Hord, HordSize  ) == FALSE ) {
									CountDown = 0;
									goto ImpossibleAcrossCase;
								}
							}
							// There is an unused space to the right so let's denote that we shall use it.
							if ( UpCounter != 0 && SquareUsed(SquareRight(CurrentSquare)) == FALSE ) UpCounter--;
							// Move the CurrentSquare one to the right either way till we hit the end or arrive at the impossible case.
							CurrentSquare = SquareRight( CurrentSquare );
						}
						// Set the CurrentSize
						CurrentSize = endcol - startcol + 1;// Make sure that the wordlist is empty.
						ClearWordList ( CurrentFittingWords );
						// Create the "PlaySpace" data structure, then fill it and pass it to the ArrayUDawg function that will fill the "CurrentFittingWords" list.	Question marks are handled on the fly.
						PlaySpaceFromSquarePopulateAcross( Shuffler, &(ThisBoard->Block[X][startcol]), CurrentSize );
						// Fill the wordlist, and note that every single word in the list represents a unique valid play.  Capital letters represent any filled tiles or face tiles to be placed.  Lower case letters can only represent a blank tile being placed.
						WordListPlaySpaceArrayUDawgRackPopulate( CurrentFittingWords, Shuffler, ThisArrayUDawg, Hord, HordSize, PlaySpaceTypeTally );
						// Generate plays from the information that we know and append them to Options.  Every single word represents a unique and valid play.
						// Make the plays and add them to the options list by using the fitting words, they all pivot at (X,Y) and have the same length, also they all start at the same square.
						for ( V = 0; V < WordListSize( CurrentFittingWords ); V++) {
								PlaceHolderPlay = PlayInit();
								PlaySet( PlaceHolderPlay, X, startcol, CurrentSize, TilesToPlay, WordListGetWord( CurrentFittingWords, V ), ACROSS );
								PlaySetPointValue( PlaceHolderPlay, BoardPlayCalculatePointValue( ThisBoard, PlaceHolderPlay ) );
								PlayListAppend( Options, PlaceHolderPlay );
						}
						ImpossibleAcrossCase:;
						// End of pivot position selection	(CountDown), and hence the analysis of one potential play space, each one should be processed in a parallel fashion.	Set CountDown to 0 to reduce number of tiles to play.
					}
					// End of TilesToPlay
				}
				// End of valid pivot if
			}
			// End of Main Y then X for loops generating the Across Plays.
		}
	}
	// Simply generate the DOWN plays in the same fashion as the across plays are generated.
	for ( Y = ThisBoard->StartCol; Y <= ThisBoard->EndCol; Y++) {
		for ( X = ThisBoard->StartRow; X <= ThisBoard->EndRow; X++) {
			// Enter only if the square is a ValidAcrossPivot or if a ValidDownPivot, then only if we have a placeable tile in our rack.	The "SquareValidDownPlayHook" function tests for this condition well.
			if ( SquareValidDownPlayHook( &((ThisBoard->Block)[X][Y]), Hord, HordSize ) == TRUE ) {
				for ( TilesToPlay = HordSize; TilesToPlay >= LeastTiles ; TilesToPlay-- ) {
					// X,Y represents the CountDown'th tile.
					for( CountDown = TilesToPlay; CountDown >= 1; CountDown-- ) {
						// Given TilesToPlay and CountDown, Discover firt Square then last Square (Make sure to check for the impossible condition); conclude on total word length.
						// Discover first Square.
						CurrentSquare = &((ThisBoard->Block)[X][Y]);
						// This variable represents the number of tiles that must be placed before X,Y.
						DownCounter = CountDown - 1;
						for ( ScrollTab = X; ScrollTab >= 0; ScrollTab-- ) {
							// End of the line, we can start the word right here.	Note that we will never arrive on a pivot that has been used before.	Play == Valid.
							if ( DownCounter == 0 && SquareUsed( SquareUp( CurrentSquare ) ) == FALSE ) {
								startrow = ScrollTab;
								break;
							}
							// Don't waste time looking for the ending column if the play, as stated, is impossible. We have reached the end of the board, and still need to place more tiles.
							if ( DownCounter != 0 && SquareUp( CurrentSquare ) == NULL ) goto ImpossibleDownCase;
							// It is a fact that we have already tried to put a word in this space on the previous pass.	Hence, the impossible dream.	Only in the "left" direction.	The selected pivot will be the leftmost.
							if ( DownCounter != 0 && SquareValidPivot( SquareUp( CurrentSquare ) ) == TRUE) goto ImpossibleDownCase;
							// We have found a place where a tile can go.
							if ( DownCounter != 0 && SquareUsed( SquareUp( CurrentSquare ) ) == FALSE ) DownCounter--;
							//	Even when DownCounter is found to be zero, we still need to find a filled square with nothing to the left of it.
							CurrentSquare = SquareUp( CurrentSquare );
						}
						// Discover last Square.	Hence reset the current square to the leftmost hook.
						CurrentSquare = &(ThisBoard->Block[X][Y]);
						// This variable represents the number of tiles that must be placed after X,Y.
						UpCounter = TilesToPlay - CountDown;
						for ( ScrollTab = X; ScrollTab < MAX; ScrollTab++ ){
							// We have successfully found the end of the play space that we are trying to fill.
							if (UpCounter == 0 && SquareUsed( SquareDown( CurrentSquare ) ) == FALSE ) {
								endrow = ScrollTab;
								break;
							}
							// We have reached the end of the board and run out of space.
							if ( UpCounter != 0 && SquareDown( CurrentSquare ) == NULL ) goto ImpossibleDownCase;
							// We do not have any of the conditional tiles for this pivot square.	Go to the impossible case and hault the countdown.	Move on to the next number of tiles.
							if ( UpCounter != 0 && SquareValidDownPivot( SquareDown( CurrentSquare ) ) == TRUE ) {
								if ( SquareValidDownPlayHook( SquareDown( CurrentSquare ), Hord, HordSize  ) == FALSE ) {
									CountDown = 0;
									goto ImpossibleDownCase;
								}
							}
							// There is an unused space to the down so let's denote that we shall use it.
							if ( UpCounter != 0 && SquareUsed(SquareDown(CurrentSquare)) == FALSE ) UpCounter--;
							// Move the CurrentSquare one to the right either way till we hit the end or arrive at the impossible case.
							CurrentSquare = SquareDown( CurrentSquare );
						}
						// Set the CurrentSize
						CurrentSize = endrow - startrow + 1;// Make sure that the wordlist is empty.
						ClearWordList ( CurrentFittingWords );
						// Create the "PlaySpace" data structure, then fill it and pass it to the ArrayUDawg function that will fill the "CurrentFittingWords" list.	Question marks are handled on the fly.
						PlaySpaceFromSquarePopulateDown( Shuffler, &((ThisBoard->Block)[startrow][Y]), CurrentSize );
						// Fill the wordlist.
						// Each of these calls should be a unique thread.  That will drastically reduce the time required for a board alalysis.  The actual play generation for a certain playspace should also be a unique thread, as to not slow down the main thread generation time.
						WordListPlaySpaceArrayUDawgRackPopulate( CurrentFittingWords, Shuffler, ThisArrayUDawg, Hord, HordSize, PlaySpaceTypeTally );
						// Generate plays from the information that we know and append them to Options
						// Make the plays and add them to the options list by using the fitting words, they all pivot at (X,Y) and have the same length, also they all start at the same square.
						// Make this loop a unique thread. but make sure that the data filling of the list does not intersect.  POSIX?
						for ( V = 0; V < WordListSize( CurrentFittingWords ); V++) {
								PlaceHolderPlay = PlayInit();
								PlaySet( PlaceHolderPlay, startrow, Y, CurrentSize, TilesToPlay, WordListGetWord( CurrentFittingWords, V ), DOWN );
								PlaySetPointValue( PlaceHolderPlay, BoardPlayCalculatePointValue( ThisBoard, PlaceHolderPlay ) );
								PlayListAppend( Options, PlaceHolderPlay );
						}
						ImpossibleDownCase:;
						// End of pivot position selection	(CountDown), and hence the analysis of one potential play space, each one should be processed in a parallel fashion.	Set CountDown to 0 to reduce number of tiles to play.
					}
					// End of TilesToPlay
				}
				// End of valid pivot if
			}
			// End of Main Y then X for loops generating the Down Plays.
		}
	}
	ClearWordList ( CurrentFittingWords );
	// We are going to need to generate 1 tile plays, only if it is not the first move...  The first move needs to contain at least 2 tiles.
	OneTilePlaysOnly:;
	if ( ThisBoard->StartRow == 7 && ThisBoard->EndRow == 7 ) goto OneTilePlayImpossible;
	// We only generate moves that involve the exact number of tiles placed by the nemesis.
	if ( Who == PLAYERTWO && HordSize != 1 ) goto OneTilePlayImpossible;
	for ( rower = ThisBoard->StartRow; rower <= ThisBoard->EndRow; rower++ ){
		for ( coler = ThisBoard->StartCol; coler <= ThisBoard->EndCol; coler++ ){
			CurrentSquare = &(ThisBoard->Block[rower][coler]);
			// This structure takes care of pure down plays.
			if ( SquareValidAcrossPivot(CurrentSquare) == TRUE && SquareValidDownPivot(CurrentSquare) == FALSE ){
				if (SquareUsed(SquareUp(CurrentSquare)) == TRUE && SquareUsed(SquareDown(CurrentSquare)) == TRUE) {
					for ( rowtwo = rower - 1; rowtwo >= 0 && SquareUsed(&(ThisBoard->Block[rowtwo][coler])) == TRUE; rowtwo--);
					rowtwo += 1;
					startrow = rowtwo;
					startcol = coler;
					for ( rowtwo = rower + 1; rowtwo <= 14 && SquareUsed(&(ThisBoard->Block[rowtwo][coler])) == TRUE; rowtwo++);
					rowtwo -= 1;
					endrow = rowtwo;
					endcol = coler;
				}
				if (SquareUsed(SquareUp(CurrentSquare)) == FALSE && SquareUsed(SquareDown(CurrentSquare)) == TRUE) {
					for ( rowtwo = rower + 1; rowtwo <= 14 && SquareUsed(&(ThisBoard->Block[rowtwo][coler])) == TRUE; rowtwo++);
					rowtwo -= 1;
					startrow = rower;
					startcol = coler;
					endrow = rowtwo;
					endcol = coler;
				}
				if (SquareUsed(SquareUp(CurrentSquare)) == TRUE && SquareUsed(SquareDown(CurrentSquare)) == FALSE) {
					for ( rowtwo = rower - 1; rowtwo >= 0 && SquareUsed(&(ThisBoard->Block[rowtwo][coler])) == TRUE; rowtwo--);
					rowtwo += 1;
					startrow = rowtwo;
					startcol = coler;
					endrow = rower;
					endcol = coler;
				}
				PotentialWordLength = endrow - startrow + 1;
				// Create and add a DOWN play to the playlist.
				for (wordcounter = 0; wordcounter < PotentialWordLength; wordcounter++){
					CurrentWord[wordcounter] = CapitalChar( SquarePlaced( &((ThisBoard->Block)[startrow + wordcounter][coler]) ) );
				}
				CurrentWord[PotentialWordLength] = '\0';
				SquareMakeValidLetterString( CurrentSquare, Hord, HordSize, Intersector, ACROSS );
				// Make all the plays that intersector indicates can be made.	Keep in mind that a question mark can be used but should never be used.
				for ( c = 0; c < (signed int)(signed int)strlen( Intersector ); c ++){
					CurrentWord[rower - startrow] = Intersector[c];
					PlaceHolderPlay = PlayInit();
					PlaySet( PlaceHolderPlay, startrow, startcol, PotentialWordLength, 1, CurrentWord, DOWN );
					PlaySetPointValue( PlaceHolderPlay, BoardPlayCalculatePointValue( ThisBoard, PlaceHolderPlay ) );
					PlayListAppend( Options, PlaceHolderPlay );
				}		
			}
			// One tile across plays are handled here.
			if ( SquareValidDownPivot( CurrentSquare ) == TRUE && SquareValidAcrossPivot( CurrentSquare ) == FALSE ) {
				if ( SquareUsed( SquareLeft( CurrentSquare ) ) == TRUE && SquareUsed( SquareRight( CurrentSquare ) ) == TRUE ) {
					for ( coltwo = coler - 1; coltwo >= 0 && SquareUsed( &(ThisBoard->Block[rower][coltwo]) ) == TRUE; coltwo-- );
					coltwo += 1;
					startrow = rower;
					startcol = coltwo;
					for ( coltwo = coler + 1; coltwo <= 14 && SquareUsed( &(ThisBoard->Block[rower][coltwo]) ) == TRUE; coltwo++ );
					coltwo--;
					endrow = rower;
					endcol = coltwo;						
				}
				if ( SquareUsed( SquareLeft( CurrentSquare ) ) == FALSE && SquareUsed( SquareRight( CurrentSquare ) ) == TRUE ) {
					for ( coltwo = coler + 1; coltwo <= 14 && SquareUsed( &(ThisBoard->Block[rower][coltwo]) ) == TRUE; coltwo++ );
					coltwo -= 1;
					startrow = rower;
					startcol = coler;
					endrow = rower;
					endcol = coltwo;						
				}
				if ( SquareUsed(SquareLeft(CurrentSquare)) == TRUE && SquareUsed(SquareRight(CurrentSquare)) == FALSE) {
					for ( coltwo = coler - 1; coltwo >= 0 && SquareUsed( &(ThisBoard->Block[rower][coltwo]) ) == TRUE; coltwo-- );
					coltwo += 1;
					startrow = rower;
					startcol = coltwo;
					endrow = rower;
					endcol = coler;						
				}
				PotentialWordLength = endcol - startcol + 1;
				// Create and add an ACROSS plays to the playlist.
				for ( wordcounter = 0; wordcounter < PotentialWordLength; wordcounter++ ) {
					CurrentWord[wordcounter] = CapitalChar( SquarePlaced( &((ThisBoard->Block)[rower][startcol + wordcounter]) ) );
				}
				CurrentWord[PotentialWordLength] = '\0';
				SquareMakeValidLetterString( CurrentSquare, Hord, HordSize, Intersector, DOWN );
				// Make all the plays that intersector indicates can be made.	Keep in mind that a question mark can be used but should never be used.
				for ( c = 0; c < (signed int)(signed int)strlen( Intersector ); c ++ ) {
					CurrentWord[coler - startcol] = Intersector[c];
					PlaceHolderPlay = PlayInit();
					PlaySet( PlaceHolderPlay, startrow, startcol, PotentialWordLength, 1, CurrentWord, ACROSS );
					PlaySetPointValue( PlaceHolderPlay, BoardPlayCalculatePointValue( ThisBoard, PlaceHolderPlay ) );
					PlayListAppend( Options, PlaceHolderPlay );
				}
			}
			// The best 1 tile plays are both across and down plays, but these plays will be cast as down plays.
			if ( SquareValidDownPivot( CurrentSquare ) == TRUE && SquareValidAcrossPivot( CurrentSquare ) == TRUE ) {
				if ( SquareUsed( SquareUp( CurrentSquare ) ) == TRUE && SquareUsed( SquareDown( CurrentSquare) ) == TRUE ) {
					for ( rowtwo = rower - 1; rowtwo >= 0 && SquareUsed( &(ThisBoard->Block[rowtwo][coler]) ) == TRUE; rowtwo-- );
					rowtwo += 1;
					startrow = rowtwo;
					startcol = coler;
					for ( rowtwo = rower + 1; rowtwo <= 14 && SquareUsed( &(ThisBoard->Block[rowtwo][coler]) ) == TRUE; rowtwo++ );
					rowtwo -= 1;
					endrow = rowtwo;
					endcol = coler;
				}
				if ( SquareUsed( SquareUp(CurrentSquare) ) == FALSE && SquareUsed( SquareDown( CurrentSquare ) ) == TRUE ) {
					for ( rowtwo = rower + 1; rowtwo <= 14 && SquareUsed(&(ThisBoard->Block[rowtwo][coler])) == TRUE; rowtwo++ );
					rowtwo -= 1;
					startrow = rower;
					startcol = coler;
					endrow = rowtwo;
					endcol = coler;
				}
				if ( SquareUsed( SquareUp( CurrentSquare ) ) == TRUE && SquareUsed( SquareDown( CurrentSquare ) ) == FALSE ) {
					for ( rowtwo = rower - 1; rowtwo >= 0 && SquareUsed( &(ThisBoard->Block[rowtwo][coler]) ) == TRUE; rowtwo-- );
					rowtwo += 1;
					startrow = rowtwo;
					startcol = coler;
					endrow = rower;
					endcol = coler;
				}
				PotentialWordLength = endrow - startrow + 1;
				// Create and add a DOWN play to the playlist.
				for (wordcounter = 0; wordcounter < PotentialWordLength; wordcounter++){
					CurrentWord[wordcounter] = CapitalChar( SquarePlaced( &((ThisBoard->Block)[startrow + wordcounter][coler]) ) );
				}
				CurrentWord[PotentialWordLength] = '\0';
				StringClearMe(Intersector);
				StringClearMe(IntersectorTwo);
				StringClearMe(IntersectorTotal);
				SquareMakeValidLetterString( CurrentSquare, Hord, HordSize, Intersector, ACROSS );
				SquareMakeValidLetterString( CurrentSquare, Hord, HordSize, IntersectorTwo, DOWN );
				StringsHaveInCommon( Intersector, IntersectorTwo, IntersectorTotal );
				// Make all the plays that intersector indicates can be made.	Keep in mind that a question mark can be used but should never be used.
				for ( c = 0; c < (signed int)(signed int)strlen( IntersectorTotal ); c ++){
					CurrentWord[rower - startrow] = IntersectorTotal[c];
					PlaceHolderPlay = PlayInit();
					PlaySet( PlaceHolderPlay, startrow, startcol, PotentialWordLength, 1, CurrentWord, DOWN );
					PlaySetPointValue( PlaceHolderPlay, BoardPlayCalculatePointValue( ThisBoard, PlaceHolderPlay ) );
					PlayListAppend( Options, PlaceHolderPlay );
				}
			}		
		}
	}
	OneTilePlayImpossible:;
	// We don't need this dynamically allocated structure anymore so free it.
	free( CurrentFittingWords );
}

void BoardArrayUDawgUpdateBlockPivotLetters( BoardPtr ThisBoard, ArrayUDawgPtr Doggy ) {
	int startrow, startcol, endrow, endcol, tryme, wordcounter, c;
	int rower, rowtwo;
	int coler, coltwo;
	int PotentialWordLength;
	char CurrentLetter;
	char CurrentWord[MAX + 1] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
	Bool RunningTab[NUMBEROFENGLISHLETTERS] = { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 
	FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 
	FALSE, FALSE, FALSE };
	SquarePtr CurrentSquare;
	for ( rower = ThisBoard->StartRow; rower <= ThisBoard->EndRow; rower++ ) {
		for ( coler = ThisBoard->StartCol; coler <= ThisBoard->EndCol; coler++ ) {
			CurrentSquare = &(ThisBoard->Block[rower][coler]);
			if ( SquareValidAcrossPivot( CurrentSquare ) == TRUE ) {
				if ( SquareUsed( SquareUp( CurrentSquare ) ) == TRUE ) {
					rowtwo = rower - 1;
					while ( SquareUsed( SquareUp( CurrentSquare ) ) == TRUE ) {
						rowtwo -= 1;
						CurrentSquare = SquareUp( CurrentSquare );
					}
					rowtwo += 1;
					startrow = rowtwo;
					CurrentSquare = &(ThisBoard->Block[rower][coler]);
				}
				else startrow = rower;
				if ( SquareUsed( SquareDown( CurrentSquare ) ) == TRUE ) {
					rowtwo = rower + 1;
					while ( SquareUsed( SquareDown( CurrentSquare ) ) == TRUE ) {
						rowtwo += 1;
						CurrentSquare = SquareDown( CurrentSquare );
					}
					rowtwo -= 1;
					endrow = rowtwo;
					CurrentSquare = &(ThisBoard->Block[rower][coler]);
				}
				else endrow = rower;
				PotentialWordLength = endrow - startrow + 1;
				for ( wordcounter = 0; wordcounter < PotentialWordLength; wordcounter++ ) {
					CurrentLetter = SquarePlaced( &(ThisBoard->Block[startrow + wordcounter][coler]) );
					CurrentWord[wordcounter] = (CurrentLetter <= Zz)? CurrentLetter: (CurrentLetter - LOWERIT);
				}
				CurrentWord[PotentialWordLength] = '\0';
				for ( tryme = Aa; tryme <= Zz; tryme++ ){
					CurrentWord[rower - startrow] = tryme;
					if ( ArrayUDawgWordSearch( Doggy, CurrentWord ) == TRUE ) RunningTab[tryme - Aa] = TRUE;
				}
				SquareSetAcrossPivotLetters( &(ThisBoard->Block[rower][coler] ), RunningTab);
				for ( c = 0; c < NUMBEROFENGLISHLETTERS; c++ ) RunningTab[c] = FALSE;
			}
			if ( SquareValidDownPivot( CurrentSquare ) == TRUE ) {
				if ( SquareUsed( SquareLeft( CurrentSquare ) ) == TRUE ) {
					coltwo = coler - 1;
					while ( SquareUsed( SquareLeft( CurrentSquare ) ) == TRUE ) {
						coltwo -= 1;
						CurrentSquare = SquareLeft( CurrentSquare );
					}
					coltwo += 1;
					startcol = coltwo;
					CurrentSquare = &(ThisBoard->Block[rower][coler]);
				}
				else startcol = coler;
				if ( SquareUsed( SquareRight( CurrentSquare ) ) == TRUE ) {
					coltwo = coler + 1;
					while ( SquareUsed( SquareRight( CurrentSquare ) ) == TRUE ) {
						coltwo += 1;
						CurrentSquare = SquareRight( CurrentSquare );
					}
					coltwo -= 1;
					endcol = coltwo;
				}
				else endcol = coler;
				PotentialWordLength = endcol - startcol + 1;
				for ( wordcounter = 0; wordcounter < PotentialWordLength; wordcounter++ ) {
					CurrentLetter = SquarePlaced( &(ThisBoard->Block[rower][startcol + wordcounter]) );
					CurrentWord[wordcounter] = (CurrentLetter <= Zz)? CurrentLetter: (CurrentLetter - LOWERIT);
				}
				CurrentWord[PotentialWordLength] = '\0';
				for ( tryme = Aa; tryme <= Zz; tryme++ ) {
					CurrentWord[coler - startcol] = tryme;
					if ( ArrayUDawgWordSearch( Doggy, CurrentWord ) == TRUE) RunningTab[tryme - Aa] = TRUE;
				}
				SquareSetDownPivotLetters( &(ThisBoard->Block[rower][coler]), RunningTab );
				for ( c = 0; c < NUMBEROFENGLISHLETTERS; c++ ) RunningTab[c] = FALSE;
			}
		}
	}
}

void BoardMakeThisPlay ( BoardPtr ThisBoard, PlayPtr ThisPlay, Player PlayMaker, ArrayUDawgPtr Doggy ) {
	int count;
	int PlayLength = PlayMainWordLength(ThisPlay);
	int CurrentRow = PlayRow(ThisPlay);
	int CurrentCol = PlayCol(ThisPlay);
	SquarePtr CurrentSquare;
	char *TheWord;
	// Set new bounds for the board analysis.
	if ( ThisBoard->StartRow > (CurrentRow - 1) ) ThisBoard->StartRow = (CurrentRow == 0)? 0: (CurrentRow - 1);
	if ( ThisBoard->StartCol > (CurrentCol - 1) ) ThisBoard->StartCol = (CurrentCol == 0)? 0: (CurrentCol - 1);
	if ( PlayMove(ThisPlay) == ACROSS ){
		if ( ThisBoard->EndRow < (CurrentRow + 1) ) ThisBoard->EndRow = (CurrentRow == MAX - 1)? MAX - 1: (CurrentRow + 1);
		if ( ThisBoard->EndCol < (CurrentCol + PlayLength) ) ThisBoard->EndCol = (CurrentCol + PlayLength - 1 == MAX - 1)? MAX - 1: (CurrentCol + PlayLength);
	}
	if ( PlayMove(ThisPlay) == DOWN ){
		if ( ThisBoard->EndRow < (CurrentRow + PlayLength) ) ThisBoard->EndRow = (CurrentRow + PlayLength - 1 == MAX - 1)? MAX - 1: (CurrentRow + PlayLength);
		if ( ThisBoard->EndCol < (CurrentCol + 1) ) ThisBoard->EndCol = (CurrentCol == MAX - 1)? MAX - 1: (CurrentCol + 1);
	}
	// Place the tiles that need to be on the board.
	CurrentSquare = &(ThisBoard->Block[CurrentRow][CurrentCol]);
	TheWord = PlayMainWord(ThisPlay);
	for (count = 0; count < PlayLength; count++) {
		if ( PlayMove(ThisPlay) == ACROSS ) {
			if ( SquarePlaced( CurrentSquare ) == SPACE ) {
				SquarePlaceChar( CurrentSquare, PlayMaker, TheWord[count] );
				SquareMakeValidAcrossPivot(SquareUp(CurrentSquare));
				SquareMakeValidAcrossPivot(SquareDown(CurrentSquare));
				SquareMakeValidDownPivot(SquareLeft(CurrentSquare));
				SquareMakeValidDownPivot(SquareRight(CurrentSquare));
			}
			CurrentSquare = SquareRight( CurrentSquare );
		}
		else {
			if ( SquarePlaced( CurrentSquare ) == SPACE) {
				SquarePlaceChar( CurrentSquare, PlayMaker, TheWord[count]);
				SquareMakeValidAcrossPivot(SquareUp(CurrentSquare));
				SquareMakeValidAcrossPivot(SquareDown(CurrentSquare));
				SquareMakeValidDownPivot(SquareLeft(CurrentSquare));
				SquareMakeValidDownPivot(SquareRight(CurrentSquare));
			}
			CurrentSquare = SquareDown( CurrentSquare );
		}		
	}
	BoardArrayUDawgUpdateBlockPivotLetters( ThisBoard, Doggy );
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct game {
	Board GameBoard;
	int NumberOfPlays;
	int NumberOfPlayers;
	// PlayerOne is always you.
	Player WhoIsUp;
	PlayListPtr TheMadePlays;
	GameType HowToPlay;
	int PlayerOneScore;
	int PlayerTwoScore;
	int PlayerThreeScore;
	int PlayerFourScore;
	ArrayUDawgPtr Lexicon;
};

typedef struct game Game;
typedef Game* GamePtr;

void GameInit( GamePtr ThisGame, GameType PlayLikeThis, Player TheFirst, ArrayUDawgPtr English ) {
	ThisGame->HowToPlay = PlayLikeThis;
	ThisGame->NumberOfPlayers = 2;
	ThisGame->WhoIsUp = TheFirst;
	ThisGame->NumberOfPlays = 0;
	ThisGame->TheMadePlays = PlayListInit();
	BoardInit(&ThisGame->GameBoard, ThisGame->NumberOfPlayers);
	ThisGame->PlayerOneScore = 0;
	ThisGame->PlayerTwoScore = 0;
	ThisGame->PlayerThreeScore = 0;
	ThisGame->PlayerFourScore = 0;
	ThisGame->Lexicon = English;
}

Player GameWhoIsUp( GamePtr ThisGame ) {
	return ThisGame->WhoIsUp;
}

void GameFetchNextPlay( GamePtr ThisGame ) {
	Bool FetchData = TRUE;
	Bool PassOverRide = FALSE;
	int X;
	int PlaySelect;
	char IsItPass = 0;
	// Let's assume that the user will never enter more then 49 chars.
	char RackLetters[50] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
	if ( ThisGame->HowToPlay == ONLINE) {
		if ( ThisGame->WhoIsUp == PLAYERONE ) {
			printf( "------------------------\n" );
			printf( "||YOUR SCORE    ||%4d||\n", ThisGame->PlayerOneScore );
			printf( "||--------------||----||\n" );
			printf( "||NEMESIS SCORE ||%4d||\n", ThisGame->PlayerTwoScore );
			printf( "------------------------\n\n" );
			BoardOutput( &(ThisGame->GameBoard) );
			printf( "\nIt Is YOUR Turn, Choose Well...\n\n" );
			while (FetchData == TRUE) {
				printf( "Do You Pass? (y/n): " );
				gets( RackLetters );
				IsItPass = RackLetters[0];
				if( IsItPass == 'Y' || IsItPass == 'y' || IsItPass == 'N' || IsItPass == 'n' ) FetchData = FALSE;
			}
			FetchData = TRUE;
			if ( IsItPass != 'Y' && IsItPass != 'y') {
				PlayPtr CopiedPlay = PlayInit();
				PlayListPtr OptionalPlays = PlayListInit();
				// if not then input rack. - check that it is 7 or less
				while (FetchData == TRUE) {
					printf( "Please Enter Your Tile Rack: " );
					gets( RackLetters );
					if( (signed int)strlen( RackLetters ) >= 1 && (signed int)strlen( RackLetters ) <= MAXTILES ) {
						MakeMeAllCapital( RackLetters );
						Alphabetize( RackLetters );
						FetchData = FALSE;
						for ( X = 0; X < (signed int)strlen( RackLetters ); X++ ) {
							if ( RackLetters[X] != '?' && !(RackLetters[X] >= 'A' && RackLetters[X] <= Zz) ) {
								FetchData = TRUE;
								break;
							}
						}
					}
				}
				FetchData = TRUE;
				// Generate Plays and sort them.
				BoardArrayUDawgDiscoverValidPlays( &(ThisGame->GameBoard), OptionalPlays, RackLetters, (signed int)strlen( RackLetters ), ThisGame->Lexicon, PLAYERONE );
				// Sort PlayList, Output PlayList and then make the user choose one
				PlayListQSortByPointValue( OptionalPlays );
				PlayListOutput( OptionalPlays );
				while (FetchData == TRUE) {
					printf( "Please Enter The p# That You Choose(1000000 = One Million = Pass Override): " );
					gets(RackLetters);
					PlaySelect = StringToInt(RackLetters);
					if( PlaySelect == 1000000 ) {
						PassOverRide = TRUE;
						break;
					}
					FetchData = FALSE;
					if( !(PlaySelect >= 1 && PlaySelect <= PlayListSize( OptionalPlays )) ) {
						FetchData = TRUE;
						continue;
					}
					PlayCopy( CopiedPlay, PlayListGetPlay( OptionalPlays, PlaySelect )  );
					printf( "\n" );
					PlayOutput( CopiedPlay, PlaySelect );
					FetchData = TRUE;
					while (FetchData == TRUE) {
						printf( "\nThis Is The Play That You Have Chosen, Would You Like To Stick With It? (Y/N): " );
						gets( RackLetters );
						IsItPass = RackLetters[0];
						if( IsItPass == 'Y' || IsItPass == 'y' || IsItPass == 'N' || IsItPass == 'n' ) FetchData = FALSE;
					}
					if( IsItPass == 'N' || IsItPass == 'n' ) FetchData = TRUE;
				}
				FetchData = TRUE;
				// Make the play
				if( PassOverRide == FALSE) {
					BoardMakeThisPlay( &(ThisGame->GameBoard), CopiedPlay, PLAYERONE, ThisGame->Lexicon );
					ThisGame->PlayerOneScore += PlayPointValue( CopiedPlay );
					PlayListAppend( ThisGame->TheMadePlays, CopiedPlay );
				}
				ClearPlayList( OptionalPlays );
				free( OptionalPlays );
			}
			ThisGame->WhoIsUp = PLAYERTWO;
		}
		else {
			printf( "------------------------\n" );
			printf( "||YOUR SCORE    ||%4d||\n", ThisGame->PlayerOneScore );
			printf( "||--------------||----||\n" );
			printf( "||NEMESIS SCORE ||%4d||\n", ThisGame->PlayerTwoScore );
			printf( "------------------------\n" );
			BoardOutput( &(ThisGame->GameBoard) );
			printf( "\nIt Is NOT YOUR turn, Deal With It...\n\n" );
			while (FetchData == TRUE) {
				printf( "Does The Nemesis Pass? (Y/N): " );
				gets( RackLetters );
				IsItPass = RackLetters[0];
				if( IsItPass == 'Y' || IsItPass == 'y' || IsItPass == 'N' || IsItPass == 'n' ) FetchData = FALSE;
			}
			FetchData = TRUE;
			if ( IsItPass != 'Y' && IsItPass != 'y') {
				PlayPtr CopiedPlay = PlayInit();
				PlayListPtr OptionalPlays = PlayListInit();
				// if not then input rack. - check that it is 7 or less
				while (FetchData == TRUE) {
					printf( "Enter The Tiles That Nemesis Has Placed, Use '?' For Letters Of 0 Value: " );
					gets( RackLetters );
					if( (signed int)strlen( RackLetters ) >= 1 && (signed int)strlen( RackLetters ) <= MAXTILES ) {
						MakeMeAllCapital( RackLetters );
						Alphabetize( RackLetters );
						FetchData = FALSE;
						for ( X = 0; X < (signed int)strlen( RackLetters ); X++ ) {
							if ( RackLetters[X] != EMPTY && !(RackLetters[X] >= Aa && RackLetters[X] <= Zz) ) {
								FetchData = TRUE;
								break;
							}
						}
					}
				}
				FetchData = TRUE;
				// Generate Plays and sort them.
				BoardArrayUDawgDiscoverValidPlays( &(ThisGame->GameBoard), OptionalPlays, RackLetters, (signed int)strlen( RackLetters ), ThisGame->Lexicon, PLAYERTWO );
				// Sort PlayList, Output PlayList and then make the user choose one
				PlayListQSortByPointValue( OptionalPlays );
				PlayListOutput( OptionalPlays );
				while (FetchData == TRUE) {
					printf( "Enter The Corresponding p# To The Nemesis Play(1000000 = One Million = Pass Override): " );
					gets(RackLetters);
					PlaySelect = StringToInt(RackLetters);
					if( PlaySelect == 1000000 ) {
						PassOverRide = TRUE;
						break;
					}
					FetchData = FALSE;
					if( !(PlaySelect >= 1 && PlaySelect <= PlayListSize( OptionalPlays )) ) {
						FetchData = TRUE;
						continue;
					}
					PlayCopy( CopiedPlay, PlayListGetPlay( OptionalPlays, PlaySelect ) );
					printf( "\n" );
					PlayOutput( CopiedPlay, PlaySelect );
					FetchData = TRUE;
					while (FetchData == TRUE) {
						printf( "\nIs This Really The Nemesis Play, Double Check Please? " );
						gets( RackLetters );
						IsItPass = RackLetters[0];
						if( IsItPass == 'Y' || IsItPass == 'y' || IsItPass == 'N' || IsItPass == 'n' ) FetchData = FALSE;
					}
					if( IsItPass == 'N' || IsItPass == 'n' ) FetchData = TRUE;
				}
				FetchData = TRUE;
				// Make the play for the Nemesis.
				if( PassOverRide == FALSE) {
					BoardMakeThisPlay( &(ThisGame->GameBoard), CopiedPlay, PLAYERTWO, ThisGame->Lexicon );
					ThisGame->PlayerTwoScore += PlayPointValue( CopiedPlay );
					PlayListAppend( ThisGame->TheMadePlays, CopiedPlay );
				}
				ClearPlayList( OptionalPlays );
				free( OptionalPlays );
			}
			ThisGame->WhoIsUp = PLAYERONE;
		}
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

int main() {
	// Fill the ArrayUnode structure to be placed into the ArrayUDawg.
	FILE *Data;
	unsigned int *OUDAWG;
	int X;
	unsigned int NumberOfNodes = 0;
	int PlayCounter;
	clock_t start_clock;
	ArrayUDawgPtr Adoggy;
	Game WeArePlayingThisGame;
	
	printf( "Begin.\n" );
	Data = fopen( OUDAWG_DATA,"rb" );
	assert ( Data != NULL );
	fread( &NumberOfNodes, 4, 1, Data );
	printf( "NumberOfNodes |%u|\n", NumberOfNodes );
	// Allocate the space for the OUDAWG.
	OUDAWG = (unsigned int *)malloc( sizeof( unsigned int ) * (NumberOfNodes + 1) );
	start_clock = clock();
	printf("Filling Udawg Array...  Patience Is A Virtue. |%d| is the size of each ArrayUnode, %f MB is the size of the whole ArrayUDawg\n", sizeof( unsigned int ), (NumberOfNodes + 1)*sizeof( unsigned int )/1024/(double)1024 );
	// NumberOfNodes written in the data file does not include the NULL node written in the first 4 bytes of the data file so read one more node exactly.
	for ( X = 0; (unsigned int)X <= NumberOfNodes; X++ ) {
		fread( &(OUDAWG[X]), 4, 1, Data );
	}
	fclose( Data );
	printf("Filling Of The %d Node OUDAWG Array Complete In Exactly... |%8.7g| Seconds.\n\n\n", NumberOfNodes, ((clock() - start_clock)/(double)(CLOCKS_PER_SEC) ) );
	Adoggy = ArrayUDawgInit( OUDAWG );
	GameInit( &WeArePlayingThisGame, ONLINE, PLAYERONE, Adoggy );
	// I wil assume that the game will have a maximum of 100 plays.  From experience, this is over-compensation.
	for( PlayCounter = 0; PlayCounter < 100; PlayCounter++ ) {
		GameFetchNextPlay( &WeArePlayingThisGame );
	}
	return 0;
}
