# ai_abstractlist.cpp

Go to the documentation of this file.

    00001 /* $Id: ai_abstractlist.cpp 17197 2009-08-15 22:06:51Z rubidium $ */
    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   this->modifications  = 0;
    00379 }
    00380
    00381 AIAbstractList::~AIAbstractList()
    00382 {
    00383   delete this->sorter;
    00384 }
    00385
    00386 bool AIAbstractList::HasItem(int32 item)
    00387 {
    00388   return this->items.count(item) == 1;
    00389 }
    00390
    00391 void AIAbstractList::Clear()
    00392 {
    00393   this->modifications++;
    00394
    00395   this->items.clear();
    00396   this->buckets.clear();
    00397   this->sorter->End();
    00398 }
    00399
    00400 void AIAbstractList::AddItem(int32 item)
    00401 {
    00402   this->modifications++;
    00403
    00404   if (this->HasItem(item)) return;
    00405
    00406   this->items[item] = 0;
    00407   this->buckets[0].insert(item);
    00408 }
    00409
    00410 void AIAbstractList::RemoveItem(int32 item)
    00411 {
    00412   this->modifications++;
    00413
    00414   if (!this->HasItem(item)) return;
    00415
    00416   int32 value = this->GetValue(item);
    00417
    00418   this->sorter->Remove(item);
    00419   this->buckets[value].erase(item);
    00420   if (this->buckets[value].empty()) this->buckets.erase(value);
    00421   this->items.erase(item);
    00422 }
    00423
    00424 int32 AIAbstractList::Begin()
    00425 {
    00426   this->initialized = true;
    00427   return this->sorter->Begin();
    00428 }
    00429
    00430 int32 AIAbstractList::Next()
    00431 {
    00432   if (this->initialized == false) {
    00433     DEBUG(ai, 0, "ERROR: Next() is invalid as Begin() is never called");
    00434     return false;
    00435   }
    00436   return this->sorter->Next();
    00437 }
    00438
    00439 bool AIAbstractList::IsEmpty()
    00440 {
    00441   return this->items.empty();
    00442 }
    00443
    00444 bool AIAbstractList::HasNext()
    00445 {
    00446   if (this->initialized == false) {
    00447     DEBUG(ai, 0, "ERROR: HasNext() is invalid as Begin() is never called");
    00448     return false;
    00449   }
    00450   return this->sorter->HasNext();
    00451 }
    00452
    00453 int32 AIAbstractList::Count()
    00454 {
    00455   return (int32)this->items.size();
    00456 }
    00457
    00458 int32 AIAbstractList::GetValue(int32 item)
    00459 {
    00460   if (!this->HasItem(item)) return 0;
    00461
    00462   return this->items[item];
    00463 }
    00464
    00465 bool AIAbstractList::SetValue(int32 item, int32 value)
    00466 {
    00467   this->modifications++;
    00468
    00469   if (!this->HasItem(item)) return false;
    00470
    00471   int32 value_old = this->GetValue(item);
    00472
    00473   this->sorter->Remove(item);
    00474   this->buckets[value_old].erase(item);
    00475   if (this->buckets[value_old].empty()) this->buckets.erase(value_old);
    00476   this->items[item] = value;
    00477   this->buckets[value].insert(item);
    00478
    00479   return true;
    00480 }
    00481
    00482 void AIAbstractList::Sort(SorterType sorter, bool ascending)
    00483 {
    00484   this->modifications++;
    00485
    00486   if (sorter != SORT_BY_VALUE && sorter != SORT_BY_ITEM) return;
    00487   if (sorter == this->sorter_type && ascending == this->sort_ascending) return;
    00488
    00489   delete this->sorter;
    00490   switch (sorter) {
    00491     case SORT_BY_ITEM:
    00492       if (ascending) this->sorter = new AIAbstractListSorterItemAscending(this);
    00493       else           this->sorter = new AIAbstractListSorterItemDescending(this);
    00494       break;
    00495
    00496     case SORT_BY_VALUE:
    00497       if (ascending) this->sorter = new AIAbstractListSorterValueAscending(this);
    00498       else           this->sorter = new AIAbstractListSorterValueDescending(this);
    00499       break;
    00500
    00501     default:
    00502       this->Sort(SORT_BY_ITEM, false);
    00503       return;
    00504   }
    00505   this->sorter_type    = sorter;
    00506   this->sort_ascending = ascending;
    00507 }
    00508
    00509 void AIAbstractList::AddList(AIAbstractList *list)
    00510 {
    00511   AIAbstractListMap *list_items = &list->items;
    00512   for (AIAbstractListMap::iterator iter = list_items->begin(); iter != list_items->end(); iter++) {
    00513     this->AddItem((*iter).first);
    00514     this->SetValue((*iter).first, (*iter).second);
    00515   }
    00516 }
    00517
    00518 void AIAbstractList::RemoveAboveValue(int32 value)
    00519 {
    00520   this->modifications++;
    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::RemoveBelowValue(int32 value)
    00534 {
    00535   this->modifications++;
    00536
    00537   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
    00538     next_iter = iter; next_iter++;
    00539     if ((*iter).second < value) this->items.erase(iter);
    00540   }
    00541
    00542   for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
    00543     next_iter = iter; next_iter++;
    00544     if ((*iter).first < value) this->buckets.erase(iter);
    00545   }
    00546 }
    00547
    00548 void AIAbstractList::RemoveBetweenValue(int32 start, int32 end)
    00549 {
    00550   this->modifications++;
    00551
    00552   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
    00553     next_iter = iter; next_iter++;
    00554     if ((*iter).second > start && (*iter).second < end) this->items.erase(iter);
    00555   }
    00556
    00557   for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
    00558     next_iter = iter; next_iter++;
    00559     if ((*iter).first > start && (*iter).first < end) this->buckets.erase(iter);
    00560   }
    00561 }
    00562
    00563 void AIAbstractList::RemoveValue(int32 value)
    00564 {
    00565   this->modifications++;
    00566
    00567   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
    00568     next_iter = iter; next_iter++;
    00569     if ((*iter).second == value) this->items.erase(iter);
    00570   }
    00571
    00572   for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
    00573     next_iter = iter; next_iter++;
    00574     if ((*iter).first == value) this->buckets.erase(iter);
    00575   }
    00576 }
    00577
    00578 void AIAbstractList::RemoveTop(int32 count)
    00579 {
    00580   this->modifications++;
    00581
    00582   if (!this->sort_ascending) {
    00583     this->Sort(this->sorter_type, !this->sort_ascending);
    00584     this->RemoveBottom(count);
    00585     this->Sort(this->sorter_type, !this->sort_ascending);
    00586     return;
    00587   }
    00588
    00589   switch (this->sorter_type) {
    00590     default: NOT_REACHED();
    00591     case SORT_BY_VALUE:
    00592       for (AIAbstractListBucket::iterator iter = this->buckets.begin(); iter != this->buckets.end(); iter = this->buckets.begin()) {
    00593         AIItemList *items = &(*iter).second;
    00594         size_t size = items->size();
    00595         for (AIItemList::iterator iter = items->begin(); iter != items->end(); iter = items->begin()) {
    00596           if (--count < 0) return;
    00597           this->RemoveItem(*iter);
    00598           /* When the last item is removed from the bucket, the bucket itself is removed.
    00599            * This means that the iterators can be invalid after a call to RemoveItem.
    00600            */
    00601           if (--size == 0) break;
    00602         }
    00603       }
    00604       break;
    00605
    00606     case SORT_BY_ITEM:
    00607       for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter = this->items.begin()) {
    00608         if (--count < 0) return;
    00609         this->RemoveItem((*iter).first);
    00610       }
    00611       break;
    00612   }
    00613 }
    00614
    00615 void AIAbstractList::RemoveBottom(int32 count)
    00616 {
    00617   this->modifications++;
    00618
    00619   if (!this->sort_ascending) {
    00620     this->Sort(this->sorter_type, !this->sort_ascending);
    00621     this->RemoveTop(count);
    00622     this->Sort(this->sorter_type, !this->sort_ascending);
    00623     return;
    00624   }
    00625
    00626   switch (this->sorter_type) {
    00627     default: NOT_REACHED();
    00628     case SORT_BY_VALUE:
    00629       for (AIAbstractListBucket::reverse_iterator iter = this->buckets.rbegin(); iter != this->buckets.rend(); iter = this->buckets.rbegin()) {
    00630         AIItemList *items = &(*iter).second;
    00631         size_t size = items->size();
    00632         for (AIItemList::reverse_iterator iter = items->rbegin(); iter != items->rend(); iter = items->rbegin()) {
    00633           if (--count < 0) return;
    00634           this->RemoveItem(*iter);
    00635           /* When the last item is removed from the bucket, the bucket itself is removed.
    00636            * This means that the iterators can be invalid after a call to RemoveItem.
    00637            */
    00638           if (--size == 0) break;
    00639         }
    00640       }
    00641
    00642     case SORT_BY_ITEM:
    00643       for (AIAbstractListMap::reverse_iterator iter = this->items.rbegin(); iter != this->items.rend(); iter = this->items.rbegin()) {
    00644         if (--count < 0) return;
    00645         this->RemoveItem((*iter).first);
    00646       }
    00647       break;
    00648   }
    00649 }
    00650
    00651 void AIAbstractList::RemoveList(AIAbstractList *list)
    00652 {
    00653   this->modifications++;
    00654
    00655   AIAbstractListMap *list_items = &list->items;
    00656   for (AIAbstractListMap::iterator iter = list_items->begin(); iter != list_items->end(); iter++) {
    00657     this->RemoveItem((*iter).first);
    00658   }
    00659 }
    00660
    00661 void AIAbstractList::KeepAboveValue(int32 value)
    00662 {
    00663   this->modifications++;
    00664
    00665   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
    00666     next_iter = iter; next_iter++;
    00667     if ((*iter).second <= value) this->items.erase(iter);
    00668   }
    00669
    00670   for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
    00671     next_iter = iter; next_iter++;
    00672     if ((*iter).first <= value) this->buckets.erase(iter);
    00673   }
    00674 }
    00675
    00676 void AIAbstractList::KeepBelowValue(int32 value)
    00677 {
    00678   this->modifications++;
    00679
    00680   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
    00681     next_iter = iter; next_iter++;
    00682     if ((*iter).second >= value) this->items.erase(iter);
    00683   }
    00684
    00685   for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
    00686     next_iter = iter; next_iter++;
    00687     if ((*iter).first >= value) this->buckets.erase(iter);
    00688   }
    00689 }
    00690
    00691 void AIAbstractList::KeepBetweenValue(int32 start, int32 end)
    00692 {
    00693   this->modifications++;
    00694
    00695   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
    00696     next_iter = iter; next_iter++;
    00697     if ((*iter).second <= start || (*iter).second >= end) this->items.erase(iter);
    00698   }
    00699
    00700   for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
    00701     next_iter = iter; next_iter++;
    00702     if ((*iter).first <= start || (*iter).first >= end) this->buckets.erase(iter);
    00703   }
    00704 }
    00705
    00706 void AIAbstractList::KeepValue(int32 value)
    00707 {
    00708   this->modifications++;
    00709
    00710   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
    00711     next_iter = iter; next_iter++;
    00712     if ((*iter).second != value) this->items.erase(iter);
    00713   }
    00714
    00715   for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
    00716     next_iter = iter; next_iter++;
    00717     if ((*iter).first != value) this->buckets.erase(iter);
    00718   }
    00719 }
    00720
    00721 void AIAbstractList::KeepTop(int32 count)
    00722 {
    00723   this->modifications++;
    00724
    00725   this->RemoveBottom(this->Count() - count);
    00726 }
    00727
    00728 void AIAbstractList::KeepBottom(int32 count)
    00729 {
    00730   this->modifications++;
    00731
    00732   this->RemoveTop(this->Count() - count);
    00733 }
    00734
    00735 void AIAbstractList::KeepList(AIAbstractList *list)
    00736 {
    00737   this->modifications++;
    00738
    00739   AIAbstractList tmp;
    00740   for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) {
    00741     tmp.AddItem((*iter).first);
    00742     tmp.SetValue((*iter).first, (*iter).second);
    00743   }
    00744
    00745   tmp.RemoveList(list);
    00746   this->RemoveList(&tmp);
    00747 }
    00748
    00749 SQInteger AIAbstractList::_get(HSQUIRRELVM vm)
    00750 {
    00751   if (sq_gettype(vm, 2) != OT_INTEGER) return SQ_ERROR;
    00752
    00753   SQInteger idx;
    00754   sq_getinteger(vm, 2, &idx);
    00755
    00756   if (!this->HasItem(idx)) return SQ_ERROR;
    00757
    00758   sq_pushinteger(vm, this->GetValue(idx));
    00759   return 1;
    00760 }
    00761
    00762 SQInteger AIAbstractList::_nexti(HSQUIRRELVM vm)
    00763 {
    00764   if (sq_gettype(vm, 2) == OT_NULL) {
    00765     if (this->IsEmpty()) {
    00766       sq_pushnull(vm);
    00767       return 1;
    00768     }
    00769     sq_pushinteger(vm, this->Begin());
    00770     return 1;
    00771   }
    00772
    00773   SQInteger idx;
    00774   sq_getinteger(vm, 2, &idx);
    00775
    00776   int val = this->Next();
    00777   if (!this->HasNext()) {
    00778     sq_pushnull(vm);
    00779     return 1;
    00780   }
    00781
    00782   sq_pushinteger(vm, val);
    00783   return 1;
    00784 }
    00785
    00786 SQInteger AIAbstractList::Valuate(HSQUIRRELVM vm)
    00787 {
    00788   this->modifications++;
    00789
    00790   /* The first parameter is the instance of AIAbstractList. */
    00791   int nparam = sq_gettop(vm) - 1;
    00792
    00793   if (nparam < 1) {
    00794     return sq_throwerror(vm, _SC("You need to give a least a Valuator as parameter to AIAbstractList::Valuate"));
    00795   }
    00796
    00797   /* Make sure the valuator function is really a function, and not any
    00798    * other type. It's parameter 2 for us, but for the user it's the
    00799    * first parameter they give. */
    00800   SQObjectType valuator_type = sq_gettype(vm, 2);
    00801   if (valuator_type != OT_CLOSURE && valuator_type != OT_NATIVECLOSURE) {
    00802     return sq_throwerror(vm, _SC("parameter 1 has an invalid type (expected function)"));
    00803   }
    00804
    00805   /* Don't allow docommand from a Valuator, as we can't resume in
    00806    * mid C++-code. */
    00807   bool backup_allow = AIObject::GetAllowDoCommand();
    00808   AIObject::SetAllowDoCommand(false);
    00809
    00810   /* Push the function to call */
    00811   sq_push(vm, 2);
    00812
    00813   /* Walk all items, and query the result */
    00814   this->buckets.clear();
    00815
    00816   /* Check for changing of items. */
    00817   int begin_modification_count = this->modifications;
    00818
    00819   for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) {
    00820     /* Push the root table as instance object, this is what squirrel does for meta-functions. */
    00821     sq_pushroottable(vm);
    00822     /* Push all arguments for the valuator function. */
    00823     sq_pushinteger(vm, (*iter).first);
    00824     for (int i = 0; i < nparam - 1; i++) {
    00825       sq_push(vm, i + 3);
    00826     }
    00827
    00828     /* Call the function. Squirrel pops all parameters and pushes the return value. */
    00829     if (SQ_FAILED(sq_call(vm, nparam + 1, SQTrue, SQTrue))) {
    00830       AIObject::SetAllowDoCommand(backup_allow);
    00831       return SQ_ERROR;
    00832     }
    00833
    00834     /* Retreive the return value */
    00835     SQInteger value;
    00836     switch (sq_gettype(vm, -1)) {
    00837       case OT_INTEGER: {
    00838         sq_getinteger(vm, -1, &value);
    00839       } break;
    00840
    00841       case OT_BOOL: {
    00842         SQBool v;
    00843         sq_getbool(vm, -1, &v);
    00844         value = v ? 1 : 0;
    00845       } break;
    00846
    00847       default: {
    00848         /* See below for explanation. The extra pop is the return value. */
    00849         sq_pop(vm, nparam + 4);
    00850
    00851         AIObject::SetAllowDoCommand(backup_allow);
    00852         return sq_throwerror(vm, _SC("return value of valuator is not valid (not integer/bool)"));
    00853       }
    00854     }
    00855
    00856     /* Was something changed? */
    00857     if (begin_modification_count != this->modifications) {
    00858       /* See below for explanation. The extra pop is the return value. */
    00859       sq_pop(vm, nparam + 4);
    00860
    00861       AIObject::SetAllowDoCommand(backup_allow);
    00862       return sq_throwerror(vm, _SC("modifying valuated list outside of valuator function"));
    00863     }
    00864
    00865     (*iter).second = (int32)value;
    00866     this->buckets[(int32)value].insert((*iter).first);
    00867
    00868     /* Pop the return value. */
    00869     sq_poptop(vm);
    00870
    00871     Squirrel::DecreaseOps(vm, 5);
    00872   }
    00873   /* Pop from the squirrel stack:
    00874    * 1. The root stable (as instance object).
    00875    * 2. The valuator function.
    00876    * 3. The parameters given to this function.
    00877    * 4. The AIAbstractList instance object. */
    00878   sq_pop(vm, nparam + 3);
    00879
    00880   AIObject::SetAllowDoCommand(backup_allow);
    00881   return 0;
    00882 }