Advertisement
Guest User

foreach.inc

a guest
Jul 10th, 2011
248
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 15.53 KB | None | 0 0
  1. /*----------------------------------------------------------------------------*-
  2.                     ===========================
  3.                      foreach efficient looping
  4.                     ===========================
  5. Description:
  6.     Provides functionality to loop efficiently through all connected players.
  7.     Removes reliance on both modification of MAX_PLAYERS for more efficient
  8.     processing on small servers (although still recommended) and
  9.     IsPlayerConnected.
  10. Legal:
  11.     Copyright (C) 2007 Alex "Y_Less" Cole
  12.  
  13.     This program is free software; you can redistribute it and/or
  14.     modify it under the terms of the GNU General Public License
  15.     as published by the Free Software Foundation; either version 2
  16.     of the License, or (at your option) any later version.
  17.  
  18.     This program is distributed in the hope that it will be useful,
  19.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.     GNU General Public License for more details.
  22.  
  23.     You should have received a copy of the GNU General Public License
  24.     along with this program; if not, write to the Free Software
  25.     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  26.     MA 02110-1301, USA.
  27. Version:
  28.     0.1.5
  29. Changelog:
  30.     02/09/09:
  31.         Fixed (again) for 0.3.
  32.         Added free slot finding.
  33.     21/08/09:
  34.         Updated to include random functions.
  35.         Made entirely stand alone.
  36.         Ported to 0.3 (separate version).
  37.         Added automatic callback hook code.
  38.         Removed debug information from stand alone version.
  39.     06/01/08:
  40.         Added debug information.
  41.     09/10/07:
  42.         Moved to system.
  43.     16/09/07:
  44.         Added list sorting.
  45.         Made this part of Y SeRver Includes, not Y Sever Includes.
  46.         Made list sorting optional.
  47.         Fixed version number.
  48.     08/09/07:
  49.         First version.
  50. Functions:
  51.     Public:
  52.         OnPlayerDisconnect - Called when a player leaves to remove them.
  53.         OnPlayerConnect - Called when a player connects to add them.
  54.     Core:
  55.         -
  56.     Stock:
  57.         Itter_ShowArray - Displays the contents of the array.
  58.         Itter_AddInternal - Add a value to an itterator.
  59.         Itter_RemoveInternal - Remove a value from an itterator.
  60.         Itter_RandomInternal - Get a random item from an itterator.
  61.         Itter_FreeInternal - Gets the first free slot in the itterator.
  62.     Static:
  63.         -
  64.     Inline:
  65.         Itter_Create - Create a new itterator value set.
  66.         Itter_Add - Wraps Itter_AddInternal.
  67.         Itter_Remove - Wraps Itter_RemoveInternal.
  68.         Itter_Random - Wraps Itter_RandomInternal.
  69.         Itter_Count - Gets the number of items in an itterator.
  70.         Itter_Debug - Wraps around Itter_ShowArray so you can use an itterator.
  71.         Itter_Free - Wraps around Itter_FreeInternal.
  72.     API:
  73.         -
  74. Callbacks:
  75.     -
  76. Hooks:
  77.     Itter_OnPlayerConnect - Hook for the OnPlayerConnect callback.
  78.     Itter_OnPlayerDisconnect - Hook for the OnPlayerDisconnect callback.
  79.     Itter_OnGameModeInit - Only exists to make the code compile correctly...
  80. Definitions:
  81.     -
  82. Enums:
  83.     -
  84. Macros:
  85.     foreach - Command to loop through all connected players efficiently.
  86.     foreachex - Like foreach but without a new variable.
  87. Tags:
  88.     -
  89. Variables:
  90.     Global:
  91.         -
  92.     Static:
  93.         YSI_g_OPC - Records wether Itter_OnPlayerConnect exists for speed.
  94. Commands:
  95.     -
  96. Compile options:
  97.     YSI_ITTER_NO_SORT - Removed.
  98. Operators:
  99.     -
  100. Iterators:
  101.     Player - List of all players connected.
  102.     Bot - List of all bots (npcs) connected.
  103.     NPC - Alias of Bot.
  104.     Character - All players and bots.
  105. -*----------------------------------------------------------------------------*/
  106.  
  107. #if defined _foreach_included
  108.     #endinput
  109. #endif
  110. #define _foreach_included
  111.  
  112. #if !defined _samp_included
  113.     #error "Please include a_samp or a_npc before foreach"
  114. #endif
  115.  
  116. #if defined SendChat
  117.     #define BOTSYNC_IS_BOT     (true)
  118. #endif
  119.  
  120. #if defined IsPlayerNPC
  121.     #define _FOREACH_BOT
  122. #endif
  123.  
  124. #if !defined BOTSYNC_IS_BOT
  125.     static
  126.         bool:YSI_g_OPC = false;
  127. #endif
  128.  
  129. #if defined YSI_ITTER_NO_SORT
  130.     #error "YSI_ITTER_NO_SORT is no longer supported by foreach"
  131. #endif
  132.  
  133. /*----------------------------------------------------------------------------*-
  134. Function:
  135.     Itter_Create
  136. Params:
  137.     name - Itterator identifier.
  138.     size - Number of values.
  139. Return:
  140.     -
  141. Notes:
  142.     Creates a new itterator start/array pair.
  143. -*----------------------------------------------------------------------------*/
  144.  
  145. #define Iter_Create Itter_Create
  146. #define Itter_Create(%1,%2) \
  147.     new \
  148.         YSI_g%1S = -1, \
  149.         YSI_g%1C = 0, \
  150.         YSI_g%1A[%2] = {-1, ...}
  151.  
  152. /*----------------------------------------------------------------------------*-
  153. Function:
  154.     Itter_Add
  155. Params:
  156.     itter - Name of the itterator to add the data to.
  157.     value - Value to add to the itterator.
  158. Return:
  159.     -
  160. Notes:
  161.     Wrapper for Itter_AddInternal.
  162. -*----------------------------------------------------------------------------*/
  163.  
  164. #define Iter_Add Itter_Add
  165. #define Itter_Add(%1,%2) \
  166.     Itter_AddInternal(YSI_g%1S, YSI_g%1C, YSI_g%1A, %2)
  167.  
  168. /*----------------------------------------------------------------------------*-
  169. Function:
  170.     Itter_Free
  171. Params:
  172.     itter - Name of the itterator to get the first free slot in.
  173. Return:
  174.     -
  175. Notes:
  176.     Wrapper for Itter_FreeInternal.
  177. -*----------------------------------------------------------------------------*/
  178.  
  179. #define Iter_Free Itter_Free
  180. #define Itter_Free(%1) \
  181.     Itter_FreeInternal(YSI_g%1S, YSI_g%1C, YSI_g%1A, sizeof (YSI_g%1A))
  182.  
  183. /*----------------------------------------------------------------------------*-
  184. Function:
  185.     Itter_Remove
  186. Params:
  187.     itter - Name of the itterator to remove data from.
  188.     value - Data to remove.
  189. Return:
  190.     -
  191. Notes:
  192.     Wrapper for Itter_RemoveInternal.
  193. -*----------------------------------------------------------------------------*/
  194.  
  195. #define Iter_Remove Itter_Remove
  196. #define Itter_Remove(%1,%2) \
  197.     Itter_RemoveInternal(YSI_g%1S, YSI_g%1C, YSI_g%1A, %2)
  198.  
  199. /*----------------------------------------------------------------------------*-
  200. Function:
  201.     Itter_Random
  202. Params:
  203.     itter - Name of the itterator to get a random slot from.
  204. Return:
  205.     -
  206. Notes:
  207.     Wrapper for Itter_RandomInternal.
  208. -*----------------------------------------------------------------------------*/
  209.  
  210. #define Iter_Random Itter_Random
  211. #define Itter_Random(%1) \
  212.     Itter_RandomInternal(YSI_g%1S, YSI_g%1C, YSI_g%1A)
  213.  
  214. /*----------------------------------------------------------------------------*-
  215. Function:
  216.     Itter_Debug
  217. Params:
  218.     itter - Name of the itterator to output debug information from.
  219. Return:
  220.     -
  221. Notes:
  222.     Wrapper for Itter_ShowArray.
  223. -*----------------------------------------------------------------------------*/
  224.  
  225. #define Iter_Debug Itter_Debug
  226. #define Itter_Debug(%1) \
  227.     Itter_ShowArray(YSI_g%1S, YSI_g%1A, YSI_g%1C)
  228.  
  229. /*----------------------------------------------------------------------------*-
  230. Function:
  231.     Itter_Count
  232. Params:
  233.     itter - Name of the itterator to get a random slot from4.
  234. Return:
  235.     -
  236. Notes:
  237.     Returns the number of items in this itterator.
  238. -*----------------------------------------------------------------------------*/
  239.  
  240. #define Iter_Count Itter_Count
  241. #define Itter_Count(%1) \
  242.     YSI_g%1C
  243.  
  244. /*----------------------------------------------------------------------------*-
  245. Create the internal itterators.
  246. -*----------------------------------------------------------------------------*/
  247.  
  248. #if !defined BOTSYNC_IS_BOT
  249.     Itter_Create(Player, MAX_PLAYERS);
  250.    
  251.     #if defined _FOREACH_BOT
  252.         Itter_Create(Bot, MAX_PLAYERS);
  253.         Itter_Create(Character, MAX_PLAYERS);
  254.        
  255.         #define YSI_gNPCS YSI_gBotS
  256.         #define YSI_gNPCC YSI_gBotC
  257.         #define YSI_gNPCA YSI_gBotA
  258.     #endif
  259. #endif
  260.  
  261. /*----------------------------------------------------------------------------*-
  262. Function:
  263.     foreach
  264. Params:
  265.     data - Data to itterate through.
  266.     as - Variable to set value to.
  267. Return:
  268.     -
  269. Notes:
  270.     Not exactly the same as PHP foreach, just itterates through a list and
  271.     returns the value of the current slot but uses that slot as the next index
  272.     too.  Variables must be in the form YSI_g<name>S for the start index and
  273.     YSI_g<name>A for the data array where <name> is what's entered in data.
  274. -*----------------------------------------------------------------------------*/
  275.  
  276. #define foreach(%1,%2) \
  277.     for (new %2 = YSI_g%1S; %2 != -1; %2 = YSI_g%1A[%2])
  278.  
  279. /*----------------------------------------------------------------------------*-
  280. Function:
  281.     foreachex
  282. Params:
  283.     data - Data to itterate through.
  284.     as - Variable to set value to.
  285. Return:
  286.     -
  287. Notes:
  288.     Similar to foreach but doesn't declare a new variable for the itterator.
  289. -*----------------------------------------------------------------------------*/
  290.  
  291. #define foreachex(%1,%2) \
  292.     for (%2 = YSI_g%1S; %2 != -1; %2 = YSI_g%1A[%2])
  293.  
  294. /*----------------------------------------------------------------------------*-
  295. Function:
  296.     Itter_OnPlayerConnect
  297. Params:
  298.     playerid - Player who joined.
  299. Return:
  300.     -
  301. Notes:
  302.     Adds a player to the loop data.  Now sorts the list too.  Note that I found
  303.     the most bizzare bug ever (I *think* it may be a compiler but, but it
  304.     requires further investigation), basically it seems that multiple variables
  305.     were being treated as the same variable (namely YSI_gBotS and
  306.     YSI_gCharacterS were the same and YSI_gBotC and YSI_gCharacterC were the
  307.     same).  Adding print statements which reference these variables seem to fix
  308.     the problem, and I've tried to make sure that the values will never actually
  309.     get printed.
  310. -*----------------------------------------------------------------------------*/
  311.  
  312. #if !defined BOTSYNC_IS_BOT
  313.     public OnPlayerConnect(playerid)
  314.     {
  315.         #if defined _FOREACH_BOT
  316.             if (IsPlayerNPC(playerid))
  317.             {
  318.                 Itter_Add(Bot, playerid);
  319.             }
  320.             else
  321.             {
  322.                 Itter_Add(Player, playerid);
  323.             }
  324.             Itter_Add(Character, playerid);
  325.         #else
  326.             Itter_Add(Player, playerid);
  327.         #endif
  328.         if (YSI_g_OPC)
  329.         {
  330.             CallLocalFunction("Itter_OnPlayerConnect", "i", playerid);
  331.         }
  332.         return 1;
  333.     }
  334.  
  335.     #define OnPlayerConnect Itter_OnPlayerConnect
  336.  
  337.     forward Itter_OnPlayerConnect(playerid);
  338. #endif
  339.  
  340. /*----------------------------------------------------------------------------*-
  341. Function:
  342.     Itter_OnGameModeInit
  343. Params:
  344.     -
  345. Return:
  346.     -
  347. Notes:
  348.     There are WIERD bugs in this script, seemingly caused by the compiler, so
  349.     this hopefully fixes them.
  350. -*----------------------------------------------------------------------------*/
  351.  
  352. #if !defined BOTSYNC_IS_BOT
  353.     public OnGameModeInit()
  354.     {
  355.         if (YSI_gPlayerC)
  356.         {
  357.             print("foreach error: Something went wrong again!  Please tell Y_less");
  358.             #if defined _FOREACH_BOT
  359.                 printf("%d", YSI_gBotS);
  360.                 printf("%d", YSI_gBotC);
  361.                 printf("%d", YSI_gCharacterS);
  362.                 printf("%d", YSI_gCharacterC);
  363.             #endif
  364.             printf("%d", YSI_gPlayerS);
  365.             printf("%d", YSI_gPlayerC);
  366.         }
  367.         YSI_g_OPC = (funcidx("Itter_OnPlayerConnect") != -1);
  368.         CallLocalFunction("Itter_OnGameModeInit", "");
  369.     }
  370.  
  371.     #define OnGameModeInit Itter_OnGameModeInit
  372.  
  373.     forward Itter_OnGameModeInit();
  374. #endif
  375.  
  376. /*----------------------------------------------------------------------------*-
  377. Function:
  378.     Itter_OnPlayerDisconnect
  379. Params:
  380.     playerid - Player who left.
  381. Return:
  382.     -
  383. Notes:
  384.     Removes a player from the loop data.
  385. -*----------------------------------------------------------------------------*/
  386.  
  387. #if !defined BOTSYNC_IS_BOT
  388.     public OnPlayerDisconnect(playerid, reason)
  389.     {
  390.         #if defined _FOREACH_BOT
  391.             if (IsPlayerNPC(playerid))
  392.             {
  393.                 Itter_Remove(Bot, playerid);
  394.             }
  395.             else
  396.             {
  397.                 Itter_Remove(Player, playerid);
  398.             }
  399.             Itter_Remove(Character, playerid);
  400.         #else
  401.             Itter_Remove(Player, playerid);
  402.         #endif
  403.         CallLocalFunction("Itter_OnPlayerDisconnect", "ii", playerid, reason);
  404.         return 1;
  405.     }
  406.  
  407.     #define OnPlayerDisconnect Itter_OnPlayerDisconnect
  408.  
  409.     forward Itter_OnPlayerDisconnect(playerid, reason);
  410. #endif
  411.  
  412. /*----------------------------------------------------------------------------*-
  413. Function:
  414.     Itter_ShowArray
  415. Params:
  416.     start - Itterator start point.
  417.     members[] - Itterator contents.
  418.     size - Number of itterator values
  419. Return:
  420.     -
  421. Notes:
  422.     Pure debug function.  Has regular prints not debug prints
  423.     as it's only called when debug is on.
  424. -*----------------------------------------------------------------------------*/
  425.  
  426. stock Itter_ShowArray(start, members[], size)
  427. {
  428.     static
  429.         sString[61];
  430.     new
  431.         i,
  432.         j = 10;
  433.     printf("Start: %d", start);
  434.     printf("Size:  %d", size);
  435.     while (i < size)
  436.     {
  437.         sString[0] = '\0';
  438.         while (i < j && i < size)
  439.         {
  440.             format(sString, sizeof (sString), "%s, %d", sString, members[i]);
  441.             i++;
  442.         }
  443.         printf("Array (%d): %s", j, sString);
  444.         j += 10;
  445.     }
  446. }
  447.  
  448. /*----------------------------------------------------------------------------*-
  449. Function:
  450.     Itter_RandomInternal
  451. Params:
  452.     start - Array start index.
  453.     count - Number of items in the itterator.
  454.     array[] - Itterator data.
  455. Return:
  456.     -
  457. Notes:
  458.     Returns a random value from an iterator.
  459. -*----------------------------------------------------------------------------*/
  460.  
  461. stock Itter_RandomInternal(start, count, array[])
  462. {
  463.     if (count == 0)
  464.     {
  465.         return -1;
  466.     }
  467.     new
  468.         rnd = random(count),
  469.         cur = start;
  470.     while (cur != -1)
  471.     {
  472.         if (rnd--)
  473.         {
  474.             cur = array[cur];
  475.         }
  476.         else
  477.         {
  478.             return cur;
  479.         }
  480.     }
  481.     return -1;
  482. }
  483.  
  484. /*----------------------------------------------------------------------------*-
  485. Function:
  486.     Itter_FreeInternal
  487. Params:
  488.     start - Array start index.
  489.     count - Number of items in the itterator.
  490.     array[] - Itterator data.
  491.     size - Size of the itterator.
  492. Return:
  493.     -
  494. Notes:
  495.     Finds the first free slot in the itterator.  Itterators now HAVE to be
  496.     sorted for this function to work correctly as it uses that fact to decide
  497.     wether a slot is unused or the last one.  If you want to use the slot
  498.     straight after finding it the itterator will need to re-find it to add in
  499.     the data.
  500. -*----------------------------------------------------------------------------*/
  501.  
  502. stock Itter_FreeInternal(start, count, array[], size)
  503. {
  504.     if (count == size)
  505.     {
  506.         return -1;
  507.     }
  508.     else if (count == 0)
  509.     {
  510.         return 0;
  511.     }
  512.     new
  513.         first = 0;
  514.     while (first != -1)
  515.     {
  516.         if (first == start)
  517.         {
  518.             start = array[start];
  519.         }
  520.         else if (array[first] == -1)
  521.         {
  522.             return first;
  523.         }
  524.         ++first;
  525.     }
  526.     return -1;
  527. }
  528.  
  529. /*----------------------------------------------------------------------------*-
  530. Function:
  531.     Itter_AddInternal
  532. Params:
  533.     &start - Array start index.
  534.     &count - Number of items in the itterator.
  535.     array[] - Itterator data.
  536.     value - Item to add.
  537. Return:
  538.     -
  539. Notes:
  540.     Adds a value to a given itterator set.
  541. -*----------------------------------------------------------------------------*/
  542.  
  543. stock Itter_AddInternal(&start, &count, array[], value)
  544. {
  545.     if (array[value] != -1)
  546.     {
  547.         return 0;
  548.     }
  549.     ++count;
  550.     if (start == -1)
  551.     {
  552.         start = value;
  553.     }
  554.     else if (start > value)
  555.     {
  556.         array[value] = start;
  557.         start = value;
  558.     }
  559.     else
  560.     {
  561.         new
  562.             cur = start,
  563.             last;
  564.         do
  565.         {
  566.             last = cur;
  567.             cur = array[cur];
  568.             if (cur > value)
  569.             {
  570.                 array[value] = cur;
  571.                 array[last] = value;
  572.                 return 1;
  573.             }
  574.         }
  575.         while (cur != -1);
  576.         array[last] = value;
  577.     }
  578.     return 1;
  579. }
  580.  
  581. /*----------------------------------------------------------------------------*-
  582. Function:
  583.     Itter_RemoveInternal
  584. Params:
  585.     &start - Array start index.
  586.     &count - Number of items in the itterator.
  587.     array[] - Itterator data.
  588.     value - Item to remove.
  589. Return:
  590.     -
  591. Notes:
  592.     Removes a value from an itterator.
  593. -*----------------------------------------------------------------------------*/
  594.  
  595. stock Itter_RemoveInternal(&start, &count, array[], value)
  596. {
  597.     if (start == -1)
  598.     {
  599.         return 0;
  600.     }
  601.     if (start == value)
  602.     {
  603.         start = array[value];
  604.     }
  605.     else
  606.     {
  607.         new
  608.             cur = start;
  609.         while (array[cur] != value)
  610.         {
  611.             cur = array[cur];
  612.             if (cur == -1)
  613.             {
  614.                 return 0;
  615.             }
  616.         }
  617.         array[cur] = array[value];
  618.     }
  619.     array[value] = -1;
  620.     --count;
  621.     return 1;
  622. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement