#include "queens.h"

#include <QtCore/qmath.h>
//const quint64 Queens::One = 1;
//const quint64 Queens::Size = 8;

Queens::Queens(ushort size) : Size(size), Hash(size*size)
{
	//Hash = 0;
}

bool Queens::solved(void) const
{
	short c = 0;

	for (int i = 0; i < Hash.size(); ++i)
	{
		if (Hash.testBit(i))
			c++;
	}

	if (c==Size)
		return true;

	return false;
}

Queens::ListT Queens::variants(void) const
{
	Queens::ListT out;

	QBitArray mask(Hash.size());
	QBitArray varianthash;

	int startline=0;

	for (int i = 0; i < Hash.size(); ++i)
	{
		if (Hash.testBit(i)) //belegt
		{
			setFields(mask, Column, i);
			setFields(mask, Row, i);
			setFields(mask, Diagonal, i);

			startline = i/Size + 1;
		}
	}

	if (startline < Size)
	{
		for (int i = startline*Size; i < (startline+1)*Size; ++i)
		{
			if (mask.testBit(i)==false) //frei
			{
				varianthash = Hash;
				varianthash.setBit(i);


				Queens copy(*this);
				copy.Hash=varianthash;
				out.append(copy);

			}
		}
	}
	//throw;

	//qDebug() << out;
	return out;
}

QString Queens::toString(bool cr) const
{
	QString out;
	for (int i = 0; i < Hash.size(); ++i)
	{
		if (Hash.testBit(i))
			out+="D";
		else
			out+="-";

		if (((i+1)%Size==0) && (cr))
			out+="\n";
	}
	return out;
}


void Queens::setFields(QBitArray& m, FieldsT t, ushort i)
{
	const int size = qSqrt(m.size());
	const ushort xi = i%size;
	const ushort yi = i/size;

//	Queens q;
//	q.Hash = m;
//	if (t==Diagonal)
//		qDebug() << i << "vorher\n" << q.toString(true);

	for (ushort ii = 0; ii < m.size(); ++ii)
	{
		const ushort xii = ii%size;
		const ushort yii = ii/size;

		switch (t)
		{
			case Row:
				if (yi == yii)
					m.setBit(ii);
				break;
			case Column:
				if (xi == xii)
					m.setBit(ii);
				break;
			case Diagonal:
				if (abs(xi - xii) == abs(yi - yii))
					m.setBit(ii);
				break;

			default: throw;
		}
	}

//	q.Hash = m;
//	if (t==Diagonal)
//		qDebug() << "nachher\n" << q.toString(true);
}
