src/ai/api/ai_list.cpp
author truelight
Sat, 14 Apr 2007 09:44:18 +0000
branchnoai
changeset 9589 2fbda08db406
parent 9581 398688c1a07a
child 9593 012f29f59906
permissions -rw-r--r--
(svn r9622) [NoAI] -Add: added AITownList, which lists all towns (and which you can iterate)
[NoAI] -Add: added AITownListValuators, to get, for example, all population of the townlist (see regression-test for example)
[NoAI] -Fix: fixed AIList to allow Valuators in a simple and safe way (tnx a lot KUDr)
[NoAI] -Update: updated regression to test above changes
[NoAI] -Fix: Valuate() of valuators are no longer public (Rubidium)
/* $Id$ */

/** @file ai_list.cpp Implementation of AIList */

#include "ai_list.hpp"

/**
 * Base class for any AIList sorter.
 */
class AIListSorter {
protected:
	AIList *list;

public:
	/**
	 * Virtual dtor, needed to mute warnings.
	 */
	virtual ~AIListSorter() { }

	/**
	 * Get the first item of the sorter.
	 */
	virtual int32 Begin() = 0;

	/**
	 * Get the next item of the sorter.
	 */
	virtual int32 Next() = 0;

	/**
	 * See if there is a next item of the sorter.
	 */
	virtual bool HasNext() = 0;
};

/**
 * Sort by value, ascending.
 */
class AIListSorterValueAscending : public AIListSorter {
private:
	AIList::AIListBucket::iterator bucket_iter;
	AIList::AIItemList *bucket_list;
	AIList::AIItemList::iterator bucket_list_iter;

public:
	AIListSorterValueAscending(AIList *list)
	{
		this->list = list;
	}

	int32 Begin()
	{
		this->bucket_iter = this->list->buckets.begin();
		this->bucket_list = &(*this->bucket_iter).second;
		this->bucket_list_iter = this->bucket_list->begin();
		return *bucket_list_iter;
	}

	int32 Next()
	{
		this->bucket_list_iter++;
		if (this->bucket_list_iter == this->bucket_list->end()) {
			this->bucket_iter++;
			if (this->bucket_iter == this->list->buckets.end()) return 0;
			this->bucket_list = &(*this->bucket_iter).second;
			this->bucket_list_iter = this->bucket_list->begin();
		}
		return *bucket_list_iter;
	}

	bool HasNext()
	{
		return this->bucket_iter != this->list->buckets.end() && this->bucket_list_iter != this->bucket_list->end();
	}
};

/**
 * Sort by value, descending.
 */
class AIListSorterValueDescending : public AIListSorter {
private:
	AIList::AIListBucket::reverse_iterator bucket_iter;
	AIList::AIItemList *bucket_list;
	AIList::AIItemList::reverse_iterator bucket_list_iter;

public:
	AIListSorterValueDescending(AIList *list)
	{
		this->list = list;
	}

	int32 Begin()
	{
		this->bucket_iter = this->list->buckets.rbegin();
		this->bucket_list = &(*this->bucket_iter).second;
		this->bucket_list_iter = this->bucket_list->rbegin();
		return *bucket_list_iter;
	}

	int32 Next()
	{
		this->bucket_list_iter++;
		if (this->bucket_list_iter == this->bucket_list->rend()) {
			this->bucket_iter++;
			if (this->bucket_iter == this->list->buckets.rend()) return 0;
			this->bucket_list = &(*this->bucket_iter).second;
			this->bucket_list_iter = this->bucket_list->rbegin();
		}
		return *bucket_list_iter;
	}

	bool HasNext()
	{
		return this->bucket_iter != this->list->buckets.rend() && this->bucket_list_iter != this->bucket_list->rend();
	}
};

/**
 * Sort by item, ascending.
 */
class AIListSorterItemAscending : public AIListSorter {
private:
	AIList::AIListMap::iterator item_iter;

public:
	AIListSorterItemAscending(AIList *list)
	{
		this->list = list;
	}

	int32 Begin()
	{
		this->item_iter = this->list->items.begin();
		return (*this->item_iter).first;
	}

	int32 Next()
	{
		this->item_iter++;
		return (*this->item_iter).first;
	}

	bool HasNext()
	{
		return this->item_iter != this->list->items.end();
	}
};

/**
 * Sort by item, descending.
 */
class AIListSorterItemDescending : public AIListSorter {
private:
	AIList::AIListMap::reverse_iterator item_iter;

public:
	AIListSorterItemDescending(AIList *list)
	{
		this->list = list;
	}

	int32 Begin()
	{
		this->item_iter = this->list->items.rbegin();
		return (*this->item_iter).first;
	}

