(svn r10579) [NoAI] -Add: functions to remove/keep the top/bottom X items from a list. noai
authorrubidium
Sun, 15 Jul 2007 12:36:43 +0000
branchnoai
changeset 9665 e889ac1e663a
parent 9664 c5741021bf59
child 9666 5765eb70736d
(svn r10579) [NoAI] -Add: functions to remove/keep the top/bottom X items from a list.
[NoAI] -Add: functions to remove/keep items given in another list.
bin/ai/regression/regression.nut
bin/ai/regression/regression.txt
src/ai/api/ai_abstractlist.cpp
src/ai/api/ai_abstractlist.hpp
src/ai/api/ai_abstractlist.hpp.sq
--- a/bin/ai/regression/regression.nut	Sun Jul 15 11:45:25 2007 +0000
+++ b/bin/ai/regression/regression.nut	Sun Jul 15 12:36:43 2007 +0000
@@ -215,7 +215,7 @@
 	print("  HasItem(1050): " + list.HasItem(1050));
 	print("  HasItem(1051): " + list.HasItem(1051));
 	print("  IsEmpty():     " + list.IsEmpty());
-	list.SortByItem(true);
+	list.Sort(AIAbstractList.SORT_BY_ITEM, true);
 	print("  List Dump:");
 	for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
 		print("    " + i + " => " + list.GetValue(i));
@@ -225,6 +225,43 @@
 	for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
 		print("    " + i + " => " + list.GetValue(i));
 	}
+
+	list.KeepTop(10);
+	print("  KeepTop(10):");
+	for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+		print("    " + i + " => " + list.GetValue(i));
+	}
+	list.KeepBottom(8);
+	print("  KeepBottom(8):");
+	for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+		print("    " + i + " => " + list.GetValue(i));
+	}
+	list.RemoveBottom(2);
+	print("  RemoveBottom(2):");
+	for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+		print("    " + i + " => " + list.GetValue(i));
+	}
+	list.RemoveTop(2);
+	print("  RemoveTop(2):");
+	for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+		print("    " + i + " => " + list.GetValue(i));
+	}
+
+	local list2 = AIList();
+	list2.AddItem(1003, 0);
+	list2.AddItem(1004, 0);
+	list.RemoveList(list2);
+	print("  RemoveList({1003, 1004}):");
+	for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+		print("    " + i + " => " + list.GetValue(i));
+	}
+	list2.AddItem(1005, 0);
+	list.KeepList(list2);
+	print("  KeepList({1003, 1004, 1005}):");
+	for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+		print("    " + i + " => " + list.GetValue(i));
+	}
+
 	list.Clear();
 	print("  IsEmpty():     " + list.IsEmpty());
 }
--- a/bin/ai/regression/regression.txt	Sun Jul 15 11:45:25 2007 +0000
+++ b/bin/ai/regression/regression.txt	Sun Jul 15 12:36:43 2007 +0000
@@ -968,6 +968,43 @@
     1097 => -1491076971
     1098 => 1172943384
     1099 => 9895172
+  KeepTop(10):
+    1 => -2039536299
+    2 => 796838333
+    1000 => 438558874
+    1001 => 179516226
+    1002 => -1007339217
+    1003 => 859527945
+    1004 => 124767077
+    1005 => 1693978408
+    1006 => -880974321
+    1007 => 559618342
+  KeepBottom(8):
+    1000 => 438558874
+    1001 => 179516226
+    1002 => -1007339217
+    1003 => 859527945
+    1004 => 124767077
+    1005 => 1693978408
+    1006 => -880974321
+    1007 => 559618342
+  RemoveBottom(2):
+    1000 => 438558874
+    1001 => 179516226
+    1002 => -1007339217
+    1003 => 859527945
+    1004 => 124767077
+    1005 => 1693978408
+  RemoveTop(2):
+    1002 => -1007339217
+    1003 => 859527945
+    1004 => 124767077
+    1005 => 1693978408
+  RemoveList({1003, 1004}):
+    1002 => -1007339217
+    1005 => 1693978408
+  KeepList({1003, 1004, 1005}):
+    1005 => 1693978408
   IsEmpty():     true
 
 --PathFinderStupid--
