00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "ai_list.hpp"
00013 #include "../../debug.h"
00014 #include "../../script/squirrel.hpp"
00015
00019 class AIListSorter {
00020 protected:
00021 AIList *list;
00022
00023 public:
00027 virtual ~AIListSorter() { }
00028
00032 virtual int32 Begin() = 0;
00033
00037 virtual void End() = 0;
00038
00042 virtual int32 Next() = 0;
00043
00047 virtual bool IsEnd() = 0;
00048
00052 virtual void Remove(int item) = 0;
00053 };
00054
00058 class AIListSorterValueAscending : public AIListSorter {
00059 private:
00060 AIList::AIListBucket::iterator bucket_iter;
00061 AIList::AIItemList *bucket_list;
00062 AIList::AIItemList::iterator bucket_list_iter;
00063 bool has_no_more_items;
00064 int32 item_next;
00065
00066 public:
00067 AIListSorterValueAscending(AIList *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->IsEnd()) 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->IsEnd()) return;
00127
00128
00129 if (item == this->item_next) {
00130 FindNext();
00131 return;
00132 }
00133 }
00134
00135 bool IsEnd()
00136 {
00137 return this->list->buckets.empty() || this->has_no_more_items;
00138 }
00139 };
00140
00144 class AIListSorterValueDescending : public AIListSorter {
00145 private:
00146 AIList::AIListBucket::iterator bucket_iter;
00147 AIList::AIItemList *bucket_list;
00148 AIList::AIItemList::iterator bucket_list_iter;
00149 bool has_no_more_items;
00150 int32 item_next;
00151
00152 public:
00153 AIListSorterValueDescending(AIList *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
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
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
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->IsEnd()) 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->IsEnd()) return;
00221
00222
00223 if (item == this->item_next) {
00224 FindNext();
00225 return;
00226 }
00227 }
00228
00229 bool IsEnd()
00230 {
00231 return this->list->buckets.empty() || this->has_no_more_items;
00232 }
00233 };
00234
00238 class AIListSorterItemAscending : public AIListSorter {
00239 private:
00240 AIList::AIListMap::iterator item_iter;
00241 bool has_no_more_items;
00242 int32 item_next;
00243
00244 public:
00245 AIListSorterItemAscending(AIList *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->IsEnd()) 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->IsEnd()) return;
00291
00292
00293 if (item == this->item_next) {
00294 FindNext();
00295 return;
00296 }
00297 }
00298
00299 bool IsEnd()
00300 {
00301 return this->list->items.empty() || this->has_no_more_items;
00302 }
00303 };
00304
00308 class AIListSorterItemDescending : public AIListSorter {
00309 private:
00310 AIList::AIListMap::iterator item_iter;
00311 bool has_no_more_items;
00312 int32 item_next;
00313
00314 public:
00315 AIListSorterItemDescending(AIList *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->IsEnd()) 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->IsEnd()) return;
00362
00363
00364 if (item == this->item_next) {
00365 FindNext();
00366 return;
00367 }
00368 }
00369
00370 bool IsEnd()
00371 {
00372 return this->list->items.empty() || this->has_no_more_items;
00373 }
00374 };
00375
00376
00377
00378 AIList::AIList()
00379 {
00380
00381 this->sorter = new AIListSorterValueDescending(this);
00382 this->sorter_type = SORT_BY_VALUE;
00383 this->sort_ascending = false;
00384 this->initialized = false;
00385 this->modifications = 0;
00386 }
00387
00388 AIList::~AIList()
00389 {
00390 delete this->sorter;
00391 }
00392
00393 bool AIList::HasItem(int32 item)
00394 {
00395 return this->items.count(item) == 1;
00396 }
00397
00398 void AIList::Clear()
00399 {
00400 this->modifications++;
00401
00402 this->items.clear();
00403 this->buckets.clear();
00404 this->sorter->End();
00405 }
00406
00407 void AIList::AddItem(int32 item, int32 value)
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 this->SetValue(item, value);
00417 }
00418
00419 void AIList::RemoveItem(int32 item)
00420 {
00421 this->modifications++;
00422
00423 if (!this->HasItem(item)) return;
00424
00425 int32 value = this->GetValue(item);
00426
00427 this->sorter->Remove(item);
00428 this->buckets[value].erase(item);
00429 if (this->buckets[value].empty()) this->buckets.erase(value);
00430 this->items.erase(item);
00431 }
00432
00433 int32 AIList::Begin()
00434 {
00435 this->initialized = true;
00436 return this->sorter->Begin();
00437 }
00438
00439 int32 AIList::Next()
00440 {
00441 if (this->initialized == false) {
00442 DEBUG(ai, 0, "Next() is invalid as Begin() is never called");
00443 return 0;
00444 }
00445 return this->sorter->Next();
00446 }
00447
00448 bool AIList::IsEmpty()
00449 {
00450 return this->items.empty();
00451 }
00452
00453 bool AIList::IsEnd()
00454 {
00455 if (this->initialized == false) {
00456 DEBUG(ai, 0, "IsEnd() is invalid as Begin() is never called");
00457 return true;
00458 }
00459 return this->sorter->IsEnd();
00460 }
00461
00462 int32 AIList::Count()
00463 {
00464 return (int32)this->items.size();
00465 }
00466
00467 int32 AIList::GetValue(int32 item)
00468 {
00469 if (!this->HasItem(item)) return 0;
00470
00471 return this->items[item];
00472 }
00473
00474 bool AIList::SetValue(int32 item, int32 value)
00475 {
00476 this->modifications++;
00477
00478 if (!this->HasItem(item)) return false;
00479
00480 int32 value_old = this->GetValue(item);
00481 if (value_old == value) return true;
00482
00483 this->sorter->Remove(item);
00484 this->buckets[value_old].erase(item);
00485 if (this->buckets[value_old].empty()) this->buckets.erase(value_old);
00486 this->items[item] = value;
00487 this->buckets[value].insert(item);
00488
00489 return true;
00490 }
00491
00492 void AIList::Sort(SorterType sorter, bool ascending)
00493 {
00494 this->modifications++;
00495
00496 if (sorter != SORT_BY_VALUE && sorter != SORT_BY_ITEM) return;
00497 if (sorter == this->sorter_type && ascending == this->sort_ascending) return;
00498
00499 delete this->sorter;
00500 switch (sorter) {
00501 case SORT_BY_ITEM:
00502 if (ascending) {
00503 this->sorter = new AIListSorterItemAscending(this);
00504 } else {
00505 this->sorter = new AIListSorterItemDescending(this);
00506 }
00507 break;
00508
00509 case SORT_BY_VALUE:
00510 if (ascending) {
00511 this->sorter = new AIListSorterValueAscending(this);
00512 } else {
00513 this->sorter = new AIListSorterValueDescending(this);
00514 }
00515 break;
00516
00517 default:
00518 this->Sort(SORT_BY_ITEM, false);
00519 return;
00520 }
00521 this->sorter_type = sorter;
00522 this->sort_ascending = ascending;
00523 this->initialized = false;
00524 }
00525
00526 void AIList::AddList(AIList *list)
00527 {
00528 AIListMap *list_items = &list->items;
00529 for (AIListMap::iterator iter = list_items->begin(); iter != list_items->end(); iter++) {
00530 this->AddItem((*iter).first);
00531 this->SetValue((*iter).first, (*iter).second);
00532 }
00533 }
00534
00535 void AIList::RemoveAboveValue(int32 value)
00536 {
00537 this->modifications++;
00538
00539 for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
00540 next_iter = iter; next_iter++;
00541 if ((*iter).second > value) this->RemoveItem((*iter).first);
00542 }
00543 }
00544
00545 void AIList::RemoveBelowValue(int32 value)
00546 {
00547 this->modifications++;
00548
00549 for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
00550 next_iter = iter; next_iter++;
00551 if ((*iter).second < value) this->RemoveItem((*iter).first);
00552 }
00553 }
00554
00555 void AIList::RemoveBetweenValue(int32 start, int32 end)
00556 {
00557 this->modifications++;
00558
00559 for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
00560 next_iter = iter; next_iter++;
00561 if ((*iter).second > start && (*iter).second < end) this->RemoveItem((*iter).first);
00562 }
00563 }
00564
00565 void AIList::RemoveValue(int32 value)
00566 {
00567 this->modifications++;
00568
00569 for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
00570 next_iter = iter; next_iter++;
00571 if ((*iter).second == value) this->RemoveItem((*iter).first);
00572 }
00573 }
00574
00575 void AIList::RemoveTop(int32 count)
00576 {
00577 this->modifications++;
00578
00579 if (!this->sort_ascending) {
00580 this->Sort(this->sorter_type, !this->sort_ascending);
00581 this->RemoveBottom(count);
00582 this->Sort(this->sorter_type, !this->sort_ascending);
00583 return;
00584 }
00585
00586 switch (this->sorter_type) {
00587 default: NOT_REACHED();
00588 case SORT_BY_VALUE:
00589 for (AIListBucket::iterator iter = this->buckets.begin(); iter != this->buckets.end(); iter = this->buckets.begin()) {
00590 AIItemList *items = &(*iter).second;
00591 size_t size = items->size();
00592 for (AIItemList::iterator iter = items->begin(); iter != items->end(); iter = items->begin()) {
00593 if (--count < 0) return;
00594 this->RemoveItem(*iter);
00595
00596
00597
00598 if (--size == 0) break;
00599 }
00600 }
00601 break;
00602
00603 case SORT_BY_ITEM:
00604 for (AIListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter = this->items.begin()) {
00605 if (--count < 0) return;
00606 this->RemoveItem((*iter).first);
00607 }
00608 break;
00609 }
00610 }
00611
00612 void AIList::RemoveBottom(int32 count)
00613 {
00614 this->modifications++;
00615
00616 if (!this->sort_ascending) {
00617 this->Sort(this->sorter_type, !this->sort_ascending);
00618 this->RemoveTop(count);
00619 this->Sort(this->sorter_type, !this->sort_ascending);
00620 return;
00621 }
00622
00623 switch (this->sorter_type) {
00624 default: NOT_REACHED();
00625 case SORT_BY_VALUE:
00626 for (AIListBucket::reverse_iterator iter = this->buckets.rbegin(); iter != this->buckets.rend(); iter = this->buckets.rbegin()) {
00627 AIItemList *items = &(*iter).second;
00628 size_t size = items->size();
00629 for (AIItemList::reverse_iterator iter = items->rbegin(); iter != items->rend(); iter = items->rbegin()) {
00630 if (--count < 0) return;
00631 this->RemoveItem(*iter);
00632
00633
00634
00635 if (--size == 0) break;
00636 }
00637 }
00638
00639 case SORT_BY_ITEM:
00640 for (AIListMap::reverse_iterator iter = this->items.rbegin(); iter != this->items.rend(); iter = this->items.rbegin()) {
00641 if (--count < 0) return;
00642 this->RemoveItem((*iter).first);
00643 }
00644 break;
00645 }
00646 }
00647
00648 void AIList::RemoveList(AIList *list)
00649 {
00650 this->modifications++;
00651
00652 AIListMap *list_items = &list->items;
00653 for (AIListMap::iterator iter = list_items->begin(); iter != list_items->end(); iter++) {
00654 this->RemoveItem((*iter).first);
00655 }
00656 }
00657
00658 void AIList::KeepAboveValue(int32 value)
00659 {
00660 this->modifications++;
00661
00662 for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
00663 next_iter = iter; next_iter++;
00664 if ((*iter).second <= value) this->RemoveItem((*iter).first);
00665 }
00666 }
00667
00668 void AIList::KeepBelowValue(int32 value)
00669 {
00670 this->modifications++;
00671
00672 for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
00673 next_iter = iter; next_iter++;
00674 if ((*iter).second >= value) this->RemoveItem((*iter).first);
00675 }
00676 }
00677
00678 void AIList::KeepBetweenValue(int32 start, int32 end)
00679 {
00680 this->modifications++;
00681
00682 for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
00683 next_iter = iter; next_iter++;
00684 if ((*iter).second <= start || (*iter).second >= end) this->RemoveItem((*iter).first);
00685 }
00686 }
00687
00688 void AIList::KeepValue(int32 value)
00689 {
00690 this->modifications++;
00691
00692 for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
00693 next_iter = iter; next_iter++;
00694 if ((*iter).second != value) this->RemoveItem((*iter).first);
00695 }
00696 }
00697
00698 void AIList::KeepTop(int32 count)
00699 {
00700 this->modifications++;
00701
00702 this->RemoveBottom(this->Count() - count);
00703 }
00704
00705 void AIList::KeepBottom(int32 count)
00706 {
00707 this->modifications++;
00708
00709 this->RemoveTop(this->Count() - count);
00710 }
00711
00712 void AIList::KeepList(AIList *list)
00713 {
00714 this->modifications++;
00715
00716 AIList tmp;
00717 for (AIListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) {
00718 tmp.AddItem((*iter).first);
00719 tmp.SetValue((*iter).first, (*iter).second);
00720 }
00721
00722 tmp.RemoveList(list);
00723 this->RemoveList(&tmp);
00724 }
00725
00726 SQInteger AIList::_get(HSQUIRRELVM vm)
00727 {
00728 if (sq_gettype(vm, 2) != OT_INTEGER) return SQ_ERROR;
00729
00730 SQInteger idx;
00731 sq_getinteger(vm, 2, &idx);
00732
00733 if (!this->HasItem(idx)) return SQ_ERROR;
00734
00735 sq_pushinteger(vm, this->GetValue(idx));
00736 return 1;
00737 }
00738
00739 SQInteger AIList::_set(HSQUIRRELVM vm)
00740 {
00741 if (sq_gettype(vm, 2) != OT_INTEGER) return SQ_ERROR;
00742 if (sq_gettype(vm, 3) != OT_INTEGER || sq_gettype(vm, 3) == OT_NULL) {
00743 return sq_throwerror(vm, _SC("you can only assign integers to this list"));
00744 }
00745
00746 SQInteger idx, val;
00747 sq_getinteger(vm, 2, &idx);
00748 if (sq_gettype(vm, 3) == OT_NULL) {
00749 this->RemoveItem(idx);
00750 return 0;
00751 }
00752
00753 sq_getinteger(vm, 3, &val);
00754 if (!this->HasItem(idx)) {
00755 this->AddItem(idx, val);
00756 return 0;
00757 }
00758
00759 this->SetValue(idx, val);
00760 return 0;
00761 }
00762
00763 SQInteger AIList::_nexti(HSQUIRRELVM vm)
00764 {
00765 if (sq_gettype(vm, 2) == OT_NULL) {
00766 if (this->IsEmpty()) {
00767 sq_pushnull(vm);
00768 return 1;
00769 }
00770 sq_pushinteger(vm, this->Begin());
00771 return 1;
00772 }
00773
00774 SQInteger idx;
00775 sq_getinteger(vm, 2, &idx);
00776
00777 int val = this->Next();
00778 if (this->IsEnd()) {
00779 sq_pushnull(vm);
00780 return 1;
00781 }
00782
00783 sq_pushinteger(vm, val);
00784 return 1;
00785 }
00786
00787 SQInteger AIList::Valuate(HSQUIRRELVM vm)
00788 {
00789 this->modifications++;
00790
00791
00792 int nparam = sq_gettop(vm) - 1;
00793
00794 if (nparam < 1) {
00795 return sq_throwerror(vm, _SC("You need to give a least a Valuator as parameter to AIList::Valuate"));
00796 }
00797
00798
00799
00800
00801 SQObjectType valuator_type = sq_gettype(vm, 2);
00802 if (valuator_type != OT_CLOSURE && valuator_type != OT_NATIVECLOSURE) {
00803 return sq_throwerror(vm, _SC("parameter 1 has an invalid type (expected function)"));
00804 }
00805
00806
00807
00808 bool backup_allow = AIObject::GetAllowDoCommand();
00809 AIObject::SetAllowDoCommand(false);
00810
00811
00812 sq_push(vm, 2);
00813
00814 for (AIListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) {
00815
00816 int previous_modification_count = this->modifications;
00817
00818
00819 sq_pushroottable(vm);
00820
00821 sq_pushinteger(vm, (*iter).first);
00822 for (int i = 0; i < nparam - 1; i++) {
00823 sq_push(vm, i + 3);
00824 }
00825
00826
00827 if (SQ_FAILED(sq_call(vm, nparam + 1, SQTrue, SQTrue))) {
00828 AIObject::SetAllowDoCommand(backup_allow);
00829 return SQ_ERROR;
00830 }
00831
00832
00833 SQInteger value;
00834 switch (sq_gettype(vm, -1)) {
00835 case OT_INTEGER: {
00836 sq_getinteger(vm, -1, &value);
00837 break;
00838 }
00839
00840 case OT_BOOL: {
00841 SQBool v;
00842 sq_getbool(vm, -1, &v);
00843 value = v ? 1 : 0;
00844 break;
00845 }
00846
00847 default: {
00848
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
00857 if (previous_modification_count != this->modifications) {
00858
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 this->SetValue((*iter).first, value);
00866
00867
00868 sq_poptop(vm);
00869
00870 Squirrel::DecreaseOps(vm, 5);
00871 }
00872
00873
00874
00875
00876
00877 sq_pop(vm, nparam + 3);
00878
00879 AIObject::SetAllowDoCommand(backup_allow);
00880 return 0;
00881 }