////////////////////////////////////////////////////////////////////////////////
//
//	COMMENTAIRES
  //
  //	Nom					nonogram.sce
  //	Auteur				Jérôme LABATUT 
  //	Date de création		2019-03-06
  //
  //	Version Scilab			6.0.1
  //	Module Atoms requis		Aucun
  //
  //	Objectif				Résolution de grilles de Nonogram / Picross
  //	
	funcprot(0)
	clearglobal()
	clear()
	
	xdel(winsid())
	tohome()
	clc()
	
	global JEU
  //
//
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
//
//	FONCTIONS MODELE
  //
  //	Initialisation des paramètres
  //
  //	Sélection des informations partielles dans la base de problèmes
  //
  // Assemblage récursif des possibilités pour une direction
  // Assemblages des matrices de possibilités
  //
  //	Calcul de la grille de probabilité
  //
  //	Réduction des possibilités
  //
  // Résolution itérative
//
////////////////////////////////////////////////////////////////////////////////

function affecterParametresModele()
	global JEU
	
	//
end
		
function parametre = donnerNiveau(matricule, nomParametre)
	select matricule
		case 'Tutoriel 1' then		// FRVR ( Tutoriel 1 )
			nomNiveau =			'Tutoriel 1 @ FRVR'
			InformationsCOL =	    [0,	0,	1	]
			InformationsLIG =	    [1]
		case 'Tutoriel 2' then		// FRVR ( Tutoriel 2 )
			nomNiveau =			'Tutoriel 2 @ FRVR'
			InformationsCOL =	    [1,	0,	1	]
			InformationsLIG =	    [1,	1	]
		case 'Tutoriel 3' then		// FRVR ( Tutoriel 3 )
			nomNiveau =			'Tutoriel 3 @ FRVR'
			InformationsCOL =	    [1,	1	]
			InformationsLIG =	    [0; 	...
								2	]
		case 'Tutoriel 4' then		// FRVR ( Tutoriel 4 )
			nomNiveau =			'Tutoriel 4 @ FRVR'
			InformationsCOL =	    [1,	0,	1; 	...
								1,	1,	1	]
			InformationsLIG =	    [1,	1; 	...
								0,	1; 	...
								1,	1	]
		case 'Tutoriel 5' then		// FRVR ( Tutoriel 5 )
			nomNiveau =			'Tutoriel 5 @ FRVR'
			InformationsCOL =	    [0,	1,	3	]
			InformationsLIG =	    [2; 	...
								1; 	...
								1	]
		case 'Tutoriel 6' then		// FRVR ( Tutoriel 6 )
			nomNiveau =			'Tutoriel 6 @ FRVR'
			InformationsCOL =	    [1,	0,	3	]
			InformationsLIG =	    [1,	1; 	...
								0,	1; 	...
								0,	1	]
		case 'Tutoriel 7' then		// FRVR ( Tutoriel 7 )
			nomNiveau =			'Tutoriel 7 @ FRVR'
			InformationsCOL =	    [2,	1,	1,	0,	0; 	...
								1,	1,	1,	0,	1	]
			InformationsLIG =	    [0,	3; 	...
								0,	1; 	...
								0,	0; 	...
								3,	1	]
		case 'Tutoriel 8' then		// FRVR ( Tutoriel 8 )		
			nomNiveau =			'Tutoriel 8 @ FRVR'
			InformationsCOL =	    [0,	1,	1,	0,	0; 	...
								1,	1,	2,	3,	4	]
			InformationsLIG =	    [3,	1; 	...
								0,	2; 	...
								0,	3; 	...
								0,	4	]
		case 'Tutoriel 9' then		// FRVR ( Tutoriel 9 )		
			nomNiveau =			'Tutoriel 9 @ FRVR'
			InformationsCOL =	    [0,	1,	0,	0,	2; 	...
								1,	1,	3,	2,	1	]
			InformationsLIG =	    [2,	1; 	...
								1,	1; 	...
								1,	2; 	...
								1,	2	]
		case '2020-07-15' then		// FRVR ( 2020-07-15 )
			nomNiveau =			'2020-07-15 @ FRVR'
			InformationsCOL =	    [0,	0,	0,	0,	1,	1,	0,	0;	...
								0,	0,	2,	0,	1,	2,	0,	0;	...
								2,	1,	1,	2,	2,	1,	2,	3	]
			
			InformationsLIG =	    [0,	1,	4;	...
								1,	1,	2;	...
								1,	2,	1;	...
								2,	1,	1;	...
								0,	0,	1;	...
								0,	1,	2	]
		case '2020-07-16' then		// FRVR ( 2020-07-16 )
			nomNiveau =			'2020-07-16 @ FRVR'
			InformationsCOL =	    [0,	1,	0,	1,	0,	0,	0;	...
								0,	2,	0,	1,	1,	2,	0;	...
								2,	1,	1,	1,	2,	1,	1	]
			
			InformationsLIG =	    [1,	1,	1; 	...
								0,	2,	1; 	...
								0,	2,	1; 	...
								0,	2,	1; 	...
								0,	0,	2; 	...
								0,	1,	2	]
		case '2020-07-17' then		// FRVR ( 2020-07-17 )
			nomNiveau =			'2020-07-17 @ FRVR'
			InformationsCOL =	    [1,	0,	1,	3,	0,	1,	0,	1,	2;	...
								1,	1,	3,	1,	1,	2,	1,	1,	2	]
			
			InformationsLIG =	    [0,	1,	1,	1; 	...
								0,	0,	2,	2; 	...
								1,	1,	2,	1; 	...
								0,	1,	1,	1; 	...
								0,	2,	1,	1; 	...
								0,	0,	1,	2	]
		case '2020-07-18' then		// FRVR ( 2020-07-18 )
			nomNiveau =			'2020-07-18 @ FRVR'
			InformationsCOL =	    [1,	0,	1,	3,	0,	1,	0,	1,	2;	...
								1,	1,	3,	1,	1,	2,	1,	1,	2	]
			
			InformationsLIG =	    [0,	1,	1,	1;	...
								0,	0,	2,	2;	...
								1,	2,	1,	1;	...
								0,	1,	1,	1;	...
								0,	2,	1,	1;	...
								0,	0,	1,	2	]	
		case '2020-07-19' then		// FRVR ( 2020-07-19 )
			nomNiveau =			'2020-07-19 @ FRVR'
			InformationsCOL =	    [0,	1,	0,	0,	0,	0,	2,	1;	...
								5,	1,	3,	1,	4,	1,	1,	2	]
			
			InformationsLIG =	    [0,	1,	1,	3;	...
								1,	1,	1,	1;	...
								0,	0,	3,	1;	...
								0,	1,	2,	2;	...
								0,	1,	1,	1;	...
								0,	0,	0,	1	]
	end
	
	select nomParametre
		case 'Nom'				then parametre = nomNiveau
		case 'Informations colonnes'	then parametre = InformationsCOL
		case 'Informations lignes'	then parametre = InformationsLIG
	end