	int32 Next()
	{
		this->item_iter++;
		return (*this->item_iter).first;
	}

	bool HasNext()
	{
		return this->item_iter != this->list->items.rend();
	}
};



AIList::AIList()
{
	/* Default sorter */
	this->sorter = new AIListSorterValueDescending(this);
}

AIList::~AIList()
{
	delete this->sorter;
}

bool AIList::HasItem(int32 item)
{
	return this->items.count(item) == 1;
}

void AIList::Clear()
{
	this->items.clear();
	this->buckets.clear();
}

void AIList::AddItem(int32 item)
{
	if (this->HasItem(item)) return;

	this->items[item] = 0;
	this->buckets[0].insert(item);
}

void AIList::RemoveItem(int32 item)
{
	if (!this->HasItem(item)) return;

	this->buckets[this->GetValue(item)].erase(item);
	this->items.erase(item);
}

int32 AIList::Begin()
{
	return this->sorter->Begin();
}

int32 AIList::Next()
{
	return this->sorter->Next();
}

bool AIList::IsEmpty()
{
	return this->items.empty();
}

bool AIList::HasNext()
{
	return this->sorter->HasNext();
}

int32 AIList::Count()
{
	return this->items.size();
}

int32 AIList::GetValue(int32 item)
{
	if (!this->HasItem(item)) return 0;

	return this->items[item];
}

void AIList::SortByItem(bool ascending)
{
	delete this->sorter;
	if (ascending) this->sorter = new AIListSorterItemAscending(this);
	else           this->sorter = new AIListSorterItemDescending(this);
}

void AIList::SortByValue(bool ascending)
{
	delete this->sorter;
	if (ascending) this->sorter = new AIListSorterValueAscending(this);
	else           this->sorter = new AIListSorterValueDescending(this);
}

void AIList::RemoveAboveValue(int32 value)
{
	for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
		next_iter = iter; next_iter++;
		if ((*iter).second > value) this->items.erase(iter);
	}

	for (AIListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
		next_iter = iter; next_iter++;
		if ((*iter).first > value) this->buckets.erase(iter);
	}
}

void AIList::RemoveBelowValue(int32 value)
{
	for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
		next_iter = iter; next_iter++;
		if ((*iter).second < value) this->items.erase(iter);
	}

	for (AIListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
		next_iter = iter; next_iter++;
		if ((*iter).first < value) this->buckets.erase(iter);
	}
}

void AIList::RemoveBetweenValue(int32 start, int32 end)
{
	for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
		next_iter = iter; next_iter++;
		if ((*iter).second > start && (*iter).second < end) this->items.erase(iter);
	}

	for (AIListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
		next_iter = iter; next_iter++;
		if ((*iter).first > start && (*iter).first < end) this->buckets.erase(iter);
	}
}

void AIList::RemoveValue(int32 value)
{
	for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
		next_iter = iter; next_iter++;
		if ((*iter).second == value) this->items.erase(iter);
	}

	for (AIListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
		next_iter = iter; next_iter++;
		if ((*iter).first == value) this->buckets.erase(iter);
	}
}

void AIList::KeepAboveValue(int32 value)
{
	for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
		next_iter = iter; next_iter++;
		if ((*iter).second <= value) this->items.erase(iter);
	}

	for (AIListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
		next_iter = iter; next_iter++;
		if ((*iter).first <= value) this->buckets.erase(iter);
	}
}

void AIList::KeepBelowValue(int32 value)
{
	for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
		next_iter = iter; next_iter++;
		if ((*iter).second >= value) this->items.erase(iter);
	}

	for (AIListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
		next_iter = iter; next_iter++;
		if ((*iter).first >= value) this->buckets.erase(iter);
	}
}

void AIList::KeepBetweenValue(int32 start, int32 end)
{
	for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
		next_iter = iter; next_iter++;
		if ((*iter).second <= start || (*iter).second >= end) this->items.erase(iter);
	}

	for (AIListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
		next_iter = iter; next_iter++;
		if ((*iter).first <= start || (*iter).first >= end) this->buckets.erase(iter);
	}
}

void AIList::KeepValue(int32 value)
{
	for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
		next_iter = iter; next_iter++;
		if ((*iter).second != value) this->items.erase(iter);
	}

	for (AIListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
		next_iter = iter; next_iter++;
		if ((*iter).first != value) this->buckets.erase(iter);
	}
}

void AIList::Valuate(const AIList::Valuator &proc)
{
	this->buckets.clear();
	for (AIListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) {
		int32 value = proc.Valuate((*iter).first);
		(*iter).second = value;
		this->buckets[value].insert((*iter).first);
	}
}