// author\code\example\ferzi.txt
// Программа находит раcстановку ферзей на шахматной доске так,
// чтоб они не угрожали друг другу.


//-------------------------------------------------------------------------------------------------------
void main(){
	randomFishka(20);
	trace("----------------------------------------");
	procces(7); // n*n - рaзмер поля
	trace("----------------------------------------");
	interpretator(4);
}


//интерпретатор второго порядка для функции procces(n)
void interpretator(var nn){
	var f=getFunction("procces");
	int n=createNewLaver();
	int p=createNewProcess(n,f);
	var names=f.getNamesStart();
	setValueInLaver(n,p,names[0],nn);
	//evalLaver(n,p,"trace(outAllMemory());");
	runLaver(n);
	//trace(getLaverMessage(n));
	var NP=getVariantov(n);
	trace("Variantov:"+NP);
	var ks=getValuesInLaver(n,"k");
	trace(ks.export());
	int max=0;
	for(int i=0;i<ks.size();++i)if(max<ks[i])max=ks[i];
	for(i=0;i<ks.size();++i)if(max>ks[i])LaverOFF(n,i);
	//trace(getListLaver(n).export());
	runLaver(n);
	NP=getVariantov(n);
	for(i=1;i<NP;++i)LaverOFF(n,i);
	runLaver(n);
	deleteLaver(n);
}



//найдет все решения задачи ферзей.
void procces(var n){
	var m=initP(n),x,y=0,ok,k=0;
	while(!nozero(&m)){
		do{
			ok=0;
			for(int i=0;i<n;++i)if(m[i][y]==0){ok=1;break;}
			if(!ok)++y;
			if(y>=n)OFF;
			}while(!ok);
		x=rozpad([0;n).getN());
		if(m[x][y])OFF;
		protect(x,y,&m);
		++k;
		//trace(toString(&m));
		}
	define();
	trace("ferzei "+k+":");
	trace(toString(&m));
	define();
	trace("Pres enter for exit.");
	getstring();
}


//найдет одно случайное решение.
void randomFishka(var n){
	var m=initP(n),x,y;
	while(!nozero(&m)){
		x=rozpad([0;n).getN());
		y=rozpad([0;n).getN());
		if(m[x][y])OFF;
		define();
		protect(x,y,&m);
		}
	trace(toString(&m));
	getstring();
}



//-------------------------------------------------------------------------------------------------------
//создаст матрицу - поле игры.
var initP(int n){
	var m=reserve(n);
	for(int i=0;i<n;++i)m[i]=reserve(n);
	return m;
}


//вернёт истену если нет клеток не под боём.
bool nozero(var*m){
	int n=m->size();
	for(int x=0;x<n;++x)
	for(int y=0;y<n;++y)if((*m)[x][y]==0)return 0;
	return 1;
}


//покроет ячейки которым угрожает фигура.
void protect(int x,int y,var*m){
	int n=m->size(),p;
	for(p=0;p<n;++p){
		(*m)[x][p]=1;
		(*m)[p][y]=1;
		}
	for(p=0;p<n;++p){
		if(x+p<n && y+p<n)(*m)[x+p][y+p]=1;
		if(x-p>=0 && y-p>=0)(*m)[x-p][y-p]=1;
		if(x-p>=0 && y+p<n)(*m)[x-p][y+p]=1;
		if(x+p<n && y-p>=0)(*m)[x+p][y-p]=1;
		}
	(*m)[x][y]=2;
}


//превратит массив в строку текста для вывода на екран.
string toString(var*m){
	string s="";
	int n=m->size(),x,y;
	for(int y=0;y<n;++y){
	for(int x=0;x<n;++x){
		if((*m)[x][y]==0)s+=".";
		if((*m)[x][y]==1)s+="O";
		if((*m)[x][y]==2)s+="F";
		}
	s+="\n";
	}
	return s;
}
