author | truelight |
Thu, 12 Apr 2007 11:37:24 +0000 | |
branch | noai |
changeset 9579 | 632263c0cf5a |
parent 9578 | 2e05c1b002f0 |
child 9580 | 53bf5a5dda46 |
--- a/bin/ai/regression/regression.nut Wed Apr 11 20:53:58 2007 +0000 +++ b/bin/ai/regression/regression.nut Thu Apr 12 11:37:24 2007 +0000 @@ -131,6 +131,33 @@ print(" GetIndustryCount(): " + industry.GetIndustryCount()); } +function Regression::List() +{ + local list = AIList(); + + print(""); + print("--List--"); + + print(" IsEmpty(): " + list.IsEmpty()); + list.AddItem(1); + list.AddItem(2); + for (local i = 1000; i < 1100; i++) { + list.AddItem(i); + } + list.RemoveItem(1050); + list.RemoveItem(1150); + print(" Count(): " + list.Count()); + print(" HasItem(1050): " + list.HasItem(1050)); + print(" HasItem(1051): " + list.HasItem(1051)); + print(" IsEmpty(): " + list.IsEmpty()); + print(" List Dump:"); + for (local i = list.Begin(); list.HasNext(); i = list.Next()) { + print(" " + i + " => " + list.GetValue(i)); + } + list.Clear(); + print(" IsEmpty(): " + list.IsEmpty()); +} + function Regression::Map() { local map = AIMap(); @@ -370,6 +397,7 @@ this.Company(); this.Industry(); this.Map(); + this.List(); this.Road(); this.Sign(); this.Town();
--- a/bin/ai/regression/regression.txt Wed Apr 11 20:53:58 2007 +0000 +++ b/bin/ai/regression/regression.txt Thu Apr 12 11:37:24 2007 +0000 @@ -506,6 +506,116 @@ DistanceSquare(): 1746 DistanceFromEdge(): 16 +--List-- + IsEmpty(): true + Count(): 101 + HasItem(1050): false + HasItem(1051): true + IsEmpty(): false + List Dump: + 1 => 0 + 2 => 0 + 1000 => 0 + 1001 => 0 + 1002 => 0 + 1003 => 0 + 1004 => 0 + 1005 => 0 + 1006 => 0 + 1007 => 0 + 1008 => 0 + 1009 => 0 + 1010 => 0 + 1011 => 0 + 1012 => 0 + 1013 => 0 + 1014 => 0 + 1015 => 0 + 1016 => 0 + 1017 => 0 + 1018 => 0 + 1019 => 0 + 1020 => 0 + 1021 => 0 + 1022 => 0 + 1023 => 0 + 1024 => 0 + 1025 => 0 + 1026 => 0 + 1027 => 0 + 1028 => 0 + 1029 => 0 + 1030 => 0 + 1031 => 0 + 1032 => 0 + 1033 => 0 + 1034 => 0 + 1035 => 0 + 1036 => 0 + 1037 => 0 + 1038 => 0 + 1039 => 0 + 1040 => 0 + 1041 => 0 + 1042 => 0 + 1043 => 0 + 1044 => 0 + 1045 => 0 + 1046 => 0 + 1047 => 0 + 1048 => 0 + 1049 => 0 + 1051 => 0 + 1052 => 0 + 1053 => 0 + 1054 => 0 + 1055 => 0 + 1056 => 0 + 1057 => 0 + 1058 => 0 + 1059 => 0 + 1060 => 0 + 1061 => 0 + 1062 => 0 + 1063 => 0 + 1064 => 0 + 1065 => 0 + 1066 => 0 + 1067 => 0 + 1068 => 0 + 1069 => 0 + 1070 => 0 + 1071 => 0 + 1072 => 0 + 1073 => 0 + 1074 => 0 + 1075 => 0 + 1076 => 0 + 1077 => 0 + 1078 => 0 + 1079 => 0 + 1080 => 0 + 1081 => 0 + 1082 => 0 + 1083 => 0 + 1084 => 0 + 1085 => 0 + 1086 => 0 + 1087 => 0 + 1088 => 0 + 1089 => 0 + 1090 => 0 + 1091 => 0 + 1092 => 0 + 1093 => 0 + 1094 => 0 + 1095 => 0 + 1096 => 0 + 1097 => 0 + 1098 => 0 + 1099 => 0 + IsEmpty(): true + --Road-- Road IsRoadTile(): false
--- a/projects/openttd.vcproj Wed Apr 11 20:53:58 2007 +0000 +++ b/projects/openttd.vcproj Thu Apr 12 11:37:24 2007 +0000 @@ -1048,6 +1048,9 @@ RelativePath=".\..\src\ai\api\ai_industry.hpp"> </File> <File + RelativePath=".\..\src\ai\api\ai_list.hpp"> + </File> + <File RelativePath=".\..\src\ai\api\ai_map.hpp"> </File> <File @@ -1103,6 +1106,9 @@ RelativePath=".\..\src\ai\api\ai_industry.cpp"> </File> <File + RelativePath=".\..\src\ai\api\ai_list.cpp"> + </File> + <File RelativePath=".\..\src\ai\api\ai_map.cpp"> </File> <File
--- a/projects/openttd_vs80.vcproj Wed Apr 11 20:53:58 2007 +0000 +++ b/projects/openttd_vs80.vcproj Thu Apr 12 11:37:24 2007 +0000 @@ -1616,6 +1616,10 @@ > </File> <File + RelativePath=".\..\src\ai\api\ai_list.hpp" + > + </File> + <File RelativePath=".\..\src\ai\api\ai_map.hpp" > </File> @@ -1688,6 +1692,10 @@ > </File> <File + RelativePath=".\..\src\ai\api\ai_list.cpp" + > + </File> + <File RelativePath=".\..\src\ai\api\ai_map.cpp" > </File>
--- a/source.list Wed Apr 11 20:53:58 2007 +0000 +++ b/source.list Thu Apr 12 11:37:24 2007 +0000 @@ -321,6 +321,7 @@ ai/api/ai_controller.hpp ai/api/ai_execmode.hpp ai/api/ai_industry.hpp +ai/api/ai_list.hpp ai/api/ai_map.hpp ai/api/ai_object.hpp ai/api/ai_order.hpp @@ -340,6 +341,7 @@ ai/api/ai_controller.cpp ai/api/ai_execmode.cpp ai/api/ai_industry.cpp +ai/api/ai_list.cpp ai/api/ai_map.cpp ai/api/ai_object.cpp ai/api/ai_order.cpp
--- a/src/ai/ai_squirrel.cpp Wed Apr 11 20:53:58 2007 +0000 +++ b/src/ai/ai_squirrel.cpp Thu Apr 12 11:37:24 2007 +0000 @@ -28,6 +28,7 @@ #include "api/ai_controller.hpp" #include "api/ai_execmode.hpp" #include "api/ai_industry.hpp" +#include "api/ai_list.hpp" #include "api/ai_map.hpp" #include "api/ai_order.hpp" #include "api/ai_road.hpp" @@ -197,6 +198,7 @@ SQAIControllerRegister(this->engine); SQAIExecModeRegister(this->engine); SQAIIndustryRegister(this->engine); + SQAIListRegister(this->engine); SQAIMapRegister(this->engine); SQAIOrderRegister(this->engine); SQAIRoadRegister(this->engine);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ai/api/ai_list.cpp Thu Apr 12 11:37:24 2007 +0000 @@ -0,0 +1,362 @@ +/* $Id$ */ + +/** @file ai_list.cpp Implementation of AIList */ + +#include "ai_list.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; + + /** + * Get the next item of the sorter. + */ + virtual int32 Next() = 0; + + /** + * See if there is a next item of the sorter. + */ + virtual bool HasNext() = 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; + +public: + AIListSorterValueAscending(AIList *list) + { + this->list = list; + } + + int32 Begin() + { + this->bucket_iter = this->list->buckets.begin(); + this->bucket_list = &(*this->bucket_iter).second; + this->bucket_list_iter = this->bucket_list->begin(); + return *bucket_list_iter; + } + + int32 Next() + { + this->bucket_list_iter++; + if (this->bucket_list_iter == this->bucket_list->end()) { + this->bucket_iter++; + if (this->bucket_iter == this->list->buckets.end()) return 0; + this->bucket_list = &(*this->bucket_iter).second; + this->bucket_list_iter = this->bucket_list->begin(); + } + return *bucket_list_iter; + } + + bool HasNext() + { + return this->bucket_iter != this->list->buckets.end() && this->bucket_list_iter != this->bucket_list->end(); + } +}; + +/** + * Sort by value, descending. + */ +class AIListSorterValueDescending : public AIListSorter { +private: + AIList::AIListBucket::reverse_iterator bucket_iter; + AIList::AIItemList *bucket_list; + AIList::AIItemList::reverse_iterator bucket_list_iter; + +public: + AIListSorterValueDescending(AIList *list) + { + this->list = list; + } + + int32 Begin() + { + this->bucket_iter = this->list->buckets.rbegin(); + this->bucket_list = &(*this->bucket_iter).second; + this->bucket_list_iter = this->bucket_list->rbegin(); + return *bucket_list_iter; + } + + int32 Next() + { + this->bucket_list_iter++; + if (this->bucket_list_iter == this->bucket_list->rend()) { + this->bucket_iter++; + if (this->bucket_iter == this->list->buckets.rend()) return 0; + this->bucket_list = &(*this->bucket_iter).second; + this->bucket_list_iter = this->bucket_list->rbegin(); + } + return *bucket_list_iter; + } + + bool HasNext() + { + return this->bucket_iter != this->list->buckets.rend() && this->bucket_list_iter != this->bucket_list->rend(); + } +}; + +/** + * Sort by item, ascending. + */ +class AIListSorterItemAscending : public AIListSorter { +private: + AIList::AIListMap::iterator item_iter; + +public: + AIListSorterItemAscending(AIList *list) + { + this->list = list; + } + + int32 Begin() + { + this->item_iter = this->list->items.begin(); + return (*this->item_iter).first; + } + + int32 Next() + { + this->item_iter++; + return (*this->item_iter).first; + } + + bool HasNext() + { + return this->item_iter != this->list->items.end(); + } +}; + +/** + * Sort by item, descending. + */ +class AIListSorterItemDescending : public AIListSorter { +private: + AIList::AIListMap::reverse_iterator item_iter; + +public: + AIListSorterItemDescending(AIList *list) + { + this->list = list; + } + + int32 Begin() + { + this->item_iter = this->list->items.rbegin(); + return (*this->item_iter).first; + } + + int32 Next() + { + this->item_iter++; + return (*this->item_iter).first; + } + + bool HasNext() + { + return this->item_iter != this->list->items.rend(); + } +}; + + + +AIList::AIList() +{ + /* Default sorter */ + this->sorter = new AIListSorterValueAscending(this); +} + +AIList::~AIList() +{ + delete this->sorter; +} + +bool AIList::HasItem(int32 item) +{ + return this->items.count(item) == 1; +} + +void AIList::Clear() +{ + this->items.clear(); + this->buckets.clear(); +} + +void AIList::AddItem(int32 item) +{ + if (this->HasItem(item)) return; + + this->items[item] = 0; + this->buckets[0].insert(item); +} + +void AIList::RemoveItem(int32 item) +{ + if (!this->HasItem(item)) return; + + this->buckets[this->GetValue(item)].erase(item); + this->items.erase(item); +} + +int32 AIList::Begin() +{ + return this->sorter->Begin(); +} + +int32 AIList::Next() +{ + return this->sorter->Next(); +} + +bool AIList::IsEmpty() +{ + return this->items.empty(); +} + +bool AIList::HasNext() +{ + return this->sorter->HasNext(); +} + +int32 AIList::Count() +{ + return this->items.size(); +} + +int32 AIList::GetValue(int32 item) +{ + if (!this->HasItem(item)) return 0; + + return this->items[item]; +} + +void AIList::SortByItem(bool ascending) +{ + delete this->sorter; + if (ascending) this->sorter = new AIListSorterItemAscending(this); + else this->sorter = new AIListSorterItemDescending(this); +} + +void AIList::SortByValue(bool ascending) +{ + delete this->sorter; + if (ascending) this->sorter = new AIListSorterValueAscending(this); + else this->sorter = new AIListSorterValueDescending(this); +} + +void AIList::RemoveAboveValue(int32 value) +{ + for (AIListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { + if ((*iter).second > value) this->items.erase(iter); + } + + for (AIListBucket::iterator iter = this->buckets.begin(); iter != this->buckets.end(); iter++) { + if ((*iter).first > value) this->buckets.erase(iter); + } +} + +void AIList::RemoveBelowValue(int32 value) +{ + for (AIListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { + if ((*iter).second < value) this->items.erase(iter); + } + + for (AIListBucket::iterator iter = this->buckets.begin(); iter != this->buckets.end(); iter++) { + if ((*iter).first < value) this->buckets.erase(iter); + } +} + +void AIList::RemoveBetweenValue(int32 start, int32 end) +{ + for (AIListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { + if ((*iter).second > start && (*iter).second < end) this->items.erase(iter); + } + + for (AIListBucket::iterator iter = this->buckets.begin(); iter != this->buckets.end(); iter++) { + if ((*iter).first > start && (*iter).first < end) this->buckets.erase(iter); + } +} + +void AIList::RemoveValue(int32 value) +{ + for (AIListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { + if ((*iter).second == value) this->items.erase(iter); + } + + for (AIListBucket::iterator iter = this->buckets.begin(); iter != this->buckets.end(); iter++) { + if ((*iter).first == value) this->buckets.erase(iter); + } +} + +void AIList::KeepAboveValue(int32 value) +{ + for (AIListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { + if ((*iter).second <= value) this->items.erase(iter); + } + + for (AIListBucket::iterator iter = this->buckets.begin(); iter != this->buckets.end(); iter++) { + if ((*iter).first <= value) this->buckets.erase(iter); + } +} + +void AIList::KeepBelowValue(int32 value) +{ + for (AIListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { + if ((*iter).second >= value) this->items.erase(iter); + } + + for (AIListBucket::iterator iter = this->buckets.begin(); iter != this->buckets.end(); iter++) { + if ((*iter).first >= value) this->buckets.erase(iter); + } +} + +void AIList::KeepBetweenValue(int32 start, int32 end) +{ + for (AIListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { + if ((*iter).second <= start || (*iter).second >= end) this->items.erase(iter); + } + + for (AIListBucket::iterator iter = this->buckets.begin(); iter != this->buckets.end(); iter++) { + if ((*iter).first <= start || (*iter).first >= end) this->buckets.erase(iter); + } +} + +void AIList::KeepValue(int32 value) +{ + for (AIListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { + if ((*iter).second != value) this->items.erase(iter); + } + + for (AIListBucket::iterator iter = this->buckets.begin(); iter != this->buckets.end(); iter++) { + if ((*iter).first != value) this->buckets.erase(iter); + } +} + +void AIList::Valuate(AIList::Valuator *proc) +{ + this->buckets.clear(); + for (AIListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { + int32 value = proc->Valuate((*iter).first); + (*iter).second = value; + this->buckets[value].insert((*iter).first); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ai/api/ai_list.hpp Thu Apr 12 11:37:24 2007 +0000 @@ -0,0 +1,233 @@ +/* $Id$ */ + +/** @file ai_list.hpp a linked list which can keep item/value pairs */ + +#ifndef AI_LIST_HPP +#define AI_LIST_HPP + +#include "ai_object.hpp" +#include <map> +#include <set> + +class AIListSorter; + +/** + * Class that creates a linked list which can keep item/value pairs. + */ +class AIList : public AIObject { +private: + AIListSorter *sorter; + +public: + typedef std::set<int32> AIItemList; + typedef std::map<int32, AIItemList> AIListBucket; + typedef std::map<int32, int32> AIListMap; + + AIListMap items; ///< The items in the list + AIListBucket buckets; ///< The items in the list, sorted by value + +public: + + /** + * The name of the class, needed by several sub-processes. + */ + static const char *GetClassName() { return "AIList"; } + + /** + * Constructor of the AIList. + */ + AIList(); + + /** + * Destructor of the AIList. + */ + ~AIList(); + + /** + * Clear the list, making Count() returning 0 and IsEmpty() returning true. + */ + void Clear(); + + /** + * Add a single item to the list. + * @param item the item to add. Should be unique, otherwise it is ignored. + * @note the value is set to 0 by default. + */ + void AddItem(int32 item); + + /** + * Remove a single item from the list. + * @param item the item to remove. If not existing, it is ignored. + */ + void RemoveItem(int32 item); + + /** + * 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. + */ + 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 HasNext() 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 next element. In other words, if this is true, + * Next() will return a valid item. + * @return true if there is a next item. + */ + bool HasNext(); + + /** + * 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); + + /** + * Sort this list by item-value. + * @param ascending if true, lowest value is on top, else at bottom. + * @note the current item stays at the same place. + */ + void SortByItem(bool ascending); + + /** + * Sort this list by the value of the items. + * @param ascending if true, lowest value is on top, else at bottom. + * @note the current item stays at the same place. + */ + void SortByValue(bool ascending); + + /** + * 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); + + /** + * 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); + + /** + * The definition how valuators should look. + */ + class Valuator { + public: + virtual ~Valuator() {} + + virtual int32 Valuate(const int32 item) = 0; + }; + + /** + * Give all items a value defined by the valuator you give. + * @note the valuator should be a valid instance. + */ + void Valuate(AIList::Valuator *proc); +}; + +#ifdef DEFINE_SQUIRREL_CLASS +namespace SQConvert { + /* Allow inner classes/structs to be used as Squirrel parameters */ + template <> AIList::Valuator *GetParam(ForceType<AIList::Valuator *>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIList::Valuator *)instance; } + + /* Allow AIList to be used as Squirrel parameter */ + template <> AIList *GetParam(ForceType<AIList *>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIList *)instance; } +}; // namespace SQConvert + +void SQAIListRegister(Squirrel *engine) { + DefSQClass <AIList> SQAIList("AIList"); + SQAIList.PreRegister(engine); + SQAIList.AddConstructor(engine); + + SQAIList.DefSQStaticMethod(engine, &AIList::GetClassName, "GetClassName", 1, "x"); + + SQAIList.DefSQMethod(engine, &AIList::Clear, "Clear", 1, "x"); + SQAIList.DefSQMethod(engine, &AIList::AddItem, "AddItem", 2, "xi"); + SQAIList.DefSQMethod(engine, &AIList::RemoveItem, "RemoveItem", 2, "xi"); + 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::HasNext, "HasNext", 1, "x"); + SQAIList.DefSQMethod(engine, &AIList::Count, "Count", 1, "x"); + SQAIList.DefSQMethod(engine, &AIList::GetValue, "GetValue", 2, "xi"); + SQAIList.DefSQMethod(engine, &AIList::SortByItem, "SortByItem", 2, "xb"); + SQAIList.DefSQMethod(engine, &AIList::SortByValue, "SortByValue", 2, "xb"); + 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::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::Valuate, "Valuate", 2, "xp"); + + SQAIList.PostRegister(engine); +} +#endif /* DEFINE_SQUIRREL_CLASS */ + +#endif /* AI_LIST_HPP */