Mercurial > hg > openttd
changeset 15881:75df4bf4f199 draft
(svn r20563) -Change: [NoAI] rename AIAbstractList to AIList
line wrap: on
line diff
--- a/bin/ai/compat_0.7.nut +++ b/bin/ai/compat_0.7.nut @@ -275,7 +275,6 @@ return AIRoad._BuildDriveThroughRoadStation(tile, front, road_veh_type, station_id); } -AIAbstractList.HasNext <- AIBridgeList.HasNext <- AIBridgeList_Length.HasNext <- AICargoList.HasNext <- @@ -316,3 +315,5 @@ { return AIIndustry._IsCargoAccepted(industry_id, cargo_id) != AIIndustry.CAS_NOT_ACCEPTED; } + +AIAbstractList <- AIList;
--- a/bin/ai/compat_1.0.nut +++ b/bin/ai/compat_1.0.nut @@ -25,7 +25,6 @@ return AIRoad._BuildDriveThroughRoadStation(tile, front, road_veh_type, station_id); } -AIAbstractList.HasNext <- AIBridgeList.HasNext <- AIBridgeList_Length.HasNext <- AICargoList.HasNext <- @@ -67,3 +66,5 @@ { return AIIndustry._IsCargoAccepted(industry_id, cargo_id) != AIIndustry.CAS_NOT_ACCEPTED; } + +AIAbstractList <- AIList;
--- a/bin/ai/regression/regression.nut +++ b/bin/ai/regression/regression.nut @@ -58,7 +58,7 @@ } list = AIList(); - list.Sort(AIAbstractList.SORT_BY_VALUE, AIAbstractList.SORT_ASCENDING); + list.Sort(AIList.SORT_BY_VALUE, AIList.SORT_ASCENDING); print(""); print(" Value Ascending"); list.AddItem( 5, 10); @@ -93,7 +93,7 @@ } list = AIList(); - list.Sort(AIAbstractList.SORT_BY_ITEM, AIAbstractList.SORT_DESCENDING); + list.Sort(AIList.SORT_BY_ITEM, AIList.SORT_DESCENDING); print(""); print(" Item Descending"); list.AddItem( 5, 10); @@ -128,7 +128,7 @@ } list = AIList(); - list.Sort(AIAbstractList.SORT_BY_ITEM, AIAbstractList.SORT_ASCENDING); + list.Sort(AIList.SORT_BY_ITEM, AIList.SORT_ASCENDING); print(""); print(" Item Ascending"); list.AddItem( 5, 10); @@ -585,7 +585,7 @@ print("--Industry--"); print(" GetIndustryCount(): " + AIIndustry.GetIndustryCount()); local list = AIIndustryList(); - list.Sort(AIAbstractList.SORT_BY_ITEM, AIAbstractList.SORT_ASCENDING); + list.Sort(AIList.SORT_BY_ITEM, AIList.SORT_ASCENDING); for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) { if (AIIndustry.IsValidIndustry(i)) j++; print(" Industry " + i); @@ -704,12 +704,12 @@ } list.RemoveItem(1050); list.RemoveItem(1150); - list.ChangeItem(1051, 12); + list.SetValue(1051, 12); print(" Count(): " + list.Count()); print(" HasItem(1050): " + list.HasItem(1050)); print(" HasItem(1051): " + list.HasItem(1051)); print(" IsEmpty(): " + list.IsEmpty()); - list.Sort(AIAbstractList.SORT_BY_ITEM, AIAbstractList.SORT_ASCENDING); + list.Sort(AIList.SORT_BY_ITEM, AIList.SORT_ASCENDING); print(" List Dump:"); for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) { print(" " + i + " => " + list.GetValue(i)); @@ -1198,7 +1198,7 @@ print(" RemoveSign(" + sign_id + "): " + AISign.RemoveSign(sign_id)); print(""); local list = AISignList(); - list.Sort(AIAbstractList.SORT_BY_ITEM, AIAbstractList.SORT_ASCENDING); + list.Sort(AIList.SORT_BY_ITEM, AIList.SORT_ASCENDING); for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) { j++; print(" Sign " + i); @@ -1467,7 +1467,7 @@ print("--Town--"); print(" GetTownCount(): " + AITown.GetTownCount()); local list = AITownList(); - list.Sort(AIAbstractList.SORT_BY_ITEM, AIAbstractList.SORT_ASCENDING); + list.Sort(AIList.SORT_BY_ITEM, AIList.SORT_ASCENDING); for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) { if (AITown.IsValidTown(i)) j++; print(" Town " + i);
--- a/projects/openttd_vs100.vcxproj +++ b/projects/openttd_vs100.vcxproj @@ -845,7 +845,6 @@ <ClCompile Include="..\src\ai\ai_scanner.cpp" /> <ClInclude Include="..\src\ai\ai_scanner.hpp" /> <ClInclude Include="..\src\ai\ai_storage.hpp" /> - <ClInclude Include="..\src\ai\api\ai_abstractlist.hpp" /> <ClInclude Include="..\src\ai\api\ai_accounting.hpp" /> <ClInclude Include="..\src\ai\api\ai_airport.hpp" /> <ClInclude Include="..\src\ai\api\ai_base.hpp" /> @@ -873,6 +872,7 @@ <ClInclude Include="..\src\ai\api\ai_industrytype.hpp" /> <ClInclude Include="..\src\ai\api\ai_industrytypelist.hpp" /> <ClInclude Include="..\src\ai\api\ai_info_docs.hpp" /> + <ClInclude Include="..\src\ai\api\ai_list.hpp" /> <ClInclude Include="..\src\ai\api\ai_log.hpp" /> <ClInclude Include="..\src\ai\api\ai_map.hpp" /> <ClInclude Include="..\src\ai\api\ai_marine.hpp" /> @@ -898,7 +898,6 @@ <ClInclude Include="..\src\ai\api\ai_vehiclelist.hpp" /> <ClInclude Include="..\src\ai\api\ai_waypoint.hpp" /> <ClInclude Include="..\src\ai\api\ai_waypointlist.hpp" /> - <ClCompile Include="..\src\ai\api\ai_abstractlist.cpp" /> <ClCompile Include="..\src\ai\api\ai_accounting.cpp" /> <ClCompile Include="..\src\ai\api\ai_airport.cpp" /> <ClCompile Include="..\src\ai\api\ai_base.cpp" /> @@ -924,6 +923,7 @@ <ClCompile Include="..\src\ai\api\ai_industrylist.cpp" /> <ClCompile Include="..\src\ai\api\ai_industrytype.cpp" /> <ClCompile Include="..\src\ai\api\ai_industrytypelist.cpp" /> + <ClCompile Include="..\src\ai\api\ai_list.cpp" /> <ClCompile Include="..\src\ai\api\ai_log.cpp" /> <ClCompile Include="..\src\ai\api\ai_map.cpp" /> <ClCompile Include="..\src\ai\api\ai_marine.cpp" />
--- a/projects/openttd_vs100.vcxproj.filters +++ b/projects/openttd_vs100.vcxproj.filters @@ -1738,9 +1738,6 @@ <ClInclude Include="..\src\ai\ai_storage.hpp"> <Filter>AI Core</Filter> </ClInclude> - <ClInclude Include="..\src\ai\api\ai_abstractlist.hpp"> - <Filter>AI API</Filter> - </ClInclude> <ClInclude Include="..\src\ai\api\ai_accounting.hpp"> <Filter>AI API</Filter> </ClInclude> @@ -1822,6 +1819,9 @@ <ClInclude Include="..\src\ai\api\ai_info_docs.hpp"> <Filter>AI API</Filter> </ClInclude> + <ClInclude Include="..\src\ai\api\ai_list.hpp"> + <Filter>AI API</Filter> + </ClInclude> <ClInclude Include="..\src\ai\api\ai_log.hpp"> <Filter>AI API</Filter> </ClInclude> @@ -1897,9 +1897,6 @@ <ClInclude Include="..\src\ai\api\ai_waypointlist.hpp"> <Filter>AI API</Filter> </ClInclude> - <ClCompile Include="..\src\ai\api\ai_abstractlist.cpp"> - <Filter>AI API Implementation</Filter> - </ClCompile> <ClCompile Include="..\src\ai\api\ai_accounting.cpp"> <Filter>AI API Implementation</Filter> </ClCompile> @@ -1975,6 +1972,9 @@ <ClCompile Include="..\src\ai\api\ai_industrytypelist.cpp"> <Filter>AI API Implementation</Filter> </ClCompile> + <ClCompile Include="..\src\ai\api\ai_list.cpp"> + <Filter>AI API Implementation</Filter> + </ClCompile> <ClCompile Include="..\src\ai\api\ai_log.cpp"> <Filter>AI API Implementation</Filter> </ClCompile>
--- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -2696,10 +2696,6 @@ Name="AI API" > <File - RelativePath=".\..\src\ai\api\ai_abstractlist.hpp" - > - </File> - <File RelativePath=".\..\src\ai\api\ai_accounting.hpp" > </File> @@ -2808,6 +2804,10 @@ > </File> <File + RelativePath=".\..\src\ai\api\ai_list.hpp" + > + </File> + <File RelativePath=".\..\src\ai\api\ai_log.hpp" > </File> @@ -2912,10 +2912,6 @@ Name="AI API Implementation" > <File - RelativePath=".\..\src\ai\api\ai_abstractlist.cpp" - > - </File> - <File RelativePath=".\..\src\ai\api\ai_accounting.cpp" > </File> @@ -3016,6 +3012,10 @@ > </File> <File + RelativePath=".\..\src\ai\api\ai_list.cpp" + > + </File> + <File RelativePath=".\..\src\ai\api\ai_log.cpp" > </File>
--- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -2693,10 +2693,6 @@ Name="AI API" > <File - RelativePath=".\..\src\ai\api\ai_abstractlist.hpp" - > - </File> - <File RelativePath=".\..\src\ai\api\ai_accounting.hpp" > </File> @@ -2805,6 +2801,10 @@ > </File> <File + RelativePath=".\..\src\ai\api\ai_list.hpp" + > + </File> + <File RelativePath=".\..\src\ai\api\ai_log.hpp" > </File> @@ -2909,10 +2909,6 @@ Name="AI API Implementation" > <File - RelativePath=".\..\src\ai\api\ai_abstractlist.cpp" - > - </File> - <File RelativePath=".\..\src\ai\api\ai_accounting.cpp" > </File> @@ -3013,6 +3009,10 @@ > </File> <File + RelativePath=".\..\src\ai\api\ai_list.cpp" + > + </File> + <File RelativePath=".\..\src\ai\api\ai_log.cpp" > </File>
--- a/source.list +++ b/source.list @@ -611,7 +611,6 @@ ai/ai_storage.hpp # AI API -ai/api/ai_abstractlist.hpp ai/api/ai_accounting.hpp ai/api/ai_airport.hpp ai/api/ai_base.hpp @@ -639,6 +638,7 @@ ai/api/ai_industrytype.hpp ai/api/ai_industrytypelist.hpp ai/api/ai_info_docs.hpp +ai/api/ai_list.hpp ai/api/ai_log.hpp ai/api/ai_map.hpp ai/api/ai_marine.hpp @@ -666,7 +666,6 @@ ai/api/ai_waypointlist.hpp # AI API Implementation -ai/api/ai_abstractlist.cpp ai/api/ai_accounting.cpp ai/api/ai_airport.cpp ai/api/ai_base.cpp @@ -692,6 +691,7 @@ ai/api/ai_industrylist.cpp ai/api/ai_industrytype.cpp ai/api/ai_industrytypelist.cpp +ai/api/ai_list.cpp ai/api/ai_log.cpp ai/api/ai_map.cpp ai/api/ai_marine.cpp
--- a/src/ai/ai_instance.cpp +++ b/src/ai/ai_instance.cpp @@ -26,7 +26,6 @@ /* Convert all AI related classes to Squirrel data. * Note: this line a marker in squirrel_export.sh. Do not change! */ -#include "api/ai_abstractlist.hpp.sq" #include "api/ai_accounting.hpp.sq" #include "api/ai_airport.hpp.sq" #include "api/ai_base.hpp.sq" @@ -52,6 +51,7 @@ #include "api/ai_industrylist.hpp.sq" #include "api/ai_industrytype.hpp.sq" #include "api/ai_industrytypelist.hpp.sq" +#include "api/ai_list.hpp.sq" #include "api/ai_log.hpp.sq" #include "api/ai_map.hpp.sq" #include "api/ai_marine.hpp.sq" @@ -171,7 +171,7 @@ { /* Register all classes */ squirrel_register_std(this->engine); - SQAIAbstractList_Register(this->engine); + SQAIList_Register(this->engine); SQAIAccounting_Register(this->engine); SQAIAirport_Register(this->engine); SQAIBase_Register(this->engine);
deleted file mode 100644 --- a/src/ai/api/ai_abstractlist.cpp +++ /dev/null @@ -1,881 +0,0 @@ -/* $Id$ */ - -/* - * This file is part of OpenTTD. - * 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. - * 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. - * 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/>. - */ - -/** @file ai_abstractlist.cpp Implementation of AIAbstractList. */ - -#include "ai_abstractlist.hpp" -#include "../../debug.h" -#include "../../script/squirrel.hpp" - -/** - * Base class for any AIAbstractList sorter. - */ -class AIAbstractListSorter { -protected: - AIAbstractList *list; - -public: - /** - * Virtual dtor, needed to mute warnings. - */ - virtual ~AIAbstractListSorter() { } - - /** - * Get the first item of the sorter. - */ - virtual int32 Begin() = 0; - - /** - * Stop iterating a sorter. - */ - virtual void End() = 0; - - /** - * Get the next item of the sorter. - */ - virtual int32 Next() = 0; - - /** - * See if the sorter has reached the end. - */ - virtual bool IsEnd() = 0; - - /** - * Callback from the list if an item gets removed. - */ - virtual void Remove(int item) = 0; -}; - -/** - * Sort by value, ascending. - */ -class AIAbstractListSorterValueAscending : public AIAbstractListSorter { -private: - AIAbstractList::AIAbstractListBucket::iterator bucket_iter; - AIAbstractList::AIItemList *bucket_list; - AIAbstractList::AIItemList::iterator bucket_list_iter; - bool has_no_more_items; - int32 item_next; - -public: - AIAbstractListSorterValueAscending(AIAbstractList *list) - { - this->list = list; - this->End(); - } - - int32 Begin() - { - if (this->list->buckets.empty()) return 0; - this->has_no_more_items = false; - - this->bucket_iter = this->list->buckets.begin(); - this->bucket_list = &(*this->bucket_iter).second; - this->bucket_list_iter = this->bucket_list->begin(); - this->item_next = *this->bucket_list_iter; - - int32 item_current = this->item_next; - FindNext(); - return item_current; - } - - void End() - { - this->bucket_list = NULL; - this->has_no_more_items = true; - this->item_next = 0; - } - - void FindNext() - { - if (this->bucket_list == NULL) { - this->has_no_more_items = true; - return; - } - - this->bucket_list_iter++; - if (this->bucket_list_iter == this->bucket_list->end()) { - this->bucket_iter++; - if (this->bucket_iter == this->list->buckets.end()) { - this->bucket_list = NULL; - return; - } - this->bucket_list = &(*this->bucket_iter).second; - this->bucket_list_iter = this->bucket_list->begin(); - } - this->item_next = *this->bucket_list_iter; - } - - int32 Next() - { - if (this->IsEnd()) return 0; - - int32 item_current = this->item_next; - FindNext(); - return item_current; - } - - void Remove(int item) - { - if (this->IsEnd()) return; - - /* If we remove the 'next' item, skip to the next */ - if (item == this->item_next) { - FindNext(); - return; - } - } - - bool IsEnd() - { - return this->list->buckets.empty() || this->has_no_more_items; - } -}; - -/** - * Sort by value, descending. - */ -class AIAbstractListSorterValueDescending : public AIAbstractListSorter { -private: - AIAbstractList::AIAbstractListBucket::iterator bucket_iter; - AIAbstractList::AIItemList *bucket_list; - AIAbstractList::AIItemList::iterator bucket_list_iter; - bool has_no_more_items; - int32 item_next; - -public: - AIAbstractListSorterValueDescending(AIAbstractList *list) - { - this->list = list; - this->End(); - } - - int32 Begin() - { - if (this->list->buckets.empty()) return 0; - this->has_no_more_items = false; - - /* Go to the end of the bucket-list */ - this->bucket_iter = this->list->buckets.begin(); - for (size_t i = this->list->buckets.size(); i > 1; i--) this->bucket_iter++; - this->bucket_list = &(*this->bucket_iter).second; - - /* Go to the end of the items in the bucket */ - this->bucket_list_iter = this->bucket_list->begin(); - for (size_t i = this->bucket_list->size(); i > 1; i--) this->bucket_list_iter++; - this->item_next = *this->bucket_list_iter; - - int32 item_current = this->item_next; - FindNext(); - return item_current; - } - - void End() - { - this->bucket_list = NULL; - this->has_no_more_items = true; - this->item_next = 0; - } - - void FindNext() - { - if (this->bucket_list == NULL) { - this->has_no_more_items = true; - return; - } - - if (this->bucket_list_iter == this->bucket_list->begin()) { - if (this->bucket_iter == this->list->buckets.begin()) { - this->bucket_list = NULL; - return; - } - this->bucket_iter--; - this->bucket_list = &(*this->bucket_iter).second; - /* Go to the end of the items in the bucket */ - this->bucket_list_iter = this->bucket_list->begin(); - for (size_t i = this->bucket_list->size(); i > 1; i--) this->bucket_list_iter++; - } else { - this->bucket_list_iter--; - } - this->item_next = *this->bucket_list_iter; - } - - int32 Next() - { - if (this->IsEnd()) return 0; - - int32 item_current = this->item_next; - FindNext(); - return item_current; - } - - void Remove(int item) - { - if (this->IsEnd()) return; - - /* If we remove the 'next' item, skip to the next */ - if (item == this->item_next) { - FindNext(); - return; - } - } - - bool IsEnd() - { - return this->list->buckets.empty() || this->has_no_more_items; - } -}; - -/** - * Sort by item, ascending. - */ -class AIAbstractListSorterItemAscending : public AIAbstractListSorter { -private: - AIAbstractList::AIAbstractListMap::iterator item_iter; - bool has_no_more_items; - int32 item_next; - -public: - AIAbstractListSorterItemAscending(AIAbstractList *list) - { - this->list = list; - this->End(); - } - - int32 Begin() - { - if (this->list->items.empty()) return 0; - this->has_no_more_items = false; - - this->item_iter = this->list->items.begin(); - this->item_next = (*this->item_iter).first; - - int32 item_current = this->item_next; - FindNext(); - return item_current; - } - - void End() - { - this->has_no_more_items = true; - } - - void FindNext() - { - if (this->item_iter == this->list->items.end()) { - this->has_no_more_items = true; - return; - } - this->item_iter++; - if (this->item_iter != this->list->items.end()) item_next = (*this->item_iter).first; - } - - int32 Next() - { - if (this->IsEnd()) return 0; - - int32 item_current = this->item_next; - FindNext(); - return item_current; - } - - void Remove(int item) - { - if (this->IsEnd()) return; - - /* If we remove the 'next' item, skip to the next */ - if (item == this->item_next) { - FindNext(); - return; - } - } - - bool IsEnd() - { - return this->list->items.empty() || this->has_no_more_items; - } -}; - -/** - * Sort by item, descending. - */ -class AIAbstractListSorterItemDescending : public AIAbstractListSorter { -private: - AIAbstractList::AIAbstractListMap::iterator item_iter; - bool has_no_more_items; - int32 item_next; - -public: - AIAbstractListSorterItemDescending(AIAbstractList *list) - { - this->list = list; - this->End(); - } - - int32 Begin() - { - if (this->list->items.empty()) return 0; - this->has_no_more_items = false; - - this->item_iter = this->list->items.begin(); - for (size_t i = this->list->items.size(); i > 1; i--) this->item_iter++; - this->item_next = (*this->item_iter).first; - - int32 item_current = this->item_next; - FindNext(); - return item_current; - } - - void End() - { - this->has_no_more_items = true; - } - - void FindNext() - { - if (this->item_iter == this->list->items.end()) { - this->has_no_more_items = true; - return; - } - this->item_iter--; - if (this->item_iter != this->list->items.end()) item_next = (*this->item_iter).first; - } - - int32 Next() - { - if (this->IsEnd()) return 0; - - int32 item_current = this->item_next; - FindNext(); - return item_current; - } - - void Remove(int item) - { - if (this->IsEnd()) return; - - /* If we remove the 'next' item, skip to the next */ - if (item == this->item_next) { - FindNext(); - return; - } - } - - bool IsEnd() - { - return this->list->items.empty() || this->has_no_more_items; - } -}; - - - -AIAbstractList::AIAbstractList() -{ - /* Default sorter */ - this->sorter = new AIAbstractListSorterValueDescending(this); - this->sorter_type = SORT_BY_VALUE; - this->sort_ascending = false; - this->initialized = false; - this->modifications = 0; -} - -AIAbstractList::~AIAbstractList() -{ - delete this->sorter; -} - -bool AIAbstractList::HasItem(int32 item) -{ - return this->items.count(item) == 1; -} - -void AIAbstractList::Clear() -{ - this->modifications++; - - this->items.clear(); - this->buckets.clear(); - this->sorter->End(); -} - -void AIAbstractList::AddItem(int32 item, int32 value) -{ - this->modifications++; - - if (this->HasItem(item)) return; - - this->items[item] = 0; - this->buckets[0].insert(item); - - this->SetValue(item, value); -} - -void AIAbstractList::RemoveItem(int32 item) -{ - this->modifications++; - - if (!this->HasItem(item)) return; - - int32 value = this->GetValue(item); - - this->sorter->Remove(item); - this->buckets[value].erase(item); - if (this->buckets[value].empty()) this->buckets.erase(value); - this->items.erase(item); -} - -int32 AIAbstractList::Begin() -{ - this->initialized = true; - return this->sorter->Begin(); -} - -int32 AIAbstractList::Next() -{ - if (this->initialized == false) { - DEBUG(ai, 0, "Next() is invalid as Begin() is never called"); - return 0; - } - return this->sorter->Next(); -} - -bool AIAbstractList::IsEmpty() -{ - return this->items.empty(); -} - -bool AIAbstractList::IsEnd() -{ - if (this->initialized == false) { - DEBUG(ai, 0, "IsEnd() is invalid as Begin() is never called"); - return true; - } - return this->sorter->IsEnd(); -} - -int32 AIAbstractList::Count() -{ - return (int32)this->items.size(); -} - -int32 AIAbstractList::GetValue(int32 item) -{ - if (!this->HasItem(item)) return 0; - - return this->items[item]; -} - -bool AIAbstractList::SetValue(int32 item, int32 value) -{ - this->modifications++; - - if (!this->HasItem(item)) return false; - - int32 value_old = this->GetValue(item); - if (value_old == value) return true; - - this->sorter->Remove(item); - this->buckets[value_old].erase(item); - if (this->buckets[value_old].empty()) this->buckets.erase(value_old); - this->items[item] = value; - this->buckets[value].insert(item); - - return true; -} - -void AIAbstractList::Sort(SorterType sorter, bool ascending) -{ - this->modifications++; - - if (sorter != SORT_BY_VALUE && sorter != SORT_BY_ITEM) return; - if (sorter == this->sorter_type && ascending == this->sort_ascending) return; - - delete this->sorter; - switch (sorter) { - case SORT_BY_ITEM: - if (ascending) { - this->sorter = new AIAbstractListSorterItemAscending(this); - } else { - this->sorter = new AIAbstractListSorterItemDescending(this); - } - break; - - case SORT_BY_VALUE: - if (ascending) { - this->sorter = new AIAbstractListSorterValueAscending(this); - } else { - this->sorter = new AIAbstractListSorterValueDescending(this); - } - break; - - default: - this->Sort(SORT_BY_ITEM, false); - return; - } - this->sorter_type = sorter; - this->sort_ascending = ascending; - this->initialized = false; -} - -void AIAbstractList::AddList(AIAbstractList *list) -{ - AIAbstractListMap *list_items = &list->items; - for (AIAbstractListMap::iterator iter = list_items->begin(); iter != list_items->end(); iter++) { - this->AddItem((*iter).first); - this->SetValue((*iter).first, (*iter).second); - } -} - -void AIAbstractList::RemoveAboveValue(int32 value) -{ - this->modifications++; - - for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { - next_iter = iter; next_iter++; - if ((*iter).second > value) this->RemoveItem((*iter).first); - } -} - -void AIAbstractList::RemoveBelowValue(int32 value) -{ - this->modifications++; - - for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { - next_iter = iter; next_iter++; - if ((*iter).second < value) this->RemoveItem((*iter).first); - } -} - -void AIAbstractList::RemoveBetweenValue(int32 start, int32 end) -{ - this->modifications++; - - for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { - next_iter = iter; next_iter++; - if ((*iter).second > start && (*iter).second < end) this->RemoveItem((*iter).first); - } -} - -void AIAbstractList::RemoveValue(int32 value) -{ - this->modifications++; - - for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { - next_iter = iter; next_iter++; - if ((*iter).second == value) this->RemoveItem((*iter).first); - } -} - -void AIAbstractList::RemoveTop(int32 count) -{ - this->modifications++; - - if (!this->sort_ascending) { - this->Sort(this->sorter_type, !this->sort_ascending); - this->RemoveBottom(count); - this->Sort(this->sorter_type, !this->sort_ascending); - return; - } - - switch (this->sorter_type) { - default: NOT_REACHED(); - case SORT_BY_VALUE: - for (AIAbstractListBucket::iterator iter = this->buckets.begin(); iter != this->buckets.end(); iter = this->buckets.begin()) { - AIItemList *items = &(*iter).second; - size_t size = items->size(); - for (AIItemList::iterator iter = items->begin(); iter != items->end(); iter = items->begin()) { - if (--count < 0) return; - this->RemoveItem(*iter); - /* When the last item is removed from the bucket, the bucket itself is removed. - * This means that the iterators can be invalid after a call to RemoveItem. - */ - if (--size == 0) break; - } - } - break; - - case SORT_BY_ITEM: - for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter = this->items.begin()) { - if (--count < 0) return; - this->RemoveItem((*iter).first); - } - break; - } -} - -void AIAbstractList::RemoveBottom(int32 count) -{ - this->modifications++; - - if (!this->sort_ascending) { - this->Sort(this->sorter_type, !this->sort_ascending); - this->RemoveTop(count); - this->Sort(this->sorter_type, !this->sort_ascending); - return; - } - - switch (this->sorter_type) { - default: NOT_REACHED(); - case SORT_BY_VALUE: - for (AIAbstractListBucket::reverse_iterator iter = this->buckets.rbegin(); iter != this->buckets.rend(); iter = this->buckets.rbegin()) { - AIItemList *items = &(*iter).second; - size_t size = items->size(); - for (AIItemList::reverse_iterator iter = items->rbegin(); iter != items->rend(); iter = items->rbegin()) { - if (--count < 0) return; - this->RemoveItem(*iter); - /* When the last item is removed from the bucket, the bucket itself is removed. - * This means that the iterators can be invalid after a call to RemoveItem. - */ - if (--size == 0) break; - } - } - - case SORT_BY_ITEM: - for (AIAbstractListMap::reverse_iterator iter = this->items.rbegin(); iter != this->items.rend(); iter = this->items.rbegin()) { - if (--count < 0) return; - this->RemoveItem((*iter).first); - } - break; - } -} - -void AIAbstractList::RemoveList(AIAbstractList *list) -{ - this->modifications++; - - AIAbstractListMap *list_items = &list->items; - for (AIAbstractListMap::iterator iter = list_items->begin(); iter != list_items->end(); iter++) { - this->RemoveItem((*iter).first); - } -} - -void AIAbstractList::KeepAboveValue(int32 value) -{ - this->modifications++; - - for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { - next_iter = iter; next_iter++; - if ((*iter).second <= value) this->RemoveItem((*iter).first); - } -} - -void AIAbstractList::KeepBelowValue(int32 value) -{ - this->modifications++; - - for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { - next_iter = iter; next_iter++; - if ((*iter).second >= value) this->RemoveItem((*iter).first); - } -} - -void AIAbstractList::KeepBetweenValue(int32 start, int32 end) -{ - this->modifications++; - - for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { - next_iter = iter; next_iter++; - if ((*iter).second <= start || (*iter).second >= end) this->RemoveItem((*iter).first); - } -} - -void AIAbstractList::KeepValue(int32 value) -{ - this->modifications++; - - for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { - next_iter = iter; next_iter++; - if ((*iter).second != value) this->RemoveItem((*iter).first); - } -} - -void AIAbstractList::KeepTop(int32 count) -{ - this->modifications++; - - this->RemoveBottom(this->Count() - count); -} - -void AIAbstractList::KeepBottom(int32 count) -{ - this->modifications++; - - this->RemoveTop(this->Count() - count); -} - -void AIAbstractList::KeepList(AIAbstractList *list) -{ - this->modifications++; - - AIAbstractList tmp; - for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { - tmp.AddItem((*iter).first); - tmp.SetValue((*iter).first, (*iter).second); - } - - tmp.RemoveList(list); - this->RemoveList(&tmp); -} - -SQInteger AIAbstractList::_get(HSQUIRRELVM vm) -{ - if (sq_gettype(vm, 2) != OT_INTEGER) return SQ_ERROR; - - SQInteger idx; - sq_getinteger(vm, 2, &idx); - - if (!this->HasItem(idx)) return SQ_ERROR; - - sq_pushinteger(vm, this->GetValue(idx)); - return 1; -} - -SQInteger AIAbstractList::_set(HSQUIRRELVM vm) -{ - if (sq_gettype(vm, 2) != OT_INTEGER) return SQ_ERROR; - if (sq_gettype(vm, 3) != OT_INTEGER || sq_gettype(vm, 3) == OT_NULL) { - return sq_throwerror(vm, _SC("you can only assign integers to this list")); - } - - SQInteger idx, val; - sq_getinteger(vm, 2, &idx); - if (sq_gettype(vm, 3) == OT_NULL) { - this->RemoveItem(idx); - return 0; - } - - sq_getinteger(vm, 3, &val); - if (!this->HasItem(idx)) { - this->AddItem(idx, val); - return 0; - } - - this->SetValue(idx, val); - return 0; -} - -SQInteger AIAbstractList::_nexti(HSQUIRRELVM vm) -{ - if (sq_gettype(vm, 2) == OT_NULL) { - if (this->IsEmpty()) { - sq_pushnull(vm); - return 1; - } - sq_pushinteger(vm, this->Begin()); - return 1; - } - - SQInteger idx; - sq_getinteger(vm, 2, &idx); - - int val = this->Next(); - if (this->IsEnd()) { - sq_pushnull(vm); - return 1; - } - - sq_pushinteger(vm, val); - return 1; -} - -SQInteger AIAbstractList::Valuate(HSQUIRRELVM vm) -{ - this->modifications++; - - /* The first parameter is the instance of AIAbstractList. */ - int nparam = sq_gettop(vm) - 1; - - if (nparam < 1) { - return sq_throwerror(vm, _SC("You need to give a least a Valuator as parameter to AIAbstractList::Valuate")); - } - - /* Make sure the valuator function is really a function, and not any - * other type. It's parameter 2 for us, but for the user it's the - * first parameter they give. */ - SQObjectType valuator_type = sq_gettype(vm, 2); - if (valuator_type != OT_CLOSURE && valuator_type != OT_NATIVECLOSURE) { - return sq_throwerror(vm, _SC("parameter 1 has an invalid type (expected function)")); - } - - /* Don't allow docommand from a Valuator, as we can't resume in - * mid C++-code. */ - bool backup_allow = AIObject::GetAllowDoCommand(); - AIObject::SetAllowDoCommand(false); - - /* Push the function to call */ - sq_push(vm, 2); - - for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { - /* Check for changing of items. */ - int previous_modification_count = this->modifications; - - /* Push the root table as instance object, this is what squirrel does for meta-functions. */ - sq_pushroottable(vm); - /* Push all arguments for the valuator function. */ - sq_pushinteger(vm, (*iter).first); - for (int i = 0; i < nparam - 1; i++) { - sq_push(vm, i + 3); - } - - /* Call the function. Squirrel pops all parameters and pushes the return value. */ - if (SQ_FAILED(sq_call(vm, nparam + 1, SQTrue, SQTrue))) { - AIObject::SetAllowDoCommand(backup_allow); - return SQ_ERROR; - } - - /* Retreive the return value */ - SQInteger value; - switch (sq_gettype(vm, -1)) { - case OT_INTEGER: { - sq_getinteger(vm, -1, &value); - break; - } - - case OT_BOOL: { - SQBool v; - sq_getbool(vm, -1, &v); - value = v ? 1 : 0; - break; - } - - default: { - /* See below for explanation. The extra pop is the return value. */ - sq_pop(vm, nparam + 4); - - AIObject::SetAllowDoCommand(backup_allow); - return sq_throwerror(vm, _SC("return value of valuator is not valid (not integer/bool)")); - } - } - - /* Was something changed? */ - if (previous_modification_count != this->modifications) { - /* See below for explanation. The extra pop is the return value. */ - sq_pop(vm, nparam + 4); - - AIObject::SetAllowDoCommand(backup_allow); - return sq_throwerror(vm, _SC("modifying valuated list outside of valuator function")); - } - - this->SetValue((*iter).first, value); - - /* Pop the return value. */ - sq_poptop(vm); - - Squirrel::DecreaseOps(vm, 5); - } - /* Pop from the squirrel stack: - * 1. The root stable (as instance object). - * 2. The valuator function. - * 3. The parameters given to this function. - * 4. The AIAbstractList instance object. */ - sq_pop(vm, nparam + 3); - - AIObject::SetAllowDoCommand(backup_allow); - return 0; -}
deleted file mode 100644 --- a/src/ai/api/ai_abstractlist.hpp +++ /dev/null @@ -1,286 +0,0 @@ -/* $Id$ */ - -/* - * This file is part of OpenTTD. - * 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. - * 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. - * 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/>. - */ - -/** @file ai_abstractlist.hpp A list which can keep item/value pairs, which you can walk. */ -/** @defgroup AIList Classes that create a list of items. */ - -#ifndef AI_ABSTRACTLIST_HPP -#define AI_ABSTRACTLIST_HPP - -#include "ai_object.hpp" -#include <map> -#include <set> - -class AIAbstractListSorter; - -/** - * Class that creates a list which can keep item/value pairs, which you can walk. - */ -class AIAbstractList : public AIObject { -public: - /** Get the name of this class to identify it towards squirrel. */ - static const char *GetClassName() { return "AIAbstractList"; } - - /** Type of sorter */ - enum SorterType { - SORT_BY_VALUE, ///< Sort the list based on the value of the item. - SORT_BY_ITEM, ///< Sort the list based on the item itself. - }; - - /** Sort ascending */ - static const bool SORT_ASCENDING = true; - /** Sort descnding */ - static const bool SORT_DESCENDING = false; - -private: - AIAbstractListSorter *sorter; ///< Sorting algorithm - SorterType sorter_type; ///< Sorting type - bool sort_ascending; ///< Whether to sort ascending or descending - bool initialized; ///< Whether an iteration has been started - int modifications; ///< Number of modification that has been done. To prevent changing data while valuating. - -public: - typedef std::set<int32> AIItemList; ///< The list of items inside the bucket - typedef std::map<int32, AIItemList> AIAbstractListBucket; ///< The bucket list per value - typedef std::map<int32, int32> AIAbstractListMap; ///< List per item - - AIAbstractListMap items; ///< The items in the list - AIAbstractListBucket buckets; ///< The items in the list, sorted by value - - AIAbstractList(); - ~AIAbstractList(); - - /** - * Add a single item to the list. - * @param item the item to add. Should be unique, otherwise it is ignored. - * @param value the value to assign. - * @note the value is set to 0 by default. - */ - void AddItem(int32 item, int32 value = 0); - - /** - * Remove a single item from the list. - * @param item the item to remove. If not existing, it is ignored. - */ - void RemoveItem(int32 item); - - /** - * Clear the list, making Count() returning 0 and IsEmpty() returning true. - */ - void Clear(); - - /** - * Check if an item is in the list. - * @param item the item to check for. - * @return true if the item is in the list. - */ - bool HasItem(int32 item); - - /** - * Go to the beginning of the list. - * @return the item value of the first item. - * @note returns 0 if beyond end-of-list. Use IsEnd() to check for end-of-list. - */ - int32 Begin(); - - /** - * Go to the next item in the list. - * @return the item value of the next item. - * @note returns 0 if beyond end-of-list. Use IsEnd() to check for end-of-list. - */ - int32 Next(); - - /** - * Check if a list is empty. - * @return true if the list is empty. - */ - bool IsEmpty(); - - /** - * Check if there is a element left. In other words, if this is false, - * the last call to Begin() or Next() returned a valid item. - * @return true if the current item is beyond end-of-list. - */ - bool IsEnd(); - - /** - * Returns the amount of items in the list. - * @return amount of items in the list. - */ - int32 Count(); - - /** - * Get the value that belongs to this item. - * @param item the item to get the value from - * @return the value that belongs to this item. - */ - int32 GetValue(int32 item); - - /** - * Set a value of an item directly. - * @param item the item to set the value for. - * @param value the value to give to the item - * @return true if we could set the item to value, false otherwise. - * @note Changing values of items while looping through a list might cause - * entries to be skipped. Be very careful with such operations. - */ - bool SetValue(int32 item, int32 value); - - /** - * Sort this list by the given sorter and direction. - * @param sorter the type of sorter to use - * @param ascending if true, lowest value is on top, else at bottom. - * @note the current item stays at the same place. - * @see SORT_ASCENDING SORT_DESCENDING - */ - void Sort(SorterType sorter, bool ascending); - - /** - * Add one list to another one. - * @param list The list that will be added to the caller. - * @post The list to be added ('list') stays unmodified. - * @note All added items keep their value as it was in 'list'. - * @note If the item already exists inside the caller, the value of the - * list that is added is set on the item. - */ - void AddList(AIAbstractList *list); - - /** - * Removes all items with a higher value than 'value'. - * @param value the value above which all items are removed. - */ - void RemoveAboveValue(int32 value); - - /** - * Removes all items with a lower value than 'value'. - * @param value the value below which all items are removed. - */ - void RemoveBelowValue(int32 value); - - /** - * Removes all items with a value above start and below end. - * @param start the lower bound of the to be removed values (exclusive). - * @param end the upper bound of the to be removed valuens (exclusive). - */ - void RemoveBetweenValue(int32 start, int32 end); - - /** - * Remove all items with this value. - * @param value the value to remove. - */ - void RemoveValue(int32 value); - - /** - * Remove the first count items. - * @param count the amount of items to remove. - */ - void RemoveTop(int32 count); - - /** - * Remove the last count items. - * @param count the amount of items to remove. - */ - void RemoveBottom(int32 count); - - /** - * Remove everything that is in the given list from this list (same item index that is). - * @param list the list of items to remove. - * @pre list != NULL - */ - void RemoveList(AIAbstractList *list); - - /** - * Keep all items with a higher value than 'value'. - * @param value the value above which all items are kept. - */ - void KeepAboveValue(int32 value); - - /** - * Keep all items with a lower value than 'value'. - * @param value the value below which all items are kept. - */ - void KeepBelowValue(int32 value); - - /** - * Keep all items with a value above start and below end. - * @param start the lower bound of the to be kept values (exclusive). - * @param end the upper bound of the to be kept values (exclusive). - */ - void KeepBetweenValue(int32 start, int32 end); - - /** - * Keep all items with this value. - * @param value the value to keep. - */ - void KeepValue(int32 value); - - /** - * Keep the first count items, i.e. remove everything except the first count items. - * @param count the amount of items to keep. - */ - void KeepTop(int32 count); - - /** - * Keep the last count items, i.e. remove everything except the last count items. - * @param count the amount of items to keep. - */ - void KeepBottom(int32 count); - - /** - * Keeps everything that is in the given list from this list (same item index that is). - * @param list the list of items to keep. - * @pre list != NULL - */ - void KeepList(AIAbstractList *list); - -#ifndef DOXYGEN_SKIP - /** - * Used for 'foreach()' and [] get from Squirrel. - */ - SQInteger _get(HSQUIRRELVM vm); - - /** - * Used for [] set from Squirrel. - */ - SQInteger _set(HSQUIRRELVM vm); - - /** - * Used for 'foreach()' from Squirrel. - */ - SQInteger _nexti(HSQUIRRELVM vm); - - /** - * The Valuate() wrapper from Squirrel. - */ - SQInteger Valuate(HSQUIRRELVM vm); -#else - /** - * Give all items a value defined by the valuator you give. - * @param valuator_function The function which will be doing the valuation. - * @param params The params to give to the valuators (minus the first param, - * which is always the index-value we are valuating). - * @note You may not add, remove or change (setting the value of) items while - * valuating. You may also not (re)sort while valuating. - * @note You can write your own valuators and use them. Just remember that - * the first parameter should be the index-value, and it should return - * an integer. - * @note Example: - * list.Valuate(AIBridge.GetPrice, 5); - * list.Valuate(AIBridge.GetMaxLength); - * function MyVal(bridge_id, myparam) - * { - * return myparam * bridge_id; // This is silly - * } - * list.Valuate(MyVal, 12); - */ - void Valuate(void *valuator_function, int params, ...); -#endif /* DOXYGEN_SKIP */ -}; - -#endif /* AI_LIST_HPP */
deleted file mode 100644 --- a/src/ai/api/ai_abstractlist.hpp.sq +++ /dev/null @@ -1,72 +0,0 @@ -/* $Id$ */ - -/* - * This file is part of OpenTTD. - * 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. - * 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. - * 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/>. - */ - -/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */ - -#include "ai_abstractlist.hpp" - -namespace SQConvert { - /* Allow enums to be used as Squirrel parameters */ - template <> AIAbstractList::SorterType GetParam(ForceType<AIAbstractList::SorterType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIAbstractList::SorterType)tmp; } - template <> int Return<AIAbstractList::SorterType>(HSQUIRRELVM vm, AIAbstractList::SorterType res) { sq_pushinteger(vm, (int32)res); return 1; } - - /* Allow AIAbstractList to be used as Squirrel parameter */ - template <> AIAbstractList *GetParam(ForceType<AIAbstractList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIAbstractList *)instance; } - template <> AIAbstractList &GetParam(ForceType<AIAbstractList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIAbstractList *)instance; } - template <> const AIAbstractList *GetParam(ForceType<const AIAbstractList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIAbstractList *)instance; } - template <> const AIAbstractList &GetParam(ForceType<const AIAbstractList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIAbstractList *)instance; } - template <> int Return<AIAbstractList *>(HSQUIRRELVM vm, AIAbstractList *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIAbstractList", res, NULL, DefSQDestructorCallback<AIAbstractList>); return 1; } -} // namespace SQConvert - -void SQAIAbstractList_Register(Squirrel *engine) -{ - DefSQClass <AIAbstractList> SQAIAbstractList("AIAbstractList"); - SQAIAbstractList.PreRegister(engine); - SQAIAbstractList.AddConstructor<void (AIAbstractList::*)(), 1>(engine, "x"); - - SQAIAbstractList.DefSQConst(engine, AIAbstractList::SORT_BY_VALUE, "SORT_BY_VALUE"); - SQAIAbstractList.DefSQConst(engine, AIAbstractList::SORT_BY_ITEM, "SORT_BY_ITEM"); - - SQAIAbstractList.DefSQConst(engine, AIAbstractList::SORT_ASCENDING, "SORT_ASCENDING"); - SQAIAbstractList.DefSQConst(engine, AIAbstractList::SORT_DESCENDING, "SORT_DESCENDING"); - - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::AddItem, "AddItem", 3, "xii"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveItem, "RemoveItem", 2, "xi"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::Clear, "Clear", 1, "x"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::HasItem, "HasItem", 2, "xi"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::Begin, "Begin", 1, "x"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::Next, "Next", 1, "x"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::IsEmpty, "IsEmpty", 1, "x"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::IsEnd, "IsEnd", 1, "x"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::Count, "Count", 1, "x"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::GetValue, "GetValue", 2, "xi"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::SetValue, "SetValue", 3, "xii"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::Sort, "Sort", 3, "xib"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::AddList, "AddList", 2, "xx"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveAboveValue, "RemoveAboveValue", 2, "xi"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveBelowValue, "RemoveBelowValue", 2, "xi"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveBetweenValue, "RemoveBetweenValue", 3, "xii"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveValue, "RemoveValue", 2, "xi"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveTop, "RemoveTop", 2, "xi"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveBottom, "RemoveBottom", 2, "xi"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveList, "RemoveList", 2, "xx"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepAboveValue, "KeepAboveValue", 2, "xi"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepBelowValue, "KeepBelowValue", 2, "xi"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepBetweenValue, "KeepBetweenValue", 3, "xii"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepValue, "KeepValue", 2, "xi"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepTop, "KeepTop", 2, "xi"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepBottom, "KeepBottom", 2, "xi"); - SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepList, "KeepList", 2, "xx"); - SQAIAbstractList.DefSQAdvancedMethod(engine, &AIAbstractList::_get, "_get"); - SQAIAbstractList.DefSQAdvancedMethod(engine, &AIAbstractList::_set, "_set"); - SQAIAbstractList.DefSQAdvancedMethod(engine, &AIAbstractList::_nexti, "_nexti"); - SQAIAbstractList.DefSQAdvancedMethod(engine, &AIAbstractList::Valuate, "Valuate"); - - SQAIAbstractList.PostRegister(engine); -}
--- a/src/ai/api/ai_bridgelist.hpp +++ b/src/ai/api/ai_bridgelist.hpp @@ -12,13 +12,13 @@ #ifndef AI_BRIDGELIST_HPP #define AI_BRIDGELIST_HPP -#include "ai_abstractlist.hpp" +#include "ai_list.hpp" /** * Create a list of bridges. * @ingroup AIList */ -class AIBridgeList : public AIAbstractList { +class AIBridgeList : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIBridgeList"; } @@ -29,7 +29,7 @@ * Create a list of bridges that can be built on a specific length. * @ingroup AIList */ -class AIBridgeList_Length : public AIAbstractList { +class AIBridgeList_Length : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIBridgeList_Length"; }
--- a/src/ai/api/ai_bridgelist.hpp.sq +++ b/src/ai/api/ai_bridgelist.hpp.sq @@ -23,7 +23,7 @@ void SQAIBridgeList_Register(Squirrel *engine) { DefSQClass <AIBridgeList> SQAIBridgeList("AIBridgeList"); - SQAIBridgeList.PreRegister(engine, "AIAbstractList"); + SQAIBridgeList.PreRegister(engine, "AIList"); SQAIBridgeList.AddConstructor<void (AIBridgeList::*)(), 1>(engine, "x"); SQAIBridgeList.PostRegister(engine); @@ -41,7 +41,7 @@ void SQAIBridgeList_Length_Register(Squirrel *engine) { DefSQClass <AIBridgeList_Length> SQAIBridgeList_Length("AIBridgeList_Length"); - SQAIBridgeList_Length.PreRegister(engine, "AIAbstractList"); + SQAIBridgeList_Length.PreRegister(engine, "AIList"); SQAIBridgeList_Length.AddConstructor<void (AIBridgeList_Length::*)(uint length), 2>(engine, "xi"); SQAIBridgeList_Length.PostRegister(engine);
--- a/src/ai/api/ai_cargolist.hpp +++ b/src/ai/api/ai_cargolist.hpp @@ -12,13 +12,13 @@ #ifndef AI_CARGOLIST_HPP #define AI_CARGOLIST_HPP -#include "ai_abstractlist.hpp" +#include "ai_list.hpp" /** * Creates a list of cargos that can be produced in the current game. * @ingroup AIList */ -class AICargoList : public AIAbstractList { +class AICargoList : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AICargoList"; } @@ -31,7 +31,7 @@ * by this industry, @see AIIndustry::IsCargoAccepted. * @ingroup AIList */ -class AICargoList_IndustryAccepting : public AIAbstractList { +class AICargoList_IndustryAccepting : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AICargoList_IndustryAccepting"; } @@ -46,7 +46,7 @@ * Creates a list of cargos that the given industry can produce. * @ingroup AIList */ -class AICargoList_IndustryProducing : public AIAbstractList { +class AICargoList_IndustryProducing : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AICargoList_IndustryProducing"; }
--- a/src/ai/api/ai_cargolist.hpp.sq +++ b/src/ai/api/ai_cargolist.hpp.sq @@ -23,7 +23,7 @@ void SQAICargoList_Register(Squirrel *engine) { DefSQClass <AICargoList> SQAICargoList("AICargoList"); - SQAICargoList.PreRegister(engine, "AIAbstractList"); + SQAICargoList.PreRegister(engine, "AIList"); SQAICargoList.AddConstructor<void (AICargoList::*)(), 1>(engine, "x"); SQAICargoList.PostRegister(engine); @@ -41,7 +41,7 @@ void SQAICargoList_IndustryAccepting_Register(Squirrel *engine) { DefSQClass <AICargoList_IndustryAccepting> SQAICargoList_IndustryAccepting("AICargoList_IndustryAccepting"); - SQAICargoList_IndustryAccepting.PreRegister(engine, "AIAbstractList"); + SQAICargoList_IndustryAccepting.PreRegister(engine, "AIList"); SQAICargoList_IndustryAccepting.AddConstructor<void (AICargoList_IndustryAccepting::*)(IndustryID industry_id), 2>(engine, "xi"); SQAICargoList_IndustryAccepting.PostRegister(engine); @@ -59,7 +59,7 @@ void SQAICargoList_IndustryProducing_Register(Squirrel *engine) { DefSQClass <AICargoList_IndustryProducing> SQAICargoList_IndustryProducing("AICargoList_IndustryProducing"); - SQAICargoList_IndustryProducing.PreRegister(engine, "AIAbstractList"); + SQAICargoList_IndustryProducing.PreRegister(engine, "AIList"); SQAICargoList_IndustryProducing.AddConstructor<void (AICargoList_IndustryProducing::*)(IndustryID industry_id), 2>(engine, "xi"); SQAICargoList_IndustryProducing.PostRegister(engine);
--- a/src/ai/api/ai_changelog.hpp +++ b/src/ai/api/ai_changelog.hpp @@ -28,6 +28,8 @@ * * API removals: * \li HasNext for all lists. + * \li AIAbstractList, use AIList instead. + * \li AIList::ChangeItem, use AIList::SetValue instead. * * Other changes: * \li AIEngine::GetMaxTractiveEffort can be used for road vehicles.
--- a/src/ai/api/ai_depotlist.hpp +++ b/src/ai/api/ai_depotlist.hpp @@ -12,14 +12,14 @@ #ifndef AI_DEPOTLIST_HPP #define AI_DEPOTLIST_HPP -#include "ai_abstractlist.hpp" +#include "ai_list.hpp" #include "ai_tile.hpp" /** * Creates a list of the locations of the depots (and hangars) of which you are the owner. * @ingroup AIList */ -class AIDepotList : public AIAbstractList { +class AIDepotList : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIDepotList"; }
--- a/src/ai/api/ai_depotlist.hpp.sq +++ b/src/ai/api/ai_depotlist.hpp.sq @@ -23,7 +23,7 @@ void SQAIDepotList_Register(Squirrel *engine) { DefSQClass <AIDepotList> SQAIDepotList("AIDepotList"); - SQAIDepotList.PreRegister(engine, "AIAbstractList"); + SQAIDepotList.PreRegister(engine, "AIList"); SQAIDepotList.AddConstructor<void (AIDepotList::*)(AITile::TransportType transport_type), 2>(engine, "xi"); SQAIDepotList.PostRegister(engine);
--- a/src/ai/api/ai_enginelist.hpp +++ b/src/ai/api/ai_enginelist.hpp @@ -12,14 +12,14 @@ #ifndef AI_ENGINELIST_HPP #define AI_ENGINELIST_HPP -#include "ai_abstractlist.hpp" +#include "ai_list.hpp" #include "ai_vehicle.hpp" /** * Create a list of engines based on a vehicle type. * @ingroup AIList */ -class AIEngineList : public AIAbstractList { +class AIEngineList : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIEngineList"; }
--- a/src/ai/api/ai_enginelist.hpp.sq +++ b/src/ai/api/ai_enginelist.hpp.sq @@ -23,7 +23,7 @@ void SQAIEngineList_Register(Squirrel *engine) { DefSQClass <AIEngineList> SQAIEngineList("AIEngineList"); - SQAIEngineList.PreRegister(engine, "AIAbstractList"); + SQAIEngineList.PreRegister(engine, "AIList"); SQAIEngineList.AddConstructor<void (AIEngineList::*)(AIVehicle::VehicleType vehicle_type), 2>(engine, "xi"); SQAIEngineList.PostRegister(engine);
--- a/src/ai/api/ai_grouplist.hpp +++ b/src/ai/api/ai_grouplist.hpp @@ -12,14 +12,14 @@ #ifndef AI_GROUPLIST_HPP #define AI_GROUPLIST_HPP -#include "ai_abstractlist.hpp" +#include "ai_list.hpp" /** * Creates a list of groups of which you are the owner. * @note Neither AIGroup::GROUP_ALL nor AIGroup::GROUP_DEFAULT is in this list. * @ingroup AIList */ -class AIGroupList : public AIAbstractList { +class AIGroupList : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIGroupList"; }
--- a/src/ai/api/ai_grouplist.hpp.sq +++ b/src/ai/api/ai_grouplist.hpp.sq @@ -23,7 +23,7 @@ void SQAIGroupList_Register(Squirrel *engine) { DefSQClass <AIGroupList> SQAIGroupList("AIGroupList"); - SQAIGroupList.PreRegister(engine, "AIAbstractList"); + SQAIGroupList.PreRegister(engine, "AIList"); SQAIGroupList.AddConstructor<void (AIGroupList::*)(), 1>(engine, "x"); SQAIGroupList.PostRegister(engine);
--- a/src/ai/api/ai_industrylist.hpp +++ b/src/ai/api/ai_industrylist.hpp @@ -12,13 +12,13 @@ #ifndef AI_INDUSTRYLIST_HPP #define AI_INDUSTRYLIST_HPP -#include "ai_abstractlist.hpp" +#include "ai_list.hpp" /** * Creates a list of industries that are currently on the map. * @ingroup AIList */ -class AIIndustryList : public AIAbstractList { +class AIIndustryList : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIIndustryList"; } @@ -29,7 +29,7 @@ * Creates a list of industries that accepts a given cargo. * @ingroup AIList */ -class AIIndustryList_CargoAccepting : public AIAbstractList { +class AIIndustryList_CargoAccepting : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIIndustryList_CargoAccepting"; } @@ -45,7 +45,7 @@ * @note It also contains industries that currently produces 0 units of the cargo. * @ingroup AIList */ -class AIIndustryList_CargoProducing : public AIAbstractList { +class AIIndustryList_CargoProducing : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIIndustryList_CargoProducing"; }
--- a/src/ai/api/ai_industrylist.hpp.sq +++ b/src/ai/api/ai_industrylist.hpp.sq @@ -23,7 +23,7 @@ void SQAIIndustryList_Register(Squirrel *engine) { DefSQClass <AIIndustryList> SQAIIndustryList("AIIndustryList"); - SQAIIndustryList.PreRegister(engine, "AIAbstractList"); + SQAIIndustryList.PreRegister(engine, "AIList"); SQAIIndustryList.AddConstructor<void (AIIndustryList::*)(), 1>(engine, "x"); SQAIIndustryList.PostRegister(engine); @@ -41,7 +41,7 @@ void SQAIIndustryList_CargoAccepting_Register(Squirrel *engine) { DefSQClass <AIIndustryList_CargoAccepting> SQAIIndustryList_CargoAccepting("AIIndustryList_CargoAccepting"); - SQAIIndustryList_CargoAccepting.PreRegister(engine, "AIAbstractList"); + SQAIIndustryList_CargoAccepting.PreRegister(engine, "AIList"); SQAIIndustryList_CargoAccepting.AddConstructor<void (AIIndustryList_CargoAccepting::*)(CargoID cargo_id), 2>(engine, "xi"); SQAIIndustryList_CargoAccepting.PostRegister(engine); @@ -59,7 +59,7 @@ void SQAIIndustryList_CargoProducing_Register(Squirrel *engine) { DefSQClass <AIIndustryList_CargoProducing> SQAIIndustryList_CargoProducing("AIIndustryList_CargoProducing"); - SQAIIndustryList_CargoProducing.PreRegister(engine, "AIAbstractList"); + SQAIIndustryList_CargoProducing.PreRegister(engine, "AIList"); SQAIIndustryList_CargoProducing.AddConstructor<void (AIIndustryList_CargoProducing::*)(CargoID cargo_id), 2>(engine, "xi"); SQAIIndustryList_CargoProducing.PostRegister(engine);
--- a/src/ai/api/ai_industrytype.cpp +++ b/src/ai/api/ai_industrytype.cpp @@ -58,13 +58,13 @@ return industrytype_name; } -/* static */ AIAbstractList *AIIndustryType::GetProducedCargo(IndustryType industry_type) +/* static */ AIList *AIIndustryType::GetProducedCargo(IndustryType industry_type) { if (!IsValidIndustryType(industry_type)) return NULL; const IndustrySpec *ins = ::GetIndustrySpec(industry_type); - AIAbstractList *list = new AIAbstractList(); + AIList *list = new AIList(); for (size_t i = 0; i < lengthof(ins->produced_cargo); i++) { if (ins->produced_cargo[i] != CT_INVALID) list->AddItem(ins->produced_cargo[i]); } @@ -72,13 +72,13 @@ return list; } -/* static */ AIAbstractList *AIIndustryType::GetAcceptedCargo(IndustryType industry_type) +/* static */ AIList *AIIndustryType::GetAcceptedCargo(IndustryType industry_type) { if (!IsValidIndustryType(industry_type)) return NULL; const IndustrySpec *ins = ::GetIndustrySpec(industry_type); - AIAbstractList *list = new AIAbstractList(); + AIList *list = new AIList(); for (size_t i = 0; i < lengthof(ins->accepts_cargo); i++) { if (ins->accepts_cargo[i] != CT_INVALID) list->AddItem(ins->accepts_cargo[i]); }
--- a/src/ai/api/ai_industrytype.hpp +++ b/src/ai/api/ai_industrytype.hpp @@ -14,7 +14,7 @@ #include "ai_object.hpp" #include "ai_error.hpp" -#include "ai_abstractlist.hpp" +#include "ai_list.hpp" /** * Class that handles all industry-type related functions. @@ -55,7 +55,7 @@ * @pre IsValidIndustryType(industry_type). * @return The CargoIDs of all cargotypes this industry could produce. */ - static AIAbstractList *GetProducedCargo(IndustryType industry_type); + static AIList *GetProducedCargo(IndustryType industry_type); /** * Get a list of CargoID accepted by this industry-type. @@ -65,7 +65,7 @@ * @pre IsValidIndustryType(industry_type). * @return The CargoIDs of all cargotypes this industry accepts. */ - static AIAbstractList *GetAcceptedCargo(IndustryType industry_type); + static AIList *GetAcceptedCargo(IndustryType industry_type); /** * Is this industry type a raw industry?
--- a/src/ai/api/ai_industrytypelist.hpp +++ b/src/ai/api/ai_industrytypelist.hpp @@ -12,14 +12,14 @@ #ifndef AI_INDUSTRYTYPELIST_HPP #define AI_INDUSTRYTYPELIST_HPP -#include "ai_abstractlist.hpp" +#include "ai_list.hpp" #include "ai_industrytype.hpp" /** * Creates a list of valid industry types. * @ingroup AIList */ -class AIIndustryTypeList : public AIAbstractList { +class AIIndustryTypeList : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIIndustryTypeList"; }
--- a/src/ai/api/ai_industrytypelist.hpp.sq +++ b/src/ai/api/ai_industrytypelist.hpp.sq @@ -23,7 +23,7 @@ void SQAIIndustryTypeList_Register(Squirrel *engine) { DefSQClass <AIIndustryTypeList> SQAIIndustryTypeList("AIIndustryTypeList"); - SQAIIndustryTypeList.PreRegister(engine, "AIAbstractList"); + SQAIIndustryTypeList.PreRegister(engine, "AIList"); SQAIIndustryTypeList.AddConstructor<void (AIIndustryTypeList::*)(), 1>(engine, "x"); SQAIIndustryTypeList.PostRegister(engine);
new file mode 100644 --- /dev/null +++ b/src/ai/api/ai_list.cpp @@ -0,0 +1,881 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * 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. + * 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. + * 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/>. + */ + +/** @file ai_list.cpp Implementation of AIList. */ + +#include "ai_list.hpp" +#include "../../debug.h" +#include "../../script/squirrel.hpp" + +/** + * Base class for any AIList sorter. + */ +class AIListSorter { +protected: + AIList *list; + +public: + /** + * Virtual dtor, needed to mute warnings. + */ + virtual ~AIListSorter() { } + + /** + * Get the first item of the sorter. + */ + virtual int32 Begin() = 0; + + /** + * Stop iterating a sorter. + */ + virtual void End() = 0; + + /** + * Get the next item of the sorter. + */ + virtual int32 Next() = 0; + + /** + * See if the sorter has reached the end. + */ + virtual bool IsEnd() = 0; + + /** + * Callback from the list if an item gets removed. + */ + virtual void Remove(int item) = 0; +}; + +/** + * Sort by value, ascending. + */ +class AIListSorterValueAscending : public AIListSorter { +private: + AIList::AIListBucket::iterator bucket_iter; + AIList::AIItemList *bucket_list; + AIList::AIItemList::iterator bucket_list_iter; + bool has_no_more_items; + int32 item_next; + +public: + AIListSorterValueAscending(AIList *list) + { + this->list = list; + this->End(); + } + + int32 Begin() + { + if (this->list->buckets.empty()) return 0; + this->has_no_more_items = false; + + this->bucket_iter = this->list->buckets.begin(); + this->bucket_list = &(*this->bucket_iter).second; + this->bucket_list_iter = this->bucket_list->begin(); + this->item_next = *this->bucket_list_iter; + + int32 item_current = this->item_next; + FindNext(); + return item_current; + } + + void End() + { + this->bucket_list = NULL; + this->has_no_more_items = true; + this->item_next = 0; + } + + void FindNext() + { + if (this->bucket_list == NULL) { + this->has_no_more_items = true; + return; + } + + this->bucket_list_iter++; + if (this->bucket_list_iter == this->bucket_list->end()) { + this->bucket_iter++; + if (this->bucket_iter == this->list->buckets.end()) { + this->bucket_list = NULL; + return; + } + this->bucket_list = &(*this->bucket_iter).second; + this->bucket_list_iter = this->bucket_list->begin(); + } + this->item_next = *this->bucket_list_iter; + } + + int32 Next() + { + if (this->IsEnd()) return 0; + + int32 item_current = this->item_next; + FindNext(); + return item_current; + } + + void Remove(int item) + { + if (this->IsEnd()) return; + + /* If we remove the 'next' item, skip to the next */ + if (item == this->item_next) { + FindNext(); + return; + } + } + + bool IsEnd() + { + return this->list->buckets.empty() || this->has_no_more_items; + } +}; + +/** + * Sort by value, descending. + */ +class AIListSorterValueDescending : public AIListSorter { +private: + AIList::AIListBucket::iterator bucket_iter; + AIList::AIItemList *bucket_list; + AIList::AIItemList::iterator bucket_list_iter; + bool has_no_more_items; + int32 item_next; + +public: + AIListSorterValueDescending(AIList *list) + { + this->list = list; + this->End(); + } + + int32 Begin() + { + if (this->list->buckets.empty()) return 0; + this->has_no_more_items = false; + + /* Go to the end of the bucket-list */ + this->bucket_iter = this->list->buckets.begin(); + for (size_t i = this->list->buckets.size(); i > 1; i--) this->bucket_iter++; + this->bucket_list = &(*this->bucket_iter).second; + + /* Go to the end of the items in the bucket */ + this->bucket_list_iter = this->bucket_list->begin(); + for (size_t i = this->bucket_list->size(); i > 1; i--) this->bucket_list_iter++; + this->item_next = *this->bucket_list_iter; + + int32 item_current = this->item_next; + FindNext(); + return item_current; + } + + void End() + { + this->bucket_list = NULL; + this->has_no_more_items = true; + this->item_next = 0; + } + + void FindNext() + { + if (this->bucket_list == NULL) { + this->has_no_more_items = true; + return; + } + + if (this->bucket_list_iter == this->bucket_list->begin()) { + if (this->bucket_iter == this->list->buckets.begin()) { + this->bucket_list = NULL; + return; + } + this->bucket_iter--; + this->bucket_list = &(*this->bucket_iter).second; + /* Go to the end of the items in the bucket */ + this->bucket_list_iter = this->bucket_list->begin(); + for (size_t i = this->bucket_list->size(); i > 1; i--) this->bucket_list_iter++; + } else { + this->bucket_list_iter--; + } + this->item_next = *this->bucket_list_iter; + } + + int32 Next() + { + if (this->IsEnd()) return 0; + + int32 item_current = this->item_next; + FindNext(); + return item_current; + } + + void Remove(int item) + { + if (this->IsEnd()) return; + + /* If we remove the 'next' item, skip to the next */ + if (item == this->item_next) { + FindNext(); + return; + } + } + + bool IsEnd() + { + return this->list->buckets.empty() || this->has_no_more_items; + } +}; + +/** + * Sort by item, ascending. + */ +class AIListSorterItemAscending : public AIListSorter { +private: + AIList::AIListMap::iterator item_iter; + bool has_no_more_items; + int32 item_next; + +public: + AIListSorterItemAscending(AIList *list) + { + this->list = list; + this->End(); + } + + int32 Begin() + { + if (this->list->items.empty()) return 0; + this->has_no_more_items = false; + + this->item_iter = this->list->items.begin(); + this->item_next = (*this->item_iter).first; + + int32 item_current = this->item_next; + FindNext(); + return item_current; + } + + void End() + { + this->has_no_more_items = true; + } + + void FindNext() + { + if (this->item_iter == this->list->items.end()) { + this->has_no_more_items = true; + return; + } + this->item_iter++; + if (this->item_iter != this->list->items.end()) item_next = (*this->item_iter).first; + } + + int32 Next() + { + if (this->IsEnd()) return 0; + + int32 item_current = this->item_next; + FindNext(); + return item_current; + } + + void Remove(int item) + { + if (this->IsEnd()) return; + + /* If we remove the 'next' item, skip to the next */ + if (item == this->item_next) { + FindNext(); + return; + } + } + + bool IsEnd() + { + return this->list->items.empty() || this->has_no_more_items; + } +}; + +/** + * Sort by item, descending. + */ +class AIListSorterItemDescending : public AIListSorter { +private: + AIList::AIListMap::iterator item_iter; + bool has_no_more_items; + int32 item_next; + +public: + AIListSorterItemDescending(AIList *list) + { + this->list = list; + this->End(); + } + + int32 Begin() + { + if (this->list->items.empty()) return 0; + this->has_no_more_items = false; + + this->item_iter = this->list->items.begin(); + for (size_t i = this->list->items.size(); i > 1; i--) this->item_iter++; + this->item_next = (*this->item_iter).first; + + int32 item_current = this->item_next; + FindNext(); + return item_current; + } + + void End() + { + this->has_no_more_items = true; + } + + void FindNext() + { + if (this->item_iter == this->list->items.end()) { + this->has_no_more_items = true; + return; + } + this->item_iter--; + if (this->item_iter != this->list->items.end()) item_next = (*this->item_iter).first; + } + + int32 Next() + { + if (this->IsEnd()) return 0; + + int32 item_current = this->item_next; + FindNext(); + return item_current; + } + + void Remove(int item) + { + if (this->IsEnd()) return; + + /* If we remove the 'next' item, skip to the next */ + if (item == this->item_next) { + FindNext(); + return; + } + } + + bool IsEnd() + { + return this->list->items.empty() || this->has_no_more_items; + } +}; + + + +AIList::AIList() +{ + /* Default sorter */ + this->sorter = new AIListSorterValueDescending(this); + this->sorter_type = SORT_BY_VALUE; + this->sort_ascending = false; + this->initialized = false; + this->modifications = 0; +} + +AIList::~AIList() +{ + delete this->sorter; +} + +bool AIList::HasItem(int32 item) +{ + return this->items.count(item) == 1; +} + +void AIList::Clear() +{ + this->modifications++; + + this->items.clear(); + this->buckets.clear(); + this->sorter->End(); +} + +void AIList::AddItem(int32 item, int32 value) +{ + this->modifications++; + + if (this->HasItem(item)) return; + + this->items[item] = 0; + this->buckets[0].insert(item); + + this->SetValue(item, value); +} + +void AIList::RemoveItem(int32 item) +{ + this->modifications++; + + if (!this->HasItem(item)) return; + + int32 value = this->GetValue(item); + + this->sorter->Remove(item); + this->buckets[value].erase(item); + if (this->buckets[value].empty()) this->buckets.erase(value); + this->items.erase(item); +} + +int32 AIList::Begin() +{ + this->initialized = true; + return this->sorter->Begin(); +} + +int32 AIList::Next() +{ + if (this->initialized == false) { + DEBUG(ai, 0, "Next() is invalid as Begin() is never called"); + return 0; + } + return this->sorter->Next(); +} + +bool AIList::IsEmpty() +{ + return this->items.empty(); +} + +bool AIList::IsEnd() +{ + if (this->initialized == false) { + DEBUG(ai, 0, "IsEnd() is invalid as Begin() is never called"); + return true; + } + return this->sorter->IsEnd(); +} + +int32 AIList::Count() +{ + return (int32)this->items.size(); +} + +int32 AIList::GetValue(int32 item) +{ + if (!this->HasItem(item)) return 0; + + return this->items[item]; +} + +bool AIList::SetValue(int32 item, int32 value) +{ + this->modifications++; + + if (!this->HasItem(item)) return false; + + int32 value_old = this->GetValue(item); + if (value_old == value) return true; + + this->sorter->Remove(item); + this->buckets[value_old].erase(item); + if (this->buckets[value_old].empty()) this->buckets.erase(value_old); + this->items[item] = value; + this->buckets[value].insert(item); + + return true; +} + +void AIList::Sort(SorterType sorter, bool ascending) +{ + this->modifications++; + + if (sorter != SORT_BY_VALUE && sorter != SORT_BY_ITEM) return; + if (sorter == this->sorter_type && ascending == this->sort_ascending) return; + + delete this->sorter; + switch (sorter) { + case SORT_BY_ITEM: + if (ascending) { + this->sorter = new AIListSorterItemAscending(this); + } else { + this->sorter = new AIListSorterItemDescending(this); + } + break; + + case SORT_BY_VALUE: + if (ascending) { + this->sorter = new AIListSorterValueAscending(this); + } else { + this->sorter = new AIListSorterValueDescending(this); + } + break; + + default: + this->Sort(SORT_BY_ITEM, false); + return; + } + this->sorter_type = sorter; + this->sort_ascending = ascending; + this->initialized = false; +} + +void AIList::AddList(AIList *list) +{ + AIListMap *list_items = &list->items; + for (AIListMap::iterator iter = list_items->begin(); iter != list_items->end(); iter++) { + this->AddItem((*iter).first); + this->SetValue((*iter).first, (*iter).second); + } +} + +void AIList::RemoveAboveValue(int32 value) +{ + this->modifications++; + + for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { + next_iter = iter; next_iter++; + if ((*iter).second > value) this->RemoveItem((*iter).first); + } +} + +void AIList::RemoveBelowValue(int32 value) +{ + this->modifications++; + + for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { + next_iter = iter; next_iter++; + if ((*iter).second < value) this->RemoveItem((*iter).first); + } +} + +void AIList::RemoveBetweenValue(int32 start, int32 end) +{ + this->modifications++; + + for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { + next_iter = iter; next_iter++; + if ((*iter).second > start && (*iter).second < end) this->RemoveItem((*iter).first); + } +} + +void AIList::RemoveValue(int32 value) +{ + this->modifications++; + + for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { + next_iter = iter; next_iter++; + if ((*iter).second == value) this->RemoveItem((*iter).first); + } +} + +void AIList::RemoveTop(int32 count) +{ + this->modifications++; + + if (!this->sort_ascending) { + this->Sort(this->sorter_type, !this->sort_ascending); + this->RemoveBottom(count); + this->Sort(this->sorter_type, !this->sort_ascending); + return; + } + + switch (this->sorter_type) { + default: NOT_REACHED(); + case SORT_BY_VALUE: + for (AIListBucket::iterator iter = this->buckets.begin(); iter != this->buckets.end(); iter = this->buckets.begin()) { + AIItemList *items = &(*iter).second; + size_t size = items->size(); + for (AIItemList::iterator iter = items->begin(); iter != items->end(); iter = items->begin()) { + if (--count < 0) return; + this->RemoveItem(*iter); + /* When the last item is removed from the bucket, the bucket itself is removed. + * This means that the iterators can be invalid after a call to RemoveItem. + */ + if (--size == 0) break; + } + } + break; + + case SORT_BY_ITEM: + for (AIListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter = this->items.begin()) { + if (--count < 0) return; + this->RemoveItem((*iter).first); + } + break; + } +} + +void AIList::RemoveBottom(int32 count) +{ + this->modifications++; + + if (!this->sort_ascending) { + this->Sort(this->sorter_type, !this->sort_ascending); + this->RemoveTop(count); + this->Sort(this->sorter_type, !this->sort_ascending); + return; + } + + switch (this->sorter_type) { + default: NOT_REACHED(); + case SORT_BY_VALUE: + for (AIListBucket::reverse_iterator iter = this->buckets.rbegin(); iter != this->buckets.rend(); iter = this->buckets.rbegin()) { + AIItemList *items = &(*iter).second; + size_t size = items->size(); + for (AIItemList::reverse_iterator iter = items->rbegin(); iter != items->rend(); iter = items->rbegin()) { + if (--count < 0) return; + this->RemoveItem(*iter); + /* When the last item is removed from the bucket, the bucket itself is removed. + * This means that the iterators can be invalid after a call to RemoveItem. + */ + if (--size == 0) break; + } + } + + case SORT_BY_ITEM: + for (AIListMap::reverse_iterator iter = this->items.rbegin(); iter != this->items.rend(); iter = this->items.rbegin()) { + if (--count < 0) return; + this->RemoveItem((*iter).first); + } + break; + } +} + +void AIList::RemoveList(AIList *list) +{ + this->modifications++; + + AIListMap *list_items = &list->items; + for (AIListMap::iterator iter = list_items->begin(); iter != list_items->end(); iter++) { + this->RemoveItem((*iter).first); + } +} + +void AIList::KeepAboveValue(int32 value) +{ + this->modifications++; + + for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { + next_iter = iter; next_iter++; + if ((*iter).second <= value) this->RemoveItem((*iter).first); + } +} + +void AIList::KeepBelowValue(int32 value) +{ + this->modifications++; + + for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { + next_iter = iter; next_iter++; + if ((*iter).second >= value) this->RemoveItem((*iter).first); + } +} + +void AIList::KeepBetweenValue(int32 start, int32 end) +{ + this->modifications++; + + for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { + next_iter = iter; next_iter++; + if ((*iter).second <= start || (*iter).second >= end) this->RemoveItem((*iter).first); + } +} + +void AIList::KeepValue(int32 value) +{ + this->modifications++; + + for (AIListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { + next_iter = iter; next_iter++; + if ((*iter).second != value) this->RemoveItem((*iter).first); + } +} + +void AIList::KeepTop(int32 count) +{ + this->modifications++; + + this->RemoveBottom(this->Count() - count); +} + +void AIList::KeepBottom(int32 count) +{ + this->modifications++; + + this->RemoveTop(this->Count() - count); +} + +void AIList::KeepList(AIList *list) +{ + this->modifications++; + + AIList tmp; + for (AIListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { + tmp.AddItem((*iter).first); + tmp.SetValue((*iter).first, (*iter).second); + } + + tmp.RemoveList(list); + this->RemoveList(&tmp); +} + +SQInteger AIList::_get(HSQUIRRELVM vm) +{ + if (sq_gettype(vm, 2) != OT_INTEGER) return SQ_ERROR; + + SQInteger idx; + sq_getinteger(vm, 2, &idx); + + if (!this->HasItem(idx)) return SQ_ERROR; + + sq_pushinteger(vm, this->GetValue(idx)); + return 1; +} + +SQInteger AIList::_set(HSQUIRRELVM vm) +{ + if (sq_gettype(vm, 2) != OT_INTEGER) return SQ_ERROR; + if (sq_gettype(vm, 3) != OT_INTEGER || sq_gettype(vm, 3) == OT_NULL) { + return sq_throwerror(vm, _SC("you can only assign integers to this list")); + } + + SQInteger idx, val; + sq_getinteger(vm, 2, &idx); + if (sq_gettype(vm, 3) == OT_NULL) { + this->RemoveItem(idx); + return 0; + } + + sq_getinteger(vm, 3, &val); + if (!this->HasItem(idx)) { + this->AddItem(idx, val); + return 0; + } + + this->SetValue(idx, val); + return 0; +} + +SQInteger AIList::_nexti(HSQUIRRELVM vm) +{ + if (sq_gettype(vm, 2) == OT_NULL) { + if (this->IsEmpty()) { + sq_pushnull(vm); + return 1; + } + sq_pushinteger(vm, this->Begin()); + return 1; + } + + SQInteger idx; + sq_getinteger(vm, 2, &idx); + + int val = this->Next(); + if (this->IsEnd()) { + sq_pushnull(vm); + return 1; + } + + sq_pushinteger(vm, val); + return 1; +} + +SQInteger AIList::Valuate(HSQUIRRELVM vm) +{ + this->modifications++; + + /* The first parameter is the instance of AIList. */ + int nparam = sq_gettop(vm) - 1; + + if (nparam < 1) { + return sq_throwerror(vm, _SC("You need to give a least a Valuator as parameter to AIList::Valuate")); + } + + /* Make sure the valuator function is really a function, and not any + * other type. It's parameter 2 for us, but for the user it's the + * first parameter they give. */ + SQObjectType valuator_type = sq_gettype(vm, 2); + if (valuator_type != OT_CLOSURE && valuator_type != OT_NATIVECLOSURE) { + return sq_throwerror(vm, _SC("parameter 1 has an invalid type (expected function)")); + } + + /* Don't allow docommand from a Valuator, as we can't resume in + * mid C++-code. */ + bool backup_allow = AIObject::GetAllowDoCommand(); + AIObject::SetAllowDoCommand(false); + + /* Push the function to call */ + sq_push(vm, 2); + + for (AIListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { + /* Check for changing of items. */ + int previous_modification_count = this->modifications; + + /* Push the root table as instance object, this is what squirrel does for meta-functions. */ + sq_pushroottable(vm); + /* Push all arguments for the valuator function. */ + sq_pushinteger(vm, (*iter).first); + for (int i = 0; i < nparam - 1; i++) { + sq_push(vm, i + 3); + } + + /* Call the function. Squirrel pops all parameters and pushes the return value. */ + if (SQ_FAILED(sq_call(vm, nparam + 1, SQTrue, SQTrue))) { + AIObject::SetAllowDoCommand(backup_allow); + return SQ_ERROR; + } + + /* Retreive the return value */ + SQInteger value; + switch (sq_gettype(vm, -1)) { + case OT_INTEGER: { + sq_getinteger(vm, -1, &value); + break; + } + + case OT_BOOL: { + SQBool v; + sq_getbool(vm, -1, &v); + value = v ? 1 : 0; + break; + } + + default: { + /* See below for explanation. The extra pop is the return value. */ + sq_pop(vm, nparam + 4); + + AIObject::SetAllowDoCommand(backup_allow); + return sq_throwerror(vm, _SC("return value of valuator is not valid (not integer/bool)")); + } + } + + /* Was something changed? */ + if (previous_modification_count != this->modifications) { + /* See below for explanation. The extra pop is the return value. */ + sq_pop(vm, nparam + 4); + + AIObject::SetAllowDoCommand(backup_allow); + return sq_throwerror(vm, _SC("modifying valuated list outside of valuator function")); + } + + this->SetValue((*iter).first, value); + + /* Pop the return value. */ + sq_poptop(vm); + + Squirrel::DecreaseOps(vm, 5); + } + /* Pop from the squirrel stack: + * 1. The root stable (as instance object). + * 2. The valuator function. + * 3. The parameters given to this function. + * 4. The AIList instance object. */ + sq_pop(vm, nparam + 3); + + AIObject::SetAllowDoCommand(backup_allow); + return 0; +}
new file mode 100644 --- /dev/null +++ b/src/ai/api/ai_list.hpp @@ -0,0 +1,286 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * 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. + * 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. + * 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/>. + */ + +/** @file ai_list.hpp A list which can keep item/value pairs, which you can walk. */ +/** @defgroup AIList Classes that create a list of items. */ + +#ifndef AI_LIST_HPP +#define AI_LIST_HPP + +#include "ai_object.hpp" +#include <map> +#include <set> + +class AIListSorter; + +/** + * Class that creates a list which can keep item/value pairs, which you can walk. + */ +class AIList : public AIObject { +public: + /** Get the name of this class to identify it towards squirrel. */ + static const char *GetClassName() { return "AIList"; } + + /** Type of sorter */ + enum SorterType { + SORT_BY_VALUE, ///< Sort the list based on the value of the item. + SORT_BY_ITEM, ///< Sort the list based on the item itself. + }; + + /** Sort ascending */ + static const bool SORT_ASCENDING = true; + /** Sort descnding */ + static const bool SORT_DESCENDING = false; + +private: + AIListSorter *sorter; ///< Sorting algorithm + SorterType sorter_type; ///< Sorting type + bool sort_ascending; ///< Whether to sort ascending or descending + bool initialized; ///< Whether an iteration has been started + int modifications; ///< Number of modification that has been done. To prevent changing data while valuating. + +public: + typedef std::set<int32> AIItemList; ///< The list of items inside the bucket + typedef std::map<int32, AIItemList> AIListBucket; ///< The bucket list per value + typedef std::map<int32, int32> AIListMap; ///< List per item + + AIListMap items; ///< The items in the list + AIListBucket buckets; ///< The items in the list, sorted by value + + AIList(); + ~AIList(); + + /** + * Add a single item to the list. + * @param item the item to add. Should be unique, otherwise it is ignored. + * @param value the value to assign. + * @note the value is set to 0 by default. + */ + void AddItem(int32 item, int32 value = 0); + + /** + * Remove a single item from the list. + * @param item the item to remove. If not existing, it is ignored. + */ + void RemoveItem(int32 item); + + /** + * Clear the list, making Count() returning 0 and IsEmpty() returning true. + */ + void Clear(); + + /** + * Check if an item is in the list. + * @param item the item to check for. + * @return true if the item is in the list. + */ + bool HasItem(int32 item); + + /** + * Go to the beginning of the list. + * @return the item value of the first item. + * @note returns 0 if beyond end-of-list. Use IsEnd() to check for end-of-list. + */ + int32 Begin(); + + /** + * Go to the next item in the list. + * @return the item value of the next item. + * @note returns 0 if beyond end-of-list. Use IsEnd() to check for end-of-list. + */ + int32 Next(); + + /** + * Check if a list is empty. + * @return true if the list is empty. + */ + bool IsEmpty(); + + /** + * Check if there is a element left. In other words, if this is false, + * the last call to Begin() or Next() returned a valid item. + * @return true if the current item is beyond end-of-list. + */ + bool IsEnd(); + + /** + * Returns the amount of items in the list. + * @return amount of items in the list. + */ + int32 Count(); + + /** + * Get the value that belongs to this item. + * @param item the item to get the value from + * @return the value that belongs to this item. + */ + int32 GetValue(int32 item); + + /** + * Set a value of an item directly. + * @param item the item to set the value for. + * @param value the value to give to the item + * @return true if we could set the item to value, false otherwise. + * @note Changing values of items while looping through a list might cause + * entries to be skipped. Be very careful with such operations. + */ + bool SetValue(int32 item, int32 value); + + /** + * Sort this list by the given sorter and direction. + * @param sorter the type of sorter to use + * @param ascending if true, lowest value is on top, else at bottom. + * @note the current item stays at the same place. + * @see SORT_ASCENDING SORT_DESCENDING + */ + void Sort(SorterType sorter, bool ascending); + + /** + * Add one list to another one. + * @param list The list that will be added to the caller. + * @post The list to be added ('list') stays unmodified. + * @note All added items keep their value as it was in 'list'. + * @note If the item already exists inside the caller, the value of the + * list that is added is set on the item. + */ + void AddList(AIList *list); + + /** + * Removes all items with a higher value than 'value'. + * @param value the value above which all items are removed. + */ + void RemoveAboveValue(int32 value); + + /** + * Removes all items with a lower value than 'value'. + * @param value the value below which all items are removed. + */ + void RemoveBelowValue(int32 value); + + /** + * Removes all items with a value above start and below end. + * @param start the lower bound of the to be removed values (exclusive). + * @param end the upper bound of the to be removed valuens (exclusive). + */ + void RemoveBetweenValue(int32 start, int32 end); + + /** + * Remove all items with this value. + * @param value the value to remove. + */ + void RemoveValue(int32 value); + + /** + * Remove the first count items. + * @param count the amount of items to remove. + */ + void RemoveTop(int32 count); + + /** + * Remove the last count items. + * @param count the amount of items to remove. + */ + void RemoveBottom(int32 count); + + /** + * Remove everything that is in the given list from this list (same item index that is). + * @param list the list of items to remove. + * @pre list != NULL + */ + void RemoveList(AIList *list); + + /** + * Keep all items with a higher value than 'value'. + * @param value the value above which all items are kept. + */ + void KeepAboveValue(int32 value); + + /** + * Keep all items with a lower value than 'value'. + * @param value the value below which all items are kept. + */ + void KeepBelowValue(int32 value); + + /** + * Keep all items with a value above start and below end. + * @param start the lower bound of the to be kept values (exclusive). + * @param end the upper bound of the to be kept values (exclusive). + */ + void KeepBetweenValue(int32 start, int32 end); + + /** + * Keep all items with this value. + * @param value the value to keep. + */ + void KeepValue(int32 value); + + /** + * Keep the first count items, i.e. remove everything except the first count items. + * @param count the amount of items to keep. + */ + void KeepTop(int32 count); + + /** + * Keep the last count items, i.e. remove everything except the last count items. + * @param count the amount of items to keep. + */ + void KeepBottom(int32 count); + + /** + * Keeps everything that is in the given list from this list (same item index that is). + * @param list the list of items to keep. + * @pre list != NULL + */ + void KeepList(AIList *list); + +#ifndef DOXYGEN_SKIP + /** + * Used for 'foreach()' and [] get from Squirrel. + */ + SQInteger _get(HSQUIRRELVM vm); + + /** + * Used for [] set from Squirrel. + */ + SQInteger _set(HSQUIRRELVM vm); + + /** + * Used for 'foreach()' from Squirrel. + */ + SQInteger _nexti(HSQUIRRELVM vm); + + /** + * The Valuate() wrapper from Squirrel. + */ + SQInteger Valuate(HSQUIRRELVM vm); +#else + /** + * Give all items a value defined by the valuator you give. + * @param valuator_function The function which will be doing the valuation. + * @param params The params to give to the valuators (minus the first param, + * which is always the index-value we are valuating). + * @note You may not add, remove or change (setting the value of) items while + * valuating. You may also not (re)sort while valuating. + * @note You can write your own valuators and use them. Just remember that + * the first parameter should be the index-value, and it should return + * an integer. + * @note Example: + * list.Valuate(AIBridge.GetPrice, 5); + * list.Valuate(AIBridge.GetMaxLength); + * function MyVal(bridge_id, myparam) + * { + * return myparam * bridge_id; // This is silly + * } + * list.Valuate(MyVal, 12); + */ + void Valuate(void *valuator_function, int params, ...); +#endif /* DOXYGEN_SKIP */ +}; + +#endif /* AI_LIST_HPP */
new file mode 100644 --- /dev/null +++ b/src/ai/api/ai_list.hpp.sq @@ -0,0 +1,72 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * 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. + * 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. + * 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/>. + */ + +/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */ + +#include "ai_list.hpp" + +namespace SQConvert { + /* Allow enums to be used as Squirrel parameters */ + template <> AIList::SorterType GetParam(ForceType<AIList::SorterType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIList::SorterType)tmp; } + template <> int Return<AIList::SorterType>(HSQUIRRELVM vm, AIList::SorterType res) { sq_pushinteger(vm, (int32)res); return 1; } + + /* Allow AIList to be used as Squirrel parameter */ + template <> AIList *GetParam(ForceType<AIList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIList *)instance; } + template <> AIList &GetParam(ForceType<AIList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIList *)instance; } + template <> const AIList *GetParam(ForceType<const AIList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIList *)instance; } + template <> const AIList &GetParam(ForceType<const AIList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIList *)instance; } + template <> int Return<AIList *>(HSQUIRRELVM vm, AIList *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIList", res, NULL, DefSQDestructorCallback<AIList>); return 1; } +} // namespace SQConvert + +void SQAIList_Register(Squirrel *engine) +{ + DefSQClass <AIList> SQAIList("AIList"); + SQAIList.PreRegister(engine); + SQAIList.AddConstructor<void (AIList::*)(), 1>(engine, "x"); + + SQAIList.DefSQConst(engine, AIList::SORT_BY_VALUE, "SORT_BY_VALUE"); + SQAIList.DefSQConst(engine, AIList::SORT_BY_ITEM, "SORT_BY_ITEM"); + + SQAIList.DefSQConst(engine, AIList::SORT_ASCENDING, "SORT_ASCENDING"); + SQAIList.DefSQConst(engine, AIList::SORT_DESCENDING, "SORT_DESCENDING"); + + SQAIList.DefSQMethod(engine, &AIList::AddItem, "AddItem", 3, "xii"); + SQAIList.DefSQMethod(engine, &AIList::RemoveItem, "RemoveItem", 2, "xi"); + SQAIList.DefSQMethod(engine, &AIList::Clear, "Clear", 1, "x"); + SQAIList.DefSQMethod(engine, &AIList::HasItem, "HasItem", 2, "xi"); + SQAIList.DefSQMethod(engine, &AIList::Begin, "Begin", 1, "x"); + SQAIList.DefSQMethod(engine, &AIList::Next, "Next", 1, "x"); + SQAIList.DefSQMethod(engine, &AIList::IsEmpty, "IsEmpty", 1, "x"); + SQAIList.DefSQMethod(engine, &AIList::IsEnd, "IsEnd", 1, "x"); + SQAIList.DefSQMethod(engine, &AIList::Count, "Count", 1, "x"); + SQAIList.DefSQMethod(engine, &AIList::GetValue, "GetValue", 2, "xi"); + SQAIList.DefSQMethod(engine, &AIList::SetValue, "SetValue", 3, "xii"); + SQAIList.DefSQMethod(engine, &AIList::Sort, "Sort", 3, "xib"); + SQAIList.DefSQMethod(engine, &AIList::AddList, "AddList", 2, "xx"); + SQAIList.DefSQMethod(engine, &AIList::RemoveAboveValue, "RemoveAboveValue", 2, "xi"); + SQAIList.DefSQMethod(engine, &AIList::RemoveBelowValue, "RemoveBelowValue", 2, "xi"); + SQAIList.DefSQMethod(engine, &AIList::RemoveBetweenValue, "RemoveBetweenValue", 3, "xii"); + SQAIList.DefSQMethod(engine, &AIList::RemoveValue, "RemoveValue", 2, "xi"); + SQAIList.DefSQMethod(engine, &AIList::RemoveTop, "RemoveTop", 2, "xi"); + SQAIList.DefSQMethod(engine, &AIList::RemoveBottom, "RemoveBottom", 2, "xi"); + SQAIList.DefSQMethod(engine, &AIList::RemoveList, "RemoveList", 2, "xx"); + SQAIList.DefSQMethod(engine, &AIList::KeepAboveValue, "KeepAboveValue", 2, "xi"); + SQAIList.DefSQMethod(engine, &AIList::KeepBelowValue, "KeepBelowValue", 2, "xi"); + SQAIList.DefSQMethod(engine, &AIList::KeepBetweenValue, "KeepBetweenValue", 3, "xii"); + SQAIList.DefSQMethod(engine, &AIList::KeepValue, "KeepValue", 2, "xi"); + SQAIList.DefSQMethod(engine, &AIList::KeepTop, "KeepTop", 2, "xi"); + SQAIList.DefSQMethod(engine, &AIList::KeepBottom, "KeepBottom", 2, "xi"); + SQAIList.DefSQMethod(engine, &AIList::KeepList, "KeepList", 2, "xx"); + SQAIList.DefSQAdvancedMethod(engine, &AIList::_get, "_get"); + SQAIList.DefSQAdvancedMethod(engine, &AIList::_set, "_set"); + SQAIList.DefSQAdvancedMethod(engine, &AIList::_nexti, "_nexti"); + SQAIList.DefSQAdvancedMethod(engine, &AIList::Valuate, "Valuate"); + + SQAIList.PostRegister(engine); +}
--- a/src/ai/api/ai_railtypelist.hpp +++ b/src/ai/api/ai_railtypelist.hpp @@ -12,13 +12,13 @@ #ifndef AI_RAILTYPELIST_HPP #define AI_RAILTYPELIST_HPP -#include "ai_abstractlist.hpp" +#include "ai_list.hpp" /** * Creates a list of all available railtypes. * @ingroup AIList */ -class AIRailTypeList : public AIAbstractList { +class AIRailTypeList : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIRailTypeList"; }
--- a/src/ai/api/ai_railtypelist.hpp.sq +++ b/src/ai/api/ai_railtypelist.hpp.sq @@ -23,7 +23,7 @@ void SQAIRailTypeList_Register(Squirrel *engine) { DefSQClass <AIRailTypeList> SQAIRailTypeList("AIRailTypeList"); - SQAIRailTypeList.PreRegister(engine, "AIAbstractList"); + SQAIRailTypeList.PreRegister(engine, "AIList"); SQAIRailTypeList.AddConstructor<void (AIRailTypeList::*)(), 1>(engine, "x"); SQAIRailTypeList.PostRegister(engine);
--- a/src/ai/api/ai_signlist.hpp +++ b/src/ai/api/ai_signlist.hpp @@ -12,13 +12,13 @@ #ifndef AI_SIGNLIST_HPP #define AI_SIGNLIST_HPP -#include "ai_abstractlist.hpp" +#include "ai_list.hpp" /** * Create a list of signs your company has created. * @ingroup AIList */ -class AISignList : public AIAbstractList { +class AISignList : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AISignList"; }
--- a/src/ai/api/ai_signlist.hpp.sq +++ b/src/ai/api/ai_signlist.hpp.sq @@ -23,7 +23,7 @@ void SQAISignList_Register(Squirrel *engine) { DefSQClass <AISignList> SQAISignList("AISignList"); - SQAISignList.PreRegister(engine, "AIAbstractList"); + SQAISignList.PreRegister(engine, "AIList"); SQAISignList.AddConstructor<void (AISignList::*)(), 1>(engine, "x"); SQAISignList.PostRegister(engine);
--- a/src/ai/api/ai_stationlist.hpp +++ b/src/ai/api/ai_stationlist.hpp @@ -12,14 +12,14 @@ #ifndef AI_STATIONLIST_HPP #define AI_STATIONLIST_HPP -#include "ai_abstractlist.hpp" +#include "ai_list.hpp" #include "ai_station.hpp" /** * Creates a list of stations of which you are the owner. * @ingroup AIList */ -class AIStationList : public AIAbstractList { +class AIStationList : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIStationList"; } @@ -34,7 +34,7 @@ * Creates a list of stations which the vehicle has in its orders. * @ingroup AIList */ -class AIStationList_Vehicle : public AIAbstractList { +class AIStationList_Vehicle : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIStationList_Vehicle"; }
--- a/src/ai/api/ai_stationlist.hpp.sq +++ b/src/ai/api/ai_stationlist.hpp.sq @@ -23,7 +23,7 @@ void SQAIStationList_Register(Squirrel *engine) { DefSQClass <AIStationList> SQAIStationList("AIStationList"); - SQAIStationList.PreRegister(engine, "AIAbstractList"); + SQAIStationList.PreRegister(engine, "AIList"); SQAIStationList.AddConstructor<void (AIStationList::*)(AIStation::StationType station_type), 2>(engine, "xi"); SQAIStationList.PostRegister(engine); @@ -41,7 +41,7 @@ void SQAIStationList_Vehicle_Register(Squirrel *engine) { DefSQClass <AIStationList_Vehicle> SQAIStationList_Vehicle("AIStationList_Vehicle"); - SQAIStationList_Vehicle.PreRegister(engine, "AIAbstractList"); + SQAIStationList_Vehicle.PreRegister(engine, "AIList"); SQAIStationList_Vehicle.AddConstructor<void (AIStationList_Vehicle::*)(VehicleID vehicle_id), 2>(engine, "xi"); SQAIStationList_Vehicle.PostRegister(engine);
--- a/src/ai/api/ai_subsidylist.hpp +++ b/src/ai/api/ai_subsidylist.hpp @@ -12,13 +12,13 @@ #ifndef AI_SUBSIDYLIST_HPP #define AI_SUBSIDYLIST_HPP -#include "ai_abstractlist.hpp" +#include "ai_list.hpp" /** * Creates a list of all current subsidies. * @ingroup AIList */ -class AISubsidyList : public AIAbstractList { +class AISubsidyList : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AISubsidyList"; }
--- a/src/ai/api/ai_subsidylist.hpp.sq +++ b/src/ai/api/ai_subsidylist.hpp.sq @@ -23,7 +23,7 @@ void SQAISubsidyList_Register(Squirrel *engine) { DefSQClass <AISubsidyList> SQAISubsidyList("AISubsidyList"); - SQAISubsidyList.PreRegister(engine, "AIAbstractList"); + SQAISubsidyList.PreRegister(engine, "AIList"); SQAISubsidyList.AddConstructor<void (AISubsidyList::*)(), 1>(engine, "x"); SQAISubsidyList.PostRegister(engine);
--- a/src/ai/api/ai_tile.hpp +++ b/src/ai/api/ai_tile.hpp @@ -12,7 +12,7 @@ #ifndef AI_TILE_HPP #define AI_TILE_HPP -#include "ai_abstractlist.hpp" +#include "ai_list.hpp" #include "ai_error.hpp" #include "ai_company.hpp"
--- a/src/ai/api/ai_tilelist.hpp +++ b/src/ai/api/ai_tilelist.hpp @@ -12,14 +12,14 @@ #ifndef AI_TILELIST_HPP #define AI_TILELIST_HPP -#include "ai_abstractlist.hpp" +#include "ai_list.hpp" #include "ai_station.hpp" /** * Creates an empty list, in which you can add tiles. * @ingroup AIList */ -class AITileList : public AIAbstractList { +class AITileList : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AITileList"; }
--- a/src/ai/api/ai_tilelist.hpp.sq +++ b/src/ai/api/ai_tilelist.hpp.sq @@ -23,7 +23,7 @@ void SQAITileList_Register(Squirrel *engine) { DefSQClass <AITileList> SQAITileList("AITileList"); - SQAITileList.PreRegister(engine, "AIAbstractList"); + SQAITileList.PreRegister(engine, "AIList"); SQAITileList.AddConstructor<void (AITileList::*)(), 1>(engine, "x"); SQAITileList.DefSQMethod(engine, &AITileList::AddRectangle, "AddRectangle", 3, "xii");
--- a/src/ai/api/ai_townlist.hpp +++ b/src/ai/api/ai_townlist.hpp @@ -12,13 +12,13 @@ #ifndef AI_TOWNLIST_HPP #define AI_TOWNLIST_HPP -#include "ai_abstractlist.hpp" +#include "ai_list.hpp" /** * Creates a list of towns that are currently on the map. * @ingroup AIList */ -class AITownList : public AIAbstractList { +class AITownList : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AITownList"; }
--- a/src/ai/api/ai_townlist.hpp.sq +++ b/src/ai/api/ai_townlist.hpp.sq @@ -23,7 +23,7 @@ void SQAITownList_Register(Squirrel *engine) { DefSQClass <AITownList> SQAITownList("AITownList"); - SQAITownList.PreRegister(engine, "AIAbstractList"); + SQAITownList.PreRegister(engine, "AIList"); SQAITownList.AddConstructor<void (AITownList::*)(), 1>(engine, "x"); SQAITownList.PostRegister(engine);
--- a/src/ai/api/ai_vehiclelist.hpp +++ b/src/ai/api/ai_vehiclelist.hpp @@ -12,14 +12,14 @@ #ifndef AI_VEHICLELIST_HPP #define AI_VEHICLELIST_HPP -#include "ai_abstractlist.hpp" +#include "ai_list.hpp" #include "ai_vehicle.hpp" /** * Creates a list of vehicles of which you are the owner. * @ingroup AIList */ -class AIVehicleList : public AIAbstractList { +class AIVehicleList : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIVehicleList"; } @@ -30,7 +30,7 @@ * Creates a list of vehicles that have orders to a given station. * @ingroup AIList */ -class AIVehicleList_Station : public AIAbstractList { +class AIVehicleList_Station : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIVehicleList_Station"; } @@ -50,7 +50,7 @@ * an empty list will be returned. * @ingroup AIList */ -class AIVehicleList_Depot : public AIAbstractList { +class AIVehicleList_Depot : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIVehicleList_Depot"; } @@ -65,7 +65,7 @@ * Creates a list of vehicles that share orders. * @ingroup AIList */ -class AIVehicleList_SharedOrders : public AIAbstractList { +class AIVehicleList_SharedOrders : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIVehicleList_SharedOrders"; } @@ -80,7 +80,7 @@ * Creates a list of vehicles that are in a group. * @ingroup AIList */ -class AIVehicleList_Group : public AIAbstractList { +class AIVehicleList_Group : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIVehicleList_Group"; } @@ -95,7 +95,7 @@ * Creates a list of vehicles that are in the default group. * @ingroup AIList */ -class AIVehicleList_DefaultGroup : public AIAbstractList { +class AIVehicleList_DefaultGroup : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIVehicleList_DefaultGroup"; }
--- a/src/ai/api/ai_vehiclelist.hpp.sq +++ b/src/ai/api/ai_vehiclelist.hpp.sq @@ -23,7 +23,7 @@ void SQAIVehicleList_Register(Squirrel *engine) { DefSQClass <AIVehicleList> SQAIVehicleList("AIVehicleList"); - SQAIVehicleList.PreRegister(engine, "AIAbstractList"); + SQAIVehicleList.PreRegister(engine, "AIList"); SQAIVehicleList.AddConstructor<void (AIVehicleList::*)(), 1>(engine, "x"); SQAIVehicleList.PostRegister(engine); @@ -41,7 +41,7 @@ void SQAIVehicleList_Station_Register(Squirrel *engine) { DefSQClass <AIVehicleList_Station> SQAIVehicleList_Station("AIVehicleList_Station"); - SQAIVehicleList_Station.PreRegister(engine, "AIAbstractList"); + SQAIVehicleList_Station.PreRegister(engine, "AIList"); SQAIVehicleList_Station.AddConstructor<void (AIVehicleList_Station::*)(StationID station_id), 2>(engine, "xi"); SQAIVehicleList_Station.PostRegister(engine); @@ -59,7 +59,7 @@ void SQAIVehicleList_Depot_Register(Squirrel *engine) { DefSQClass <AIVehicleList_Depot> SQAIVehicleList_Depot("AIVehicleList_Depot"); - SQAIVehicleList_Depot.PreRegister(engine, "AIAbstractList"); + SQAIVehicleList_Depot.PreRegister(engine, "AIList"); SQAIVehicleList_Depot.AddConstructor<void (AIVehicleList_Depot::*)(TileIndex tile), 2>(engine, "xi"); SQAIVehicleList_Depot.PostRegister(engine); @@ -77,7 +77,7 @@ void SQAIVehicleList_SharedOrders_Register(Squirrel *engine) { DefSQClass <AIVehicleList_SharedOrders> SQAIVehicleList_SharedOrders("AIVehicleList_SharedOrders"); - SQAIVehicleList_SharedOrders.PreRegister(engine, "AIAbstractList"); + SQAIVehicleList_SharedOrders.PreRegister(engine, "AIList"); SQAIVehicleList_SharedOrders.AddConstructor<void (AIVehicleList_SharedOrders::*)(VehicleID vehicle_id), 2>(engine, "xi"); SQAIVehicleList_SharedOrders.PostRegister(engine); @@ -95,7 +95,7 @@ void SQAIVehicleList_Group_Register(Squirrel *engine) { DefSQClass <AIVehicleList_Group> SQAIVehicleList_Group("AIVehicleList_Group"); - SQAIVehicleList_Group.PreRegister(engine, "AIAbstractList"); + SQAIVehicleList_Group.PreRegister(engine, "AIList"); SQAIVehicleList_Group.AddConstructor<void (AIVehicleList_Group::*)(GroupID group_id), 2>(engine, "xi"); SQAIVehicleList_Group.PostRegister(engine); @@ -113,7 +113,7 @@ void SQAIVehicleList_DefaultGroup_Register(Squirrel *engine) { DefSQClass <AIVehicleList_DefaultGroup> SQAIVehicleList_DefaultGroup("AIVehicleList_DefaultGroup"); - SQAIVehicleList_DefaultGroup.PreRegister(engine, "AIAbstractList"); + SQAIVehicleList_DefaultGroup.PreRegister(engine, "AIList"); SQAIVehicleList_DefaultGroup.AddConstructor<void (AIVehicleList_DefaultGroup::*)(AIVehicle::VehicleType vehicle_type), 2>(engine, "xi"); SQAIVehicleList_DefaultGroup.PostRegister(engine);
--- a/src/ai/api/ai_waypointlist.hpp +++ b/src/ai/api/ai_waypointlist.hpp @@ -12,14 +12,14 @@ #ifndef AI_WAYPOINTLIST_HPP #define AI_WAYPOINTLIST_HPP -#include "ai_abstractlist.hpp" +#include "ai_list.hpp" #include "ai_waypoint.hpp" /** * Creates a list of waypoints of which you are the owner. * @ingroup AIList */ -class AIWaypointList : public AIAbstractList { +class AIWaypointList : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIWaypointList"; } @@ -34,7 +34,7 @@ * Creates a list of waypoints which the vehicle has in its orders. * @ingroup AIList */ -class AIWaypointList_Vehicle : public AIAbstractList { +class AIWaypointList_Vehicle : public AIList { public: /** Get the name of this class to identify it towards squirrel. */ static const char *GetClassName() { return "AIWaypointList_Vehicle"; }
--- a/src/ai/api/ai_waypointlist.hpp.sq +++ b/src/ai/api/ai_waypointlist.hpp.sq @@ -23,7 +23,7 @@ void SQAIWaypointList_Register(Squirrel *engine) { DefSQClass <AIWaypointList> SQAIWaypointList("AIWaypointList"); - SQAIWaypointList.PreRegister(engine, "AIAbstractList"); + SQAIWaypointList.PreRegister(engine, "AIList"); SQAIWaypointList.AddConstructor<void (AIWaypointList::*)(AIWaypoint::WaypointType waypoint_type), 2>(engine, "xi"); SQAIWaypointList.PostRegister(engine); @@ -41,7 +41,7 @@ void SQAIWaypointList_Vehicle_Register(Squirrel *engine) { DefSQClass <AIWaypointList_Vehicle> SQAIWaypointList_Vehicle("AIWaypointList_Vehicle"); - SQAIWaypointList_Vehicle.PreRegister(engine, "AIAbstractList"); + SQAIWaypointList_Vehicle.PreRegister(engine, "AIList"); SQAIWaypointList_Vehicle.AddConstructor<void (AIWaypointList_Vehicle::*)(VehicleID vehicle_id), 2>(engine, "xi"); SQAIWaypointList_Vehicle.PostRegister(engine);
--- a/src/ai/api/squirrel_export.sh +++ b/src/ai/api/squirrel_export.sh @@ -89,7 +89,9 @@ print \$0 gsub(\"^.*/\", \"\") print \" squirrel_register_std(this->engine);\" \$0 - split(\"`grep '^void SQAI.*_Register(Squirrel \*engine)$' *.hpp.sq | sed 's/^.*void //;s/Squirrel \*/this->/;s/$/;/;s/_Register/0000Register/g;' | sort | sed 's/0000Register/_Register/g' | tr -d '\r' | tr '\n' ' '`\", regs, \" \") + # AIList needs to be registered with squirrel before all AIList subclasses. + print \" SQAIList_Register(this->engine);\" \$0 + split(\"`grep '^void SQAI.*_Register(Squirrel \*engine)$' *.hpp.sq | grep -v 'SQAIList_Register' | sed 's/^.*void //;s/Squirrel \*/this->/;s/$/;/;s/_Register/0000Register/g;' | sort | sed 's/0000Register/_Register/g' | tr -d '\r' | tr '\n' ' '`\", regs, \" \") for (i = 1; regs[i] != \"\"; i++) { if (regs[i] == \"SQAIController_Register(this->engine);\") continue