--- a/src/ai/api/ai_abstractlist.cpp	Sun Jul 15 11:45:25 2007 +0000
+++ b/src/ai/api/ai_abstractlist.cpp	Sun Jul 15 12:36:43 2007 +0000
@@ -206,7 +206,9 @@
 AIAbstractList::AIAbstractList()
 {
 	/* Default sorter */
-	this->sorter = new AIAbstractListSorterValueDescending(this);
+	this->sorter         = new AIAbstractListSorterValueDescending(this);
+	this->sorter_type    = SORT_BY_VALUE;
+	this->sort_ascending = false;
 }
 
 AIAbstractList::~AIAbstractList()
@@ -286,18 +288,28 @@
 	return true;
 }
 
-void AIAbstractList::SortByItem(bool ascending)
+void AIAbstractList::Sort(SorterType sorter, bool ascending)
 {
+	if (sorter == this->sorter_type && ascending == this->sort_ascending) return;
+
 	delete this->sorter;
-	if (ascending) this->sorter = new AIAbstractListSorterItemAscending(this);
-	else           this->sorter = new AIAbstractListSorterItemDescending(this);
-}
+	switch (sorter) {
+		case SORT_BY_ITEM:
+			if (ascending) this->sorter = new AIAbstractListSorterItemAscending(this);
+			else           this->sorter = new AIAbstractListSorterItemDescending(this);
+			break;
 
-void AIAbstractList::SortByValue(bool ascending)
-{
-	delete this->sorter;
-	if (ascending) this->sorter = new AIAbstractListSorterValueAscending(this);
-	else           this->sorter = new AIAbstractListSorterValueDescending(this);
+		case SORT_BY_VALUE:
+			if (ascending) this->sorter = new AIAbstractListSorterItemAscending(this);
+			else           this->sorter = new AIAbstractListSorterItemDescending(this);
+			break;
+
+		default:
+			this->Sort(SORT_BY_ITEM, false);
+			return;
+	}
+	this->sorter_type    = sorter;
+	this->sort_ascending = ascending;
 }
 
 void AIAbstractList::RemoveAboveValue(int32 value)
@@ -352,6 +364,79 @@
 	}
 }
 
+void AIAbstractList::RemoveTop(int32 count)
+{
+	if (!this->sort_ascending) {
+		this->Sort(this->sorter_type, !this->sort_ascending);
+		this->RemoveBottom(count);
+		this->Sort(this->sorter_type, !this->sort_ascending);
+		return;
+	}
+
+	switch (this->sorter_type) {
+		default: NOT_REACHED();
+		case SORT_BY_VALUE:
+			for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
+				next_iter = iter; next_iter++;
+				AIItemList *items = &(*iter).second;
+				for (AIItemList::iterator next_iter, iter = items->begin(); iter != items->end(); iter = next_iter) {
+					if (--count < 0) return;
+					next_iter = iter; next_iter++;
+					this->RemoveItem(*iter);
+				}
+			}
+			break;
+
+		case SORT_BY_ITEM:
+			for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
+				if (--count < 0) return;
+				next_iter = iter; next_iter++;
+				this->RemoveItem((*iter).first);
+			}
+			break;
+	}
+}
+
+void AIAbstractList::RemoveBottom(int32 count)
+{
+	if (!this->sort_ascending) {
+		this->Sort(this->sorter_type, !this->sort_ascending);
+		this->RemoveTop(count);
+		this->Sort(this->sorter_type, !this->sort_ascending);
+		return;
+	}
+
+	switch (this->sorter_type) {
+		default: NOT_REACHED();
+		case SORT_BY_VALUE:
+			for (AIAbstractListBucket::reverse_iterator next_iter, iter = this->buckets.rbegin(); iter != this->buckets.rend(); iter = next_iter) {
+				next_iter = iter; next_iter++;
+				AIItemList *items = &(*iter).second;
+				for (AIItemList::reverse_iterator next_iter, iter = items->rbegin(); iter != items->rend(); iter = next_iter) {
+					if (--count < 0) return;
+					next_iter = iter; next_iter++;
+					this->RemoveItem(*iter);
+				}
+			}
+
+		case SORT_BY_ITEM:
+			for (AIAbstractListMap::reverse_iterator next_iter, iter = this->items.rbegin(); iter != this->items.rend(); iter = next_iter) {
+				if (--count < 0) return;
+				next_iter = iter; next_iter++;
+				this->RemoveItem((*iter).first);
+			}
+			break;
+	}
+}
+
+void AIAbstractList::RemoveList(AIAbstractList *list)
+{
+	AIAbstractListMap *list_items = &list->items;
+	for (AIAbstractListMap::iterator iter = list_items->begin(); iter != list_items->end(); iter++) {
+		this->RemoveItem((*iter).first);
+	}
+}
+
 void AIAbstractList::KeepAboveValue(int32 value)
 {
 	for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
@@ -404,6 +489,28 @@
 	}
 }
 
