<commit_before>#include "tile.h"

#include "game.h"

#include <unordered_map>

#if PRINT_CONNECTIONS
#include <QDebug>
#endif

Node::Node(TerrainType t, const Tile * parent, const Game * g)
    : data(this, g->getPlayerCount())
{
	Q_ASSERT(g != 0);
	
	data.t = t;
	
	data.tiles.insert(parent);
}

Node::~Node()
{
//	for (Node ** p : pointers)
//	{
//		if (p)
//			*p = 0;
//	}
}

void Node::removeMeeple(int player, Game * g)
{
	checkUnclose(g);
	if (d->meeples[player]-- == d->maxMeples)
	{
		d->maxMeples = 0;
		for (uint i = 0; i < g->getPlayerCount(); ++i)
			if (d->meeples[i] > d->maxMeples)
				d->maxMeples = d->meeples[i];
	}
}

void Node::connect(Node * n, Game * g)
{
	Q_ASSERT_X(n->getTerrain() == this->getTerrain(), "Node::connect", "TerrainType does not match");
	Q_ASSERT_X(typeid(*n) == typeid(*this), "Node::connect", "classes do not match");
	Q_ASSERT(getScored() == NotScored);
	Q_ASSERT(n->getScored() == NotScored);
	Q_ASSERT(data.scored == NotScored);
	Q_ASSERT(n->data.scored == NotScored);

#if PRINT_CONNECTIONS
	qDebug() << "  connect:" << n->id() << "->" << id() << "   BEFORE";
//	for (Tile const * t : d->tiles)
//		qDebug() << "    " << id() << t->id;
//	for (Tile const * t : n->d->tiles)
//		qDebug() << "    " << n->id() << t->id;
#endif
	
	if (!isSame(n))
	{
//	for (Node ** & p : n->pointers)
//	{
//		*p = this;
//		pointers.push_back(p);
////		p = 0;
//	}
		d->tiles.insert(n->d->tiles.begin(), n->d->tiles.end());
		for (uchar * tm = d->meeples, * end = d->meeples + (g->getPlayerCount()), * nm = n->d->meeples;
			 tm < end;
			 ++tm, ++nm)
		{
			*tm = (uchar)(*tm + *nm);
			if (*tm > d->maxMeples)
				d->maxMeples = *tm;
		}
		
		if (isOccupied())
			checkClose(g);
		
		d->nodes.insert(n->d->nodes.begin(), n->d->nodes.end());
#if PRINT_CONNECTIONS
//		qDebug() << "  connect:" << n->id() << "->" << id();
#endif
	}
#if PRINT_CONNECTIONS
	else
	{
//		qDebug() << "  connect:" << n->id() << "->" << id() << "skipped";
		qDebug() << "  skpped";
	}
	
//	qDebug() << "  connect:" << n->id() << "->" << id() << "   AFTER";
//	for (Tile const * t : d->tiles)
//		qDebug() << "    " << id() << t->id;
//	for (Tile const * t : n->d->tiles)
//		qDebug() << "    " << n->id() << t->id;
#endif
	
//	Q_ASSERT(n->d == &n->data);

	for (Node * o : d->nodes)
	{
		if (o == this)
			continue;
		o->ds.push_back(d);
		o->d = d;
	}
}

