// MotsFleches.cpp : Defines the class behaviors for the application.
//
// mettre sauvegarde
// mettre mélange aléatoire des mots
//

#include "stdafx.h"
#include "MotsFleches.h"

#include "MainFrm.h"
#include "MotsFlechesDoc.h"
#include "MotsFlechesView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

extern "C" Record;
int Record = 539;

#define THREAD_STOP 1
#define THREAD_AUTOMATIC 2

unsigned int PRIORITY = 1;
void OutputStr(char	*str);
void Compute(void);
int Statistics(int niveau);
//void Croise(int niveau);
extern "C" void ASMCroise(void);
extern "C" void Solution(void);
extern "C" void DisplayStatus(char *);

extern "C" int volatile THREAD_EVENT;
extern "C" int volatile CumulTime;

#define DURATION 0		// temps en millisecondes

int THREAD_ACTIVE1 = 0;		// true if Thread 1 is active
int THREAD_ACTIVE2 = 0;		// true if Thread 2 is active
int volatile THREAD_EVENT = 0;
HANDLE	CURRENT_THREAD1 = 0;
HANDLE	CURRENT_THREAD2 = 0;
int volatile CumulTime;
CWinThread *thread1 = NULL;
CWinThread *thread2 = NULL;
int FORCE_QUIT = 0;

/////////////////////////////////////////////////////////////////////////////
// CMotsFlechesApp

BEGIN_MESSAGE_MAP(CMotsFlechesApp, CWinApp)
	//{{AFX_MSG_MAP(CMotsFlechesApp)
	ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
	ON_COMMAND(ID_STOP, OnStop)
	ON_UPDATE_COMMAND_UI(ID_STOP, OnUpdateStop)
	//}}AFX_MSG_MAP
	// Standard file based document commands
	ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
	ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
	// Standard print setup command
	ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMotsFlechesApp construction

