# HG changeset patch # User truebrain # Date 1214229141 0 # Node ID 3305a425f55b29f243c94801a428afb28c8d1c5c # Parent 188a9ca6d8de79bbf95875e39019e28898bcaad3 (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) diff -r 188a9ca6d8de -r 3305a425f55b bin/ai/regression/regression.nut --- 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 */ diff -r 188a9ca6d8de -r 3305a425f55b bin/ai/regression/regression.txt --- 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 diff -r 188a9ca6d8de -r 3305a425f55b src/ai/api/Doxyfile --- 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 #--------------------------------------------------------------------------- diff -r 188a9ca6d8de -r 3305a425f55b src/ai/api/ai_abstractlist.cpp --- 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 */ diff -r 188a9ca6d8de -r 3305a425f55b src/ai/api/ai_abstractlist.hpp --- 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 */ diff -r 188a9ca6d8de -r 3305a425f55b src/ai/api/ai_abstractlist.hpp.sq --- 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); diff -r 188a9ca6d8de -r 3305a425f55b src/ai/api/ai_list.cpp --- 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 #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; +} diff -r 188a9ca6d8de -r 3305a425f55b src/ai/api/ai_list.hpp --- 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 */ diff -r 188a9ca6d8de -r 3305a425f55b src/ai/api/ai_list.hpp.sq --- 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); } diff -r 188a9ca6d8de -r 3305a425f55b src/ai/api/squirrel_export.awk --- 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; }