# ai_abstractlist.cpp

Go to the documentation of this file.

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