1 /* 2 * This file is part of OpenTTD. 3 * 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. 4 * 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. 5 * 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/>. 6 */ 7 8 /** @file script_list.hpp A list which can keep item/value pairs, which you can walk. */ 9 /** @defgroup ScriptList Classes that create a list of items. */ 10 11 #ifndef SCRIPT_LIST_HPP 12 #define SCRIPT_LIST_HPP 13 14 #include "script_object.hpp" 15 #include <map> 16 #include <set> 17 18 class ScriptListSorter; 19 20 /** 21 * Class that creates a list which can keep item/value pairs, which you can walk. 22 * @api ai game 23 */ 24 class ScriptList : public ScriptObject { 25 public: 26 /** Type of sorter */ 27 enum SorterType { 28 SORT_BY_VALUE, ///< Sort the list based on the value of the item. 29 SORT_BY_ITEM, ///< Sort the list based on the item itself. 30 }; 31 32 /** Sort ascending */ 33 static const bool SORT_ASCENDING = true; 34 /** Sort descending */ 35 static const bool SORT_DESCENDING = false; 36 37 private: 38 ScriptListSorter *sorter; ///< Sorting algorithm 39 SorterType sorter_type; ///< Sorting type 40 bool sort_ascending; ///< Whether to sort ascending or descending 41 bool initialized; ///< Whether an iteration has been started 42 int modifications; ///< Number of modification that has been done. To prevent changing data while valuating. 43 44 public: 45 typedef std::set<int64> ScriptItemList; ///< The list of items inside the bucket 46 typedef std::map<int64, ScriptItemList> ScriptListBucket; ///< The bucket list per value 47 typedef std::map<int64, int64> ScriptListMap; ///< List per item 48 49 ScriptListMap items; ///< The items in the list 50 ScriptListBucket buckets; ///< The items in the list, sorted by value 51 52 ScriptList(); 53 ~ScriptList(); 54 55 #ifdef DOXYGEN_API 56 /** 57 * Add a single item to the list. 58 * @param item the item to add. Should be unique, otherwise it is ignored. 59 * @param value the value to assign. 60 */ 61 void AddItem(int64 item, int64 value); 62 #else 63 void AddItem(int64 item, int64 value = 0); 64 #endif /* DOXYGEN_API */ 65 66 /** 67 * Remove a single item from the list. 68 * @param item the item to remove. If not existing, it is ignored. 69 */ 70 void RemoveItem(int64 item); 71 72 /** 73 * Clear the list, making Count() returning 0 and IsEmpty() returning true. 74 */ 75 void Clear(); 76 77 /** 78 * Check if an item is in the list. 79 * @param item the item to check for. 80 * @return true if the item is in the list. 81 */ 82 bool HasItem(int64 item); 83 84 /** 85 * Go to the beginning of the list and return the item. To get the value use list.GetValue(list.Begin()). 86 * @return the first item. 87 * @note returns 0 if beyond end-of-list. Use IsEnd() to check for end-of-list. 88 */ 89 int64 Begin(); 90 91 /** 92 * Go to the next item in the list and return the item. To get the value use list.GetValue(list.Next()). 93 * @return the next item. 94 * @note returns 0 if beyond end-of-list. Use IsEnd() to check for end-of-list. 95 */ 96 int64 Next(); 97 98 /** 99 * Check if a list is empty. 100 * @return true if the list is empty. 101 */ 102 bool IsEmpty(); 103 104 /** 105 * Check if there is a element left. In other words, if this is false, 106 * the last call to Begin() or Next() returned a valid item. 107 * @return true if the current item is beyond end-of-list. 108 */ 109 bool IsEnd(); 110 111 /** 112 * Returns the amount of items in the list. 113 * @return amount of items in the list. 114 */ 115 int32 Count(); 116 117 /** 118 * Get the value that belongs to this item. 119 * @param item the item to get the value from 120 * @return the value that belongs to this item. 121 */ 122 int64 GetValue(int64 item); 123 124 /** 125 * Set a value of an item directly. 126 * @param item the item to set the value for. 127 * @param value the value to give to the item 128 * @return true if we could set the item to value, false otherwise. 129 * @note Changing values of items while looping through a list might cause 130 * entries to be skipped. Be very careful with such operations. 131 */ 132 bool SetValue(int64 item, int64 value); 133 134 /** 135 * Sort this list by the given sorter and direction. 136 * @param sorter the type of sorter to use 137 * @param ascending if true, lowest value is on top, else at bottom. 138 * @note the current item stays at the same place. 139 * @see SORT_ASCENDING SORT_DESCENDING 140 */ 141 void Sort(SorterType sorter, bool ascending); 142 143 /** 144 * Add one list to another one. 145 * @param list The list that will be added to the caller. 146 * @post The list to be added ('list') stays unmodified. 147 * @note All added items keep their value as it was in 'list'. 148 * @note If the item already exists inside the caller, the value of the 149 * list that is added is set on the item. 150 */ 151 void AddList(ScriptList *list); 152 153 /** 154 * Swap the contents of two lists. 155 * @param list The list that will be swapped with. 156 */ 157 void SwapList(ScriptList *list); 158 159 /** 160 * Removes all items with a higher value than 'value'. 161 * @param value the value above which all items are removed. 162 */ 163 void RemoveAboveValue(int64 value); 164 165 /** 166 * Removes all items with a lower value than 'value'. 167 * @param value the value below which all items are removed. 168 */ 169 void RemoveBelowValue(int64 value); 170 171 /** 172 * Removes all items with a value above start and below end. 173 * @param start the lower bound of the to be removed values (exclusive). 174 * @param end the upper bound of the to be removed values (exclusive). 175 */ 176 void RemoveBetweenValue(int64 start, int64 end); 177 178 /** 179 * Remove all items with this value. 180 * @param value the value to remove. 181 */ 182 void RemoveValue(int64 value); 183 184 /** 185 * Remove the first count items. 186 * @param count the amount of items to remove. 187 */ 188 void RemoveTop(int32 count); 189 190 /** 191 * Remove the last count items. 192 * @param count the amount of items to remove. 193 */ 194 void RemoveBottom(int32 count); 195 196 /** 197 * Remove everything that is in the given list from this list (same item index that is). 198 * @param list the list of items to remove. 199 * @pre list != nullptr 200 */ 201 void RemoveList(ScriptList *list); 202 203 /** 204 * Keep all items with a higher value than 'value'. 205 * @param value the value above which all items are kept. 206 */ 207 void KeepAboveValue(int64 value); 208 209 /** 210 * Keep all items with a lower value than 'value'. 211 * @param value the value below which all items are kept. 212 */ 213 void KeepBelowValue(int64 value); 214 215 /** 216 * Keep all items with a value above start and below end. 217 * @param start the lower bound of the to be kept values (exclusive). 218 * @param end the upper bound of the to be kept values (exclusive). 219 */ 220 void KeepBetweenValue(int64 start, int64 end); 221 222 /** 223 * Keep all items with this value. 224 * @param value the value to keep. 225 */ 226 void KeepValue(int64 value); 227 228 /** 229 * Keep the first count items, i.e. remove everything except the first count items. 230 * @param count the amount of items to keep. 231 */ 232 void KeepTop(int32 count); 233 234 /** 235 * Keep the last count items, i.e. remove everything except the last count items. 236 * @param count the amount of items to keep. 237 */ 238 void KeepBottom(int32 count); 239 240 /** 241 * Keeps everything that is in the given list from this list (same item index that is). 242 * @param list the list of items to keep. 243 * @pre list != nullptr 244 */ 245 void KeepList(ScriptList *list); 246 247 #ifndef DOXYGEN_API 248 /** 249 * Used for 'foreach()' and [] get from Squirrel. 250 */ 251 SQInteger _get(HSQUIRRELVM vm); 252 253 /** 254 * Used for [] set from Squirrel. 255 */ 256 SQInteger _set(HSQUIRRELVM vm); 257 258 /** 259 * Used for 'foreach()' from Squirrel. 260 */ 261 SQInteger _nexti(HSQUIRRELVM vm); 262 263 /** 264 * The Valuate() wrapper from Squirrel. 265 */ 266 SQInteger Valuate(HSQUIRRELVM vm); 267 #else 268 /** 269 * Give all items a value defined by the valuator you give. 270 * @param valuator_function The function which will be doing the valuation. 271 * @param params The params to give to the valuators (minus the first param, 272 * which is always the index-value we are valuating). 273 * @note You may not add, remove or change (setting the value of) items while 274 * valuating. You may also not (re)sort while valuating. 275 * @note You can write your own valuators and use them. Just remember that 276 * the first parameter should be the index-value, and it should return 277 * an integer. 278 * @note Example: 279 * list.Valuate(ScriptBridge.GetPrice, 5); 280 * list.Valuate(ScriptBridge.GetMaxLength); 281 * function MyVal(bridge_id, myparam) 282 * { 283 * return myparam * bridge_id; // This is silly 284 * } 285 * list.Valuate(MyVal, 12); 286 */ 287 void Valuate(void *valuator_function, int params, ...); 288 #endif /* DOXYGEN_API */ 289 }; 290 291 #endif /* SCRIPT_LIST_HPP */ 292