# ai_abstractlist.cpp

Go to the documentation of this file.

    00001 /* $Id: ai_abstractlist.cpp 15658 2009-03-09 22:14:47Z yexo $ */
    00002
    00005 #include <squirrel.h>
    00006 #include "ai_abstractlist.hpp"
    00007 #include "../../debug.h"
    00008 #include "../../core/alloc_func.hpp"
    00009 #include "../../script/squirrel.hpp"
    00010
    00014 class AIAbstractListSorter {
    00015 protected:
    00016   AIAbstractList *list;
    00017
    00018 public:
    00022   virtual ~AIAbstractListSorter() { }
    00023
    00027   virtual int32 Begin() = 0;
    00028
    00032   virtual void End() = 0;
    00033
    00037   virtual int32 Next() = 0;
    00038
    00042   virtual bool HasNext() = 0;
    00043
    00047   virtual void Remove(int item) = 0;
    00048 };
    00049
    00053 class AIAbstractListSorterValueAscending : public AIAbstractListSorter {
    00054 private:
    00055   AIAbstractList::AIAbstractListBucket::iterator bucket_iter;
    00056   AIAbstractList::AIItemList *bucket_list;
    00057   AIAbstractList::AIItemList::iterator bucket_list_iter;
    00058   bool has_no_more_items;
    00059   int32 item_next;
    00060
    00061 public:
    00062   AIAbstractListSorterValueAscending(AIAbstractList *list)
    00063   {
    00064     this->list = list;
    00065     this->End();
    00066   }
    00067
    00068   int32 Begin()
    00069   {
    00070     if (this->list->buckets.empty()) return 0;
    00071     this->has_no_more_items = false;
    00072
    00073     this->bucket_iter = this->list->buckets.begin();
    00074     this->bucket_list = &(*this->bucket_iter).second;
    00075     this->bucket_list_iter = this->bucket_list->begin();
    00076     this->item_next = *this->bucket_list_iter;
    00077
    00078     int32 item_current = this->item_next;
    00079     FindNext();
    00080     return item_current;
    00081   }
    00082
    00083   void End()
    00084   {
    00085     this->bucket_list = NULL;
    00086     this->has_no_more_items = true;
    00087     this->item_next = 0;
    00088   }
    00089
    00090   void FindNext()
    00091   {
    00092     if (this->bucket_list == NULL) {
    00093       this->has_no_more_items = true;
    00094       return;
    00095     }
    00096
    00097     this->bucket_list_iter++;
    00098     if (this->bucket_list_iter == this->bucket_list->end()) {
    00099       this->bucket_iter++;
    00100       if (this->bucket_iter == this->list->buckets.end()) {
    00101         this->bucket_list = NULL;
    00102         return;
    00103       }
    00104       this->bucket_list = &(*this->bucket_iter).second;
    00105       this->bucket_list_iter = this->bucket_list->begin();
    00106     }
    00107     this->item_next = *this->bucket_list_iter;
    00108   }
    00109
    00110   int32 Next()
    00111   {
    00112     if (!this->HasNext()) return 0;
    00113
    00114     int32 item_current = this->item_next;
    00115     FindNext();
    00116     return item_current;
    00117   }
    00118
    00119   void Remove(int item)
    00120   {
    00121     if (!this->HasNext()) return;
    00122
    00123     /* If we remove the 'next' item, skip to the next */
    00124     if (item == this->item_next) {
    00125       FindNext();
    00126       return;
    00127     }
    00128   }
    00129
    00130   bool HasNext()
    00131   {
    00132     return !(this->list->buckets.empty() || this->has_no_more_items);
    00133   }
    00134 };
    00135
    00139 class AIAbstractListSorterValueDescending : public AIAbstractListSorter {
    00140 private:
    00141   AIAbstractList::AIAbstractListBucket::iterator bucket_iter;
    00142   AIAbstractList::AIItemList *bucket_list;
    00143   AIAbstractList::AIItemList::iterator bucket_list_iter;
    00144   bool has_no_more_items;
    00145   int32 item_next;
    00146
    00147 public:
    00148   AIAbstractListSorterValueDescending(AIAbstractList *list)
    00149   {
    00150     this->list = list;
    00151     this->End();
    00152   }
    00153
    00154   int32 Begin()
    00155   {
    00156     if (this->list->buckets.empty()) return 0;
    00157     this->has_no_more_items = false;
    00158
    00159     /* Go to the end of the bucket-list */
    00160     this->bucket_iter = this->list->buckets.begin();
    00161     for (size_t i = this->list->buckets.size(); i > 1; i--) this->bucket_iter++;
    00162     this->bucket_list = &(*this->bucket_iter).second;
    00163
    00164     /* Go to the end of the items in the bucket */
    00165     this->bucket_list_iter = this->bucket_list->begin();
    00166     for (size_t i = this->bucket_list->size(); i > 1; i--) this->bucket_list_iter++;
    00167     this->item_next = *this->bucket_list_iter;
    00168
    00169     int32 item_current = this->item_next;
    00170     FindNext();
    00171     return item_current;
    00172   }
    00173
    00174   void End() {
    00175     this->bucket_list = NULL;
    00176     this->has_no_more_items = true;
    00177     this->item_next = 0;
    00178   }
    00179
    00180   void FindNext()
    00181   {
    00182     if (this->bucket_list == NULL) {
    00183       this->has_no_more_items = true;
    00184       return;
    00185     }
    00186
    00187     if (this->bucket_list_iter == this->bucket_list->begin()) {
    00188       if (this->bucket_iter == this->list->buckets.begin()) {
    00189         this->bucket_list = NULL;
    00190         return;
    00191       }
    00192       this->bucket_iter--;
    00193       this->bucket_list = &(*this->bucket_iter).second;
    00194       /* Go to the end of the items in the bucket */
    00195       this->bucket_list_iter = this->bucket_list->begin();
    00196       for (size_t i = this->bucket_list->size(); i > 1; i--) this->bucket_list_iter++;
    00197     } else {
    00198       this->bucket_list_iter--;
    00199     }
    00200     this->item_next = *this->bucket_list_iter;
    00201   }
    00202
    00203   int32 Next()
    00204   {
    00205     if (!this->HasNext()) return 0;
    00206
    00207     int32 item_current = this->item_next;
    00208     FindNext();
    00209     return item_current;
    00210   }
    00211
    00212   void Remove(int item)
    00213   {
    00214     if (!this->HasNext()) return;
    00215
    00216     /* If we remove the 'next' item, skip to the next */
    00217     if (item == this->item_next) {
    00218       FindNext();
    00219       return;
    00220     }
    00221   }
    00222
    00223   bool HasNext()
    00224   {
    00225     return !(this->list->buckets.empty() || this->has_no_more_items);
    00226   }
    00227 };
    00228
    00232 class AIAbstractListSorterItemAscending : public AIAbstractListSorter {
    00233 private:
    00234   AIAbstractList::AIAbstractListMap::iterator item_iter;
    00235   bool has_no_more_items;
    00236   int32 item_next;
    00237
    00238 public:
    00239   AIAbstractListSorterItemAscending(AIAbstractList *list)
    00240   {
    00241     this->list = list;
    00242     this->End();
    00243   }
    00244
    00245   int32 Begin()
    00246   {
    00247     if (this->list->items.empty()) return 0;
    00248     this->has_no_more_items = false;
    00249
    00250     this->item_iter = this->list->items.begin();
    00251     this->item_next = (*this->item_iter).first;
    00252
    00253     int32 item_current = this->item_next;
    00254     FindNext();
    00255     return item_current;
    00256   }
    00257
    00258   void End()
    00259   {
    00260     this->has_no_more_items = true;
    00261   }
    00262
    00263   void FindNext()
    00264   {
    00265     if (this->item_iter == this->list->items.end()) {
    00266       this->has_no_more_items = true;
    00267       return;
    00268     }
    00269     this->item_iter++;
    00270     if (this->item_iter != this->list->items.end()) item_next = (*this->item_iter).first;
    00271   }
    00272
    00273   int32 Next()
    00274   {
    00275     if (!this->HasNext()) return 0;
    00276
    00277     int32 item_current = this->item_next;
    00278     FindNext();
    00279     return item_current;
    00280   }
    00281
    00282   void Remove(int item) {
    00283     if (!this->HasNext()) return;
    00284
    00285     /* If we remove the 'next' item, skip to the next */
    00286     if (item == this->item_next) {
    00287       FindNext();
    00288       return;
    00289     }
    00290   }
    00291
    00292   bool HasNext()
    00293   {
    00294     return !(this->list->items.empty() || this->has_no_more_items);
    00295   }
    00296 };
    00297
    00301 class AIAbstractListSorterItemDescending : public AIAbstractListSorter {
    00302 private:
    00303   AIAbstractList::AIAbstractListMap::iterator item_iter;
    00304   bool has_no_more_items;
    00305   int32 item_next;
    00306
    00307 public:
    00308   AIAbstractListSorterItemDescending(AIAbstractList *list)
    00309   {
    00310     this->list = list;
    00311     this->End();
    00312   }
    00313
    00314   int32 Begin()
    00315   {
    00316     if (this->list->items.empty()) return 0;
    00317     this->has_no_more_items = false;
    00318
    00319     this->item_iter = this->list->items.begin();
    00320     for (size_t i = this->list->items.size(); i > 1; i--) this->item_iter++;
    00321     this->item_next = (*this->item_iter).first;
    00322
    00323     int32 item_current = this->item_next;
    00324     FindNext();
    00325     return item_current;
    00326   }
    00327
    00328   void End()
    00329   {
    00330     this->has_no_more_items = true;
    00331   }
    00332
    00333   void FindNext()
    00334   {
    00335     if (this->item_iter == this->list->items.end()) {
    00336       this->has_no_more_items = true;
    00337       return;
    00338     }
    00339     this->item_iter--;
    00340     if (this->item_iter != this->list->items.end()) item_next = (*this->item_iter).first;
    00341   }
    00342
    00343   int32 Next()
    00344   {
    00345     if (!this->HasNext()) return 0;
    00346
    00347     int32 item_current = this->item_next;
    00348     FindNext();
    00349     return item_current;
    00350   }
    00351
    00352   void Remove(int item)
    00353   {
    00354     if (!this->HasNext()) return;
    00355
    00356     /* If we remove the 'next' item, skip to the next */
    00357     if (item == this->item_next) {
    00358       FindNext();
    00359       return;
    00360     }
    00361   }
    00362
    00363   bool HasNext()
    00364   {
    00365     return !(this->list->items.empty() || this->has_no_more_items);
    00366   }
    00367 };
    00368
    00369
    00370
    00371 AIAbstractList::AIAbstractList()
    00372 {
    00373   /* Default sorter */
    00374   this->sorter         = new AIAbstractListSorterValueDescending(this);
    00375   this->sorter_type    = SORT_BY_VALUE;
    00376   this->sort_ascending = false;
    00377   this->initialized    = false;
    00378 }
    00379
    00380 AIAbstractList::~AIAbstractList()
    00381 {
    00382   delete this->sorter;
    00383 }
    00384
    00385 bool AIAbstractList::HasItem(int32 item)
    00386 {
    00387   return this->items.count(item) == 1;
    00388 }
    00389
    00390 void AIAbstractList::Clear()
    00391 {
    00392   this->items.clear();
    00393   this->buckets.clear();
    00394   this->sorter->End();
    00395 }
    00396
    00397 void AIAbstractList::AddItem(int32 item)
    00398 {
    00399   if (this->HasItem(item)) return;
    00400
    00401   this->items[item] = 0;
    00402   this->buckets[0].insert(item);
    00403 }
    00404
    00405 void AIAbstractList::RemoveItem(int32 item)
    00406 {
    00407   if (!this->HasItem(item)) return;
    00408
    00409   int32 value = this->GetValue(item);
    00410
    00411   this->sorter->Remove(item);
    00412   this->buckets[value].erase(item);
    00413   if (this->buckets[value].empty()) this->buckets.erase(value);
    00414   this->items.erase(item);
    00415 }
    00416
    00417 int32 AIAbstractList::Begin()
    00418 {
    00419   this->initialized = true;
    00420   return this->sorter->Begin();
    00421 }
    00422
    00423 int32 AIAbstractList::Next()
    00424 {
    00425   if (this->initialized == false) {
    00426     DEBUG(ai, 0, "ERROR: Next() is invalid as Begin() is never called");
    00427     return false;
    00428   }
    00429   return this->sorter->Next();
    00430 }
    00431
    00432 bool AIAbstractList::IsEmpty()
    00433 {
    00434   return this->items.empty();
    00435 }
    00436
    00437 bool AIAbstractList::HasNext()
    00438 {
    00439   if (this->initialized == false) {
    00440     DEBUG(ai, 0, "ERROR: HasNext() is invalid as Begin() is never called");
    00441     return false;
    00442   }
    00443   return this->sorter->HasNext();
    00444 }
    00445
    00446 int32 AIAbstractList::Count()
    00447 {
    00448   return (int32)this->items.size();
    00449 }
    00450
    00451 int32 AIAbstractList::GetValue(int32 item)
    00452 {
    00453   if (!this->HasItem(item)) return 0;
    00454
    00455   return this->items[item];
    00456 }
    00457
    00458 bool AIAbstractList::SetValue(int32 item, int32 value)
    00459 {
    00460   if (!this->HasItem(item)) return false;
    00461
    00462   int32 value_old = this->GetValue(item);
    00463
    00464   this->sorter->Remove(item);
    00465   this->buckets[value_old].erase(item);
    00466   if (this->buckets[value_old].empty()) this->buckets.erase(value_old);
    00467   this->items[item] = value;
    00468   this->buckets[value].insert(item);
    00469
    00470   return true;
    00471 }
    00472
    00473 void AIAbstractList::Sort(SorterType sorter, bool ascending)
    00474 {
    00475   if (sorter != SORT_BY_VALUE && sorter != SORT_BY_ITEM) return;
    00476   if (sorter == this->sorter_type && ascending == this->sort_ascending) return;
    00477
    00478   delete this->sorter;
    00479   switch (sorter) {
    00480     case SORT_BY_ITEM:
    00481       if (ascending) this->sorter = new AIAbstractListSorterItemAscending(this);
    00482       else           this->sorter = new AIAbstractListSorterItemDescending(this);
    00483       break;
    00484
    00485     case SORT_BY_VALUE:
    00486       if (ascending) this->sorter = new AIAbstractListSorterValueAscending(this);
    00487       else           this->sorter = new AIAbstractListSorterValueDescending(this);
    00488       break;
    00489
    00490     default:
    00491       this->Sort(SORT_BY_ITEM, false);
    00492       return;
    00493   }
    00494   this->sorter_type    = sorter;
    00495   this->sort_ascending = ascending;
    00496 }
    00497
    00498 void AIAbstractList::AddList(AIAbstractList *list)
    00499 {
    00500   AIAbstractListMap *list_items = &list->items;
    00501   for (AIAbstractListMap::iterator iter = list_items->begin(); iter != list_items->end(); iter++) {
    00502     this->AddItem((*iter).first);
    00503     this->SetValue((*iter).first, (*iter).second);
    00504   }
    00505 }
    00506
    00507 void AIAbstractList::RemoveAboveValue(int32 value)
    00508 {
    00509   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
    00510     next_iter = iter; next_iter++;
    00511     if ((*iter).second > value) this->items.erase(iter);
    00512   }
    00513
    00514   for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
    00515     next_iter = iter; next_iter++;
    00516     if ((*iter).first > value) this->buckets.erase(iter);
    00517   }
    00518 }
    00519
    00520 void AIAbstractList::RemoveBelowValue(int32 value)
    00521 {
    00522   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
    00523     next_iter = iter; next_iter++;
    00524     if ((*iter).second < value) this->items.erase(iter);
    00525   }
    00526
    00527   for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
    00528     next_iter = iter; next_iter++;
    00529     if ((*iter).first < value) this->buckets.erase(iter);
    00530   }
    00531 }
    00532
    00533 void AIAbstractList::RemoveBetweenValue(int32 start, int32 end)
    00534 {
    00535   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
    00536     next_iter = iter; next_iter++;
    00537     if ((*iter).second > start && (*iter).second < end) this->items.erase(iter);
    00538   }
    00539
    00540   for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
    00541     next_iter = iter; next_iter++;
    00542     if ((*iter).first > start && (*iter).first < end) this->buckets.erase(iter);
    00543   }
    00544 }
    00545
    00546 void AIAbstractList::RemoveValue(int32 value)
    00547 {
    00548   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
    00549     next_iter = iter; next_iter++;
    00550     if ((*iter).second == value) this->items.erase(iter);
    00551   }
    00552
    00553   for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
    00554     next_iter = iter; next_iter++;
    00555     if ((*iter).first == value) this->buckets.erase(iter);
    00556   }
    00557 }
    00558
    00559 void AIAbstractList::RemoveTop(int32 count)
    00560 {
    00561   if (!this->sort_ascending) {
    00562     this->Sort(this->sorter_type, !this->sort_ascending);
    00563     this->RemoveBottom(count);
    00564     this->Sort(this->sorter_type, !this->sort_ascending);
    00565     return;
    00566   }
    00567
    00568   switch (this->sorter_type) {
    00569     default: NOT_REACHED();
    00570     case SORT_BY_VALUE:
    00571       for (AIAbstractListBucket::iterator iter = this->buckets.begin(); iter != this->buckets.end(); iter = this->buckets.begin()) {
    00572         AIItemList *items = &(*iter).second;
    00573         size_t size = items->size();
    00574         for (AIItemList::iterator iter = items->begin(); iter != items->end(); iter = items->begin()) {
    00575           if (--count < 0) return;
    00576           this->RemoveItem(*iter);
    00577           /* When the last item is removed from the bucket, the bucket itself is removed.
    00578            * This means that the iterators can be invalid after a call to RemoveItem.
    00579            */
    00580           if (--size == 0) break;
    00581         }
    00582       }
    00583       break;
    00584
    00585     case SORT_BY_ITEM:
    00586       for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter = this->items.begin()) {
    00587         if (--count < 0) return;
    00588         this->RemoveItem((*iter).first);
    00589       }
    00590       break;
    00591   }
    00592 }
    00593
    00594 void AIAbstractList::RemoveBottom(int32 count)
    00595 {
    00596   if (!this->sort_ascending) {
    00597     this->Sort(this->sorter_type, !this->sort_ascending);
    00598     this->RemoveTop(count);
    00599     this->Sort(this->sorter_type, !this->sort_ascending);
    00600     return;
    00601   }
    00602
    00603   switch (this->sorter_type) {
    00604     default: NOT_REACHED();
    00605     case SORT_BY_VALUE:
    00606       for (AIAbstractListBucket::reverse_iterator iter = this->buckets.rbegin(); iter != this->buckets.rend(); iter = this->buckets.rbegin()) {
    00607         AIItemList *items = &(*iter).second;
    00608         size_t size = items->size();
    00609         for (AIItemList::reverse_iterator iter = items->rbegin(); iter != items->rend(); iter = items->rbegin()) {
    00610           if (--count < 0) return;
    00611           this->RemoveItem(*iter);
    00612           /* When the last item is removed from the bucket, the bucket itself is removed.
    00613            * This means that the iterators can be invalid after a call to RemoveItem.
    00614            */
    00615           if (--size == 0) break;
    00616         }
    00617       }
    00618
    00619     case SORT_BY_ITEM:
    00620       for (AIAbstractListMap::reverse_iterator iter = this->items.rbegin(); iter != this->items.rend(); iter = this->items.rbegin()) {
    00621         if (--count < 0) return;
    00622         this->RemoveItem((*iter).first);
    00623       }
    00624       break;
    00625   }
    00626 }
    00627
    00628 void AIAbstractList::RemoveList(AIAbstractList *list)
    00629 {
    00630   AIAbstractListMap *list_items = &list->items;
    00631   for (AIAbstractListMap::iterator iter = list_items->begin(); iter != list_items->end(); iter++) {
    00632     this->RemoveItem((*iter).first);
    00633   }
    00634 }
    00635
    00636 void AIAbstractList::KeepAboveValue(int32 value)
    00637 {
    00638   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
    00639     next_iter = iter; next_iter++;
    00640     if ((*iter).second <= value) this->items.erase(iter);
    00641   }
    00642
    00643   for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
    00644     next_iter = iter; next_iter++;
    00645     if ((*iter).first <= value) this->buckets.erase(iter);
    00646   }
    00647 }
    00648
    00649 void AIAbstractList::KeepBelowValue(int32 value)
    00650 {
    00651   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
    00652     next_iter = iter; next_iter++;
    00653     if ((*iter).second >= value) this->items.erase(iter);
    00654   }
    00655
    00656   for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
    00657     next_iter = iter; next_iter++;
    00658     if ((*iter).first >= value) this->buckets.erase(iter);
    00659   }
    00660 }
    00661
    00662 void AIAbstractList::KeepBetweenValue(int32 start, int32 end)
    00663 {
    00664   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
    00665     next_iter = iter; next_iter++;
    00666     if ((*iter).second <= start || (*iter).second >= end) this->items.erase(iter);
    00667   }
    00668
    00669   for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
    00670     next_iter = iter; next_iter++;
    00671     if ((*iter).first <= start || (*iter).first >= end) this->buckets.erase(iter);
    00672   }
    00673 }
    00674
    00675 void AIAbstractList::KeepValue(int32 value)
    00676 {
    00677   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
    00678     next_iter = iter; next_iter++;
    00679     if ((*iter).second != value) this->items.erase(iter);
    00680   }
    00681
    00682   for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
    00683     next_iter = iter; next_iter++;
    00684     if ((*iter).first != value) this->buckets.erase(iter);
    00685   }
    00686 }
    00687
    00688 void AIAbstractList::KeepTop(int32 count)
    00689 {
    00690   this->RemoveBottom(this->Count() - count);
    00691 }
    00692
    00693 void AIAbstractList::KeepBottom(int32 count)
    00694 {
    00695   this->RemoveTop(this->Count() - count);
    00696 }
    00697
    00698 void AIAbstractList::KeepList(AIAbstractList *list)
    00699 {
    00700   AIAbstractList tmp;
    00701   for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) {
    00702     tmp.AddItem((*iter).first);
    00703     tmp.SetValue((*iter).first, (*iter).second);
    00704   }
    00705
    00706   tmp.RemoveList(list);
    00707   this->RemoveList(&tmp);
    00708 }
    00709
    00710 SQInteger AIAbstractList::_get(HSQUIRRELVM vm)
    00711 {
    00712   if (sq_gettype(vm, 2) != OT_INTEGER) return SQ_ERROR;
    00713
    00714   SQInteger idx;
    00715   sq_getinteger(vm, 2, &idx);
    00716
    00717   if (!this->HasItem(idx)) return SQ_ERROR;
    00718
    00719   sq_pushinteger(vm, this->GetValue(idx));
    00720   return 1;
    00721 }
    00722
    00723 SQInteger AIAbstractList::_nexti(HSQUIRRELVM vm)
    00724 {
    00725   if (sq_gettype(vm, 2) == OT_NULL) {
    00726     if (this->IsEmpty()) {
    00727       sq_pushnull(vm);
    00728       return 1;
    00729     }
    00730     sq_pushinteger(vm, this->Begin());
    00731     return 1;
    00732   }
    00733
    00734   SQInteger idx;
    00735   sq_getinteger(vm, 2, &idx);
    00736
    00737   int val = this->Next();
    00738   if (!this->HasNext()) {
    00739     sq_pushnull(vm);
    00740     return 1;
    00741   }
    00742
    00743   sq_pushinteger(vm, val);
    00744   return 1;
    00745 }
    00746
    00747 SQInteger AIAbstractList::Valuate(HSQUIRRELVM vm)
    00748 {
    00749   /* The first parameter is the instance of AIAbstractList. */
    00750   int nparam = sq_gettop(vm) - 1;
    00751
    00752   if (nparam < 1) {
    00753     return sq_throwerror(vm, _SC("You need to give a least a Valuator as parameter to AIAbstractList::Valuate"));
    00754   }
    00755
    00756   /* Make sure the valuator function is really a function, and not any
    00757    * other type. It's parameter 2 for us, but for the user it's the
    00758    * first parameter they give. */
    00759   SQObjectType valuator_type = sq_gettype(vm, 2);
    00760   if (valuator_type != OT_CLOSURE && valuator_type != OT_NATIVECLOSURE) {
    00761     return sq_throwerror(vm, _SC("parameter 1 has an invalid type (expected function)"));
    00762   }
    00763
    00764   /* Don't allow docommand from a Valuator, as we can't resume in
    00765    * mid C++-code. */
    00766   bool backup_allow = AIObject::GetAllowDoCommand();
    00767   AIObject::SetAllowDoCommand(false);
    00768
    00769   /* Push the function to call */
    00770   sq_push(vm, 2);
    00771
    00772   /* Walk all items, and query the result */
    00773   this->buckets.clear();
    00774   for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) {
    00775     /* Push the root table as instance object, this is what squirrel does for meta-functions. */
    00776     sq_pushroottable(vm);
    00777     /* Push all arguments for the valuator function. */
    00778     sq_pushinteger(vm, (*iter).first);
    00779     for (int i = 0; i < nparam - 1; i++) {
    00780       sq_push(vm, i + 3);
    00781     }
    00782
    00783     /* Call the function. Squirrel pops all parameters and pushes the return value. */
    00784     if (SQ_FAILED(sq_call(vm, nparam + 1, SQTrue, SQTrue))) {
    00785       AIObject::SetAllowDoCommand(backup_allow);
    00786       return SQ_ERROR;
    00787     }
    00788
    00789     /* Retreive the return value */
    00790     SQInteger value;
    00791     switch (sq_gettype(vm, -1)) {
    00792       case OT_INTEGER: {
    00793         sq_getinteger(vm, -1, &value);
    00794       } break;
    00795
    00796       case OT_BOOL: {
    00797         SQBool v;
    00798         sq_getbool(vm, -1, &v);
    00799         value = v ? 1 : 0;
    00800       } break;
    00801
    00802       default: {
    00803         /* See below for explanation. The extra pop is the return value. */
    00804         sq_pop(vm, nparam + 4);
    00805
    00806         AIObject::SetAllowDoCommand(backup_allow);
    00807         return sq_throwerror(vm, _SC("return value of valuator is not valid (not integer/bool)"));
    00808       }
    00809     }
    00810
    00811     (*iter).second = (int32)value;
    00812     this->buckets[(int32)value].insert((*iter).first);
    00813
    00814     /* Pop the return value. */
    00815     sq_poptop(vm);
    00816
    00817     Squirrel::DecreaseOps(vm, 5);
    00818   }
    00819   /* Pop from the squirrel stack:
    00820    * 1. The root stable (as instance object).
    00821    * 2. The valuator function.
    00822    * 3. The parameters given to this function.
    00823    * 4. The AIAbstractList instance object. */
    00824   sq_pop(vm, nparam + 3);
    00825
    00826   AIObject::SetAllowDoCommand(backup_allow);
    00827   return 0;
    00828 }