(svn r13615) [NoAI] -Fix: fixed most, if not all, problems around AIAbstractList. It is now safe to remove values while looping, among other things.
[NoAI] -Add: allow foreach() usage for AIAbstractList
[NoAI] -Add: allow [] usage for AIAbstractList (read-only)
[NoAI] -Add: allow [] usage for AIList (read/write)
--- a/bin/ai/regression/regression.nut Mon Jun 23 12:46:38 2008 +0000
+++ b/bin/ai/regression/regression.nut Mon Jun 23 13:52:21 2008 +0000
@@ -24,6 +24,146 @@
print(" min(3, 6): " + min(3, 6));
print(" max(6, 3): " + max(6, 3));
print(" max(3, 6): " + max(3, 6));
+
+ print(" AIList Consistency Tests");
+ print("");
+ print(" Value Descending");
+ local list = AIList();
+ list.AddItem( 5, 10);
+ list.AddItem(10, 10);
+ list.AddItem(15, 20);
+ list.AddItem(20, 20);
+ list.AddItem(25, 30);
+ list.AddItem(30, 30);
+ list.AddItem(35, 40);
+ list.AddItem(40, 40);
+
+ for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+ list.RemoveItem(i - 10);
+ list.RemoveItem(i - 5);
+ list.RemoveItem(i);
+ print(" " + i);
+ }
+
+ list.AddItem(10, 10);
+ list.AddItem(20, 20);
+ list.AddItem(30, 30);
+ list.AddItem(40, 40);
+
+ print("");
+ for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+ list.SetValue(i, 2);
+ print(" " + i);
+ }
+ print("");
+ for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+ print(" " + i);
+ }
+
+ list = AIList();
+ list.Sort(AIAbstractList.SORT_BY_VALUE, true);
+ print("");
+ print(" Value Ascending");
+ list.AddItem( 5, 10);
+ list.AddItem(10, 10);
+ list.AddItem(15, 20);
+ list.AddItem(20, 20);
+ list.AddItem(25, 30);
+ list.AddItem(30, 30);
+ list.AddItem(35, 40);
+ list.AddItem(40, 40);
+
+ for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+ list.RemoveItem(i + 10);
+ list.RemoveItem(i + 5);
+ list.RemoveItem(i);
+ print(" " + i);
+ }
+
+ list.AddItem(10, 10);
+ list.AddItem(20, 20);
+ list.AddItem(30, 30);
+ list.AddItem(40, 40);
+
+ print("");
+ for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+ list.SetValue(i, 50);
+ print(" " + i);
+ }
+ print("");
+ for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+ print(" " + i);
+ }
+
+ list = AIList();
+ list.Sort(AIAbstractList.SORT_BY_ITEM, false);
+ print("");
+ print(" Item Descending");
+ list.AddItem( 5, 10);
+ list.AddItem(10, 10);
+ list.AddItem(15, 20);
+ list.AddItem(20, 20);
+ list.AddItem(25, 30);
+ list.AddItem(30, 30);
+ list.AddItem(35, 40);
+ list.AddItem(40, 40);
+
+ for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+ list.RemoveItem(i - 10);
+ list.RemoveItem(i - 5);
+ list.RemoveItem(i);
+ print(" " + i);
+ }
+
+ list.AddItem(10, 10);
+ list.AddItem(20, 20);
+ list.AddItem(30, 30);
+ list.AddItem(40, 40);
+
+ print("");
+ for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+ list.SetValue(i, 2);
+ print(" " + i);
+ }
+ print("");
+ for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+ print(" " + i);
+ }
+
+ list = AIList();
+ list.Sort(AIAbstractList.SORT_BY_ITEM, true);
+ print("");
+ print(" Item Ascending");
+ list.AddItem( 5, 10);
+ list.AddItem(10, 10);
+ list.AddItem(15, 20);
+ list.AddItem(20, 20);
+ list.AddItem(25, 30);
+ list.AddItem(30, 30);
+ list.AddItem(35, 40);
+ list.AddItem(40, 40);
+
+ for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+ list.RemoveItem(i + 10);
+ list.RemoveItem(i + 5);
+ list.RemoveItem(i);
+ print(" " + i);
+ }
+
+ list.AddItem(10, 10);
+ list.AddItem(20, 20);
+ list.AddItem(30, 30);
+ list.AddItem(40, 40);
+
+ print("");
+ for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+ list.SetValue(i, 50);
+ print(" " + i);
+ }
+ print("");
+ for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
+ print(" " + i);
+ }
}
function Regression::Std()
@@ -593,7 +733,7 @@
}
list2.Clear();
for (local i = 4000; i < 4003; i++) {
- list2.AddItem(i, i);
+ list2.AddItem(i, i * 2);
}
list2.AddItem(1005, 1005);
list.AddList(list2);
@@ -601,6 +741,15 @@
for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
+ list[4000] = 50;
+ list[4006] = 12;
+
+ print(" foreach():");
+ foreach (idx, val in list) {
+ print(" " + idx + " => " + val);
+ }
+ print(" []:");
+ print(" 4000 => " + list[4000]);
list.Clear();
print(" IsEmpty(): " + list.IsEmpty());
@@ -753,6 +902,10 @@
for (local i = list.Begin(); list.HasNext(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
+ print(" foreach():");
+ foreach (idx, val in list) {
+ print(" " + idx + " => " + val);
+ }
}
function Regression::Pathfinder()
@@ -1427,6 +1580,8 @@
this.Vehicle();
/* Order has to be after Vehicle */
this.Order();
+ print("");
+ print(" First Subsidy Test");
PrintSubsidy(0);
/* Sleep now, to give time for events to happen */
--- a/bin/ai/regression/regression.txt Mon Jun 23 12:46:38 2008 +0000
+++ b/bin/ai/regression/regression.txt Mon Jun 23 13:52:21 2008 +0000
@@ -10,6 +10,75 @@
min(3, 6): 3
max(6, 3): 6
max(3, 6): 6
+ AIList Consistency Tests
+
+ Value Descending
+ 40
+ 25
+ 10
+
+ 40
+ 30
+ 20
+ 10
+ 40
+ 30
+ 20
+ 10
+
+ 40
+ 30
+ 20
+ 10
+
+ Value Ascending
+ 5
+ 20
+ 35
+
+ 10
+ 20
+ 30
+ 40
+ 10
+ 20
+ 30
+ 40
+
+ 10
+ 20
+ 30
+ 40
+
+ Item Descending
+ 40
+ 25
+ 10
+
+ 40
+ 30
+ 20
+ 10
+
+ 40
+ 30
+ 20
+ 10
+
+ Item Ascending
+ 5
+ 20
+ 35
+
+ 10
+ 20
+ 30
+ 40
+
+ 10
+ 20
+ 30
+ 40
--Std--
abs(-21): 21
@@ -488,9 +557,17 @@
1005 => 1911873386
AddList({1005, 4000, 4001, 4002}):
1005 => 1005
- 4000 => 4000
- 4001 => 4001
- 4002 => 4002
+ 4000 => 8000
+ 4001 => 8002
+ 4002 => 8004
+ foreach():
+ 1005 => 1005
+ 4000 => 50
+ 4001 => 8002
+ 4002 => 8004
+ 4006 => 12
+ []:
+ 4000 => 50
IsEmpty(): true
--AIAirport--
@@ -7215,6 +7292,10 @@
Count(): 1
Location ListDump:
11 => 33417
+ foreach():
+ 11 => 33417
+
+ First Subsidy Test
--Subsidy (0) --
IsValidSubsidy(): false
IsAwarded(): false
--- a/src/ai/api/Doxyfile Mon Jun 23 12:46:38 2008 +0000
+++ b/src/ai/api/Doxyfile Mon Jun 23 13:52:21 2008 +0000
@@ -200,7 +200,7 @@
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
-PREDEFINED =
+PREDEFINED = DOXYGEN_SKIP
EXPAND_AS_DEFINED = DEF_COMMAND
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
--- a/src/ai/api/ai_abstractlist.cpp Mon Jun 23 12:46:38 2008 +0000
+++ b/src/ai/api/ai_abstractlist.cpp Mon Jun 23 13:52:21 2008 +0000
@@ -34,6 +34,11 @@
* See if there is a next item of the sorter.
*/
virtual bool HasNext() = 0;
+
+ /**
+ * Callback from the list if an item gets removed.
+ */
+ virtual void Remove(int item) = 0;
};
/**
@@ -44,43 +49,77 @@
AIAbstractList::AIAbstractListBucket::iterator bucket_iter;
AIAbstractList::AIItemList *bucket_list;
AIAbstractList::AIItemList::iterator bucket_list_iter;
+ bool has_no_more_items;
+ int32 item_next;
public:
AIAbstractListSorterValueAscending(AIAbstractList *list)
{
this->list = list;
this->bucket_list = NULL;
+ this->has_no_more_items = true;
+
+ this->item_next = 0;
}
int32 Begin()
{
if (this->list->buckets.empty()) return 0;
+ this->has_no_more_items = false;
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;
+ this->item_next = *this->bucket_list_iter;
+
+ int32 item_current = this->item_next;
+ FindNext();
+ return item_current;
+ }
+
+ void FindNext()
+ {
+ if (this->bucket_list == NULL) {
+ this->has_no_more_items = true;
+ return;
+ }
+
+ this->bucket_list_iter++;
+ if (this->bucket_list_iter == this->bucket_list->end()) {
+ this->bucket_iter++;
+ if (this->bucket_iter == this->list->buckets.end()) {
+ this->bucket_list = NULL;
+ return;
+ }
+ this->bucket_list = &(*this->bucket_iter).second;
+ this->bucket_list_iter = this->bucket_list->begin();
+ }
+ this->item_next = *this->bucket_list_iter;
}
int32 Next()
{
- if (this->list->buckets.empty() || this->bucket_list == NULL) return 0;
+ if (!this->HasNext()) return 0;
- 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();
+ int32 item_current = this->item_next;
+ FindNext();
+ return item_current;
+ }
+
+ void Remove(int item)
+ {
+ if (!this->HasNext()) return;
+
+ /* If we remove the 'next' item, skip to the next */
+ if (item == this->item_next) {
+ FindNext();
+ return;
}
- return *bucket_list_iter;
}
bool HasNext()
{
- if (this->list->buckets.empty() || this->bucket_list == NULL) return false;
-
- return this->bucket_iter != this->list->buckets.end() && this->bucket_list_iter != this->bucket_list->end();
+ return !(this->list->buckets.empty() || this->has_no_more_items);
}
};
@@ -89,46 +128,88 @@
*/
class AIAbstractListSorterValueDescending : public AIAbstractListSorter {
private:
- AIAbstractList::AIAbstractListBucket::reverse_iterator bucket_iter;
+ AIAbstractList::AIAbstractListBucket::iterator bucket_iter;
AIAbstractList::AIItemList *bucket_list;
- AIAbstractList::AIItemList::reverse_iterator bucket_list_iter;
+ AIAbstractList::AIItemList::iterator bucket_list_iter;
+ bool has_no_more_items;
+ int32 item_next;
public:
AIAbstractListSorterValueDescending(AIAbstractList *list)
{
this->list = list;
this->bucket_list = NULL;
+ this->has_no_more_items = true;
+
+ this->item_next = 0;
}
int32 Begin()
{
if (this->list->buckets.empty()) return 0;
+ this->has_no_more_items = false;
- this->bucket_iter = this->list->buckets.rbegin();
+ /* Go to the end of the bucket-list */
+ this->bucket_iter = this->list->buckets.begin();
+ for (int i = this->list->buckets.size(); i > 1; i--) this->bucket_iter++;
this->bucket_list = &(*this->bucket_iter).second;
- this->bucket_list_iter = this->bucket_list->rbegin();
- return *bucket_list_iter;
+
+ /* Go to the end of the items in the bucket */
+ this->bucket_list_iter = this->bucket_list->begin();
+ for (int i = this->bucket_list->size(); i > 1; i--) this->bucket_list_iter++;
+ this->item_next = *this->bucket_list_iter;
+
+ int32 item_current = this->item_next;
+ FindNext();
+ return item_current;
+ }
+
+ void FindNext()
+ {
+ if (this->bucket_list == NULL) {
+ this->has_no_more_items = true;
+ return;
+ }
+
+ if (this->bucket_list_iter == this->bucket_list->begin()) {
+ if (this->bucket_iter == this->list->buckets.begin()) {
+ this->bucket_list = NULL;
+ return;
+ }
+ this->bucket_iter--;
+ this->bucket_list = &(*this->bucket_iter).second;
+ /* Go to the end of the items in the bucket */
+ this->bucket_list_iter = this->bucket_list->begin();
+ for (int i = this->bucket_list->size(); i > 1; i--) this->bucket_list_iter++;
+ } else {
+ this->bucket_list_iter--;
+ }
+ this->item_next = *this->bucket_list_iter;
}
int32 Next()
{
- if (this->list->buckets.empty() || this->bucket_list == NULL) return 0;
+ if (!this->HasNext()) return 0;
- 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();
+ int32 item_current = this->item_next;
+ FindNext();
+ return item_current;
+ }
+
+ void Remove(int item)
+ {
+ if (!this->HasNext()) return;
+
+ /* If we remove the 'next' item, skip to the next */
+ if (item == this->item_next) {
+ FindNext();
+ return;
}
- return *bucket_list_iter;
}
bool HasNext()
{
- if (this->list->buckets.empty() || this->bucket_list == NULL) return false;
-
- return this->bucket_iter != this->list->buckets.rend() && this->bucket_list_iter != this->bucket_list->rend();
+ return !(this->list->buckets.empty() || this->has_no_more_items);
}
};
@@ -138,34 +219,61 @@
class AIAbstractListSorterItemAscending : public AIAbstractListSorter {
private:
AIAbstractList::AIAbstractListMap::iterator item_iter;
+ bool has_no_more_items;
+ int32 item_next;
public:
AIAbstractListSorterItemAscending(AIAbstractList *list)
{
this->list = list;
+ this->has_no_more_items = true;
}
int32 Begin()
{
if (this->list->items.empty()) return 0;
+ this->has_no_more_items = false;
this->item_iter = this->list->items.begin();
- return (*this->item_iter).first;
+ this->item_next = (*this->item_iter).first;
+
+ int32 item_current = this->item_next;
+ FindNext();
+ return item_current;
+ }
+
+ void FindNext()
+ {
+ if (this->item_iter == this->list->items.end()) {
+ this->has_no_more_items = true;
+ return;
+ }
+ this->item_iter++;
+ if (this->item_iter != this->list->items.end()) item_next = (*this->item_iter).first;
}
int32 Next()
{
- if (this->list->items.empty()) return 0;
+ if (!this->HasNext()) return 0;
- this->item_iter++;
- return (*this->item_iter).first;
+ int32 item_current = this->item_next;
+ FindNext();
+ return item_current;
+ }
+
+ void Remove(int item) {
+ if (!this->HasNext()) return;
+
+ /* If we remove the 'next' item, skip to the next */
+ if (item == this->item_next) {
+ FindNext();
+ return;
+ }
}
bool HasNext()
{
- if (this->list->items.empty()) return false;
-
- return this->item_iter != this->list->items.end();
+ return !(this->list->items.empty() || this->has_no_more_items);
}
};
@@ -175,34 +283,62 @@
class AIAbstractListSorterItemDescending : public AIAbstractListSorter {
private:
AIAbstractList::AIAbstractListMap::reverse_iterator item_iter;
+ bool has_no_more_items;
+ int32 item_next;
public:
AIAbstractListSorterItemDescending(AIAbstractList *list)
{
this->list = list;
+ this->has_no_more_items = true;
}
int32 Begin()
{
if (this->list->items.empty()) return 0;
+ this->has_no_more_items = false;
this->item_iter = this->list->items.rbegin();
- return (*this->item_iter).first;
+ this->item_next = (*this->item_iter).first;
+
+ int32 item_current = this->item_next;
+ FindNext();
+ return item_current;
+ }
+
+ void FindNext()
+ {
+ if (this->item_iter == this->list->items.rend()) {
+ this->has_no_more_items = true;
+ return;
+ }
+ this->item_iter++;
+ if (this->item_iter != this->list->items.rend()) item_next = (*this->item_iter).first;
}
int32 Next()
{
- if (this->list->items.empty()) return 0;
+ if (!this->HasNext()) return 0;
- this->item_iter++;
- return (*this->item_iter).first;
+ int32 item_current = this->item_next;
+ FindNext();
+ return item_current;
+ }
+
+ void Remove(int item)
+ {
+ if (!this->HasNext()) return;
+
+ /* If we remove the 'next' item, skip to the next */
+ if (item == this->item_next) {
+ FindNext();
+ return;
+ }
}
bool HasNext()
{
- if (this->list->items.empty()) return false;
-
- return this->item_iter != this->list->items.rend();
+ return !(this->list->items.empty() || this->has_no_more_items);
}
};
@@ -245,8 +381,11 @@
{
if (!this->HasItem(item)) return;
- this->buckets[this->GetValue(item)].erase(item);
- if (this->buckets[this->GetValue(item)].empty()) this->buckets.erase(this->GetValue(item));
+ int32 value = this->GetValue(item);
+
+ this->sorter->Remove(item);
+ this->buckets[value].erase(item);
+ if (this->buckets[value].empty()) this->buckets.erase(value);
this->items.erase(item);
}
@@ -295,8 +434,11 @@
{
if (!this->HasItem(item)) return false;
- this->buckets[this->GetValue(item)].erase(item);
- if (this->buckets[this->GetValue(item)].empty()) this->buckets.erase(this->GetValue(item));
+ int32 value_old = this->GetValue(item);
+
+ this->sorter->Remove(item);
+ this->buckets[value_old].erase(item);
+ if (this->buckets[value_old].empty()) this->buckets.erase(value_old);
this->items[item] = value;
this->buckets[value].insert(item);
@@ -539,6 +681,37 @@
this->RemoveList(&tmp);
}
+SQInteger AIAbstractList::_get(HSQUIRRELVM vm) {
+ if (sq_gettype(vm, 2) != OT_INTEGER) return SQ_ERROR;
+
+ SQInteger idx;
+ sq_getinteger(vm, 2, &idx);
+
+ if (!this->HasItem(idx)) return SQ_ERROR;
+
+ sq_pushinteger(vm, this->GetValue(idx));
+ return 1;
+}
+
+SQInteger AIAbstractList::_nexti(HSQUIRRELVM vm) {
+ if (sq_gettype(vm, 2) == OT_NULL) {
+ sq_pushinteger(vm, this->Begin());
+ return 1;
+ }
+
+ SQInteger idx;
+ sq_getinteger(vm, 2, &idx);
+
+ int val = this->Next();
+ if (!this->HasNext()) {
+ sq_pushnull(vm);
+ return 1;
+ }
+
+ sq_pushinteger(vm, val);
+ return 1;
+}
+
SQInteger AIAbstractList::Valuate(HSQUIRRELVM vm) {
int nparam = sq_gettop(vm) - 2;
@@ -548,12 +721,10 @@
sq_getstackobj(vm, 2, &obj_func);
if (sq_isclass(obj_list)) {
- sq_throwerror(vm, _SC("parameter 1 has an invalid type (expected instance)"));
- return -1;
+ return sq_throwerror(vm, _SC("parameter 1 has an invalid type (expected instance)"));
}
if (sq_isfunction(obj_func)) {
- sq_throwerror(vm, _SC("parameter 2 has an invalid type (expected function)"));
- return -1;
+ return sq_throwerror(vm, _SC("parameter 2 has an invalid type (expected function)"));
}
sq_addref(vm, &obj_func);
@@ -582,7 +753,7 @@
}
/* Call the function */
- if (SQ_FAILED(sq_call(vm, nparam + 2, SQTrue, SQTrue))) return -1;
+ if (SQ_FAILED(sq_call(vm, nparam + 2, SQTrue, SQTrue))) return SQ_ERROR;
/* Retreive the return value */
SQInteger value;
@@ -602,8 +773,7 @@
sq_release(vm, &obj_func);
for (int i = 0; i < nparam; i++) sq_release(vm, &obj_params[i]);
- sq_throwerror(vm, _SC("return value of valuator is not valid (not integer/bool)"));
- return -1;
+ return sq_throwerror(vm, _SC("return value of valuator is not valid (not integer/bool)"));
}
}
/* Remove junk */
--- a/src/ai/api/ai_abstractlist.hpp Mon Jun 23 12:46:38 2008 +0000
+++ b/src/ai/api/ai_abstractlist.hpp Mon Jun 23 13:52:21 2008 +0000
@@ -113,6 +113,8 @@
* @param item the item to set the value for.
* @param value the value to give to the item
* @return true if we could set the item to value, false otherwise.
+ * @note Changing values of items while looping through a list might cause
+ * entries to be skipped. Be very careful with such operations.
*/
bool SetValue(int32 item, int32 value);
@@ -222,15 +224,31 @@
*/
void KeepList(AIAbstractList *list);
+#ifndef DOXYGEN_SKIP
+ /**
+ * Used for 'foreach()' and [] get from Squirrel.
+ */
+ SQInteger _get(HSQUIRRELVM vm);
+
+ /**
+ * Used for 'foreach()' from Squirrel.
+ */
+ SQInteger _nexti(HSQUIRRELVM vm);
+
+ /**
+ * The Valuate() wrapper from Squirrel.
+ */
+ SQInteger Valuate(HSQUIRRELVM vm);
+#else
/**
* Give all items a value defined by the valuator you give.
- * @param vm Internal pointer, not something you need to specify.
- * @return The result of the valuation.
- * @note The first param for this function is the function you want to use
- * to valuate the items in the list. It should accept at least one integer
- * which will be set to the item, and should return an integer, which will
- * become the value of the item. Additional parameters are possible, then
- * you need to add them to the Valuator to. Example:
+ * @param valuator_function The function which will be doing the valuation.
+ * @param params The params to give to the valuators (minus the first param,
+ * which is always the index-value we are valuating).
+ * @note You can write your own valuators and use them. Just remember that
+ * the first parameter should be the index-value, and it should return
+ * an integer.
+ * @note Example:
* list.Valuate(AIBridge.GetPrice, 5);
* list.Valuate(AIBridge.GetMaxLength);
* function MyVal(bridge_id, myparam) {
@@ -238,7 +256,8 @@
* }
* list.Valuate(MyVal, 12);
*/
- SQInteger Valuate(HSQUIRRELVM vm);
+ void Valuate(void *valuator_function, int params, ...);
+#endif /* DOXYGEN_SKIP */
};
#endif /* AI_LIST_HPP */
--- a/src/ai/api/ai_abstractlist.hpp.sq Mon Jun 23 12:46:38 2008 +0000
+++ b/src/ai/api/ai_abstractlist.hpp.sq Mon Jun 23 13:52:21 2008 +0000
@@ -51,6 +51,8 @@
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.DefSQAdvancedMethod(engine, &AIAbstractList::_get, "_get");
+ SQAIAbstractList.DefSQAdvancedMethod(engine, &AIAbstractList::_nexti, "_nexti");
SQAIAbstractList.DefSQAdvancedMethod(engine, &AIAbstractList::Valuate, "Valuate");
SQAIAbstractList.PostRegister(engine);
--- a/src/ai/api/ai_list.cpp Mon Jun 23 12:46:38 2008 +0000
+++ b/src/ai/api/ai_list.cpp Mon Jun 23 13:52:21 2008 +0000
@@ -2,6 +2,7 @@
/** @file ai_list.cpp Implementation of AIList. */
+#include <squirrel.h>
#include "ai_list.hpp"
void AIList::AddItem(int32 item, int32 value)
@@ -19,3 +20,26 @@
{
AIAbstractList::RemoveItem(item);
}
+
+SQInteger AIList::_set(HSQUIRRELVM vm) {
+ if (sq_gettype(vm, 2) != OT_INTEGER) return SQ_ERROR;
+ if (sq_gettype(vm, 3) != OT_INTEGER || sq_gettype(vm, 3) == OT_NULL) {
+ return sq_throwerror(vm, _SC("you can only assign integers to this list"));
+ }
+
+ SQInteger idx, val;
+ sq_getinteger(vm, 2, &idx);
+ if (sq_gettype(vm, 3) == OT_NULL) {
+ this->RemoveItem(idx);
+ return 0;
+ }
+
+ sq_getinteger(vm, 3, &val);
+ if (!this->HasItem(idx)) {
+ this->AddItem(idx, val);
+ return 0;
+ }
+
+ this->ChangeItem(idx, val);
+ return 0;
+}
--- a/src/ai/api/ai_list.hpp Mon Jun 23 12:46:38 2008 +0000
+++ b/src/ai/api/ai_list.hpp Mon Jun 23 13:52:21 2008 +0000
@@ -35,6 +35,13 @@
* @param item the item to remove.
*/
void RemoveItem(int32 item);
+
+#ifndef DOXYGEN_SKIP
+ /**
+ * Used for [] set from Squirrel.
+ */
+ SQInteger _set(HSQUIRRELVM vm);
+#endif /* DOXYGEN_SKIP */
};
#endif /* AI_LIST_HPP */
--- a/src/ai/api/ai_list.hpp.sq Mon Jun 23 12:46:38 2008 +0000
+++ b/src/ai/api/ai_list.hpp.sq Mon Jun 23 13:52:21 2008 +0000
@@ -22,6 +22,7 @@
SQAIList.DefSQMethod(engine, &AIList::AddItem, "AddItem", 3, "xii");
SQAIList.DefSQMethod(engine, &AIList::ChangeItem, "ChangeItem", 3, "xii");
SQAIList.DefSQMethod(engine, &AIList::RemoveItem, "RemoveItem", 2, "xi");
+ SQAIList.DefSQAdvancedMethod(engine, &AIList::_set, "_set");
SQAIList.PostRegister(engine);
}
--- a/src/ai/api/squirrel_export.awk Mon Jun 23 12:46:38 2008 +0000
+++ b/src/ai/api/squirrel_export.awk Mon Jun 23 13:52:21 2008 +0000
@@ -81,6 +81,20 @@
/^( *)protected/ { if (cls_level == 1) public = "false"; next; }
/^( *)private/ { if (cls_level == 1) public = "false"; next; }
+# Ignore special doxygen blocks
+/^#ifndef DOXYGEN_SKIP/ { doxygen_skip = "next"; next; }
+/^#ifdef DOXYGEN_SKIP/ { doxygen_skip = "true"; next; }
+/^#endif/ { doxygen_skip = "false"; next; }
+/^#else/ {
+ if (doxygen_skip == "next") {
+ doxygen_skip = "true";
+ } else {
+ doxygen_skip = "false";
+ }
+ next;
+}
+{ if (doxygen_skip == "true") next }
+
# Ignore the comments
/^#/ { next; }
/\/\*.*\*\// { comment = "false"; next; }