void Node::disconnect(Node * n, Game * g)	//only works in reverse order of connecting.
{
	for (Node * o : d->nodes)
	{
		if (o == this)
			continue;
		o->ds.pop_back();
		Q_ASSERT(o->ds.size() > 0);
		o->d = o->ds.back();
	}
	
#if PRINT_CONNECTIONS
	qDebug() << "  disconnect:" << n->id() << "->" << id() << "   BEFORE";
//	for (Tile const * t : d->tiles)
//		qDebug() << "    " << id() << t->id;
//	for (Tile const * t : n->d->tiles)
//		qDebug() << "    " << n->id() << t->id;
#endif
	
	if (!isSame(n))
	{	
		for (auto const & t : n->d->nodes)
		{
			auto const & i = d->nodes.find(t);
			Q_ASSERT(i != d->nodes.end());
			d->nodes.erase(i);
		}
		
		if (isOccupied())
			checkUnclose(g);
		
		d->maxMeples = 0;
		for (uchar * tm = d->meeples, * end = d->meeples + (g->getPlayerCount()), * nm = n->d->meeples;
			 tm < end;
			 ++tm, ++nm)
		{
			*tm = (uchar)(*tm - *nm);
			if (*tm > d->maxMeples)
				d->maxMeples = *tm;
		}
		
		for (auto const & t : n->d->tiles)
			d->tiles.erase(d->tiles.find(t));
		
	//	for (Node ** & p : n->pointers)
	//	{
	//		*p = n;
	//		pointers.pop_back();
	////		p = ?;
	//	}
		
#if PRINT_CONNECTIONS
	//	qDebug() << "  disconnect:" << n->id() << "->" << id();
#endif
	}
#if PRINT_CONNECTIONS
	else
	{<commit_msg>F*CK! Bugfix in the game core.<commit_after>#include "tile.h"

#include "game.h"

#include <unordered_map>

#if PRINT_CONNECTIONS
#include <QDebug>
#endif

Node::Node(TerrainType t, const Tile * parent, const Game * g)
    : data(this, g->getPlayerCount())
{
	Q_ASSERT(g != 0);
	
	data.t = t;
	
	data.tiles.insert(parent);
}

Node::~Node()
{
//	for (Node ** p : pointers)
//	{
//		if (p)
//			*p = 0;
//	}
}

void Node::removeMeeple(int player, Game * g)
{
	checkUnclose(g);
	if (d->meeples[player]-- == d->maxMeples)
	{
		d->maxMeples = 0;
		for (uint i = 0; i < g->getPlayerCount(); ++i)
			if (d->meeples[i] > d->maxMeples)
				d->maxMeples = d->meeples[i];
	}
}

void Node::connect(Node * n, Game * g)
{
	Q_ASSERT_X(n->getTerrain() == this->getTerrain(), "Node::connect", "TerrainType does not match");
	Q_ASSERT_X(typeid(*n) == typeid(*this), "Node::connect", "classes do not match");
	Q_ASSERT(getScored() == NotScored);
	Q_ASSERT(n->getScored() == NotScored);
	Q_ASSERT(data.scored == NotScored);
	Q_ASSERT(n->data.scored == NotScored);

#if PRINT_CONNECTIONS
	qDebug() << "  connect:" << n->id() << "->" << id() << "   BEFORE";
//	for (Tile const * t : d->tiles)
//		qDebug() << "    " << id() << t->id;
//	for (Tile const * t : n->d->tiles)
//		qDebug() << "    " << n->id() << t->id;
#endif
	
	if (!isSame(n))
	{
//	for (Node ** & p : n->pointers)
//	{
//		*p = this;
//		pointers.push_back(p);
////		p = 0;
//	}
		d->tiles.insert(n->d->tiles.begin(), n->d->tiles.end());
		for (uchar * tm = d->meeples, * end = d->meeples + (g->getPlayerCount()), * nm = n->d->meeples;
			 tm < end;
			 ++tm, ++nm)
		{
			*tm = (uchar)(*tm + *nm);
			if (*tm > d->maxMeples)
				d->maxMeples = *tm;
		}
		
		d->nodes.insert(n->d->nodes.begin(), n->d->nodes.end());
#if PRINT_CONNECTIONS
//		qDebug() << "  connect:" << n->id() << "->" << id();
#endif
	}
#if PRINT_CONNECTIONS
	else
	{
//		qDebug() << "  connect:" << n->id() << "->" << id() << "skipped";
		qDebug() << "  skpped";
	}
	
//	qDebug() << "  connect:" << n->id() << "->" << id() << "   AFTER";
//	for (Tile const * t : d->tiles)
//		qDebug() << "    " << id() << t->id;
//	for (Tile const * t : n->d->tiles)
//		qDebug() << "    " << n->id() << t->id;
#endif

	if (isOccupied())
		checkClose(g);
	
//	Q_ASSERT(n->d == &n->data);

	for (Node * o : d->nodes)
	{
		if (o == this)
			continue;
		o->ds.push_back(d);
		o->d = d;
	}
}

void Node::disconnect(Node * n, Game * g)	//only works in reverse order of connecting.
{
	for (Node * o : d->nodes)
	{
		if (o == this)
			continue;
		o->ds.pop_back();
		Q_ASSERT(o->ds.size() > 0);
		o->d = o->ds.back();
	}

	if (isOccupied())
		checkUnclose(g);
	
#if PRINT_CONNECTIONS
	qDebug() << "  disconnect:" << n->id() << "->" << id() << "   BEFORE";
//	for (Tile const * t : d->tiles)
//		qDebug() << "    " << id() << t->id;
//	for (Tile const * t : n->d->tiles)
//		qDebug() << "    " << n->id() << t->id;
#endif
	
	if (!isSame(n))
	{	
		for (auto const & t : n->d->nodes)
		{
			auto const & i = d->nodes.find(t);
			Q_ASSERT(i != d->nodes.end());
			d->nodes.erase(i);
		}
		
		d->maxMeples = 0;
		for (uchar * tm = d->meeples, * end = d->meeples + (g->getPlayerCount()), * nm = n->d->meeples;
			 tm < end;
			 ++tm, ++nm)
		{
			*tm = (uchar)(*tm - *nm);
			if (*tm > d->maxMeples)
				d->maxMeples = *tm;
		}
		
		for (auto const & t : n->d->tiles)
			d->tiles.erase(d->tiles.find(t));
		
	//	for (Node ** & p : n->pointers)
	//	{
	//		*p = n;
	//		pointers.pop_back();
	////		p = ?;
	//	}
		
#if PRINT_CONNECTIONS
	//	qDebug() << "  disconnect:" << n->id() << "->" << id();
#endif
	}
#if PRINT_CONNECTIONS
	else
	{
{'fraction_non_alphanumeric': 0.26490524277216765, 'fraction_numerical': 0.001936644072485821, 'mean_word_length': 2.6533602829711977, 'pattern_counts': {'":': 0, '<': 201, '<?xml version=': 0, '>': 193, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7020218', 'n_tokens_mistral': 3416, 'n_tokens_neox': 3203, 'n_words': 631}