ai_list.cpp

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

Generated on Mon May 9 05:18:50 2011 for OpenTTD by  doxygen 1.6.1