CMotsFlechesApp::CMotsFlechesApp()
{
	// TODO: add construction code here,
	// Place all significant initialization in InitInstance
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CMotsFlechesApp object

CMotsFlechesApp theApp;

/////////////////////////////////////////////////////////////////////////////
// CMotsFlechesApp initialization

BOOL CMotsFlechesApp::InitInstance()
{
	AfxEnableControlContainer();

	// Standard initialization
	// If you are not using these features and wish to reduce the size
	//  of your final executable, you should remove from the following
	//  the specific initialization routines you do not need.

#ifdef _AFXDLL
	Enable3dControls();			// Call this when using MFC in a shared DLL
#else
	Enable3dControlsStatic();	// Call this when linking to MFC statically
#endif

	// Change the registry key under which our settings are stored.
	// TODO: You should modify this string to be something appropriate
	// such as the name of your company or organization.
	SetRegistryKey(_T("Local AppWizard-Generated Applications"));

	LoadStdProfileSettings();  // Load standard INI file options (including MRU)

	// Register the application's document templates.  Document templates
	//  serve as the connection between documents, frame windows and views.

	CSingleDocTemplate* pDocTemplate;
	pDocTemplate = new CSingleDocTemplate(
		IDR_MAINFRAME,
		RUNTIME_CLASS(CMotsFlechesDoc),
		RUNTIME_CLASS(CMainFrame),       // main SDI frame window
		RUNTIME_CLASS(CMotsFlechesView));
	AddDocTemplate(pDocTemplate);

	// Parse command line for standard shell commands, DDE, file open
	CCommandLineInfo cmdInfo;
	ParseCommandLine(cmdInfo);

	// Dispatch commands specified on the command line
	if (!ProcessShellCommand(cmdInfo))
		return FALSE;

	//TrayMessage (NIM_ADD, NULL);
	// The one and only window has been initialized, so show and update it.
	m_pMainWnd->ShowWindow(SW_SHOW);
	m_pMainWnd->UpdateWindow();

//	OutputStr("OK\n");

	Compute();

	return TRUE;
}

#if 0
void TrayMessage (UINT message, LPCSTR prompt)
{
	NOTIFYICONDATA tnd;

	switch (message) {
	case NIM_ADD :
		//WINDOWS95_TRAY_ADD = 0;
		tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
		break;
	case NIM_MODIFY :
		tnd.uFlags = NIF_TIP;
		break;
	case NIM_DELETE :
		tnd.uFlags = 0;
	}

	if (prompt)
		lstrcpy (tnd.szTip, prompt);
	else
		lstrcpy (tnd.szTip, "Sum95");

	tnd.uID = 352;
	tnd.cbSize = sizeof(tnd);
	tnd.hWnd = m_pMainWnd->m_hWnd;
	tnd.uCallbackMessage = MYWM_TRAYMESSAGE;
	//tnd.hIcon = LoadIcon (IDR_MAINFRAME);
	tnd.hIcon = LoadIcon (AFX_IDI_STD_MDIFRAME);

	if (Shell_NotifyIcon(message, &tnd)) return;

// The shell command failed.  This could be due to running
// as a Windows 95 service.  Set a flag to try and add the
// icon at a later time

	if (message == NIM_ADD)
		WINDOWS95_TRAY_ADD = 1;
}
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
		// No message handlers
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

// App command to run the dialog
void CMotsFlechesApp::OnAppAbout()
{
	CAboutDlg aboutDlg;
	aboutDlg.DoModal();
}

/////////////////////////////////////////////////////////////////////////////
// CMotsFlechesApp message handlers
#define NumLines 48
#define WidthLine 128

char line[NumLines][WidthLine] = {0};

void OutputStr(char	*str)
{
	char *p = line[0] + strlen (line[0]);
	char *q = line[0];
	for ( ; *str; str++) {
		if (*str == '\n')
		{
			*p = 0;
			// Scroll the line on the screen
			memmove (line[1], line[0], (NumLines-1)*WidthLine);
			memset(line[0], 0, WidthLine);
			p = q;
		}
		else
		if (p - q < WidthLine-1)
		{
			*p++ = *str;
		}
	}
	*p = 0;
	if (!FORCE_QUIT)
	{
		CWnd* pMainWnd = AfxGetThread()->m_pMainWnd;
		//m_pMainWnd->RedrawWindow();
		pMainWnd->RedrawWindow();
	}
}

static char *File = "SOLUTION.TXT";

int OutputFile(char	*msg)
{
	static	time_t	last_time = 0;
	time_t	this_time;
	FILE *fd;

/* Open file, position to end */

	fd = fopen (File, "at");
	if (fd == NULL)
	{
		OutputStr("Error opening the results file.\n");
		return (FALSE);
	}

/* If it has been at least 5 minutes since the last time stamp */
/* was output, then output a new timestamp */

	time (&this_time);
	if (this_time - last_time > 300) {
		char	buf[32];
		last_time = this_time;
		buf[0] = '[';
		strcpy (buf+1, ctime (&this_time));
		buf[25] = ']';
		buf[26] = '\n';
		fwrite (buf, 27, 1, fd);
	}

/* Output the message */

	if (fwrite (msg, strlen (msg), 1, fd) < 0) return (FALSE);
	fclose (fd);
	return (TRUE);
}

void OutputBoth(char	*str)
{
	OutputStr(str);
	OutputFile(str);
}


void SetPriority(HANDLE thread)
{
	SetPriorityClass (GetCurrentProcess (),
		(PRIORITY < 2 || PRIORITY > 6) ?
			NORMAL_PRIORITY_CLASS :
			IDLE_PRIORITY_CLASS);

	SetThreadPriority (thread,
		(PRIORITY == 1) ? THREAD_PRIORITY_IDLE :
		(PRIORITY == 2 || PRIORITY == 7) ? THREAD_PRIORITY_LOWEST :
		(PRIORITY == 3 || PRIORITY == 8) ? THREAD_PRIORITY_BELOW_NORMAL :
		(PRIORITY == 4 || PRIORITY == 9) ? THREAD_PRIORITY_NORMAL :
		(PRIORITY == 5 || PRIORITY == 10) ? THREAD_PRIORITY_ABOVE_NORMAL :
		THREAD_PRIORITY_HIGHEST);
/*	if (CPU_AFFINITY != 99 && !isWindows95 ())
		SetThreadAffinityMask (thread, 1 << CPU_AFFINITY);*/
}

UINT threadTimer(LPVOID stuff)
{
	THREAD_ACTIVE2 = 1;
	CURRENT_THREAD2 = GetCurrentThread();
	SetPriority(CURRENT_THREAD2);
	// infinite loop
	for(;;)
	{
		for (int j = 0; j < 1000/100; ++j)
		{
			Sleep(100);
			if (THREAD_EVENT & THREAD_STOP)
			{
				THREAD_ACTIVE2 = 0;
				return 0;
			}
			CumulTime += 100;
#if DURATION
			if (CumulTime >= DURATION)
			{
				THREAD_EVENT |= THREAD_AUTOMATIC;
				CumulTime = 0;
			}
#endif
		}
	}
}

UINT threadCompute(LPVOID stuff)
{
// Set thread-active flags
	THREAD_ACTIVE1 = 1;

/* Set the process/thread priority */
	CURRENT_THREAD1 = GetCurrentThread();
	SetPriority(CURRENT_THREAD1);

	// put the computation here

	ASMCroise();

// Free memory used in the assembly code
// Output informative message

	if (THREAD_EVENT & THREAD_STOP)
	{
		OutputStr ("Execution halted.\n");
	}
	else
	{
		//
		OutputStr ("Computation finished.\n");
	}

// Clear thread-active flags
	THREAD_ACTIVE1 = 0;
	while (THREAD_ACTIVE2)
	{
		THREAD_EVENT = THREAD_STOP;
		Sleep (50);
	}
	//THREAD_EVENT = 0;
	//theApp.title ("IDLE");
// Thread complete
	return (0);
}

void Stop(void)
{
	// TODO: Add your command handler code here
	THREAD_EVENT = THREAD_STOP;
	SetPriorityClass (GetCurrentProcess (), NORMAL_PRIORITY_CLASS);
	::SetThreadPriority(CURRENT_THREAD1, THREAD_PRIORITY_ABOVE_NORMAL);
	::SetThreadPriority(CURRENT_THREAD2, THREAD_PRIORITY_ABOVE_NORMAL);
}

int CMotsFlechesApp::ExitInstance() 
{
	// TODO: Add your specialized code here and/or call the base class
	if (THREAD_ACTIVE1|THREAD_ACTIVE2)
	{
		FORCE_QUIT = 1;
		Stop();
		while (THREAD_ACTIVE1|THREAD_ACTIVE2)
		{
			THREAD_EVENT = THREAD_STOP;
			Sleep (50);
		}
	}
	
	return CWinApp::ExitInstance();
}

// code de croise.C

#define N 13
#define NBMOTS 24

typedef struct
{
	int	len;
	int pos;
	int dir;
	int croise[5];
} ORDER;

extern "C" ORDER ordre[];
extern "C" int Window[];
int Window[NBMOTS];


#if 0
ORDER ordre[NBMOTS] =
{
	{ 9,N*6+2,1,	6,4,1,5,7 },		//0
	{ 9,N*2+6,N,	2,3,-1,-1,-1 },		//1
	{ 9,N*2+2,1,	6,19,20,7,-1 },		//2
	{ 9,N*10+2,1,	4,22,23,5,-1 },		//3

	{ 7,N*6+3,N,	16,12,-1,-1,-1 },	//4
	{ 7,N*6+9,N,	17,13,-1,-1,-1 },	//5
	{ 7,N*0+2,N,	10,14,-1,-1,-1 },	//6
	{ 7,N*0+10,N,	11,15,-1,-1,-1 },	//7

	{ 7,N*0+0,N,	10,14,-1,-1,-1 },	//8
	{ 7,N*0+12,N,	11,15,-1,-1,-1 },	//9

	{ 6,N*0+0,1,	18,-1,-1,-1,-1 },	//10
	{ 6,N*0+7,1,	19,-1,-1,-1,-1 },	//11

	{ 6,N*12+0,1,	20,22,-1,-1,-1 },	//12
	{ 6,N*12+7,1,	23,21,-1,-1,-1 },	//13

	{ 5,N*4+0,1,	18,-1,-1,-1,-1 },	//14
	{ 5,N*4+8,1,	19,-1,-1,-1,-1 },	//15
	{ 5,N*8+0,1,	20,-1,-1,-1,-1 },	//16
	{ 5,N*8+8,1,	21,-1,-1,-1,-1 },	//17
	{ 5,N*0+4,N,	-1,-1,-1,-1,-1 },	//18
	{ 5,N*0+8,N,	-1,-1,-1,-1,-1 },	//19

	{ 5,N*8+0,N,	-1,-1,-1,-1,-1 },	//20
	{ 5,N*8+12,N,	-1,-1,-1,-1,-1 },	//21

	{ 3,N*10+5,N,	-1,-1,-1,-1,-1 },
	{ 3,N*10+7,N,	-1,-1,-1,-1,-1 }

};

#else
ORDER ordre[NBMOTS] =
{
	{ 9,N*6+2,1,	6,4,1,5,7 },		//0
	{ 9,N*2+6,N,	2,3,-1,-1,-1 },		//1
	{ 9,N*2+2,1,	6,16,17,7,-1 },		//2
	{ 9,N*10+2,1,	4,22,23,5,-1 },		//3

	{ 7,N*6+3,N,	18,12,-1,-1,-1 },	//4
	{ 7,N*6+9,N,	19,13,-1,-1,-1 },	//5
	{ 7,N*0+2,N,	8,14,-1,-1,-1 },	//6
	{ 7,N*0+10,N,	9,15,-1,-1,-1 },	//7

	{ 6,N*0+0,1,	10,16,-1,-1,-1 },	//8
	{ 6,N*0+7,1,	17,11,-1,-1,-1 },	//9

	{ 7,N*0+0,N,	14,-1,-1,-1,-1 },	//10
	{ 7,N*0+12,N,	15,-1,-1,-1,-1 },	//11

	{ 6,N*12+0,1,	20,22,-1,-1,-1 },	//12
	{ 6,N*12+7,1,	23,21,-1,-1,-1 },	//13

	{ 5,N*4+0,1,	16,-1,-1,-1,-1 },	//14
	{ 5,N*4+8,1,	17,-1,-1,-1,-1 },	//15
	{ 5,N*0+4,N,	-1,-1,-1,-1,-1 },	//16
	{ 5,N*0+8,N,	-1,-1,-1,-1,-1 },	//17

	{ 5,N*8+0,1,	20,-1,-1,-1,-1 },	//18
	{ 5,N*8+8,1,	21,-1,-1,-1,-1 },	//19
	{ 5,N*8+0,N,	-1,-1,-1,-1,-1 },
	{ 5,N*8+12,N,	-1,-1,-1,-1,-1 },

	{ 3,N*10+5,N,	-1,-1,-1,-1,-1 },
	{ 3,N*10+7,N,	-1,-1,-1,-1,-1 }

};

#endif

extern "C" char tableau[];
char tableau[N*N];
int nbmots = 0;
#define MAX_MOTS 1600
#define MAX_LEN 9

typedef struct _MOT
{
	_MOT *next;
	char used;
	char mot[MAX_LEN+1+1];
} MOT;

extern "C" MOT *Mots[];
extern "C" int NbMots[];

MOT Mot[MAX_MOTS];

// pointeurs sur les longueurs et les premiers mots
int NbMots[MAX_LEN+1];
MOT *Mots[MAX_LEN+1];

char memo[NBMOTS][MAX_LEN];

extern "C" int value[];
int value[256];



void store(char *p)
{
	int len;
	char *q;

	len = strlen(p);
	if (len == 0) return;
	
	q = p;
	while (*q && *q != '=')
	{
		++q;
	}
	if (*q == '=')
	{
		*q++ = 0;
		len = strlen(p);
	}
	else
	{
		q = NULL;
	}
	
	if (len > MAX_LEN)
	{
		OutputBoth("Mot trop grand\n");
		exit(1);
	}
	if (nbmots >= MAX_MOTS)
	{
		OutputBoth("Trop de mots\n");
		exit(1);
	}

	if (Mots[len] == NULL)
	{
		Mots[len] = &Mot[nbmots];
	}
	++NbMots[len];
	
	strcpy(Mot[nbmots].mot,p);
	Mot[nbmots].used = 0;
	Mot[nbmots].next = NULL;

	if (q != NULL)
	{
		int i;
		for (i = 0;i < nbmots;++i)
		{
			if (strcmp(Mot[i].mot, q) == 0)
			{
				if (Mot[i].next != NULL)
				{
					OutputBoth("Double\n");
					exit(1);
				}
				Mot[i].next = &Mot[nbmots];
				break;
			}
		}
		if (i >= nbmots)
		{
			OutputBoth("Mot non trouvé\n");
			exit(1);
		}
	}	
	++nbmots;
}

int parse(char *name)
{
	FILE *in;
	char str[200];
	int c,n;

	in = fopen(name,"rb");
	if (in == NULL)
	{
		OutputBoth("Unable to open\n");
		return 1;
	}

	for (n = 0;n <= MAX_LEN;++n)
	{
		NbMots[n] = 0;
		Mots[n] = NULL;
	}

	n = 0;
	while (1)
	{
		c = fgetc(in);
		if (c == EOF)
		{
			str[n] = 0;
			store(str);
			break;
		}
		if (c == 0x0D)
		{
			str[n] = 0;
			store(str);
			n = 0;
		}
		if (c > 0x20)
		{
			str[n] = c;
			++n;
		}
	}

	fclose(in);
	return 0;
}

int NbTri;

char *Tries[NBMOTS];

char MotsTries[NBMOTS][MAX_LEN+1];

void InsertTri(char *name)
{
	int i,j;
	for (i = 0;i < NbTri;++i)
	{
		if (strcmp(Tries[i], name) > 0)
		{
			// on insère le nom
			for (j = NbTri-1; j >= i;--j)
			{
				Tries[j+1] = Tries[j];
			}
			Tries[i] = name;
			++NbTri;
			return;
		}
	}
	Tries[NbTri] = name;
	++NbTri;
}

void Solution(void)
{
	int i,j;
	int sum;
//	int sum;
	char *p,*q;
	char buf[256];

/*	sum = 0;
	for (i = 0;i < N*N;++i)
	{
		sum += value[tableau[i]];
	}
	if (sum < Record)
	{
		return;
	}
	Record = sum;*/

	sprintf(buf,"Somme=%d\n",Record);
	OutputBoth(buf);

	p = tableau;
	for (i = 0;i < N;++i)
	{
		q = buf;
		sum = 0;
		for (j = 0;j < N;++j)
		{
			if (*p)
			{
				*q++ = *p;
				sum += value[*p];
			}
			else
			{
				*q++ = ' ';
			}
			++p;
		}
		sprintf(q,"  :%d\n",sum);
		//strcpy(q, "\n");
		OutputFile(buf);
	}

	NbTri = 0;
	
	/* tri des mots présents */
	for (i = 0; i < NBMOTS;++i)
	{
		p = &tableau[ordre[i].pos];
		for (j = 0; j < ordre[i].len; ++j)
		{
			MotsTries[i][j] = *p;
			p += ordre[i].dir;
		}
		MotsTries[i][j] = 0;
		InsertTri(MotsTries[i]);
	}

	for (i = 0; i < NBMOTS;++i)
	{
		sprintf(buf,">%s\n", Tries[i]);
		OutputFile(buf);
	}
}

void DisplayStatus(char *str)
{
	char buf[256];
	sprintf(buf, "%s\n", str);
	OutputStr(buf);
}

//unsigned int pattern[MAX_LEN+1][MAX_LEN+1];

void initmots(void)
{
	MOT *m;
	int length,count;
	for (length = 0;length <= MAX_LEN; ++length)
	{
		m = Mots[length];
		count = NbMots[length];
		while(count)
		{
			//int i;
			if (strlen(m->mot) != length)
			{
				OutputBoth("Bad length\n");
				exit(1);
			}
			/*
			for (i = 0;i < length;++i)
			{
				pattern[length][i] |= 1<<(m->mot[i] - 'A');
			}*/
			++m;
			--count;
		}
	}
}

#if 0
int VerifyWord(int niveau)
{
	int length,dir;
	char *pos,*p;
	int flag,j;
	MOT *m;
	int count;

	if (niveau < 0 || niveau >= NBMOTS)
	{
		OutputBoth("Bug\n");
		exit(1);
	}
	length = ordre[niveau].len;
	pos = &tableau[ordre[niveau].pos];
	dir = ordre[niveau].dir;

// test rapide si le mot rentre ou non
	// jamais exécuté ???
#if 0
	p = pos;
	for (j = 0;j < length;++j)
	{
		if (*p)
		{
			if ((pattern[length][j] & (1<<(*p-'A'))) == 0)
			{
				return 0;
			}
		}
		p += dir;
	}
#endif
	m = Mots[length];
	count = NbMots[length];
	while(count)
	{
		if (m->used == 0)
		{
			// bonne longueur ?
			flag = 0;
			p = pos;
			for (j = 0;j < length;++j)
			{
				if (*p)
				{
					if (*p != m->mot[j])
					{
						flag = 1;
						break;
					}
				}
				p += dir;
			}
			if (flag == 0)
			{
				// un mot rentre !!!!
				return 1;
			}
		}
		++m;
		--count;
	}
	return 0;
}

void Croise(int niveau)
{
	int length,dir;
	char *pos,*p;
	int flag,j;
	MOT *m;
	int count;

	if (niveau >= NBMOTS)
	{
		solution();
		return;
	}
	if (THREAD_EVENT & THREAD_STOP)
	{
		return;
	}
	length = ordre[niveau].len;
	pos = &tableau[ordre[niveau].pos];
	dir = ordre[niveau].dir;

	if (niveau <= 3)
	{
		// we reset the time
		CumulTime = 0;
		THREAD_EVENT = 0;
	}
	if (THREAD_EVENT & THREAD_AUTOMATIC)
	{
		return;
	}

	//printf("%d %d %d\n",length,ordre[niveau].pos,dir);

	p = pos;
	for (j = 0;j < length;++j)
	{
		memo[niveau][j] = *p;
		p += dir;
	}
		
	m = Mots[length];
	count = NbMots[length];

#if 0
	if (niveau >= 2 && length > 5)
	{
#define MAJORE 50
		// on majore le nombre de mots, pour éviter trop de calculs...
		if (count > MAJORE)
		{
			count = MAJORE;
		}
	}
#endif

	while(count)
	{
		if (m->used == 0)
		{
			// bonne longueur ?
			flag = 0;
			p = pos;
			for (j = 0;j < length;++j)
			{
				if (*p)
				{
					if (*p != m->mot[j])
					{
						flag = 1;
						break;
					}
				}
				p += dir;
			}
			if (flag == 0)
			{
				// le mot rentre
				p = pos;
				for (j = 0;j < length;++j)
				{
					*p = m->mot[j];
					p += dir;
				}
				m->used = 1;

				if (niveau == 0)
				{
					if (THREAD_EVENT & THREAD_STOP)
					{
						return;
					}
					{
						char buf[256];
						sprintf(buf, "%s (%d/%d)\n", m->mot, m-Mots[length], NbMots[length]);
						OutputStr(buf);
					}
				}
				// avant d'aller plus loin, on vérifie qu'on peut rentrer d'autres mots
				flag = 1;
				for (j = 0;j < 5;++j)
				{
					if (ordre[niveau].croise[j] >= 0)
					{
						if (VerifyWord(ordre[niveau].croise[j]) == 0)
						{
							flag = 0;
							break;
						}
					}
				}
				if (flag)
				{
					Croise(niveau+1);
				}
				m->used = 0;
				p = pos;
				for (j = 0;j < length;++j)
				{
					*p = memo[niveau][j];
					p += dir;
				}
				//solution();
			}
		}
		++m;
		--count;
	}

}

#endif

void Compute(void)
{
	THREAD_EVENT = 0;

/*
	Initialisation du code
 */
	int i;
	if (parse("DICO.TXT"))
	{
		return;
	}
	for (i = 0;i < 256;++i)
	{
		value[i] = 0;
	}
	value['N'] = 5;
	value['O'] = 6;
	value['C'] = 4;
	value['T'] = 6;
	value['A'] = 4;
	value['M'] = 2;
	value['B'] = 1;
	value['U'] = 3;
	value['L'] = 1;
	value['E'] = 2;

	initmots();
	
	for (i = 0;i < NBMOTS;++i)
	{
		int n;
		//char buf[256];
		n = Statistics(i);
		Window[i] = n;
		/*sprintf(buf, "Level %d: %d\n",i,n);
		OutputBoth(buf);*/
	}
	// on réserve une pile de 32Ko...
	thread1 = AfxBeginThread(threadCompute, NULL, THREAD_PRIORITY_NORMAL);
	thread2 = AfxBeginThread(threadTimer, NULL, THREAD_PRIORITY_NORMAL);
}


void CMotsFlechesApp::OnStop() 
{
	// TODO: Add your command handler code here
	Stop();	
}

void CMotsFlechesApp::OnUpdateStop(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->Enable ((THREAD_ACTIVE1|THREAD_ACTIVE2) && !(THREAD_EVENT & THREAD_STOP));

}


/*
	Statistics
*/
int RecurseStatistics(int niveau)
{
	int length,dir;
	char *pos,*p;
	int j;
	MOT *m;
	int count;
	int rec, record;

	length = ordre[niveau].len;
	pos = &tableau[ordre[niveau].pos];
	dir = ordre[niveau].dir;

	record = 0;
	m = Mots[length];
	count = NbMots[length];
	while(count)
	{
		rec = 0;
		// bonne longueur ?
		p = pos;
		for (j = 0;j < length;++j)
		{
			if (*p == 0)
			{
				rec += value[m->mot[j]];
			}
			p += dir;
		}

		if (rec > record)
		{
			record = rec;
		}
		++m;
		--count;
	}
	if (niveau < NBMOTS-1)
	{
		record += RecurseStatistics(niveau+1);
	}
	return record;
}

int Statistics(int niveau)
{
	int length,dir;
	char *pos;
	int i;
	int rec;

	if (niveau < 0 || niveau >= NBMOTS)
	{
		return -1;
	}
	if (niveau == 23)
	{
		rec = 0;
	}

	// on essaye de compter les lettres
	memset(tableau, 0, sizeof(tableau));
	for (i = 0;i < niveau;++i)
	{
		length = ordre[i].len;
		pos = &tableau[ordre[i].pos];
		dir = ordre[i].dir;
		while(length)
		{
			*pos = 0x7F;
			pos += dir;
			--length;
		}
	}

	rec = RecurseStatistics(niveau);
	memset(tableau, 0, sizeof(tableau));
	return rec;
}
