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 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
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
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
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
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
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
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
00375 if (item == this->item_next) {
00376 FindNext();
00377 return;
00378 }
00379 }
00380 };
00381
00382
00383
00384 AIList::AIList()
00385 {
00386
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
00602
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
00639
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
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
00805
00806
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
00813
00814 bool backup_allow = AIObject::GetAllowDoCommand();
00815 AIObject::SetAllowDoCommand(false);
00816
00817
00818 sq_push(vm, 2);
00819
00820 for (AIListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) {
00821
00822 int previous_modification_count = this->modifications;
00823
00824
00825 sq_pushroottable(vm);
00826
00827 sq_pushinteger(vm, (*iter).first);
00828 for (int i = 0; i < nparam - 1; i++) {
00829 sq_push(vm, i + 3);
00830 }
00831
00832
00833 if (SQ_FAILED(sq_call(vm, nparam + 1, SQTrue, SQTrue))) {
00834 AIObject::SetAllowDoCommand(backup_allow);
00835 return SQ_ERROR;
00836 }
00837
00838
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
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
00863 if (previous_modification_count != this->modifications) {
00864
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
00874 sq_poptop(vm);
00875
00876 Squirrel::DecreaseOps(vm, 5);
00877 }
00878
00879
00880
00881
00882
00883 sq_pop(vm, nparam + 3);
00884
00885 AIObject::SetAllowDoCommand(backup_allow);
00886 return 0;
00887 }