+void AIAbstractList::KeepTop(int32 count)
+{
+	this->RemoveBottom(this->Count() - count);
+}
+
+void AIAbstractList::KeepBottom(int32 count)
+{
+	this->RemoveTop(this->Count() - count);
+}
+
+void AIAbstractList::KeepList(AIAbstractList *list)
+{
+	AIAbstractList tmp;
+	for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) {
+		tmp.AddItem((*iter).first);
+		tmp.SetValue((*iter).first, (*iter).second);
+	}
+
+	tmp.RemoveList(list);
+	this->RemoveList(&tmp);
+}
+
 void AIAbstractList::Valuate(const AIAbstractList::Valuator &proc)
 {
 	this->buckets.clear();
--- a/src/ai/api/ai_abstractlist.hpp	Sun Jul 15 11:45:25 2007 +0000
+++ b/src/ai/api/ai_abstractlist.hpp	Sun Jul 15 12:36:43 2007 +0000
@@ -15,8 +15,17 @@
  * Class that creates a linked list which can keep item/value pairs.
  */
 class AIAbstractList : public AIObject {
+public:
+	/** Type of sorter */
+	enum SorterType {
+		SORT_BY_VALUE = 0,
+		SORT_BY_ITEM  = 1,
+	};
+
 private:
 	AIAbstractListSorter *sorter;
+	SorterType sorter_type;
+	bool sort_ascending;
 
 public:
 	typedef std::set<int32> AIItemList;               ///< The list of items inside the bucket
@@ -116,18 +125,12 @@
 	bool SetValue(int32 item, int32 value);
 
 	/**
-	 * Sort this list by item-value.
+	 * Sort this list by the given sorter and direction.
+	 * @param sorter    the type of sorter to use
 	 * @param ascending if true, lowest value is on top, else at bottom.
 	 * @note the current item stays at the same place.
 	 */
-	void SortByItem(bool ascending);
-
-	/**
-	 * Sort this list by the value of the items.
-	 * @param ascending if true, lowest value is on top, else at bottom.
-	 * @note the current item stays at the same place.
-	 */
-	void SortByValue(bool ascending);
+	void Sort(SorterType sorter, bool ascending);
 
 	/**
 	 * Removes all items with a higher value than 'value'.
@@ -155,6 +158,25 @@
 	void RemoveValue(int32 value);
 
 	/**
+	 * Remove the first count items.
+	 * @param count the amount of items to remove.
+	 */
+	void RemoveTop(int32 count);
+
+	/**
+	 * Remove the last count items.
+	 * @param count the amount of items to remove.
+	 */
+	void RemoveBottom(int32 count);
+
+	/**
+	 * Remove everything that is in the given list from this list (same item index that is).
+	 * @param list the list of items to remove.
+	 * @pre list != NULL
+	 */
+	void RemoveList(AIAbstractList *list);
+
+	/**
 	 * Keep all items with a higher value than 'value'.
 	 * @param value the value above which all items are kept.
 	 */
@@ -180,6 +202,25 @@
 	void KeepValue(int32 value);
 
 	/**
+	 * Keep the first count items, i.e. remove everything except the first count items.
+	 * @param count the amount of items to keep.
+	 */
+	void KeepTop(int32 count);
+
+	/**
+	 * Keep the last count items, i.e. remove everything except the last count items.
+	 * @param count the amount of items to keep.
+	 */
+	void KeepBottom(int32 count);
+
+	/**
+	 * Keps everything that is in the given list from this list (same item index that is).
+	 * @param list the list of items to keep.
+	 * @pre list != NULL
+	 */
+	void KeepList(AIAbstractList *list);
+
+	/**
 	 * The definition how valuators should look.
 	 */
 	class Valuator {
--- a/src/ai/api/ai_abstractlist.hpp.sq	Sun Jul 15 11:45:25 2007 +0000
+++ b/src/ai/api/ai_abstractlist.hpp.sq	Sun Jul 15 12:36:43 2007 +0000
@@ -1,6 +1,9 @@
 #include "ai_abstractlist.hpp"
 
 namespace SQConvert {
+	/* Allow enums to be used as Squirrel parameters */
+	template <> AIAbstractList::SorterType GetParam(ForceType<AIAbstractList::SorterType>, HSQUIRRELVM vm, int index) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIAbstractList::SorterType)tmp; }
+	template <> int Return<AIAbstractList::SorterType>(HSQUIRRELVM vm, AIAbstractList::SorterType res) { sq_pushinteger(vm, (int32)res); return 1; }
 	/* Allow inner classes/structs to be used as Squirrel parameters */
 	template <> AIAbstractList::Valuator *GetParam(ForceType<AIAbstractList::Valuator *>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AIAbstractList::Valuator *)instance; }
 	template <> AIAbstractList::Valuator &GetParam(ForceType<AIAbstractList::Valuator &>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIAbstractList::Valuator *)instance; }
