ai_abstractlist.cpp

Go to the documentation of this file.
00001 /* $Id: ai_abstractlist.cpp 19376 2010-03-08 22:19:39Z 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, "Next() is invalid as Begin() is never called");
00441     return 0;
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, "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   this->initialized    = false;
00521 }
00522 
00523 void AIAbstractList::AddList(AIAbstractList *list)
00524 {
00525   AIAbstractListMap *list_items = &list->items;
00526   for (AIAbstractListMap::iterator iter = list_items->begin(); iter != list_items->end(); iter++) {
00527     this->AddItem((*iter).first);
00528     this->SetValue((*iter).first, (*iter).second);
00529   }
00530 }
00531 
00532 void AIAbstractList::RemoveAboveValue(int32 value)
00533 {
00534   this->modifications++;
00535 
00536   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
00537     next_iter = iter; next_iter++;
00538     if ((*iter).second > value) this->RemoveItem((*iter).first);
00539   }
00540 }
00541 
00542 void AIAbstractList::RemoveBelowValue(int32 value)
00543 {
00544   this->modifications++;
00545 
00546   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
00547     next_iter = iter; next_iter++;
00548     if ((*iter).second < value) this->RemoveItem((*iter).first);
00549   }
00550 }
00551 
00552 void AIAbstractList::RemoveBetweenValue(int32 start, int32 end)
00553 {
00554   this->modifications++;
00555 
00556   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
00557     next_iter = iter; next_iter++;
00558     if ((*iter).second > start && (*iter).second < end) this->RemoveItem((*iter).first);
00559   }
00560 }
00561 
00562 void AIAbstractList::RemoveValue(int32 value)
00563 {
00564   this->modifications++;
00565 
00566   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
00567     next_iter = iter; next_iter++;
00568     if ((*iter).second == value) this->RemoveItem((*iter).first);
00569   }
00570 }
00571 
00572 void AIAbstractList::RemoveTop(int32 count)
00573 {
00574   this->modifications++;
00575 
00576   if (!this->sort_ascending) {
00577     this->Sort(this->sorter_type, !this->sort_ascending);
00578     this->RemoveBottom(count);
00579     this->Sort(this->sorter_type, !this->sort_ascending);
00580     return;
00581   }
00582 
00583   switch (this->sorter_type) {
00584     default: NOT_REACHED();
00585     case SORT_BY_VALUE:
00586       for (AIAbstractListBucket::iterator iter = this->buckets.begin(); iter != this->buckets.end(); iter = this->buckets.begin()) {
00587         AIItemList *items = &(*iter).second;
00588         size_t size = items->size();
00589         for (AIItemList::iterator iter = items->begin(); iter != items->end(); iter = items->begin()) {
00590           if (--count < 0) return;
00591           this->RemoveItem(*iter);
00592           /* When the last item is removed from the bucket, the bucket itself is removed.
00593            * This means that the iterators can be invalid after a call to RemoveItem.
00594            */
00595           if (--size == 0) break;
00596         }
00597       }
00598       break;
00599 
00600     case SORT_BY_ITEM:
00601       for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter = this->items.begin()) {
00602         if (--count < 0) return;
00603         this->RemoveItem((*iter).first);
00604       }
00605       break;
00606   }
00607 }
00608 
00609 void AIAbstractList::RemoveBottom(int32 count)
00610 {
00611   this->modifications++;
00612 
00613   if (!this->sort_ascending) {
00614     this->Sort(this->sorter_type, !this->sort_ascending);
00615     this->RemoveTop(count);
00616     this->Sort(this->sorter_type, !this->sort_ascending);
00617     return;
00618   }
00619 
00620   switch (this->sorter_type) {
00621     default: NOT_REACHED();
00622     case SORT_BY_VALUE:
00623       for (AIAbstractListBucket::reverse_iterator iter = this->buckets.rbegin(); iter != this->buckets.rend(); iter = this->buckets.rbegin()) {
00624         AIItemList *items = &(*iter).second;
00625         size_t size = items->size();
00626         for (AIItemList::reverse_iterator iter = items->rbegin(); iter != items->rend(); iter = items->rbegin()) {
00627           if (--count < 0) return;
00628           this->RemoveItem(*iter);
00629           /* When the last item is removed from the bucket, the bucket itself is removed.
00630            * This means that the iterators can be invalid after a call to RemoveItem.
00631            */
00632           if (--size == 0) break;
00633         }
00634       }
00635 
00636     case SORT_BY_ITEM:
00637       for (AIAbstractListMap::reverse_iterator iter = this->items.rbegin(); iter != this->items.rend(); iter = this->items.rbegin()) {
00638         if (--count < 0) return;
00639         this->RemoveItem((*iter).first);
00640       }
00641       break;
00642   }
00643 }
00644 
00645 void AIAbstractList::RemoveList(AIAbstractList *list)
00646 {
00647   this->modifications++;
00648 
00649   AIAbstractListMap *list_items = &list->items;
00650   for (AIAbstractListMap::iterator iter = list_items->begin(); iter != list_items->end(); iter++) {
00651     this->RemoveItem((*iter).first);
00652   }
00653 }
00654 
00655 void AIAbstractList::KeepAboveValue(int32 value)
00656 {
00657   this->modifications++;
00658 
00659   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
00660     next_iter = iter; next_iter++;
00661     if ((*iter).second <= value) this->RemoveItem((*iter).first);
00662   }
00663 }
00664 
00665 void AIAbstractList::KeepBelowValue(int32 value)
00666 {
00667   this->modifications++;
00668 
00669   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
00670     next_iter = iter; next_iter++;
00671     if ((*iter).second >= value) this->RemoveItem((*iter).first);
00672   }
00673 }
00674 
00675 void AIAbstractList::KeepBetweenValue(int32 start, int32 end)
00676 {
00677   this->modifications++;
00678 
00679   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
00680     next_iter = iter; next_iter++;
00681     if ((*iter).second <= start || (*iter).second >= end) this->RemoveItem((*iter).first);
00682   }
00683 }
00684 
00685 void AIAbstractList::KeepValue(int32 value)
00686 {
00687   this->modifications++;
00688 
00689   for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
00690     next_iter = iter; next_iter++;
00691     if ((*iter).second != value) this->RemoveItem((*iter).first);
00692   }
00693 }
00694 
00695 void AIAbstractList::KeepTop(int32 count)
00696 {
00697   this->modifications++;
00698 
00699   this->RemoveBottom(this->Count() - count);
00700 }
00701 
00702 void AIAbstractList::KeepBottom(int32 count)
00703 {
00704   this->modifications++;
00705 
00706   this->RemoveTop(this->Count() - count);
00707 }
00708 
00709 void AIAbstractList::KeepList(AIAbstractList *list)
00710 {
00711   this->modifications++;
00712 
00713   AIAbstractList tmp;
00714   for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) {
00715     tmp.AddItem((*iter).first);
00716     tmp.SetValue((*iter).first, (*iter).second);
00717   }
00718 
00719   tmp.RemoveList(list);
00720   this->RemoveList(&tmp);
00721 }
00722 
00723 SQInteger AIAbstractList::_get(HSQUIRRELVM vm)
00724 {
00725   if (sq_gettype(vm, 2) != OT_INTEGER) return SQ_ERROR;
00726 
00727   SQInteger idx;
00728   sq_getinteger(vm, 2, &idx);
00729 
00730   if (!this->HasItem(idx)) return SQ_ERROR;
00731 
00732   sq_pushinteger(vm, this->GetValue(idx));
00733   return 1;
00734 }
00735 
00736 SQInteger AIAbstractList::_nexti(HSQUIRRELVM vm)
00737 {
00738   if (sq_gettype(vm, 2) == OT_NULL) {
00739     if (this->IsEmpty()) {
00740       sq_pushnull(vm);
00741       return 1;
00742     }
00743     sq_pushinteger(vm, this->Begin());
00744     return 1;
00745   }
00746 
00747   SQInteger idx;
00748   sq_getinteger(vm, 2, &idx);
00749 
00750   int val = this->Next();
00751   if (!this->HasNext()) {
00752     sq_pushnull(vm);
00753     return 1;
00754   }
00755 
00756   sq_pushinteger(vm, val);
00757   return 1;
00758 }
00759 
00760 SQInteger AIAbstractList::Valuate(HSQUIRRELVM vm)
00761 {
00762   this->modifications++;
00763 
00764   /* The first parameter is the instance of AIAbstractList. */
00765   int nparam = sq_gettop(vm) - 1;
00766 
00767   if (nparam < 1) {
00768     return sq_throwerror(vm, _SC("You need to give a least a Valuator as parameter to AIAbstractList::Valuate"));
00769   }
00770 
00771   /* Make sure the valuator function is really a function, and not any
00772    * other type. It's parameter 2 for us, but for the user it's the
00773    * first parameter they give. */
00774   SQObjectType valuator_type = sq_gettype(vm, 2);
00775   if (valuator_type != OT_CLOSURE && valuator_type != OT_NATIVECLOSURE) {
00776     return sq_throwerror(vm, _SC("parameter 1 has an invalid type (expected function)"));
00777   }
00778 
00779   /* Don't allow docommand from a Valuator, as we can't resume in
00780    * mid C++-code. */
00781   bool backup_allow = AIObject::GetAllowDoCommand();
00782   AIObject::SetAllowDoCommand(false);
00783 
00784   /* Push the function to call */
00785   sq_push(vm, 2);
00786 
00787   for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) {
00788     /* Check for changing of items. */
00789     int previous_modification_count = this->modifications;
00790 
00791     /* Push the root table as instance object, this is what squirrel does for meta-functions. */
00792     sq_pushroottable(vm);
00793     /* Push all arguments for the valuator function. */
00794     sq_pushinteger(vm, (*iter).first);
00795     for (int i = 0; i < nparam - 1; i++) {
00796       sq_push(vm, i + 3);
00797     }
00798 
00799     /* Call the function. Squirrel pops all parameters and pushes the return value. */
00800     if (SQ_FAILED(sq_call(vm, nparam + 1, SQTrue, SQTrue))) {
00801       AIObject::SetAllowDoCommand(backup_allow);
00802       return SQ_ERROR;
00803     }
00804 
00805     /* Retreive the return value */
00806     SQInteger value;
00807     switch (sq_gettype(vm, -1)) {
00808       case OT_INTEGER: {
00809         sq_getinteger(vm, -1, &value);
00810       } break;
00811 
00812       case OT_BOOL: {
00813         SQBool v;
00814         sq_getbool(vm, -1, &v);
00815         value = v ? 1 : 0;
00816       } break;
00817 
00818       default: {
00819         /* See below for explanation. The extra pop is the return value. */
00820         sq_pop(vm, nparam + 4);
00821 
00822         AIObject::SetAllowDoCommand(backup_allow);
00823         return sq_throwerror(vm, _SC("return value of valuator is not valid (not integer/bool)"));
00824       }
00825     }
00826 
00827     /* Was something changed? */
00828     if (previous_modification_count != this->modifications) {
00829       /* See below for explanation. The extra pop is the return value. */
00830       sq_pop(vm, nparam + 4);
00831 
00832       AIObject::SetAllowDoCommand(backup_allow);
00833       return sq_throwerror(vm, _SC("modifying valuated list outside of valuator function"));
00834     }
00835 
00836     this->SetValue((*iter).first, value);
00837 
00838     /* Pop the return value. */
00839     sq_poptop(vm);
00840 
00841     Squirrel::DecreaseOps(vm, 5);
00842   }
00843   /* Pop from the squirrel stack:
00844    * 1. The root stable (as instance object).
00845    * 2. The valuator function.
00846    * 3. The parameters given to this function.
00847    * 4. The AIAbstractList instance object. */
00848   sq_pop(vm, nparam + 3);
00849 
00850   AIObject::SetAllowDoCommand(backup_allow);
00851   return 0;
00852 }

Generated on Fri Apr 30 21:55:17 2010 for OpenTTD by  doxygen 1.6.1