impl.inc 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509
  1. /**--------------------------------------------------------------------------**\
  2. ===========================
  3. foreach efficient looping
  4. ===========================
  5. Description:
  6. Provides efficient looping through sparse data sets, such as connected
  7. players. Significantly improved from the original version to be a generic
  8. loop system, rather then purely a player loop system. When used for
  9. players this has constant time O(n) for number of connected players (n),
  10. unlike standard player loops which are O(MAX_PLAYERS), regardless of the
  11. actual number of connected players. Even when n is MAX_PLAYERS this is
  12. still faster.
  13. For extensive documentation on writing and using iterators, see this topic:
  14. http://forum.sa-mp.com/showthread.php?t=481877
  15. Legal:
  16. Version: MPL 1.1
  17. The contents of this file are subject to the Mozilla Public License Version
  18. 1.1 (the "License"); you may not use this file except in compliance with
  19. the License. You may obtain a copy of the License at
  20. [url]http://www.mozilla.org/MPL/[/url]
  21. Software distributed under the License is distributed on an "AS IS" basis,
  22. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  23. for the specific language governing rights and limitations under the
  24. License.
  25. The Original Code is the YSI foreach include.
  26. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  27. Portions created by the Initial Developer are Copyright (C) 2011
  28. the Initial Developer. All Rights Reserved.
  29. Contributors:
  30. ZeeX, koolk, JoeBullet/Google63, g_aSlice/Slice
  31. Thanks:
  32. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  33. ZeeX - Very productive conversations.
  34. koolk - IsPlayerinAreaEx code.
  35. TheAlpha - Danish translation.
  36. breadfish - German translation.
  37. Fireburn - Dutch translation.
  38. yom - French translation.
  39. 50p - Polish translation.
  40. Zamaroht - Spanish translation.
  41. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes
  42. for me to strive to better.
  43. Pixels^ - Running XScripters where the idea was born.
  44. Matite - Pestering me to release it and using it.
  45. Very special thanks to:
  46. Thiadmer - PAWN, whose limits continue to amaze me!
  47. Kye/Kalcor - SA:MP.
  48. SA:MP Team past, present and future - SA:MP.
  49. Version:
  50. 0.4
  51. Changelog:
  52. 29/03/15:
  53. More testing.
  54. Repaired special iterators.
  55. 28/03/15:
  56. Breaking change: "Iter_Add" returns value added, not true/false.
  57. Breaking change: Special iterators take "cellmin", not "-1".
  58. Wrote many tests.
  59. Split in to multiple files.
  60. Added multi-iterators.
  61. Officially deprecated "foreach (Player, i)".
  62. 26/03/15:
  63. Re-added reverse iterators.
  64. Added support for extra spaces in "foreach".
  65. 26/12/13:
  66. Added sections.
  67. 17/10/12:
  68. Fixed a bug that was here but not in "foreach.inc".
  69. 04/10/12:
  70. Added a tiny tweak to detect tag-returning iterator functions.
  71. Added Iter_InternalSize.
  72. 13/01/12:
  73. Fixed the count thanks to AndreT.
  74. 05/01/12:
  75. Fixed multi-dimensional iterators.
  76. Fixed "FOREACH_NO_BOTS".
  77. Made "Iterator:" support multi-dimensional arrays.
  78. 24/12/11:
  79. Added _YSI_SPECIAL_DEBUG support.
  80. Added fix for function iterators.
  81. Ported back to YSI.
  82. Changed to use internal YSI "__" natives.
  83. Fixed calls order by using ALS.
  84. 31/10/11:
  85. Changed the underlying loop code to be slightly faster.
  86. Added support for Iter_SafeRemove, prompting refactoring.
  87. 17/09/11:
  88. Fixed arrays under the new syntax.
  89. 28/04/11:
  90. Moved iterator identifiers to end of variables.
  91. Rewrote "foreach" to accept two syntaxes for "foreach (new i : Iter)".
  92. 16/08/10:
  93. Removed all the "2" versions of the functions.
  94. 14/08/10:
  95. Added Iter_Clear to reset an array.
  96. 06/08/10:
  97. Added special array declaration format.
  98. 18/12/09:
  99. Added Iter_Func2 functions for multi-dimensional iterators.
  100. Renamed foreact et al as keywords in the documentation.
  101. Changed licensing from GPL to MPL.
  102. 02/09/09:
  103. Fixed (again) for 0.3.
  104. Added free slot finding.
  105. 21/08/09:
  106. Updated to include random functions.
  107. Made entirely stand alone.
  108. Ported to 0.3 (separate version).
  109. Added automatic callback hook code.
  110. Removed debug information from stand alone version.
  111. 06/01/08:
  112. Added debug information.
  113. 09/10/07:
  114. Moved to system.
  115. 16/09/07:
  116. Added list sorting.
  117. Made this part of Y SeRver Includes, not Y Sever Includes.
  118. Made list sorting optional.
  119. Fixed version number.
  120. 08/09/07:
  121. First version.
  122. Functions:
  123. Public:
  124. OnPlayerDisconnect - Called when a player leaves to remove them.
  125. OnPlayerConnect - Called when a player connects to add them.
  126. Core:
  127. -
  128. Stock:
  129. Iter_ShowArray - Displays the contents of the array.
  130. Iter_AddInternal - Add a value to an iterator.
  131. Iter_RemoveInternal - Remove a value from an iterator.
  132. Iter_RandomInternal - Get a random item from an iterator.
  133. Iter_FreeInternal - Gets the first free slot in the iterator.
  134. Iter_InitInternal - Initialises a multi-dimensional iterator.
  135. Static:
  136. -
  137. Inline:
  138. Iter_Create - Create a new iterator value set.
  139. Iter_Add - Wraps Iter_AddInternal.
  140. Iter_Remove - Wraps Iter_RemoveInternal.
  141. Iter_Random - Wraps Iter_RandomInternal.
  142. Iter_Count - Gets the number of items in an iterator.
  143. Iter_Debug - Wraps around Iter_ShowArray.
  144. Iter_Free - Wraps around Iter_FreeInternal.
  145. Iter_Create2 - Create a new iterator array value set.
  146. Iter_Add2 - Wraps Iter_AddInternal for arrays.
  147. Iter_Remove2 - Wraps Iter_RemoveInternal for arrays.
  148. Iter_Random2 - Wraps Iter_RandomInternal for arrays.
  149. Iter_Count2 - Gets the number of items in an iterator array.
  150. Iter_Debug2 - Wraps around Iter_ShowArray for arrays.
  151. Iter_Free2 - Wraps around Iter_FreeInternal for arrays.
  152. API:
  153. -
  154. Callbacks:
  155. -
  156. Hooks:
  157. Iter_OnPlayerConnect - Hook for the OnPlayerConnect callback.
  158. Iter_OnPlayerDisconnect - Hook for the OnPlayerDisconnect callback.
  159. Iter_OnGameModeInit - Only exists to make the code compile correctly...
  160. Definitions:
  161. -
  162. Enums:
  163. -
  164. Macros:
  165. -
  166. Keywords:
  167. foreach - Command to loop an iterator.
  168. foreachex - Like foreach but without a new variable.
  169. foreach2 - Command to loop through an iterator array.
  170. foreachex - Like foreach2 but without a new variable.
  171. Tags:
  172. Iterator - Declare an iterator.
  173. Variables:
  174. Global:
  175. -
  176. Static:
  177. YSI_g_OPC - Records wether Iter_OnPlayerConnect exists for speed.
  178. YSI_g_OPDC - Records wether Iter_OnPlayerDisconnect exists for speed.
  179. Commands:
  180. -
  181. Compile options:
  182. YSI_ITTER_NO_SORT - Removed.
  183. FOREACH_NO_BOTS - Remove the bot iterators for smaller code.
  184. FOREACH_NO_PLAYERS - Remove all default code for player itteration.
  185. Operators:
  186. -
  187. Iterators:
  188. Player - List of all players connected.
  189. Bot - List of all bots (npcs) connected.
  190. NPC - Alias of Bot.
  191. Character - All players and bots.
  192. \**--------------------------------------------------------------------------**/
  193. /*
  194. 88 a8P 88
  195. 88 ,88' 88
  196. 88 ,88" 88
  197. 88,d88' ,adPPYba, 8b d8 8b db d8 ,adPPYba, 8b,dPPYba, ,adPPYb,88 ,adPPYba,
  198. 8888"88, a8P_____88 `8b d8' `8b d88b d8' a8" "8a 88P' "Y8 a8" `Y88 I8[ ""
  199. 88P Y8b 8PP""""""" `8b d8' `8b d8'`8b d8' 8b d8 88 8b 88 `"Y8ba,
  200. 88 "88, "8b, ,aa `8b,d8' `8bd8' `8bd8' "8a, ,a8" 88 "8a, ,d88 aa ]8I
  201. 88 Y8b `"Ybbd8"' Y88' YP YP `"YbbdP"' 88 `"8bbdP"Y8 `"YbbdP"'
  202. d8'
  203. d8'
  204. */
  205. /**--------------------------------------------------------------------------**\
  206. Array:
  207. Iterator
  208. </returns>
  209. <remarks>
  210. Creates a new iterator start/array pair.
  211. </remarks>
  212. \**--------------------------------------------------------------------------**/
  213. #define Iterator:%1<%2> Iterator@%1[_:F@c:F@d:((%2)+1)]={(-(%2))*((%2)-1),(-(%2))*((%2)-2),...}F@a$,Iter_Single@%1 F@a$F@a$
  214. /**--------------------------------------------------------------------------**\
  215. <summary>foreach</summary>
  216. <param name="data">Data to itterate through.</param>
  217. <param name="as">Variable to set value to.</param>
  218. <returns>
  219. -
  220. </returns>
  221. <remarks>
  222. Not exactly the same as PHP foreach, just iterates through a list and
  223. returns the value of the current slot but uses that slot as the next index
  224. too. Variables must be in the form @YSII_<gname>S for the start index and
  225. @YSII_<gname>A for the data array where <name> is what's entered in data.
  226. </remarks>
  227. \**--------------------------------------------------------------------------**/
  228. #define foreach(%0) for(new Y_FOREACH_SECOND|||Y_FOREACH_THIRD|||%0|||)
  229. /**--------------------------------------------------------------------------**\
  230. <summary>iterfunc</summary>
  231. <returns>
  232. -
  233. </returns>
  234. <remarks>
  235. Used to declare a special iterator function.
  236. </remarks>
  237. \**--------------------------------------------------------------------------**/
  238. #define iterfunc%0(%1) F@y:%0(%1)
  239. /**--------------------------------------------------------------------------**\
  240. <summary>@iterfunc</summary>
  241. <returns>
  242. -
  243. </returns>
  244. <remarks>
  245. Converts an array-like iterator to a special iterator.
  246. </remarks>
  247. \**--------------------------------------------------------------------------**/
  248. #define @iterfunc%9|||%9))-1);_:(%1=%9)!=(F@s(Iterator@%0)-1); F@o)-2)+_:F@l:$%1,%0()$
  249. /**--------------------------------------------------------------------------**\
  250. <summary>iterstart</summary>
  251. <returns>
  252. -
  253. </returns>
  254. <remarks>
  255. Used to declare the default special iterator value.
  256. </remarks>
  257. \**--------------------------------------------------------------------------**/
  258. /**--------------------------------------------------------------------------**\
  259. <summary>Reverse</summary>
  260. <returns>
  261. -
  262. </returns>
  263. <remarks>
  264. Run an iterator backwards.
  265. </remarks>
  266. \**--------------------------------------------------------------------------**/
  267. #define iterstart@Reverse%9$);%9!=_:(%1=%9(_:%9,%0)); F@p:F@q:$%1,%0$
  268. /*
  269. 88b d88 88 db 88888888ba 88
  270. 888b d888 "" d88b 88 "8b 88
  271. 88`8b d8'88 d8'`8b 88 ,8P 88
  272. 88 `8b d8' 88 ,adPPYYba, 88 8b,dPPYba, d8' `8b 88aaaaaa8P' 88
  273. 88 `8b d8' 88 "" `Y8 88 88P' `"8a d8YaaaaY8b 88""""""' 88
  274. 88 `8b d8' 88 ,adPPPPP88 88 88 88 d8""""""""8b 88 88
  275. 88 `888' 88 88, ,88 88 88 88 d8' `8b 88 88
  276. 88 `8' 88 `"8bbdP"Y8 88 88 88 d8' `8b 88 88
  277. */
  278. /**--------------------------------------------------------------------------**\
  279. <summary>Iter_Init</summary>
  280. <param name="iter">Name of the iterator array to initialise.</param>
  281. <returns>
  282. -
  283. </returns>
  284. <remarks>
  285. Wrapper for Iter_Init_Internal. When "NESTED_ELLIPSIS" is set, this isn't
  286. needed because multi-dimensional iterators can be initialised with the new
  287. "{{0, 1, ...), ...}" feature. In that case "I@ = 0" is called as a "void"
  288. function that does nothing but ends in a semi-colon ("I@" is used a lot in
  289. YSI as a "do nothing" enabler).
  290. native Iter_Init(IteratorArray:Name[]<>);
  291. </remarks>
  292. \**--------------------------------------------------------------------------**/
  293. #if defined NESTED_ELLIPSIS
  294. #define Iter_Init(%0) (I@=0)
  295. #else
  296. #define Iter_Init(%0) Iter_Init_Internal(F@r(Iterator@%0),F@r(Iterator@%0)[0],F@s(Iterator@%0),F@s(Iterator@%0[]),F@r(Iter_Init@%0))
  297. #endif
  298. /**--------------------------------------------------------------------------**\
  299. <summary>Iter_Add</summary>
  300. <param name="iter">Name of the iterator to add the data to.</param>
  301. <param name="value">Value to add to the iterator.</param>
  302. <returns>
  303. -
  304. </returns>
  305. <remarks>
  306. Wrapper for Iter_AddInternal.
  307. native Iter_Add(Iterator:Name<>, value);
  308. </remarks>
  309. \**--------------------------------------------------------------------------**/
  310. #define Iter_Add _ITER<Add>
  311. #define Iter_Add_InternalA(%0,%1,%9) Iter_Add_InternalC(%0,%1,F@s(%1)-1,%9)
  312. #define Iter_Add_InternalB(%0,%2,%1,%9) Iter_Add_InternalD(%0[%2],%1,F@s(%1)-1-(%2),F@s(%1)-F@s(%0),%9)
  313. /**--------------------------------------------------------------------------**\
  314. <summary>Iter_Remove</summary>
  315. <param name="iter">Name of the iterator to remove data from.</param>
  316. <param name="value">Data to remove.</param>
  317. <returns>
  318. -
  319. </returns>
  320. <remarks>
  321. Wrapper for Iter_RemoveInternal.
  322. native Iter_Remove(Iterator:Name<>, value);
  323. </remarks>
  324. \**--------------------------------------------------------------------------**/
  325. #define Iter_Remove _ITER<Remove>
  326. #define Iter_Remove_InternalA(%0,%1,%9) Iter_Remove_InternalC(%0,%1,F@s(%1)-1,%9)
  327. #define Iter_Remove_InternalB(%0,%2,%1,%9) Iter_Remove_InternalD(%0[%2],%1,F@s(%1)-1-(%2),F@s(%1)-F@s(%0),%9)
  328. /**--------------------------------------------------------------------------**\
  329. <summary>Iter_Free</summary>
  330. <param name="iter">Name of the iterator to get the first free slot in.</param>
  331. <returns>
  332. -
  333. </returns>
  334. <remarks>
  335. Wrapper for Iter_Free_Internal. Returns a slot NOT in the current
  336. iterator.
  337. native Iter_Free(Iterator:Name<>);
  338. </remarks>
  339. \**--------------------------------------------------------------------------**/
  340. #define Iter_Free _ITER<Free>
  341. #define Iter_Free_InternalA(%0,%1) Iter_Free_Internal(%1,F@s(%1)-F@s(%0))
  342. #define Iter_Free_InternalB(%0,%2,%1) Iter_Free_Internal(%1,F@s(%1)-F@s(%0))
  343. /**--------------------------------------------------------------------------**\
  344. <summary>Iter_FreeMulti</summary>
  345. <param name="iter">Name of the multi-iterator to get the first free slot in.</param>
  346. <returns>
  347. -
  348. </returns>
  349. <remarks>
  350. Wrapper for Iter_FreeMulti_Internal. Returns a slot NOT in the current
  351. multi-iterator.
  352. native Iter_FreeMulti(Iterator:Name<>);
  353. </remarks>
  354. \**--------------------------------------------------------------------------**/
  355. #define Iter_FreeMulti _ITER<FreeMulti>
  356. #define Iter_FreeMulti_InternalA(%0,%1) Iter_FreeMulti_Internal(%1,F@s(%1),F@s(%1)-F@s(%0))
  357. #define Iter_FreeMulti_InternalB(%0,%2,%1) Iter_FreeMulti_Internal(%1,F@s(%1),F@s(%1)-F@s(%0))
  358. /**--------------------------------------------------------------------------**\
  359. <summary>Iter_Contains</summary>
  360. <param name="iter">Name of the iterator to check membership of.</param>
  361. <param name="value">Value to check.</param>
  362. <returns>
  363. -
  364. </returns>
  365. <remarks>
  366. Checks if the given value is in the given iterator.
  367. native Iter_Contains(Iterator:Name<>, value);
  368. </remarks>
  369. \**--------------------------------------------------------------------------**/
  370. #define Iter_Contains(%0) (bool:_ITER<Contains>(%0))
  371. #define Iter_Contains_InternalA(%0,%1,%9) Iter_Contains_InternalC(%1,F@s(%1)-F@s(%0),%9)
  372. #define Iter_Contains_InternalB(%0,%2,%1,%9) Iter_Contains_InternalD(%0[%2],%1,F@s(%1)-F@s(%0),%9,-%2+F@s(%1)-1)
  373. #define Iter_Contains_InternalD(%0,%1,%2,%3,-+%8) Iter_Contains_InternalC(%1,%2,%3)
  374. /**--------------------------------------------------------------------------**\
  375. <summary>Iter_GetMulti</summary>
  376. <param name="iter">Name of the iterator to check membership of.</param>
  377. <param name="value">Value to check.</param>
  378. <returns>
  379. Index in which the value is contained in the multi-iterator.
  380. </returns>
  381. <remarks>
  382. Checks if the given value is in the given iterator, and if it is return which index it is contained.
  383. native Iter_GetMulti(Iterator:Name<>, value);
  384. </remarks>
  385. \**--------------------------------------------------------------------------**/
  386. #define Iter_GetMulti _ITER<GetMulti>
  387. #define Iter_GetMulti_InternalA(%0,%1,%9) Iter_GetMulti_Internal(%1,F@s(%1),F@s(%1)-F@s(%0),%9)
  388. #define Iter_GetMulti_InternalB(%0,%2,%1,%9) Iter_GetMulti_Internal(%1,F@s(%1),F@s(%1)-F@s(%0),%9)
  389. /**--------------------------------------------------------------------------**\
  390. <summary>Iter_SafeRemove</summary>
  391. <param name="iter">Name of the iterator to remove data from.</param>
  392. <param name="value">Data to remove.</param>
  393. <param name="next">Container for the pointer to the next element.</param>
  394. <returns>
  395. -
  396. </returns>
  397. <remarks>
  398. Wrapper for Iter_SafeRemoveInternal. Common use:
  399. Iter_SafeRemove(iter, i, i);
  400. native Iter_SafeRemove(Iterator:Name<>, value, &next);
  401. </remarks>
  402. \**--------------------------------------------------------------------------**/
  403. #define Iter_SafeRemove _ITER<SafeRemove>
  404. #define Iter_SafeRemove_InternalA(%0,%1,%9) Iter_SafeRemove_InternalC(%0,%1,F@s(%1)-1,%9)
  405. #define Iter_SafeRemove_InternalB(%0,%2,%1,%9) Iter_SafeRemove_InternalD(%0[%2],%1,F@s(%1)-1-(%2),F@s(%1)-F@s(%0),%9)
  406. /**--------------------------------------------------------------------------**\
  407. <summary>Iter_RandomAdd</summary>
  408. <param name="iter">Name of the iterator to add a random slot to.</param>
  409. <returns>
  410. -
  411. </returns>
  412. <remarks>
  413. Wrapper for Iter_RandomAddInternal.
  414. native Iter_RandomAdd(Iterator:Name<>);
  415. </remarks>
  416. \**--------------------------------------------------------------------------**/
  417. #define Iter_RandomAdd(%0) Iter_Add(%0,Iter_RandomFree(%0))
  418. /**--------------------------------------------------------------------------**\
  419. <summary>Iter_RandomRemove</summary>
  420. <param name="iter">Name of the iterator to remove a random slot from.</param>
  421. <returns>
  422. -
  423. </returns>
  424. <remarks>
  425. Wrapper for Iter_RandomRemoveInternal.
  426. native Iter_RandomRemove(Iterator:Name<>);
  427. </remarks>
  428. \**--------------------------------------------------------------------------**/
  429. #define Iter_RandomRemove(%0) Iter_Remove(%0,Iter_Random(%0))
  430. /**--------------------------------------------------------------------------**\
  431. <summary>Iter_RandomFree</summary>
  432. <param name="iter">Name of the iterator to get a random unused slot for.</param>
  433. <returns>
  434. -
  435. </returns>
  436. <remarks>
  437. Wrapper for Iter_RandomFree_Internal.
  438. native Iter_RandomFree(Iterator:Name<>);
  439. </remarks>
  440. \**--------------------------------------------------------------------------**/
  441. #define Iter_RandomFree _ITER<RandomFree>
  442. #define Iter_RandomFree_InternalA(%0,%1) Iter_RandomFree_InternalC(%0,%1,F@s(%1)-1)
  443. #define Iter_RandomFree_InternalB(%0,%2,%1) Iter_RandomFree_InternalD(%0,%1,F@s(%1)-F@s(%0),F@s(%0))
  444. /**--------------------------------------------------------------------------**\
  445. <summary>Iter_Random</summary>
  446. <param name="iter">Name of the iterator to get a random slot from.</param>
  447. <returns>
  448. -
  449. </returns>
  450. <remarks>
  451. Wrapper for Iter_RandomInternal.
  452. native Iter_Random(Iterator:Name<>);
  453. </remarks>
  454. \**--------------------------------------------------------------------------**/
  455. #define Iter_Random _ITER<Random>
  456. #define Iter_Random_InternalA(%0,%1) Iter_Random_Internal(%0,%1,F@s(%1)-1)
  457. #define Iter_Random_InternalB(%0,%2,%1) Iter_Random_Internal(%0[%2],%1,F@s(%1)-1-(%2))
  458. /**--------------------------------------------------------------------------**\
  459. <summary>Iter_Count</summary>
  460. <param name="iter">Name of the iterator to get a random slot from.</param>
  461. <returns>
  462. -
  463. </returns>
  464. <remarks>
  465. Returns the number of items in this iterator.
  466. native Iter_Count(Iterator:Name<>);
  467. </remarks>
  468. \**--------------------------------------------------------------------------**/
  469. #define Iter_Count _ITER<Count>
  470. #define Iter_Count_InternalA(%0,%1) (%0)
  471. #define Iter_Count_InternalB(%0,%2,%1) (%0[%2])
  472. /**--------------------------------------------------------------------------**\
  473. <summary>Iter_Clear</summary>
  474. <param name="iter">Name of the iterator to empty.</param>
  475. <returns>
  476. -
  477. </returns>
  478. <remarks>
  479. Wrapper for Iter_Clear_Internal.
  480. Although it doesn't fit my normal strict spacing, the end of "B" is correct,
  481. namely: "_:F@s(%0),%2)". This uses the "_:%0,)" macro to consume
  482. a trailing comma when nothing is given in "%2", so I can't have a leading
  483. space sadly.
  484. "- 2" in place of the normal "- 1" is CORRECT!
  485. native Iter_Clear(IteratorArray:Name[]<>);
  486. </remarks>
  487. \**--------------------------------------------------------------------------**/
  488. #define Iter_Clear _ITER<Clear>
  489. #define Iter_Clear_InternalA(%0,%1) Iter_Clear_InternalC(%1,F@s(%1),F@s(%0),F@s(%1)-2,%0)
  490. #define Iter_Clear_InternalB(%0,%2,%1) Iter_Clear_InternalD(%1,F@s(%1),F@s(%0),F@s(%1)-F@s(%0),%0,%2)
  491. #define Iter_Clear_InternalD(%0,%1,%2,%3,%4,) Iter_Clear_InternalC(%0,%1,%2,%3-1,%4)
  492. /**--------------------------------------------------------------------------**\
  493. <summary>Iter_Alloc</summary>
  494. <param name="iter">Name of the iterator to get the first free slot in.</param>
  495. <returns>
  496. -
  497. </returns>
  498. <remarks>
  499. Finds an empty slot in an iterator, adds that slot to the iterator, and
  500. returns the now added slot.
  501. native Iter_Alloc(Iterator:Name<>);
  502. </remarks>
  503. \**--------------------------------------------------------------------------**/
  504. #define Iter_Alloc(%0) Iter_Add(%0,Iter_Free(%0))
  505. /*
  506. 88888888888 db 88888888ba 88
  507. 88 ,d d88b 88 "8b 88
  508. 88 88 d8'`8b 88 ,8P 88
  509. 88aaaaa 8b, ,d8 MM88MMM 8b,dPPYba, ,adPPYYba, d8' `8b 88aaaaaa8P' 88
  510. 88""""" `Y8, ,8P' 88 88P' "Y8 "" `Y8 d8YaaaaY8b 88""""""' 88
  511. 88 )888( 88 88 ,adPPPPP88 d8""""""""8b 88 88
  512. 88 ,d8" "8b, 88, 88 88, ,88 d8' `8b 88 88
  513. 88888888888 8P' `Y8 "Y888 88 `"8bbdP"Y8 d8' `8b 88 88
  514. */
  515. /**--------------------------------------------------------------------------**\
  516. <summary>Iter_FastClear</summary>
  517. <param name="iter">Name of the iterator to empty.</param>
  518. <returns>
  519. -
  520. </returns>
  521. <remarks>
  522. Uses a static array copy to blank the iterator instead of a loop.
  523. BROKEN!
  524. native Iter_FastClear(IteratorArray:Name[]<>);
  525. </remarks>
  526. \**--------------------------------------------------------------------------**/
  527. #define Iter_FastClear _ITER<FastClear>
  528. #define Iter_FastClear_InternalA(%0,%1); {static YSII_Xg@Clear[F@s(%1)]={0,1,...};%1=YSII_Xg@Clear;%0=0;}
  529. #define Iter_FastClear_InternalB(%0,%2,%1); {static YSII_Xg@Clear[F@s(%1)]={0,1,...},YSII_Yg@Clear[F@s(%0)]={0,0,...};%1=YSII_Xg@Clear;%0=YSII_Yg@Clear;}
  530. /**--------------------------------------------------------------------------**\
  531. <summary>Iter_Begin</summary>
  532. <param name="iter">Name of the iterator to get the start of.</param>
  533. <returns>
  534. -
  535. </returns>
  536. <remarks>
  537. Gets a point BEFORE the start of the iterator (the theoretical beginning).
  538. </remarks>
  539. \**--------------------------------------------------------------------------**/
  540. #define Iter_Begin _ITER<Begin>
  541. #define Iter_Begin_InternalA(%0,%1) (F@s(%1)-F@s(%0))
  542. #define Iter_Begin_InternalB(%0,%2,%1) (F@s(%1)-1-(%2))
  543. /**--------------------------------------------------------------------------**\
  544. <summary>Iter_End</summary>
  545. <param name="iter">Name of the iterator to get the end of.</param>
  546. <returns>
  547. -
  548. </returns>
  549. <remarks>
  550. Gets a point AFTER the end of the iterator (think "MAX_PLAYERS").
  551. </remarks>
  552. \**--------------------------------------------------------------------------**/
  553. #define Iter_End _ITER<End>
  554. #define Iter_End_InternalA(%0,%1) (F@s(%1)-F@s(%0))
  555. #define Iter_End_InternalB(%0,%2,%1) (F@s(%1)-1-(%2))
  556. /**--------------------------------------------------------------------------**\
  557. <summary>Iter_First</summary>
  558. <param name="iter">Name of the iterator to get the first valid element in.</param>
  559. <returns>
  560. -
  561. </returns>
  562. <remarks>
  563. Gets the first element in an iterator.
  564. </remarks>
  565. \**--------------------------------------------------------------------------**/
  566. #define Iter_First _ITER<First>
  567. #define Iter_First_InternalA(%0,%1) (%1[(F@s(%1)- F@s(%0))])
  568. #define Iter_First_InternalB(%0,%2,%1) (%1[(F@s(%1)-1-(%2))])
  569. /**--------------------------------------------------------------------------**\
  570. <summary>Iter_Last</summary>
  571. <param name="iter">Name of the iterator to</param>
  572. <returns>
  573. -
  574. </returns>
  575. <remarks>
  576. Gets the last element in an iterator. Works by getting the previous item
  577. from the one BEFORE the first element (i.e. the one before the sentinel).
  578. </remarks>
  579. \**--------------------------------------------------------------------------**/
  580. #define Iter_Last _ITER<Last>
  581. #define Iter_Last_InternalA(%0,%1) ((%1[Iter_End_InternalA(%0,%1)-1])-1)
  582. #define Iter_Last_InternalB(%0,%2,%1) (Iter_Prev_InternalB(%0,%2,%1,Iter_End_InternalB(%0,%2,%1)))
  583. /**--------------------------------------------------------------------------**\
  584. <summary>Iter_Next</summary>
  585. <param name="iter">Name of the iterator to get the next element in.</param>
  586. <param name="cur">The current element.</param>
  587. <returns>
  588. -
  589. </returns>
  590. <remarks>
  591. Gets the element in an iterator after the current one.
  592. </remarks>
  593. \**--------------------------------------------------------------------------**/
  594. #define Iter_Next _ITER<Next>
  595. #define Iter_Next_InternalA(%0,%1,%9) (%1[(%9)])
  596. #define Iter_Next_InternalB(%0,%2,%1,%9) (%1[(%9)])
  597. /**--------------------------------------------------------------------------**\
  598. <summary>Iter_Prev</summary>
  599. <param name="iter">Name of the iterator to get the previous element in.</param>
  600. <param name="cur">The current element.</param>
  601. <returns>
  602. -
  603. </returns>
  604. <remarks>
  605. Gets the element in an iterator before the current one. Slow.
  606. </remarks>
  607. \**--------------------------------------------------------------------------**/
  608. #define Iter_Prev _ITER<Prev>
  609. #define Iter_Prev_InternalA(%0,%1,%9) (((%1[((%9)-1)%F@s(%1)])-1)%F@s(%1))
  610. #define Iter_Prev_InternalB(%0,%2,%1,%9) Iter_Prev_Internal(%1,F@s(%1)-F@s(%0),F@s(%1),%9)
  611. /**--------------------------------------------------------------------------**\
  612. <summary>Iter_TrueArray</summary>
  613. <param name="iter">Name of the iterator to get the true array of.</param>
  614. <returns>
  615. -
  616. </returns>
  617. <remarks>
  618. Accesses the internal array of an iterator.
  619. </remarks>
  620. \**--------------------------------------------------------------------------**/
  621. #define Iter_TrueArray(%1) F@r(Iterator@%1)
  622. /**--------------------------------------------------------------------------**\
  623. <summary>Iter_TrueCount</summary>
  624. <param name="iter">Name of the iterator to get the true count of.</param>
  625. <returns>
  626. -
  627. </returns>
  628. <remarks>
  629. Accesses the internal count of an iterator.
  630. </remarks>
  631. \**--------------------------------------------------------------------------**/
  632. #define Iter_TrueCount(%1) F@r(Iter_Single@%1)
  633. /**--------------------------------------------------------------------------**\
  634. <summary>Iter_TrueMulti</summary>
  635. <param name="iter">Multi iterator to get the true count of.</param>
  636. <returns>
  637. -
  638. </returns>
  639. <remarks>
  640. Accesses the internal count of a multi-iterator.
  641. </remarks>
  642. \**--------------------------------------------------------------------------**/
  643. #define Iter_TrueMulti(%1) F@r(Iter_Multi@%1)
  644. /**--------------------------------------------------------------------------**\
  645. <summary>Iter_TrueSize</summary>
  646. <param name="iter">Name of the iterator to get the true size of.</param>
  647. <returns>
  648. -
  649. </returns>
  650. <remarks>
  651. Accesses the internal size of an iterator.
  652. </remarks>
  653. \**--------------------------------------------------------------------------**/
  654. #define Iter_TrueSize _ITER<TrueSize>
  655. #define Iter_TrueSize_InternalA(%0,%1) (F@s(%1))
  656. #define Iter_TrueSize_InternalB(%0,%2,%1) (F@s(%1))
  657. /**--------------------------------------------------------------------------**\
  658. <summary>Iter_Starts</summary>
  659. <param name="iter">Name of the iterator to get the true starts of.</param>
  660. <returns>
  661. -
  662. </returns>
  663. <remarks>
  664. Accesses the number of starts in a multi-iterator.
  665. </remarks>
  666. \**--------------------------------------------------------------------------**/
  667. #define Iter_Starts _ITER<Starts>
  668. #define Iter_Starts_InternalA(%0,%1) (F@s(%0))
  669. #define Iter_Starts_InternalB(%0,%2,%1) (F@s(%0))
  670. /**--------------------------------------------------------------------------**\
  671. <summary>Iter_Size</summary>
  672. <param name="iter">Name of the iterator to get the size of.</param>
  673. <returns>
  674. -
  675. </returns>
  676. <remarks>
  677. Accesses the size of an iterator.
  678. </remarks>
  679. \**--------------------------------------------------------------------------**/
  680. #define Iter_Size _ITER<Size>
  681. #define Iter_Size_InternalA(%0,%1) (F@s(%1)-F@s(%0))
  682. #define Iter_Size_InternalB(%0,%2,%1) (F@s(%1)-F@s(%0))
  683. /**--------------------------------------------------------------------------**\
  684. <summary>Iter_Index</summary>
  685. <param name="iter">Name of the iterator to get a slot in by index.</param>
  686. <param name="index">Index.</param>
  687. <param name="wrap">Keep going around until a value is found?</param>
  688. <returns>
  689. -
  690. </returns>
  691. <remarks>
  692. Wrapper for Iter_Free_Internal. Returns the Nth value in the iterator
  693. (requires looping due to the way iterators are stored and optimised for
  694. loops not direct access).
  695. native Iter_Index(Iterator:Name<>);
  696. </remarks>
  697. \**--------------------------------------------------------------------------**/
  698. #define Iter_Index _ITER<Index>
  699. #define Iter_Index_InternalA(%0,%1,%9) Iter_Index_Internal(%0,%1,F@s(%1)-1,F@s(%1)-1,%9)
  700. #define Iter_Index_InternalB(%0,%2,%1,%9) Iter_Index_Internal(%0[%2],%1,F@s(%1)-1-(%2),F@s(%1)-F@s(%0),%9)
  701. /*
  702. 88b d88
  703. 888b d888
  704. 88`8b d8'88
  705. 88 `8b d8' 88 ,adPPYYba, ,adPPYba, 8b,dPPYba, ,adPPYba, ,adPPYba,
  706. 88 `8b d8' 88 "" `Y8 a8" "" 88P' "Y8 a8" "8a I8[ ""
  707. 88 `8b d8' 88 ,adPPPPP88 8b 88 8b d8 `"Y8ba,
  708. 88 `888' 88 88, ,88 "8a, ,aa 88 "8a, ,a8" aa ]8I
  709. 88 `8' 88 `"8bbdP"Y8 `"Ybbd8"' 88 `"YbbdP"' `"YbbdP"'
  710. */
  711. // Remove trailing spaces. This looks really unsafe because of the "%0\32;"
  712. // allowing anything to come before the space, but it would have to be
  713. // "anything" not text immediately following a "YSII_X@" prefix.
  714. #define Iterator@%0\32;%1$ Iterator@%0%1$
  715. #define Iter_Func@%0\32;%1$ Iter_Func@%0%1$
  716. #define iterstart@%0\32;%1$ iterstart@%0%1$
  717. #define Iter_Single@%0\32;%1$ Iter_Single@%0%1$
  718. #define Iter_Multi@%0\32;%1$ Iter_Multi@%0%1$
  719. #define Iter_Init@%0\32;%1$ Iter_Init@%0%1$
  720. // Allow "iterfunc stock", "stock iterfunc", and other varieties.
  721. #define Iter_Func@stock%0(%2)%1$ stock F@y:%0(%2)
  722. #define Iter_Func@static%0(%2)%1$ static F@y:%0(%2)
  723. #define Iter_Func@foreign%0(%2)%1$ foreign F@y:%0(%2)
  724. #define Iter_Func@global%0(%2)%1$ global F@y:%0(%2)
  725. #define Iter_Func@public%0(%2)%1$ public F@y:%0(%2)
  726. #define Iter_Func@forward%0(%2)%1$ forward F@y:%0(%2)
  727. // A nice "match" symbol that we can scan for, then remove after it is used.
  728. #define F@a$
  729. #define F@b|||
  730. // Detect array declarations: "Iterator:X[20]<4>", "Iterator:X<10, 4>", and the
  731. // frankly silly "Iterator:X[20]<10, 4>".
  732. #define F@c:F@d:((%0,%1)+1)]%2$,Iter_Single@%9$%7$ F@d:((%0)+(%1))]={0,1,...}F@a$,Iter_Multi@%9$[%0]%7$
  733. #if defined NESTED_ELLIPSIS
  734. #define F@d:%0]%2$,Iter_%8@%9[%3$%7$ %0]={{0,1,...},...},Iter_%8@%9[%3$%7$
  735. #else
  736. #define F@d:%0]%2$,Iter_%8@%9[%3$%7$ %0],Iter_%8@%9[%3$%7$,F@g(Iter_Init@%9,)=F@s(Iter_%8@%9[%3$)
  737. #endif
  738. // Special "sizeof" that strips subscripts. "|||" prevents "sizeof" recursion.
  739. #define F@e:%0|||(%1[%2]%3|||%4)) F@e:%0|||(%1%3|||%4[]))
  740. #define F@f:%0|||(F@g(%1,%5)%3|||) %0|||(%1 %3|||)
  741. #define F@s(%0) (_:F@f:F@e:sizeof F@b|||(%0 F@a$F@b|||))
  742. // Reify macros.
  743. #define F@r(%0) %0 F@a$
  744. #define F@g(%0,%8) %0 F@a$
  745. #define F@h:%0) %0 F@a$)
  746. // y_iterate parser. Takes an array input, and splits up all the components.
  747. #define _ITER<%5>(%1) (_:F@i:F@j:$Iter_%5_Internal(%1))
  748. // Separate "<>"s. Parameters to the resulting macro/function:
  749. //
  750. // %0 - Count.
  751. // %1 - Multi iterator position.
  752. // %2 - Array.
  753. // ... - All other parameters.
  754. //
  755. #define F@j:%7$%5(%0) %5A(F@g(Iter_Single@%0,),F@h:Iterator@%0)
  756. #define F@i:%7$%5(%0<%2>%1) %5B(F@h:Iter_Multi@%0,%2,F@h:Iterator@%0%1)
  757. #define _Y_ITER_DO_FOREACH(%1,%0) (_:F@n:F@l:F@m:F@a$%1,%0$
  758. // Multi-iterator.
  759. #define F@n:%9$%1,%0<%2>$ F@s(Iterator@%0)-1-(%2));_:(%1=F@h:Iterator@%0[%1])<(F@s(Iterator@%0)-F@s(Iter_Multi@%0));
  760. // Special iterator.
  761. #define F@l:%9$%1,%0(%2)%8$ F@r(iterstart@%0));_:(F@r(iterstart@%0))!=_:(%1=F@h:Iter_Func@%0(_:%1,%2));
  762. // Normal iterator.
  763. #define F@m:%9$%1,%0$ F@s(Iterator@%0)-1);_:(%1=F@h:Iterator@%0[%1])!=(F@s(Iterator@%0)-1);
  764. // Convert from a normal iterator to a special iterator with parameters.
  765. #define F@o)-2)+%8$%1,%0[%2]()$ F@o)-2)+%8$%1,%0(%2)$
  766. // Reverse multi-iterator.
  767. #define F@p:%9$%1,%0<%2>$ F@s(Iterator@%0)-1-(%2));_:(%1=Iter_Prev_InternalB(Iter_Multi@%0,,Iterator@%0,%1))<(F@s(Iterator@%0)-F@s(Iter_Multi@%0));
  768. // Reverse normal iterator.
  769. #define F@q:%9$%1,%0$ F@s(Iterator@%0)-1);_:(%1=Iter_Prev_InternalA(,Iterator@%0,%1))!=(F@s(Iterator@%0)-1);
  770. // Special iterator function declaration.
  771. #define F@y:%0(%1) Iter_Func@%0(%1)F@a$
  772. // Local state for iterator functions that need more than one variable.
  773. #define iterstate(%5,%6)%9);%9!=_:(%1=%2( %5),itrst:Iter_State@%1=itrst:(%6);_:(%5)!=_:(%1=%2(_:Iter_State@%1,
  774. // Make the internal state an array if there is more than one value.
  775. #define itrst:%1=itrst:(%6,%7) %1[]={%6,%7}
  776. // Consume spaces in the iterator state variables.
  777. #define Iter_State@%0\32;%1) Iter_State@%0%1)
  778. /**--------------------------------------------------------------------------**\
  779. The workings of these macros are very extensively documented at:
  780. http://forum.sa-mp.com/showpost.php?p=2823668
  781. \**--------------------------------------------------------------------------**/
  782. // This allows us to use "new" multiple times - stripping off ONLY whole words.
  783. #define new%0|||%3|||%1:%2||| %3|||%0|||%1|||%2|||
  784. // This one is called if the new syntax is required, but the state of "new" is
  785. // as-yet unknown. This attempts to call "%1" as a macro, if it starts with
  786. // "new" as a whole word then it will (and will also helpfully strip off the
  787. // "new" keyword for us).
  788. #define Y_FOREACH_THIRD|||%9|||%1|||%2||| %1=Y_FOREACH_FIFTH|||Y_FOREACH_FOURTH|||%1:%2|||
  789. // This is called if the "new" macro is called for a second time.
  790. #define Y_FOREACH_FOURTH|||%1=Y_FOREACH_FIFTH|||%9|||%2||| new Y_FOREACH_SIXTH;%1|||Y_FOREACH_SEVENTH|||%2|||
  791. // This is called when there are tags on the "new" declaration (%9 = "new ").
  792. #define Y_FOREACH_SEVENTH|||%9Y_FOREACH_SIXTH;%0|||%1|||%2||| new %0:%1=%0:_Y_ITER_DO_FOREACH(%1,%2)
  793. // This is called when there aren't.
  794. #define Y_FOREACH_SIXTH;%1|||Y_FOREACH_SEVENTH|||%2||| %1=_Y_ITER_DO_FOREACH(%1,%2)
  795. // This is called if "%1" didn't have "new" at the start.
  796. #define Y_FOREACH_FIFTH|||Y_FOREACH_FOURTH|||%1:%2||| _Y_ITER_DO_FOREACH(%1,%2)
  797. // This is the old version, but DON'T add "new" because that already exists from
  798. // the failed "new" macro call above.
  799. #define Y_FOREACH_SECOND|||Y_FOREACH_THIRD|||%2,%1||| using_deprecated_foreach_syntax,%1=_Y_ITER_DO_FOREACH(%1,%2)++using_deprecated_foreach_syntax
  800. stock const
  801. // This variable is re-declared when you do "foreach (Player, i)" or similar
  802. // so that a warning is generated. The warning will read:
  803. //
  804. // local variable "using_deprecated_foreach_syntax" shadows a variable at a preceding level
  805. //
  806. // This is the best I could do to warn about the old syntax. That code
  807. // should now be "foreach (new i : Player)". It may become an error later.
  808. bool:using_deprecated_foreach_syntax = false,
  809. F@o[2];
  810. /*
  811. db 88888888ba 88 ,ad8888ba, 88
  812. d88b 88 "8b 88 d8"' `"8b 88
  813. d8'`8b 88 ,8P 88 d8' 88
  814. d8' `8b 88aaaaaa8P' 88 88 ,adPPYba, ,adPPYb,88 ,adPPYba,
  815. d8YaaaaY8b 88""""""' 88 88 a8" "8a a8" `Y88 a8P_____88
  816. d8""""""""8b 88 88 Y8, 8b d8 8b 88 8PP"""""""
  817. d8' `8b 88 88 Y8a. .a8P "8a, ,a8" "8a, ,d88 "8b, ,aa
  818. d8' `8b 88 88 `"Y8888Y"' `"YbbdP"' `"8bbdP"Y8 `"Ybbd8"'
  819. */
  820. /**--------------------------------------------------------------------------**\
  821. <summary>Iter_RandomInternal</summary>
  822. <param name="count">Number of items in the iterator.</param>
  823. <param name="array[]">iterator data.</param>
  824. <param name="start">Size of the iterator.</param>
  825. <returns>
  826. -
  827. </returns>
  828. <remarks>
  829. Returns a random value from an iterator.
  830. </remarks>
  831. \**--------------------------------------------------------------------------**/
  832. stock Iter_Random_Internal(count, array[], start)
  833. {
  834. if (count)
  835. {
  836. count = random(count);
  837. do
  838. {
  839. start = array[start];
  840. }
  841. while (count--);
  842. return start;
  843. }
  844. return cellmin;
  845. }
  846. /**--------------------------------------------------------------------------**\
  847. <summary>Iter_RandomAdd_InternalC</summary>
  848. <param name="count">Number of items in the iterator.</param>
  849. <param name="array[]">iterator data.</param>
  850. <param name="start">Size of the iterator.</param>
  851. <param name="slots">Number of multi-iterator values.</param>
  852. <returns>
  853. -
  854. </returns>
  855. <remarks>
  856. Returns a random unused value from an iterator.
  857. </remarks>
  858. \**--------------------------------------------------------------------------**/
  859. //stock Iter_RandomAdd_InternalC(&count, array[], start)
  860. //{
  861. // return Iter_Add_InternalC(count, array, start, Iter_RandomFree_InternalC(count, array, start));
  862. //}
  863. //
  864. //stock Iter_RandomAdd_InternalD(counts[], array[], size, slots, start, slot)
  865. //{
  866. // // This is subtly different to the "C" version - it operates on multi
  867. // // iterators, which have many counts, and thus we need to sum those first.
  868. // return Iter_Add_InternalD(counts[slot], array, start, size, Iter_RandomFree_InternalD(counts, array, size, slots));
  869. //}
  870. /**--------------------------------------------------------------------------**\
  871. <summary>Iter_RandomRemove_InternalC</summary>
  872. <param name="count">Number of items in the iterator.</param>
  873. <param name="array[]">iterator data.</param>
  874. <param name="start">Size of the iterator.</param>
  875. <param name="slots">Number of multi-iterator values.</param>
  876. <returns>
  877. -
  878. </returns>
  879. <remarks>
  880. Returns a random unused value from an iterator.
  881. </remarks>
  882. \**--------------------------------------------------------------------------**/
  883. //stock Iter_RandomRemove_InternalC(&count, array[], start)
  884. //{
  885. // return Iter_Remove_InternalC(count, array, start, Iter_RandomFree_InternalC(count, array, start));
  886. //}
  887. //
  888. //stock Iter_RandomRemove_InternalD(counts[], array[], size, slots, start, slot)
  889. //{
  890. // // This is subtly different to the "C" version - it operates on multi
  891. // // iterators, which have many counts, and thus we need to sum those first.
  892. // return Iter_Remove_InternalD(counts[slot], array, start, size, Iter_RandomFree_InternalD(counts, array, size, slots));
  893. //}
  894. /**--------------------------------------------------------------------------**\
  895. <summary>Iter_RandomFree_InternalC</summary>
  896. <param name="count">Number of items in the iterator.</param>
  897. <param name="array[]">iterator data.</param>
  898. <param name="start">Size of the iterator.</param>
  899. <param name="slots">Number of multi-iterator values.</param>
  900. <returns>
  901. -
  902. </returns>
  903. <remarks>
  904. Returns a random unused value from an iterator.
  905. </remarks>
  906. \**--------------------------------------------------------------------------**/
  907. stock Iter_RandomFree_InternalC(count, array[], start)
  908. {
  909. count = start - count;
  910. if (count)
  911. {
  912. count = random(count);
  913. while (start--)
  914. {
  915. // Check if this value is not included in any iterator. If it isn't
  916. // then decrement the count until we have run out of values to test.
  917. if (array[start] <= start && !count--)
  918. return start;
  919. }
  920. }
  921. return cellmin;
  922. }
  923. stock Iter_RandomFree_InternalD(counts[], array[], start, slots)
  924. {
  925. // This is subtly different to the "C" version - it operates on multi
  926. // iterators, which have many counts, and thus we need to sum those first.
  927. new
  928. count = 0;
  929. while (slots--)
  930. count += counts[slots];
  931. return Iter_RandomFree_InternalC(count, array, start);
  932. }
  933. /**--------------------------------------------------------------------------**\
  934. <summary>Iter_Free_Internal</summary>
  935. <param name="array[]">iterator data.</param>
  936. <param name="size">Size of the iterator.</param>
  937. <returns>
  938. -
  939. </returns>
  940. <remarks>
  941. Finds the first free slot in the iterator.
  942. </remarks>
  943. \**--------------------------------------------------------------------------**/
  944. stock Iter_Free_Internal(array[], size)
  945. {
  946. for (new i = 0; i != size; ++i)
  947. {
  948. if (array[i] <= i)
  949. {
  950. return i;
  951. }
  952. }
  953. return cellmin;
  954. }
  955. /**--------------------------------------------------------------------------**\
  956. <summary>Iter_FreeMulti_Internal</summary>
  957. <param name="array[]">multi-iterator data.</param>
  958. <param name="trueSize">Size of the multi-iterator.</param>
  959. <param name="start">End [?, since start points are backwards] of the multi-iterator.</param>
  960. <returns>
  961. -
  962. </returns>
  963. <remarks>
  964. Finds the first free multi index in the multi-iterator.
  965. </remarks>
  966. \**--------------------------------------------------------------------------**/
  967. stock Iter_FreeMulti_Internal(array[], trueSize, start)
  968. {
  969. for (new i = 0; trueSize-- > start; ++i)
  970. {
  971. if (array[trueSize] >= start)
  972. return i;
  973. }
  974. return -1;
  975. }
  976. /**--------------------------------------------------------------------------**\
  977. <summary>Iter_AddInternal</summary>
  978. <param name="&start">Array start index.</param>
  979. <param name="&count">Number of items in the iterator.</param>
  980. <param name="array[]">iterator data.</param>
  981. <param name="value">Item to add.</param>
  982. <returns>
  983. -
  984. </returns>
  985. <remarks>
  986. Adds a value to a given iterator set. Now detects when you try and add the
  987. last item multiple times, as well as all the other items. Now simplified
  988. even further with the new internal representation. The modulo code is for
  989. iterator reversal.
  990. </remarks>
  991. \**--------------------------------------------------------------------------**/
  992. stock Iter_Add_InternalC(&count, array[], size, value)
  993. {
  994. if (0 <= value < size && array[value] <= value)
  995. {
  996. new
  997. last = size++,
  998. next = array[last];
  999. while (next < value)
  1000. {
  1001. last = next,
  1002. next = array[last];
  1003. }
  1004. return
  1005. ++count,
  1006. array[(value - 1) % size] = (last + 1) % size,
  1007. array[next - 1] = value + 1,
  1008. array[value] = next,
  1009. array[last] = value;
  1010. }
  1011. return cellmin;
  1012. }
  1013. stock Iter_Add_InternalD(&count, array[], start, size, value)
  1014. {
  1015. if (0 <= value < size && start >= size && array[value] <= value)
  1016. {
  1017. new
  1018. last = start,
  1019. next = array[last];
  1020. while (next < value)
  1021. {
  1022. last = next,
  1023. next = array[last];
  1024. }
  1025. return
  1026. ++count,
  1027. array[value] = next,
  1028. array[last] = value;
  1029. }
  1030. return cellmin;
  1031. }
  1032. /**--------------------------------------------------------------------------**\
  1033. <summary>Iter_IndexInternal</summary>
  1034. <param name="count">Number of items in the iterator.</param>
  1035. <param name="array[]">iterator data.</param>
  1036. <param name="start">Array start index.</param>
  1037. <param name="size">Array size.</param>
  1038. <param name="index">Index to find Nth value.</param>
  1039. <param name="wrap">Keep going around until a value is found?</param>
  1040. <returns>
  1041. -
  1042. </returns>
  1043. <remarks>
  1044. Allows you to find the Nth value in the iterator. DO NOT call this in a
  1045. loop to get all values - that totally defeats the purpose of "foreach", just
  1046. use a normal "foreach" loop with an index counter for that case.
  1047. </remarks>
  1048. \**--------------------------------------------------------------------------**/
  1049. stock Iter_Index_Internal(count, array[], start, size, index, bool:wrap = false)
  1050. {
  1051. // If there are no elements in the iterator, we can't ever return the Nth
  1052. // item. Also if the parameters are invalid.
  1053. if (index < 0 || start < size || array[start] >= size)
  1054. return cellmin;
  1055. // We could wrap around in the loop (it would work), but it is better to set
  1056. // the limit first.
  1057. if (wrap)
  1058. index %= count;
  1059. else if (index >= count)
  1060. return cellmin;
  1061. start = array[start];
  1062. while (index--)
  1063. start = array[start];
  1064. return start;
  1065. }
  1066. /**--------------------------------------------------------------------------**\
  1067. <summary>Iter_RemoveInternal</summary>
  1068. <param name="&count">Number of items in the iterator.</param>
  1069. <param name="array[]">iterator data.</param>
  1070. <param name="size">Number of iterator elements.</param>
  1071. <param name="value">Item to remove.</param>
  1072. <returns>
  1073. -
  1074. </returns>
  1075. <remarks>
  1076. Removes a value from an iterator.
  1077. </remarks>
  1078. \**--------------------------------------------------------------------------**/
  1079. stock Iter_Remove_InternalC(&count, array[], size, value)
  1080. {
  1081. new
  1082. last;
  1083. return Iter_SafeRemove_InternalC(count, array, size, value, last);
  1084. }
  1085. stock Iter_Remove_InternalD(&count, array[], start, size, value)
  1086. {
  1087. new
  1088. last;
  1089. return Iter_SafeRemove_InternalD(count, array, start, size, value, last);
  1090. }
  1091. /**--------------------------------------------------------------------------**\
  1092. <summary>Iter_SafeRemoveInternal</summary>
  1093. <param name="&count">Number of items in the iterator.</param>
  1094. <param name="array[]">Iterator data.</param>
  1095. <param name="size">Number of iterator elements.</param>
  1096. <param name="value">Item to remove.</param>
  1097. <param name="&last">Pointer in which to store the last pointer.</param>
  1098. <returns>
  1099. -
  1100. </returns>
  1101. <remarks>
  1102. Removes a value from an iterator safely.
  1103. </remarks>
  1104. \**--------------------------------------------------------------------------**/
  1105. stock Iter_SafeRemove_InternalC(&count, array[], size, value, &last)
  1106. {
  1107. if (0 <= value < size++ && array[value] > value)
  1108. {
  1109. // This version has reverse iterators, which need maintaining, and can
  1110. // be used in place of a loop to jump backwards in the list.
  1111. return
  1112. --count,
  1113. last = (array[(value - 1) % size] - 1) % size,
  1114. array[last] = array[value],
  1115. array[value] = value,
  1116. array[(array[last] - 1) % size] = (last + 1) % size;
  1117. }
  1118. return cellmin;
  1119. }
  1120. stock Iter_SafeRemove_InternalD(&count, array[], start, size, value, &last)
  1121. {
  1122. if (0 <= value < size && start >= size && count && array[value] > value)
  1123. {
  1124. // This version doesn't have reverse iterators, so we need to
  1125. // manually loop through the list.
  1126. last = start;
  1127. while ((start = array[last]) < size)
  1128. {
  1129. if (start == value)
  1130. {
  1131. return
  1132. --count,
  1133. array[last] = array[value],
  1134. array[value] = value;
  1135. }
  1136. last = start;
  1137. }
  1138. }
  1139. return cellmin;
  1140. }
  1141. /**--------------------------------------------------------------------------**\
  1142. <summary>Iter_ContainsInternal</summary>
  1143. <param name="array[]">iterator data.</param>
  1144. <param name="value">Item to check.</param>
  1145. <param name="size">Size of the iterator.</param>
  1146. <returns>
  1147. -
  1148. </returns>
  1149. <remarks>
  1150. Checks if this item is in the iterator.
  1151. </remarks>
  1152. \**--------------------------------------------------------------------------**/
  1153. stock Iter_Contains_InternalC(array[], size, value)
  1154. {
  1155. // Only need to know that this element is in ANY list, because there is only
  1156. // one list it can be in.
  1157. return 0 <= value < size && array[value] > value;
  1158. }
  1159. stock Iter_Contains_InternalD(count, array[], size, value, start)
  1160. {
  1161. // Check the count first, and that this element is in ANY list. There is no
  1162. // point searching an empty list for this element, hence the count check.
  1163. if (0 <= value < size && start >= size && count && array[value] > value)
  1164. {
  1165. // Then loop over that list to check if this element is in it.
  1166. size = start;
  1167. while ((size = array[size]) != start)
  1168. {
  1169. if (size == value)
  1170. {
  1171. return 1;
  1172. }
  1173. }
  1174. }
  1175. return 0;
  1176. }
  1177. /**--------------------------------------------------------------------------**\
  1178. <summary>Iter_GetMulti_Internal</summary>
  1179. <param name="array[]">multi-iterator data.</param>
  1180. <param name="trueSize">Size of the multi-iterator per index.</param>
  1181. <param name="size">Size of the multi-iterator.</param>
  1182. <param name="value">Item to check.</param>
  1183. <returns>
  1184. -1 on failure.
  1185. Index of the multi-iterator the value is contained.
  1186. </returns>
  1187. <remarks>
  1188. Checks if this item is in the multi-iterator at all, and if it is returns which index it is in.
  1189. </remarks>
  1190. \**--------------------------------------------------------------------------**/
  1191. stock Iter_GetMulti_Internal(array[], trueSize, size, value)
  1192. {
  1193. if (0 <= value < size && array[value] > value)
  1194. {
  1195. // Find the end of this list.
  1196. while ((value = array[value]) < size) {}
  1197. // Start points are actually backwards.
  1198. return trueSize - value - 1;
  1199. }
  1200. return -1;
  1201. }
  1202. /**--------------------------------------------------------------------------**\
  1203. <summary>Iter_Clear_Internal</summary>
  1204. <param name="array[]">iterator data.</param>
  1205. <param name="size">Size of base array.</param>
  1206. <param name="entries">Size of the count data.</param>
  1207. <param name="&count">Number of items in the iterator.</param>
  1208. <param name="elems">Number of iterator elements.</param>
  1209. <param name="lst">Last valid index in the iterator array.</param>
  1210. <param name="start">Optional single multi-iterator to clear.</param>
  1211. <returns>
  1212. -
  1213. </returns>
  1214. <remarks>
  1215. Resets an iterator.
  1216. </remarks>
  1217. \**--------------------------------------------------------------------------**/
  1218. stock Iter_Clear_InternalC(array[], size, entries, lst, ...)
  1219. {
  1220. // Clear an entire iterator.
  1221. while (size--)
  1222. {
  1223. array[size] = size;
  1224. }
  1225. array[lst] = 0;
  1226. while (entries--)
  1227. {
  1228. setarg(4, entries, 0);
  1229. }
  1230. }
  1231. stock Iter_Clear_InternalD(array[], size, entries, elems, counts[], start)
  1232. {
  1233. // Clear just one part of a multi-iterator.
  1234. if (0 <= start < entries)
  1235. {
  1236. counts[start] = 0,
  1237. start = size - 1 - start,
  1238. entries = array[start],
  1239. array[start] = start;
  1240. while (entries < elems)
  1241. {
  1242. start = array[entries],
  1243. array[entries] = 0,
  1244. entries = start;
  1245. }
  1246. }
  1247. }
  1248. /**--------------------------------------------------------------------------**\
  1249. <summary>Iter_InitInternal</summary>
  1250. <param name="array[][]">Iterator array to initialise.</param>
  1251. <param name="first[]">First iterator slot.</param>
  1252. <param name="s0">Size of first dimension.</param>
  1253. <param name="s1">Size of second dimension.</param>
  1254. <param name="entries">Number of start points.</param>
  1255. <returns>
  1256. -
  1257. </returns>
  1258. <remarks>
  1259. Multi-dimensional arrays can't be initialised at compile time, so need to be
  1260. done at run time, which is slightly annoying.
  1261. </remarks>
  1262. \**--------------------------------------------------------------------------**/
  1263. stock
  1264. Iter_Init_Internal(arr[][], first[], s0, s1, entries)
  1265. {
  1266. new
  1267. elems = s1 - entries,
  1268. i = s1;
  1269. entries *= elems;
  1270. while (i--)
  1271. {
  1272. first[i] = entries,
  1273. entries -= elems;
  1274. }
  1275. while (++i != s0)
  1276. {
  1277. memcpy(arr[i], first, 0, s1 * 4, s1);
  1278. }
  1279. }
  1280. /**--------------------------------------------------------------------------**\
  1281. <summary>Iter_PrevInternal</summary>
  1282. <param name="array[]">iterator data.</param>
  1283. <param name="elems">Number of elements in the iterator.</param>
  1284. <param name="size">Size of the iterator.</param>
  1285. <param name="slot">The current slot.</param>
  1286. <returns>
  1287. -
  1288. </returns>
  1289. <remarks>
  1290. Gets the element in an iterator that points to the current element.
  1291. </remarks>
  1292. \**--------------------------------------------------------------------------**/
  1293. stock
  1294. Iter_Prev_Internal(array[], elems, size, slot)
  1295. {
  1296. if ((slot < elems) ?
  1297. (0 <= slot < array[slot]) :
  1298. (slot < size && array[slot] < elems))
  1299. {
  1300. for (new last = slot; last--; )
  1301. {
  1302. if (array[last] == slot)
  1303. {
  1304. return last;
  1305. }
  1306. }
  1307. }
  1308. return elems;
  1309. }