end

function Possiblites = donnerPossibilites(Possiblites, Longueur, Informations, LigneCourante)
	global JEU
	
	if (length(Informations) == 1)
		DDL =					Longueur - Informations(1, $) + 1
		
		for l = 1:DDL
			IntervalleGauche =		zeros(1, l - 1)
			Segment =				ones(1, Informations(1, $))
			IntervalleDroit =		zeros(1, DDL - l)
			
			NouvellePossibilite =	[LigneCourante, IntervalleGauche, Segment, IntervalleDroit]
			Possiblites =			[Possiblites; NouvellePossibilite]
		end
	end
	if (length(Informations) > 1)
		DDL =					Longueur - (Informations(1, 1) + 1) + 1
		Segment =					ones(1, Informations(1, 1))
		
		for l = 1:DDL
			IntervalleGauche =		zeros(1, l - 1)
			LigneCourante_E =		[LigneCourante, IntervalleGauche, Segment, 0]
			
			Informations_E =		Informations(1, 2:$)
			Longueur_E =			Longueur - length(IntervalleGauche) - length(Segment) - 1
			
			Possiblites =			donnerPossibilites(Possiblites, Longueur_E, Informations_E, LigneCourante_E)
		end
	end
end
function [PossibilitesLIG, PossibilitesCOL] = donnerMatricesPossibilites(InformationsLIG, InformationsCOL)
	global JEU
	
	for l = 1:JEU.HAUTEUR
		Information =				InformationsLIG(l, InformationsLIG(l, :) ~= 0)
		
		PossibilitesLIG{l} =		donnerPossibilites([], JEU.LARGEUR, Information, [])
	end
	for c = 1:JEU.LARGEUR
		Information =				InformationsCOL(InformationsCOL(:, c) ~= 0, c)'
		
		PossibilitesCOL{c} =		donnerPossibilites([], JEU.HAUTEUR, Information, [])
	end
end

