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