@@ -19,6 +22,9 @@
 	SQAIAbstractList.PreRegister(engine);
 	SQAIAbstractList.AddConstructor<void (AIAbstractList::*)(), 1>(engine, "x");
 
+	SQAIAbstractList.DefSQConst(engine, AIAbstractList::SORT_BY_VALUE, "SORT_BY_VALUE");
+	SQAIAbstractList.DefSQConst(engine, AIAbstractList::SORT_BY_ITEM,  "SORT_BY_ITEM");
+
 	SQAIAbstractList.DefSQStaticMethod(engine, &AIAbstractList::GetClassName, "GetClassName", 1, "x");
 
 	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::Clear,              "Clear",              1, "x");
@@ -30,16 +36,21 @@
 	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::Count,              "Count",              1, "x");
 	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::GetValue,           "GetValue",           2, "xi");
 	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::SetValue,           "SetValue",           3, "xii");
-	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::SortByItem,         "SortByItem",         2, "xb");
-	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::SortByValue,        "SortByValue",        2, "xb");
+	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::Sort,               "Sort",               3, "xib");
 	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveAboveValue,   "RemoveAboveValue",   2, "xi");
 	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveBelowValue,   "RemoveBelowValue",   2, "xi");
 	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveBetweenValue, "RemoveBetweenValue", 3, "xii");
 	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveValue,        "RemoveValue",        2, "xi");
+	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveTop,          "RemoveTop",          2, "xi");
+	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveBottom,       "RemoveBottom",       2, "xi");
+	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveList,         "RemoveList",         2, "xx");
 	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepAboveValue,     "KeepAboveValue",     2, "xi");
 	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepBelowValue,     "KeepBelowValue",     2, "xi");
 	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepBetweenValue,   "KeepBetweenValue",   3, "xii");
 	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepValue,          "KeepValue",          2, "xi");
+	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepTop,            "KeepTop",            2, "xi");
+	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepBottom,         "KeepBottom",         2, "xi");
+	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepList,           "KeepList",           2, "xx");
 	SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::Valuate,            "Valuate",            2, "xx");
 
 	SQAIAbstractList.PostRegister(engine);