function Grille = completerGrille(PossibilitesLIG, PossibilitesCOL)
	global JEU
	
	for l = 1:JEU.HAUTEUR
		EsperancesLIG(l, :) =		mean(PossibilitesLIG{l}, 1)
	end
	for c = 1:JEU.LARGEUR
		EsperancesCOL(c, :) =		mean(PossibilitesCOL{c}, 1)
	end
	
	Grille =						9*ones(JEU.HAUTEUR, JEU.LARGEUR)
	
	// Seules les cases occupées de manière certaine sont retenues
	//Grille =					1*((EsperancesLIG == 1) + (EsperancesCOL == 1)')
	
	// Seules les cases non-occupées de manière certaine sont éliminées
	//Grille =					0*((EsperancesLIG == 0) .* (EsperancesCOL == 0)')
	
	// Les cases occupées de manière certaine sont retenues
	Grille(EsperancesLIG == 1) =		1
	Grille(EsperancesCOL' == 1) =		1
	
	// Les cases non-occupées de manière certaine sont éliminées
	Grille(EsperancesLIG == 0) =		0
	Grille(EsperancesCOL' == 0) =		0
end

function [PossibilitesLIGReduites, PossibilitesCOLReduites] = reduirePossibilites(Grille, PossibilitesLIG, PossibilitesCOL)
	global JEU
	
	for l = 1:JEU.HAUTEUR
		GrilleEtendue =			ones(size(PossibilitesLIG{l}, 1), 1)*Grille(l, :)
		Coefficients_LIGNES_1 =		( sum( (GrilleEtendue == 1) .* (PossibilitesLIG{l} ~= 1) , 2) == 0 )
		Coefficients_LIGNES_0 =		( sum( (GrilleEtendue == 0) .* (PossibilitesLIG{l} ~= 0) , 2) == 0 )
		Coefficients_LIGNES =		Coefficients_LIGNES_0(Coefficients_LIGNES_1)
		
		POSSIBILITES	=			PossibilitesLIG{l}
		POSSIBILITES_1 =			POSSIBILITES(Coefficients_LIGNES_1, :)
		PossibilitesLIGReduites{l} =	POSSIBILITES_1(Coefficients_LIGNES, :)
	end
	
	for c = 1:JEU.LARGEUR
		GrilleEtendue =			ones(size(PossibilitesCOL{c}, 1), 1)*Grille(:, c)'
		Coefficients_COLONNES_1 =	( sum( (GrilleEtendue == 1) .* (PossibilitesCOL{c} ~= 1) , 2) == 0 )
		Coefficients_COLONNES_0 =	( sum( (GrilleEtendue == 0) .* (PossibilitesCOL{c} ~= 0) , 2) == 0 )
		Coefficients_COLONNES =		Coefficients_COLONNES_0(Coefficients_COLONNES_1)
		
		POSSIBILITES	=			PossibilitesCOL{c}
		POSSIBILITES_1 =			POSSIBILITES(Coefficients_COLONNES_1, :)
		PossibilitesCOLReduites{c} =	POSSIBILITES_1(Coefficients_COLONNES, :)
	end
end

function Grille_S = resoudreIterativement(Grille, PossibilitesLIG, PossibilitesCOL)
		global JEU
	
		Grille_E =				Grille
		[PossibilitesLIG_E, PossibilitesCOL_E] = reduirePossibilites(Grille, PossibilitesLIG, PossibilitesCOL)
	
	for iteration = 1:JEU.NombreIterations
		JEU.Evaluations =			JEU.Evaluations + 1
		
		Grille_S =				completerGrille(PossibilitesLIG_E, PossibilitesCOL_E)
		
		mettreAJourCases(Grille_S, JEU.HAUTEUR, JEU.LARGEUR)
		mettreAJourConsole(JEU.ETAT.RECHERCHE, Grille, Grille_S)
		sleep(JEU.Pause)
		
		[PossibilitesLIG_S, PossibilitesCOL_S] = reduirePossibilites(Grille_E, PossibilitesLIG_E, PossibilitesCOL_E)
		
		Grille_E =				Grille_S
		PossibilitesLIG_E =			PossibilitesLIG_S
		PossibilitesCOL_E = 		PossibilitesCOL_S		
	end
end

////////////////////////////////////////////////////////////////////////////////
//
//	FONCTIONS VUES
  //
  //	Initialisation des paramètres
  //
  //	Interface utilisateur
  //
  //	Console simplifiée
  //	Affichage d'une grille dans la console
  //	Affichage de deux grilles dans la console
//
///////////////////////////////////////////////////////////////////////////////

function affecterParametresVues()
	global JEU
	
	// Interface
		JEU.INTERFACE.Etiquette =	'Interface'
		JEU.INTERFACE.Position =		[0, 0]
		JEU.INTERFACE.Taille =		[700, 700]
		JEU.INTERFACE.CouleurRVB =	[0.8 0.8 0.8]
		JEU.INTERFACE.Titre =		'NONOGRAM / PICROSS'
	
	// Boutons de contrôle
		JEU.BOUTONS.Nombre =		5
		JEU.BOUTONS.Unites =		'normalized'
		JEU.BOUTONS.CouleurRVB =		[0.9 0.9 0.9]
		JEU.BOUTONS.TaillePolice =	15
	
	// Damier ( Axes )
		TailleDamier =				(JEU.BOUTONS.Nombre - 1)/JEU.BOUTONS.Nombre
		
		JEU.DAMIER.Etiquette =		'Damier'
		JEU.DAMIER.Position =		[0, 0, TailleDamier, TailleDamier]
		JEU.DAMIER.Marges =			[0, 0, 0, 0]
	
	// Console
		JEU.CONSOLE.Marge =			'\t'
		JEU.CONSOLE.SautDeLigne =	'\n'
		JEU.CONSOLE.Espace =		' '
		
		JEU.CONSOLE.SeparateurColonne = '|'
		JEU.CONSOLE.SeparateurLigne =	'-'
		JEU.CONSOLE.Separateur =		'+'
end

function creerInterface()
	global JEU
	
	// (figure) Interface
		interface1 =				figure('figure_position', JEU.INTERFACE.Position)
		interface1.tag =			JEU.INTERFACE.Etiquette
		
		interface1.figure_size =		JEU.INTERFACE.Taille
		interface1.auto_resize =		'on'
		interface1.figure_name =		JEU.INTERFACE.Titre
		interface1.backgroundcolor =	JEU.INTERFACE.CouleurRVB
		
		delmenu(interface1.figure_id, gettext('File'))
		delmenu(interface1.figure_id, gettext('Tools'))
		delmenu(interface1.figure_id, gettext('Edit'))
		delmenu(interface1.figure_id, gettext('?'))
		toolbar(interface1.figure_id, 'off')
		
	// (axes) Axes de la figure
		creerDamier()
		
	// (boutons) Commandes de jeu
		for bb = [1, 2, 5]
			select bb
			case 1 then BOUTON =	JEU.BOUTON1 // Résolution de la grille ( sélectionnée )
			case 2 then BOUTON =	JEU.BOUTON2 // Affichage de la base de problèmes
			case 5 then BOUTON =	JEU.BOUTON5 // Sortie
			end
			
			bouton =				uicontrol(get(JEU.INTERFACE.Etiquette), 'style', 'pushbutton')
			bouton.Tag =			BOUTON.Etiquette
			bouton.Units =			BOUTON.Unites
			bouton.Position =		BOUTON.Position
			bouton.BackgroundColor =	BOUTON.CouleurRVB
			bouton.FontSize =		BOUTON.TaillePolice
			bouton.Relief =		BOUTON.Relief
			bouton.String =		BOUTON.Titre
			bouton.Callback =		BOUTON.Action
		end
	
	// (menus) Sélection
		for mm = [1, 2]
			select mm
			case 1 then MENU =		JEU.MENU1 // Sélection de la grille à complèter
			case 2 then MENU =		JEU.MENU2 // Sélection du nombre maximum d'itérations
			end
			menu =				uimenu(get(JEU.INTERFACE.Etiquette), 'Tag', MENU.Etiquette, 'Label', MENU.Nom)
			
			for m = 1:1:size(MENU.Choix, 1)
				nom =			MENU.Choix(m, 1)
				action =			MENU.Choix(m, 2)
								uimenu(menu, 'Label', nom, 'Callback', action)
			end
		end	
end
function mettreAJourInterface(Etat)
	global JEU
	
	if ( Etat == JEU.ETAT.RECHERCHE ) then
		set(get(JEU.BOUTON1.Etiquette), 'Enable', 'off')
		set(get(JEU.BOUTON2.Etiquette), 'Enable', 'off')
		set(get(JEU.BOUTON5.Etiquette), 'Enable', 'off')
		
		set(get(JEU.MENU1.Etiquette),   'Enable', 'off')
		set(get(JEU.MENU2.Etiquette),   'Enable', 'off')
	else
		set(get(JEU.BOUTON1.Etiquette), 'Enable', 'on')
		set(get(JEU.BOUTON2.Etiquette), 'Enable', 'on')
		set(get(JEU.BOUTON5.Etiquette), 'Enable', 'on')
		
		set(get(JEU.MENU1.Etiquette),   'Enable', 'on')
		set(get(JEU.MENU2.Etiquette),   'Enable', 'on')	
	end
end

function creerDamier()
	global JEU
	
	damier =						newaxes(get(JEU.INTERFACE.Etiquette))
	damier.tag = 					JEU.DAMIER.Etiquette
	
	damier.axes_bounds =			JEU.DAMIER.Position
	damier.margins =				JEU.DAMIER.Marges
	
	damier.axes_visible =			'off'
	damier.x_location =				'top'
	damier.y_location =				'left'
	damier.box =					'off'
	damier.isoview =				'on'
end
function creerCases()
	global JEU
	
	set(get(JEU.DAMIER.Etiquette), 'data_bounds', [0, 0; JEU.LARGEUR_INFO + JEU.LARGEUR, JEU.HAUTEUR + JEU.HAUTEUR_INFO])
	
	for l = 1:JEU.HAUTEUR_INFO
	for c = 1:JEU.LARGEUR
		xCase =					JEU.LARGEUR_INFO + c - 1
		yCase =					JEU.HAUTEUR_INFO + JEU.HAUTEUR - 1 - (l - 1)
		if (JEU.InformationsCOL(l, c) == 0 )
			vCase =				''
		else
			vCase = 				string(JEU.InformationsCOL(l, c))
		end
		
		xstringb(xCase, yCase, vCase, 1, 1, 'fill')
	end
	end

	for l = 1:JEU.HAUTEUR
	for c = 1:JEU.LARGEUR_INFO
		xCase =					                   c - 1
		yCase =					JEU.HAUTEUR - 1 - (l - 1)
		if (JEU.InformationsLIG(l, c) == 0 )
			vCase =				''
		else
			vCase = 				string(JEU.InformationsLIG(l, c))
		end
		
		xstringb(xCase, yCase, vCase, 1, 1, 'fill')
	end
	end
	
	for l = 1:JEU.HAUTEUR
	for c = 1:JEU.LARGEUR
		etiquette =				'Case' + 'L' + string(l) + 'C' + string(c)
		xCase =					JEU.LARGEUR_INFO + c - 1
		yCase =					JEU.HAUTEUR      - l
		
		xstringb(xCase, yCase, '?', 1, 1)
		objet =					gce()
		objet.tag =				etiquette
		objet.auto_dimensionning =	'on'
		objet.box =				'off'
		objet.line_mode =			'off'
		objet.fill_mode =			'off'
		objet.text_box_mode =		'filled'
		objet.font_foreground =		color('grey')
		
		JEU.CASE.Etiquettes(l, c) =	etiquette
	end
	end
end
function mettreAJourCases(Grille, Lignes, Colonnes)
	global JEU
	
	for l = 1:Lignes
	for c = 1:Colonnes		
		objet =					get(JEU.CASE.Etiquettes(l, c))
		select Grille(l, c)
		case 0
			objet.text =			'X'
			objet.font_foreground  =	color('red')
		case 1
			objet.text =			'O'
			objet.font_foreground  =	color('blue')
		case 9
			objet.text =			'?'
			objet.font_foreground  =	color('grey')
		end
	end
	end
end
function effacerCases()
	global JEU
	
	objet = get(JEU.DAMIER.Etiquette)
	
	delete(objet.children())
end

function mettreAJourConsole(Etat, varargin)
	global JEU
	
	tohome
	clc
	
	message =						'NONOGRAM'
	message =						message + JEU.CONSOLE.SautDeLigne
	message =						message + JEU.CONSOLE.SautDeLigne
	
	message =						donnerNiveau(JEU.MatriculeNiveau, 'Nom')
	message =						message + JEU.CONSOLE.SautDeLigne
	
	select Etat
	case JEU.ETAT.SELECTION then
		Grille =					varargin(1)
		
		message =					message + typographierGrille(Grille, JEU.InformationsCOL, JEU.InformationsLIG)
	case JEU.ETAT.RECHERCHE then
		Grille1 =					varargin(1)
		Grille2 =					varargin(2)
		
		message =					message + typographier2Grilles(Grille1, Grille2, JEU.InformationsCOL, JEU.InformationsLIG)
		message =					message + JEU.CONSOLE.SautDeLigne
		message =					message + JEU.CONSOLE.SautDeLigne
		
		message =					message + string(JEU.Evaluations) + ' évaluations sur '
		message =					message + string(JEU.NombreIterations) + ' autorisées'
		message =					message + JEU.CONSOLE.SautDeLigne
		message =					message + JEU.CONSOLE.SautDeLigne
	end

	mprintf(message)
end
function Texte = typographierGrille(Grille, InformationsCOL, InformationsLIG)
	global JEU
	
	JEU.HAUTEUR_INFO =				size(InformationsCOL, 1)
	JEU.HAUTEUR_TEXTE =				JEU.HAUTEUR_INFO + 1 + JEU.HAUTEUR
	
	JEU.LARGEUR_INFO =				size(InformationsLIG, 2)
	
	Texte =						''
	
	for l = 1:JEU.HAUTEUR_TEXTE
		Texte =					Texte + JEU.CONSOLE.Marge
		
		// Espaces blanc OU informations partielles selon les colonnes
		if ( l  < JEU.HAUTEUR_INFO + 1)
			for c = 1:JEU.LARGEUR_INFO
				Texte =			Texte + JEU.CONSOLE.Espace + JEU.CONSOLE.Espace
			end
				Texte =			Texte + JEU.CONSOLE.SeparateurColonne + JEU.CONSOLE.Espace
			for c = 1:JEU.LARGEUR
				Texte = 			Texte + string(InformationsCOL(l, c)) + JEU.CONSOLE.Espace
			end
		end
		
		// Séparateurs
		if ( l == JEU.HAUTEUR_INFO + 1 )
			for c = 1:JEU.LARGEUR_INFO
				Texte = 			Texte + JEU.CONSOLE.SeparateurLigne + JEU.CONSOLE.SeparateurLigne
			end
				Texte =			Texte + JEU.CONSOLE.Separateur + JEU.CONSOLE.SeparateurLigne
			for c = 1:JEU.LARGEUR
				Texte =			Texte + JEU.CONSOLE.SeparateurLigne + JEU.CONSOLE.SeparateurLigne
			end
		end
		
		// Informations partielles selon les lignes OU grilles
		if ( l  > JEU.HAUTEUR_INFO + 1 )
			dl =					l - JEU.HAUTEUR_INFO - 1
			
			for c = 1:JEU.LARGEUR_INFO
				Texte = 			Texte + string(InformationsLIG(dl, c)) + JEU.CONSOLE.Espace
			end
				Texte =			Texte + JEU.CONSOLE.SeparateurColonne + JEU.CONSOLE.Espace
			for c = 1:JEU.LARGEUR
				Texte = 			Texte + string(Grille(dl, c)) + JEU.CONSOLE.Espace
			end
		end
		
		// Fin de ligne
		Texte =					Texte + JEU.CONSOLE.SautDeLigne
	end
end
function Texte = typographier2Grilles(Grille1, Grille2, InformationsCOL, InformationsLIG)
	global JEU
	
	JEU.HAUTEUR_INFO =				size(InformationsCOL, 1)
	JEU.HAUTEUR_TEXTE =				JEU.HAUTEUR_INFO + 1 + JEU.HAUTEUR
	
	JEU.LARGEUR_INFO =				size(InformationsLIG, 2)
	
	Texte =						''
	
	for l = 1:JEU.HAUTEUR_TEXTE
		Texte =					Texte + JEU.CONSOLE.Marge
		
		// Espaces blanc OU informations partielles selon les colonnes
		if ( l  < JEU.HAUTEUR_INFO + 1)
			for c = 1:JEU.LARGEUR_INFO
				Texte =			Texte + JEU.CONSOLE.Espace + JEU.CONSOLE.Espace
			end
				Texte =			Texte + JEU.CONSOLE.SeparateurColonne + JEU.CONSOLE.Espace
			for c = 1:JEU.LARGEUR
				Texte = 			Texte + string(InformationsCOL(l, c)) + JEU.CONSOLE.Espace
			end
			
				Texte =			Texte + JEU.CONSOLE.Marge + JEU.CONSOLE.Marge
			
			for c = 1:JEU.LARGEUR_INFO
				Texte =			Texte + JEU.CONSOLE.Espace + JEU.CONSOLE.Espace
			end
				Texte =			Texte + JEU.CONSOLE.SeparateurColonne + JEU.CONSOLE.Espace
			for c = 1:JEU.LARGEUR
				Texte = 			Texte + string(InformationsCOL(l, c)) + JEU.CONSOLE.Espace
			end
		end
		
		// Séparateurs
		if ( l == JEU.HAUTEUR_INFO + 1 )
			for c = 1:JEU.LARGEUR_INFO
				Texte = 			Texte + JEU.CONSOLE.SeparateurLigne + JEU.CONSOLE.SeparateurLigne
			end
				Texte =			Texte + JEU.CONSOLE.Separateur + JEU.CONSOLE.SeparateurLigne
			for c = 1:JEU.LARGEUR
				Texte =			Texte + JEU.CONSOLE.SeparateurLigne + JEU.CONSOLE.SeparateurLigne
			end
			
				Texte =			Texte + JEU.CONSOLE.Marge + JEU.CONSOLE.Marge
			
			for c = 1:JEU.LARGEUR_INFO
				Texte = 			Texte + JEU.CONSOLE.SeparateurLigne + JEU.CONSOLE.SeparateurLigne
			end
				Texte =			Texte + JEU.CONSOLE.Separateur + JEU.CONSOLE.SeparateurLigne
			for c = 1:JEU.LARGEUR
				Texte =			Texte + JEU.CONSOLE.SeparateurLigne + JEU.CONSOLE.SeparateurLigne
			end
		end
		
		// Informations partielles selon les lignes OU grilles
		if ( l  > JEU.HAUTEUR_INFO + 1 )
			dl =					l - JEU.HAUTEUR_INFO - 1
			
			for c = 1:JEU.LARGEUR_INFO
				Texte = 			Texte + string(InformationsLIG(dl, c)) + JEU.CONSOLE.Espace
			end
				Texte =			Texte + JEU.CONSOLE.SeparateurColonne + JEU.CONSOLE.Espace
			for c = 1:JEU.LARGEUR
				Texte = 			Texte + string(Grille1(dl, c)) + JEU.CONSOLE.Espace
			end
			
			Texte =				Texte + JEU.CONSOLE.Marge + JEU.CONSOLE.Marge
			
			for c = 1:JEU.LARGEUR_INFO
				Texte = 			Texte + string(InformationsLIG(dl, c)) + JEU.CONSOLE.Espace
			end
				Texte =			Texte + JEU.CONSOLE.SeparateurColonne + JEU.CONSOLE.Espace
			for c = 1:JEU.LARGEUR
				Texte = 			Texte + string(Grille2(dl, c)) + JEU.CONSOLE.Espace
			end
		end
		
		// Fin de ligne
		Texte =					Texte + JEU.CONSOLE.SautDeLigne
	end
end

////////////////////////////////////////////////////////////////////////////////
//
//	FONCTIONS CONTROLEURS
  //
  //	Initialisation des paramètres
  //
  // Sélection d'un problème
  // Sélection du maximum d'itérations
  //
  // Lancement de la résolution
  // Diaporama des problèmes
  // Sortie du programme
//
////////////////////////////////////////////////////////////////////////////////

function affecterParametresControleurs()
	global JEU
	
	// Menus de sélection
		JEU.MENU1.Etiquette =		'SélectionGrilles'
		JEU.MENU1.Nom =			'Grilles'
		JEU.MENU1.Matricules =		['Tutoriel 1';		...
								 'Tutoriel 2';		...
								 'Tutoriel 3';		...
								 'Tutoriel 4';		...
								 'Tutoriel 5';		...
								 'Tutoriel 6';		...
								 'Tutoriel 7';		...
								 'Tutoriel 8';		...
								 'Tutoriel 9';		...
								 '2020-07-15';		...
								 '2020-07-16';		...
								 '2020-07-17';		...
								 '2020-07-18';		...
								 '2020-07-19'	]
		
		JEU.MENU1.Choix =			[]
		for m = 1:size(JEU.MENU1.Matricules, 1)
			matricule =			JEU.MENU1.Matricules(m, 1)
			nom =				donnerNiveau(matricule, 'Nom')
			action =				'choisirGrille(' + '''' + matricule + '''' + ')'
			
			JEU.MENU1.Choix =		[JEU.MENU1.Choix; [nom, action]]
		end
		
		JEU.MENU2.Etiquette =		'SélectionNombreIterations'
		JEU.MENU2.Nom =			'Maximum d''itérations'
		JEU.MENU2.Matricules =		[10; 20; 30; 40; 50; 60; 70; 80; 90; 100]
		
		JEU.MENU2.Choix =			[]
		for m = 1:1:size(JEU.MENU2.Matricules, 1)
			matricule =			JEU.MENU2.Matricules(m, 1)
			nom =				string(matricule)
			action =				'choisirMaximumIterations(' + string(matricule) + ')'
			
			JEU.MENU2.Choix =		[JEU.MENU2.Choix; [nom, action]]
		end
		
	// Boutons de contrôle
		largeurEspace =			1/JEU.BOUTONS.Nombre
		hauteurEspace =			1/JEU.BOUTONS.Nombre	
		xEspace =					((1:JEU.BOUTONS.Nombre) - 1)*largeurEspace
		yEspace =					((1:JEU.BOUTONS.Nombre) - 1)*hauteurEspace
		
		coeffMarge =				1/10
		
		xBouton =					xEspace + coeffMarge*largeurEspace
		yBouton =					yEspace + coeffMarge*hauteurEspace
		largeurBouton =			(1 - 2*coeffMarge)*largeurEspace
		hauteurBouton =			(1 - 2*coeffMarge)*hauteurEspace
		
		JEU.BOUTON1.Etiquette =		'ControleurResolution'
		JEU.BOUTON1.Unites =		JEU.BOUTONS.Unites
		JEU.BOUTON1.Position =		[xBouton($), yBouton($), largeurBouton, hauteurBouton]
		JEU.BOUTON1.CouleurRVB =		JEU.BOUTONS.CouleurRVB
		JEU.BOUTON1.TaillePolice =	JEU.BOUTONS.TaillePolice
		JEU.BOUTON1.Titre =			'Résolution'
		JEU.BOUTON1.Relief =		'raised'
		JEU.BOUTON1.Action =		'resoudreGrille'
		
		JEU.BOUTON2.Etiquette =		'ControleurAffichageBase'
		JEU.BOUTON2.Unites =		JEU.BOUTONS.Unites
		JEU.BOUTON2.Position =		[xBouton($), yBouton($ - 1), largeurBouton, hauteurBouton]
		JEU.BOUTON2.CouleurRVB =		JEU.BOUTONS.CouleurRVB
		JEU.BOUTON2.TaillePolice =	JEU.BOUTONS.TaillePolice
		JEU.BOUTON2.Titre =			'Problèmes'
		JEU.BOUTON2.Relief =		'raised'
		JEU.BOUTON2.Action =		'afficherBaseGrilles()'
		
		JEU.BOUTON3.Etiquette =		'ControleurEdition'
		JEU.BOUTON3.Unites =		JEU.BOUTONS.Unites
		JEU.BOUTON3.Position =		[xBouton($), yBouton($ - 2), largeurBouton, hauteurBouton]
		JEU.BOUTON3.CouleurRVB =		JEU.BOUTONS.CouleurRVB
		JEU.BOUTON3.TaillePolice =	JEU.BOUTONS.TaillePolice
		JEU.BOUTON3.Titre =			'Saisie'
		JEU.BOUTON3.Relief =		'raised'
		JEU.BOUTON3.Action =		''
		
		JEU.BOUTON5.Etiquette =		'SortieCalcul'
		JEU.BOUTON5.Unites =		JEU.BOUTONS.Unites
		JEU.BOUTON5.Position =		[xBouton($), yBouton(1), largeurBouton, hauteurBouton]
		JEU.BOUTON5.CouleurRVB =		JEU.BOUTONS.CouleurRVB
		JEU.BOUTON5.TaillePolice =	JEU.BOUTONS.TaillePolice
		JEU.BOUTON5.Titre =			'Sortie'
		JEU.BOUTON5.Relief =		'raised'
		JEU.BOUTON5.Action =		'sortir'
		
	// États
		JEU.ETAT.SELECTION =		10 // grille incomplète sélectionnée
		JEU.ETAT.CONTRADICTOIRE =	11 // une des matrice Possibilites*_R est VIDE []
		JEU.ETAT.RECHERCHE =		20 // résolution en cours
		JEU.ETAT.BLOQUE =			21 // pas de progrès dans la levée d'incertitude entre deux itérations
		JEU.ETAT.TERMINE =			22 // grille certaine (valeur 0 ou 1) ET valeurs de la grille incompatibles avec INFO_LIGNES et/ou INFO_COLONNES
		JEU.ETAT.RESOLU =			23 // grille certaine (valeur 0 ou 1) ET valeurs de la grille compatibles avec INFO_LIGNES et INFO_COLONNES

	// Paramètres de la partie
		JEU.MatriculeDefaut =		'2020-07-16'
		JEU.Matricule =			JEU.MatriculeDefaut
		
		JEU.NombreIterations =		20
		
		JEU.Pause =				1000
end

function choisirGrille(matricule)
	global JEU
	
	JEU.MatriculeNiveau =			matricule

	JEU.InformationsCOL =			donnerNiveau(matricule, 'Informations colonnes')
	JEU.InformationsLIG =			donnerNiveau(matricule, 'Informations lignes')
	
	JEU.LARGEUR =					size(JEU.InformationsCOL, 2)
	JEU.HAUTEUR =					size(JEU.InformationsLIG, 1)
	
	JEU.LARGEUR_INFO =				size(JEU.InformationsLIG, 2)
	JEU.HAUTEUR_INFO =				size(JEU.InformationsCOL, 1)
	
	GrilleRemplissage =				zeros(JEU.HAUTEUR, JEU.LARGEUR)
	
	effacerCases()
	creerCases()
	mettreAJourConsole(JEU.ETAT.SELECTION, GrilleRemplissage)
end
function choisirMaximumIterations(maximumIterations)
	global JEU
	
	JEU.Texte =			maximumIterations
end

function resoudreGrille()
	global JEU
	
	mettreAJourInterface(JEU.ETAT.RECHERCHE)
	
	JEU.Evaluations =				0
	
	[PossibilitesLIG, PossibilitesCOL] = donnerMatricesPossibilites(JEU.InformationsLIG, JEU.InformationsCOL)
	JEU.GrilleIncomplete =			completerGrille(PossibilitesLIG, PossibilitesCOL)
	
	mettreAJourCases(JEU.GrilleIncomplete, JEU.HAUTEUR, JEU.LARGEUR)
	mettreAJourConsole(JEU.ETAT.SELECTION, JEU.GrilleIncomplete)
	
	JEU.GrilleResolue =				resoudreIterativement(JEU.GrilleIncomplete, PossibilitesLIG, PossibilitesCOL)
	
	mettreAJourInterface(JEU.ETAT.RESOLU)
	mettreAJourCases(JEU.GrilleResolue, JEU.HAUTEUR, JEU.LARGEUR)
	mettreAJourConsole(JEU.ETAT.RESOLU, JEU.GrilleResolue)
end
function afficherBaseGrilles()
	global JEU
	
	for numero = 1:size(JEU.MENU1.Matricules, 1)
		choisirGrille(JEU.MENU1.Matricules(numero, 1))
		sleep(JEU.Pause)
	end
end
function sortir()
	global JEU
	
	xdel(winsid())
end

////////////////////////////////////////////////////////////////////////////////
//
//	LANCEMENT
//
////////////////////////////////////////////////////////////////////////////////

affecterParametresModele()
affecterParametresVues()
affecterParametresControleurs()

creerInterface()
choisirGrille(JEU.MatriculeDefaut)