DEADSOFTWARE

replaced manual pool walking with nice iterator (yet one should still call `.release...
authorKetmar Dark <ketmar@ketmar.no-ip.org>
Sat, 20 Jan 2018 23:10:48 +0000 (01:10 +0200)
committerKetmar Dark <ketmar@ketmar.no-ip.org>
Sat, 20 Jan 2018 23:14:00 +0000 (01:14 +0200)
src/game/g_grid.pas
src/game/g_holmes.pas
src/game/g_map.pas
src/game/g_monsters.pas
src/game/g_weapons.pas
src/shared/mempool.pas

index 99eb0ef6328eded53312d6727422e333b4baceb1..ce31c63546d60a9721f1211e1cdeab54ad4fa950 100644 (file)
@@ -49,6 +49,9 @@ type
     x, y: Integer;
   end;
 
+  CellCoordIter = specialize PoolIter<TGridCellCoord>;
+
+
 type
   TBodyProxyId = Integer;
 
@@ -57,6 +60,8 @@ type
     type PITP = ^ITP;
     type TCellQueryCB = procedure (x, y: Integer) is nested; // top-left cell corner coords
 
+    type Iter = specialize PoolIter<ITP>;
+
     const TagDisabled = $40000000;
     const TagFullMask = $3fffffff;
 
@@ -194,11 +199,11 @@ type
 
     // return number of ITP thingys put into frame pool
     // if `firstHit` is `true`, return on first hit (obviously)
-    function forEachInAABB (x, y, w, h: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Integer;
+    function forEachInAABB (x, y, w, h: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Iter;
 
     // return number of ITP thingys put into frame pool
     // if `firstHit` is `true`, return on first hit (obviously)
-    function forEachAtPoint (x, y: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Integer;
+    function forEachAtPoint (x, y: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Iter;
 
     function atCellInPoint (x, y: Integer): TAtPointEnumerator;
 
@@ -214,7 +219,7 @@ type
 
     // trace line along the grid, put all objects from passed cells into frame pool, in no particular order
     // return number of ITP thingys put into frame pool
-    function forEachAlongLine (ax0, ay0, ax1, ay1: Integer; tagmask: Integer=-1; log: Boolean=false): Integer;
+    function forEachAlongLine (ax0, ay0, ax1, ay1: Integer; tagmask: Integer=-1; log: Boolean=false): Iter;
 
     // trace box with the given velocity; return object hit (if any)
     // `cb` is used unconvetionally here: if it returns `false`, tracer will ignore the object
@@ -222,8 +227,8 @@ type
     function traceBox (out ex, ey: Integer; const ax0, ay0, aw, ah: Integer; const dx, dy: Integer; tagmask: Integer=-1): ITP;
 
     // debug
-    function forEachBodyCell (body: TBodyProxyId): Integer; // this puts `TGridCellCoord` into frame pool for each cell
-    function forEachInCell (x, y: Integer): Integer; // this puts `ITP` into frame pool
+    function forEachBodyCell (body: TBodyProxyId): CellCoordIter; // this puts `TGridCellCoord` into frame pool for each cell
+    function forEachInCell (x, y: Integer): Iter; // this puts `ITP` into frame pool
     procedure dumpStats ();
 
   public
@@ -693,14 +698,14 @@ begin
 end;
 
 
-function TBodyGridBase.forEachBodyCell (body: TBodyProxyId): Integer;
+function TBodyGridBase.forEachBodyCell (body: TBodyProxyId): CellCoordIter;
 var
   g, f, ccidx: Integer;
   cc: PGridCell;
   presobj: PGridCellCoord;
 begin
-  result := 0;
-  if (body < 0) or (body > High(mProxies)) then exit;
+  result := CellCoordIter.Create(true);
+  if (body < 0) or (body > High(mProxies)) then begin result.finishIt(); exit; end;
   for g := 0 to High(mGrid) do
   begin
     ccidx := mGrid[g];
@@ -715,7 +720,6 @@ begin
           presobj := PGridCellCoord(framePool.alloc(sizeof(TGridCellCoord)));
           presobj^.x := (g mod mWidth)*mTileSize+mMinX;
           presobj^.y := (g div mWidth)*mTileSize+mMinY;
-          Inc(result);
           //cb((g mod mWidth)*mTileSize+mMinX, (g div mWidth)*mTileSize+mMinY);
         end;
       end;
@@ -723,19 +727,20 @@ begin
       ccidx := cc.next;
     end;
   end;
+  result.finishIt();
 end;
 
 
-function TBodyGridBase.forEachInCell (x, y: Integer): Integer;
+function TBodyGridBase.forEachInCell (x, y: Integer): Iter;
 var
   f, ccidx: Integer;
   cc: PGridCell;
   presobj: PITP;
 begin
-  result := 0;
+  result := Iter.Create(true);
   Dec(x, mMinX);
   Dec(y, mMinY);
-  if (x < 0) or (y < 0) or (x >= mWidth*mTileSize) or (y > mHeight*mTileSize) then exit;
+  if (x < 0) or (y < 0) or (x >= mWidth*mTileSize) or (y > mHeight*mTileSize) then begin result.finishIt(); exit; end;
   ccidx := mGrid[(y div mTileSize)*mWidth+(x div mTileSize)];
   while (ccidx <> -1) do
   begin
@@ -747,11 +752,11 @@ begin
       presobj := PITP(framePool.alloc(sizeof(ITP)));
       //presobj^ := mProxies[cc.bodies[f]].mObj;
       Move(mProxies[cc.bodies[f]].mObj, presobj^, sizeof(ITP));
-      Inc(result);
     end;
     // next cell
     ccidx := cc.next;
   end;
+  result.finishIt();
 end;
 
 
@@ -1331,7 +1336,7 @@ end;
 
 // ////////////////////////////////////////////////////////////////////////// //
 // no callback: return `true` on the first hit
-function TBodyGridBase.forEachAtPoint (x, y: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Integer;
+function TBodyGridBase.forEachAtPoint (x, y: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Iter;
 var
   f: Integer;
   idx, curci: Integer;
@@ -1341,9 +1346,9 @@ var
   ptag: Integer;
   presobj: PITP;
 begin
-  result := 0;
+  result := Iter.Create(true);
   tagmask := tagmask and TagFullMask;
-  if (tagmask = 0) then exit;
+  if (tagmask = 0) then begin result.finishIt(); exit; end;
 
   {$IF DEFINED(D2F_DEBUG_XXQ)}
   if (assigned(cb)) then e_WriteLog(Format('0: grid pointquery: (%d,%d)', [x, y]), MSG_NOTIFY);
@@ -1352,7 +1357,7 @@ begin
   // make coords (0,0)-based
   Dec(x, mMinX);
   Dec(y, mMinY);
-  if (x < 0) or (y < 0) or (x >= mWidth*mTileSize) or (y >= mHeight*mTileSize) then exit;
+  if (x < 0) or (y < 0) or (x >= mWidth*mTileSize) or (y >= mHeight*mTileSize) then begin result.finishIt(); exit; end;
 
   curci := mGrid[(y div mTileSize)*mWidth+(x div mTileSize)];
 
@@ -1400,19 +1405,19 @@ begin
       begin
         presobj := PITP(framePool.alloc(sizeof(ITP)));
         Move(px.mObj, presobj^, sizeof(ITP));
-        Inc(result);
-        if (firstHit) then exit;
+        if (firstHit) then begin result.finishIt(); exit; end;
       end;
     end;
     curci := cc.next;
   end;
+  result.finishIt();
 end;
 
 
 // ////////////////////////////////////////////////////////////////////////// //
 // no callback: return `true` on the first hit
 // return number of ITP thingys put into frame pool
-function TBodyGridBase.forEachInAABB (x, y, w, h: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Integer;
+function TBodyGridBase.forEachInAABB (x, y, w, h: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Iter;
 var
   idx: Integer;
   gx, gy: Integer;
@@ -1427,17 +1432,17 @@ var
   ptag: Integer;
   presobj: PITP;
 begin
-  result := 0;
-  if (w < 1) or (h < 1) then exit;
-
   if (w = 1) and (h = 1) then
   begin
     result := forEachAtPoint(x, y, tagmask, allowDisabled, firstHit);
     exit;
   end;
 
+  result := Iter.Create(true);
+  if (w < 1) or (h < 1) then begin result.finishIt(); exit; end;
+
   tagmask := tagmask and TagFullMask;
-  if (tagmask = 0) then exit;
+  if (tagmask = 0) then begin result.finishIt(); exit; end;
 
   x0 := x;
   y0 := y;
@@ -1449,8 +1454,8 @@ begin
   gw := mWidth;
   gh := mHeight;
 
-  if (x+w <= 0) or (y+h <= 0) then exit;
-  if (x >= gw*mTileSize) or (y >= gh*mTileSize) then exit;
+  if (x+w <= 0) or (y+h <= 0) then begin result.finishIt(); exit; end;
+  if (x >= gw*mTileSize) or (y >= gh*mTileSize) then begin result.finishIt(); exit; end;
 
   sx := x div mTileSize;
   sy := y div mTileSize;
@@ -1462,7 +1467,7 @@ begin
   if (sy < 0) then sy := 0 else if (sy >= gh) then sy := gh-1;
   if (ex < 0) then ex := 0 else if (ex >= gw) then ex := gw-1;
   if (ey < 0) then ey := 0 else if (ey >= gh) then ey := gh-1;
-  if (sx > ex) or (sy > ey) then exit; // just in case
+  if (sx > ex) or (sy > ey) then begin result.finishIt(); exit; end; // just in case
 
   // has something to do
 
@@ -1501,18 +1506,18 @@ begin
           if (x0+w <= px.mX) or (y0+h <= px.mY) then continue;
           presobj := PITP(framePool.alloc(sizeof(ITP)));
           Move(px.mObj, presobj^, sizeof(ITP));
-          Inc(result);
-          if (firstHit) then exit;
+          if (firstHit) then begin result.finishIt(); exit; end;
         end;
         curci := cc.next;
       end;
     end;
   end;
+  result.finishIt();
 end;
 
 
 // ////////////////////////////////////////////////////////////////////////// //
-function TBodyGridBase.forEachAlongLine (ax0, ay0, ax1, ay1: Integer; tagmask: Integer=-1; log: Boolean=false): Integer;
+function TBodyGridBase.forEachAlongLine (ax0, ay0, ax1, ay1: Integer; tagmask: Integer=-1; log: Boolean=false): Iter;
 var
   lw: TLineWalker;
   ccidx: Integer;
@@ -1528,9 +1533,9 @@ var
   presobj: PITP;
 begin
   log := false;
-  result := 0;
+  result := Iter.Create(true);
   tagmask := tagmask and TagFullMask;
-  if (tagmask = 0) then exit;
+  if (tagmask = 0) then begin result.finishIt(); exit; end;
 
   gw := mWidth;
   gh := mHeight;
@@ -1544,7 +1549,7 @@ begin
   y1 := ay1-miny;
 
   lw := TLineWalker.Create(0, 0, gw*mTileSize-1, gh*mTileSize-1);
-  if not lw.setup(x0, y0, x1, y1) then exit; // out of screen
+  if not lw.setup(x0, y0, x1, y1) then begin result.finishIt(); exit; end; // out of screen
 
   // increase query counter
   Inc(mLastQuery);
@@ -1574,7 +1579,6 @@ begin
           px.mQueryMark := lq; // mark as processed
           presobj := PITP(framePool.alloc(sizeof(ITP)));
           Move(px.mObj, presobj^, sizeof(ITP));
-          Inc(result);
         end;
       end;
       // next cell
@@ -1582,12 +1586,12 @@ begin
     end;
     // done processing cells, move to next tile
   until lw.stepToNextTile();
+  result.finishIt();
 end;
 
 
 // ////////////////////////////////////////////////////////////////////////// //
 // trace box with the given velocity; return object hit (if any)
-// `cb` is used unconvetionally here: if it returns `false`, tracer will ignore the object
 function TBodyGridBase.traceBox (out ex, ey: Integer; const ax0, ay0, aw, ah: Integer; const dx, dy: Integer; tagmask: Integer=-1): ITP;
 var
   gx, gy: Integer;
@@ -1701,7 +1705,7 @@ var
   {$IF DEFINED(D2F_DEBUG_OTR)}
   s: AnsiString = '';
   {$ENDIF}
-  pmark: PoolMark;
+  it: Iter;
 begin
   result := false;
   ex := ax1;
@@ -1711,9 +1715,9 @@ begin
   tagmask := tagmask and TagFullMask;
   if (tagmask = 0) then exit;
 
-  pmark := framePool.mark();
-  if (forEachAtPoint(ax0, ay0, tagmask, false, true) = 0) then exit;
-  framePool.release(pmark);
+  it := forEachAtPoint(ax0, ay0, tagmask, false, true);
+  if (it.length = 0) then begin it.release(); exit; end;
+  it.release();
 
   minx := mMinX;
   miny := mMinY;
@@ -1828,7 +1832,6 @@ begin
 end;
 
 
-// no callback: return `true` on the nearest hit
 // you are not supposed to understand this
 function TBodyGridBase.traceRay (out ex, ey: Integer; const ax0, ay0, ax1, ay1: Integer; tagmask: Integer=-1): ITP;
 var
index f4fe415cbf97a6f499b01b65e342e0ae1b12136e..d16aa603f57a480a8319ae940fde412e0763bb10 100644 (file)
@@ -974,21 +974,13 @@ procedure plrDebugDraw ();
 
   procedure hilightBodyCells (proxyId: Integer);
   var
-    pmark: PoolMark;
-    hitcount: Integer;
+    it: CellCoordIter;
     pcellxy: PGridCellCoord;
   begin
     //monsGrid.forEachBodyCell(mon.proxyId, hilightCell);
-    pmark := framePool.mark();
-    hitcount := monsGrid.forEachBodyCell(proxyId);
-    pcellxy := PGridCellCoord(framePool.getPtr(pmark));
-    while (hitcount > 0) do
-    begin
-      hilightCell(pcellxy^.x, pcellxy^.y);
-      Inc(pcellxy);
-      Dec(hitcount);
-    end;
-    framePool.release(pmark);
+    it := monsGrid.forEachBodyCell(proxyId);
+    for pcellxy in it do hilightCell(pcellxy^.x, pcellxy^.y);
+    it.release();
   end;
 
   procedure hilightCell1 (cx, cy: Integer);
@@ -1252,12 +1244,11 @@ procedure plrDebugDraw ();
 
 var
   mon: TMonster;
+  mit: PMonster;
+  it: TMonsterGrid.Iter;
   mx, my, mw, mh: Integer;
   //pan: TPanel;
   //ex, ey: Integer;
-  pmark: PoolMark;
-  hitcount: Integer;
-  pmon: PMonster;
 begin
   if (gPlayer1 = nil) then exit;
 
@@ -1282,16 +1273,9 @@ begin
     if (laserSet) then
     begin
       //g_Mons_AlongLine(laserX0, laserY0, laserX1, laserY1, monsCollector, true);
-      pmark := framePool.mark();
-      hitcount := monsGrid.forEachAlongLine(laserX0, laserY0, laserX1, laserY1, -1, true);
-      pmon := PMonster(framePool.getPtr(pmark));
-      while (hitcount > 0) do
-      begin
-        monsCollector(pmon^);
-        Inc(pmon);
-        Dec(hitcount);
-      end;
-      framePool.release(pmark);
+      it := monsGrid.forEachAlongLine(laserX0, laserY0, laserX1, laserY1, -1, true);
+      for mit in it do monsCollector(mit^);
+      it.release();
     end;
 
     if (monMarkedUID <> -1) then
@@ -1562,9 +1546,8 @@ procedure cbAtcurSelectMonster ();
 var
   plr: TPlayer;
   x, y, w, h: Integer;
-  pmark: PoolMark;
-  hitcount: Integer;
-  pmon: PMonster;
+  mit: PMonster;
+  it: TMonsterGrid.Iter;
 begin
   monMarkedUID := -1;
   if (Length(gPlayers) > 0) then
@@ -1580,16 +1563,9 @@ begin
     end;
   end;
   //e_WriteLog('===========================', MSG_NOTIFY);
-  pmark := framePool.mark();
-  hitcount := monsGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY);
-  pmon := PMonster(framePool.getPtr(pmark));
-  while (hitcount > 0) do
-  begin
-    monsAtDump(pmon^);
-    Inc(pmon);
-    Dec(hitcount);
-  end;
-  framePool.release(pmark);
+  it := monsGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY);
+  for mit in it do monsAtDump(mit^);
+  it.release();
   //e_WriteLog('---------------------------', MSG_NOTIFY);
 end;
 
@@ -1600,25 +1576,17 @@ procedure cbAtcurDumpMonsters ();
     e_WriteLog(Format('monster #%d (UID:%u) (proxyid:%d)', [mon.arrIdx, mon.UID, mon.proxyId]), TMsgType.Notify);
   end;
 var
-  pmark: PoolMark;
-  hitcount: Integer;
-  pmon: PMonster;
+  mit: PMonster;
+  it: TMonsterGrid.Iter;
 begin
-  pmark := framePool.mark();
-  hitcount := monsGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY);
-  if (hitcount > 0) then
+  it := monsGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY);
+  if (it.length > 0) then
   begin
     e_WriteLog('===========================', TMsgType.Notify);
-    pmon := PMonster(framePool.getPtr(pmark));
-    while (hitcount > 0) do
-    begin
-      monsAtDump(pmon^);
-      Inc(pmon);
-      Dec(hitcount);
-    end;
+    for mit in it do monsAtDump(mit^);
     e_WriteLog('---------------------------', TMsgType.Notify);
   end;
-  framePool.release(pmark);
+  it.release();
 end;
 
 procedure cbAtcurDumpWalls ();
@@ -1633,26 +1601,18 @@ var
   hasTrigs: Boolean = false;
   f: Integer;
   trig: PTrigger;
-  pmark: PoolMark;
-  hitcount: Integer;
-  ppan: PPanel;
+  mwit: PPanel;
+  it: TPanelGrid.Iter;
 begin
   platMarkedGUID := -1;
-  pmark := framePool.mark();
-  hitcount := mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, (GridTagWall or GridTagDoor));
-  if (hitcount > 0) then
+  it := mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, (GridTagWall or GridTagDoor));
+  if (it.length > 0) then
   begin
     e_WriteLog('=== TOGGLE WALL ===', TMsgType.Notify);
-    ppan := PPanel(framePool.getPtr(pmark));
-    while (hitcount > 0) do
-    begin
-      wallToggle(ppan^);
-      Inc(ppan);
-      Dec(hitcount);
-    end;
+    for mwit in it do wallToggle(mwit^);
     e_WriteLog('--- toggle wall ---', TMsgType.Notify);
   end;
-  framePool.release(pmark);
+  it.release();
   if showTriggers then
   begin
     for f := 0 to High(gTriggers) do
@@ -1676,22 +1636,14 @@ procedure cbAtcurToggleWalls ();
     if pan.Enabled then g_Map_DisableWallGUID(pan.guid) else g_Map_EnableWallGUID(pan.guid);
   end;
 var
-  pmark: PoolMark;
-  hitcount: Integer;
-  ppan: PPanel;
+  mwit: PPanel;
+  it: TPanelGrid.Iter;
 begin
   //e_WriteLog('=== TOGGLE WALL ===', MSG_NOTIFY);
   //e_WriteLog('--- toggle wall ---', MSG_NOTIFY);
-  pmark := framePool.mark();
-  hitcount := mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, (GridTagWall or GridTagDoor));
-  ppan := PPanel(framePool.getPtr(pmark));
-  while (hitcount > 0) do
-  begin
-    wallToggle(ppan^);
-    Inc(ppan);
-    Dec(hitcount);
-  end;
-  framePool.release(pmark);
+  it := mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, (GridTagWall or GridTagDoor));
+  for mwit in it do wallToggle(mwit^);
+  it.release();
 end;
 
 
index 4455ed9a66578a53b0e53cca9dec46c7ab79292c..1ddbffdd052253d446f2163e1f4597294dd445ff 100644 (file)
@@ -612,9 +612,8 @@ end;
 function g_Map_HasAnyPanelAtPoint (x, y: Integer; panelType: Word): Boolean;
 var
   tagmask: Integer = 0;
-  pmark: PoolMark;
-  hitcount: Integer;
-  ppan: PPanel;
+  mwit: PPanel;
+  it: TPanelGrid.Iter;
 begin
   result := false;
 
@@ -628,39 +627,31 @@ begin
 
   if (tagmask = 0) then exit;// just in case
 
-  pmark := framePool.mark();
   if ((tagmask and GridTagLift) <> 0) then
   begin
     // slow
-    hitcount := mapGrid.forEachAtPoint(x, y, tagmask);
-    ppan := PPanel(framePool.getPtr(pmark));
-    while (hitcount > 0) do
-    begin
-      if (xxPanAtPointChecker(ppan^, PanelType)) then begin result := true; break; end;
-      Inc(ppan);
-      Dec(hitcount);
-    end;
+    it := mapGrid.forEachAtPoint(x, y, tagmask);
+    for mwit in it do if (xxPanAtPointChecker(mwit^, PanelType)) then begin result := true; break; end;
   end
   else
   begin
     // fast
-    result := (mapGrid.forEachAtPoint(x, y, tagmask, false, true) <> 0); // firsthit
+    it := mapGrid.forEachAtPoint(x, y, tagmask, false, true);
+    result := (it.length <> 0); // firsthit
   end;
-  framePool.release(pmark);
+  it.release();
 end;
 
 
 function g_Map_PanelAtPoint (x, y: Integer; tagmask: Integer=-1): TPanel;
 var
-  pmark: PoolMark;
-  hitcount: Integer;
+  it: TPanelGrid.Iter;
 begin
   result := nil;
   if (tagmask = 0) then exit;
-  pmark := framePool.mark();
-  hitcount := mapGrid.forEachAtPoint(x, y, tagmask, false, true); // firsthit
-  if (hitcount <> 0) then result := PPanel(framePool.getPtr(pmark))^;
-  framePool.release(pmark);
+  it := mapGrid.forEachAtPoint(x, y, tagmask, false, true); // firsthit
+  if (it.length <> 0) then result := it.first^;
+  it.release();
 end;
 
 
@@ -2625,43 +2616,25 @@ end;
 // new algo
 procedure g_Map_CollectDrawPanels (x0, y0, wdt, hgt: Integer);
 var
-  pmark: PoolMark;
-  phit: PPanel;
-  hitcount: Integer;
+  mwit: PPanel;
+  it: TPanelGrid.Iter;
 begin
   dplClear();
-  pmark := framePool.mark();
-  hitcount := mapGrid.forEachInAABB(x0, y0, wdt, hgt, GridDrawableMask);
-  if (hitcount = 0) then exit;
-  phit := PPanel(framePool.getPtr(pmark));
-  while (hitcount > 0) do
-  begin
-    if (((phit^.tag and GridTagDoor) <> 0) = phit^.Door) then gDrawPanelList.insert(phit^);
-    Inc(phit);
-    Dec(hitcount);
-  end;
-  framePool.release(pmark);
+  it := mapGrid.forEachInAABB(x0, y0, wdt, hgt, GridDrawableMask);
+  for mwit in it do if (((mwit^.tag and GridTagDoor) <> 0) = mwit^.Door) then gDrawPanelList.insert(mwit^);
+  it.release();
   // list will be rendered in `g_game.DrawPlayer()`
 end;
 
 
 procedure g_Map_DrawPanelShadowVolumes (lightX: Integer; lightY: Integer; radius: Integer);
 var
-  pmark: PoolMark;
-  phit: PPanel;
-  hitcount: Integer;
+  mwit: PPanel;
+  it: TPanelGrid.Iter;
 begin
-  pmark := framePool.mark();
-  hitcount := mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, (GridTagWall or GridTagDoor));
-  if (hitcount = 0) then exit;
-  phit := PPanel(framePool.getPtr(pmark));
-  while (hitcount > 0) do
-  begin
-    phit^.DrawShadowVolume(lightX, lightY, radius);
-    Inc(phit);
-    Dec(hitcount);
-  end;
-  framePool.release(pmark);
+  it := mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, (GridTagWall or GridTagDoor));
+  for mwit in it do mwit^.DrawShadowVolume(lightX, lightY, radius);
+  it.release();
 end;
 
 
@@ -2862,9 +2835,8 @@ const
 
 var
   tagmask: Integer = 0;
-  pmark: PoolMark;
-  phit: PPanel;
-  hitcount: Integer;
+  mwit: PPanel;
+  it: TPanelGrid.Iter;
   pan: TPanel;
 begin
   result := false;
@@ -2881,15 +2853,13 @@ begin
   if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('*solids');
   if gdbg_map_use_accel_coldet then
   begin
-    pmark := framePool.mark();
     if ((tagmask and SlowMask) <> 0) then
     begin
       // slow
-      hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask);
-      phit := PPanel(framePool.getPtr(pmark));
-      while (hitcount > 0) do
+      it := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask);
+      for mwit in it do
       begin
-        pan := phit^;
+        pan := mwit^;
         if ((pan.tag and GridTagLift) <> 0) then
         begin
           result :=
@@ -2909,17 +2879,15 @@ begin
           result := true; // i found her!
         end;
         if (result) then break;
-        Inc(phit);
-        Dec(hitcount);
       end;
     end
     else
     begin
       // fast
-      hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask, false, true); // return first hit
-      result := (hitcount > 0);
+      it := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask, false, true); // return first hit
+      result := (it.length > 0);
     end;
-    framePool.release(pmark);
+    it.release();
   end
   else
   begin
@@ -2955,27 +2923,16 @@ end;
 function g_Map_CollideLiquid_Texture(X, Y: Integer; Width, Height: Word): DWORD;
 var
   cctype: Integer = 3; // priority: 0: water was hit, 1: acid1 was hit, 2: acid2 was hit; 3: nothing was hit
-  pmark: PoolMark;
-  phit: PPanel;
-  hitcount: Integer;
-  pan: TPanel;
+  mwit: PPanel;
+  it: TPanelGrid.Iter;
 begin
   if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('liquids');
   if gdbg_map_use_accel_coldet then
   begin
     result := LongWord(TEXTURE_NONE);
-    pmark := framePool.mark();
-    hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, (GridTagWater or GridTagAcid1 or GridTagAcid2));
-    if (hitcount = 0) then exit;
-    phit := PPanel(framePool.getPtr(pmark));
-    while (hitcount > 0) do
-    begin
-      pan := phit^;
-      Inc(phit);
-      Dec(hitcount);
-      if (liquidChecker(pan, result, cctype)) then break;
-    end;
-    framePool.release(pmark);
+    it := mapGrid.forEachInAABB(X, Y, Width, Height, (GridTagWater or GridTagAcid1 or GridTagAcid2));
+    for mwit in it do if (liquidChecker(mwit^, result, cctype)) then break;
+    it.release();
   end
   else
   begin
index 018a69359a90fa4598097ea48ad3fc4193454653..bb3d293ded57dc0413327ff01394b2a2055f41f8 100644 (file)
@@ -781,10 +781,9 @@ function isCorpse (o: PObj; immediately: Boolean): Integer;
 
 var
   a: Integer;
-  mon: TMonster = nil;
-  pmark: PoolMark;
-  phit: PMonster;
-  hitcount: Integer;
+  mon: PMonster;
+  mres: TMonster = nil;
+  it: TMonsterGrid.Iter;
 begin
   result := -1;
 
@@ -796,24 +795,19 @@ begin
   begin
     //mon := monsGrid.forEachInAABB(o.X+o.Rect.X, o.Y+o.Rect.Y, o.Rect.Width, o.Rect.Height, monsCollCheck);
     //if (mon <> nil) then result := mon.mArrIdx;
-    pmark := framePool.mark();
-    hitcount := monsGrid.forEachInAABB(o.X+o.Rect.X, o.Y+o.Rect.Y, o.Rect.Width, o.Rect.Height);
-    if (hitcount = 0) then exit;
-    phit := PMonster(framePool.getPtr(pmark));
-    while (hitcount > 0) do
+    it := monsGrid.forEachInAABB(o.X+o.Rect.X, o.Y+o.Rect.Y, o.Rect.Width, o.Rect.Height);
+    for mon in it do
     begin
-      mon := phit^;
-      Inc(phit);
-      Dec(hitcount);
       case mon.FMonsterType of // Íå âîñêðåñèòü:
         MONSTER_SOUL, MONSTER_PAIN, MONSTER_CYBER, MONSTER_SPIDER,
-        MONSTER_VILE, MONSTER_BARREL, MONSTER_ROBO: mon := nil;
+        MONSTER_VILE, MONSTER_BARREL, MONSTER_ROBO: begin end;
         // Îñòàëüíûõ ìîæíî âîñêðåñèòü
+        else mres := mon^;
       end;
-      if (mon <> nil) then break;
+      if (mres <> nil) then break;
     end;
-    framePool.release(pmark);
-    if (mon <> nil) then result := mon.mArrIdx;
+    it.release();
+    if (mres <> nil) then result := mres.mArrIdx;
   end
   else
   begin
@@ -4725,27 +4719,17 @@ function g_Mons_IsAnyAliveAt (x, y: Integer; width, height: Integer): Boolean;
 var
   idx: Integer;
   mon: TMonster;
-  pmark: PoolMark;
-  phit: PMonster;
-  hitcount: Integer;
+  mit: PMonster;
+  it: TMonsterGrid.Iter;
 begin
   result := false;
   if (width < 1) or (height < 1) then exit;
   if gmon_debug_use_sqaccel then
   begin
     //result := (monsGrid.forEachInAABB(x, y, width, height, monsCollCheck) <> nil);
-    pmark := framePool.mark();
-    hitcount := monsGrid.forEachInAABB(x, y, width, height);
-    if (hitcount = 0) then exit;
-    phit := PMonster(framePool.getPtr(pmark));
-    while (hitcount > 0) do
-    begin
-      mon := phit^;
-      Inc(phit);
-      Dec(hitcount);
-      if (mon.alive) then begin result := true; break; end;
-    end;
-    framePool.release(pmark);
+    it := monsGrid.forEachInAABB(x, y, width, height);
+    for mit in it do if (mit.alive) then begin result := true; break; end;
+    it.release();
   end
   else
   begin
@@ -4775,27 +4759,17 @@ function g_Mons_ForEachAt (x, y: Integer; width, height: Integer; cb: TEachMonst
 var
   idx: Integer;
   mon: TMonster;
-  pmark: PoolMark;
-  phit: PMonster;
-  hitcount: Integer;
+  mit: PMonster;
+  it: TMonsterGrid.Iter;
 begin
   result := false;
   if (width < 1) or (height < 1) then exit;
   if gmon_debug_use_sqaccel then
   begin
     //result := (monsGrid.forEachInAABB(x, y, width, height, monsCollCheck) <> nil);
-    pmark := framePool.mark();
-    hitcount := monsGrid.forEachInAABB(x, y, width, height);
-    if (hitcount = 0) then exit;
-    phit := PMonster(framePool.getPtr(pmark));
-    while (hitcount > 0) do
-    begin
-      mon := phit^;
-      Inc(phit);
-      Dec(hitcount);
-      if (cb(mon)) then begin result := true; break; end;
-    end;
-    framePool.release(pmark);
+    it := monsGrid.forEachInAABB(x, y, width, height);
+    for mit in it do if (cb(mit^)) then begin result := true; break; end;
+    it.release();
   end
   else
   begin
@@ -4827,9 +4801,8 @@ function g_Mons_ForEachAliveAt (x, y: Integer; width, height: Integer; cb: TEach
 var
   idx: Integer;
   mon: TMonster;
-  pmark: PoolMark;
-  phit: PMonster;
-  hitcount: Integer;
+  mit: PMonster;
+  it: TMonsterGrid.Iter;
 begin
   result := false;
   if (width < 1) or (height < 1) then exit;
@@ -4845,21 +4818,15 @@ begin
       result := (monsGrid.forEachInAABB(x, y, width, height, monsCollCheck) <> nil);
     end;
     }
-    pmark := framePool.mark();
-    hitcount := monsGrid.forEachInAABB(x, y, width, height);
-    if (hitcount = 0) then exit;
-    phit := PMonster(framePool.getPtr(pmark));
-    while (hitcount > 0) do
+    it := monsGrid.forEachInAABB(x, y, width, height);
+    for mit in it do
     begin
-      mon := phit^;
-      Inc(phit);
-      Dec(hitcount);
-      if (mon.alive) then
+      if (mit^.alive) then
       begin
-        if (cb(mon)) then begin result := true; break; end;
+        if (cb(mit^)) then begin result := true; break; end;
       end;
     end;
-    framePool.release(pmark);
+    it.release();
   end
   else
   begin
index 725ab6d701a05634adb9baffe2e256e6b94d41ee..3b1330170a988940f5d158494d4972a722faff6d 100644 (file)
@@ -1467,9 +1467,8 @@ var
   {$IF DEFINED(D2F_DEBUG)}
   stt: UInt64;
   {$ENDIF}
-  pmark: PoolMark;
-  hitcount: Integer;
-  pmon: PMonster;
+  mit: PMonster;
+  it: TMonsterGrid.Iter;
 begin
   (*
   if not gwep_debug_fast_trace then
@@ -1526,16 +1525,9 @@ begin
   // collect monsters
   //g_Mons_AlongLine(x, y, x2, y2, sqchecker);
 
-  pmark := framePool.mark();
-  hitcount := monsGrid.forEachAlongLine(x, y, x2, y2, -1);
-  pmon := PMonster(framePool.getPtr(pmark));
-  while (hitcount > 0) do
-  begin
-    sqchecker(pmon^);
-    Inc(pmon);
-    Dec(hitcount);
-  end;
-  framePool.release(pmark);
+  it := monsGrid.forEachAlongLine(x, y, x2, y2, -1);
+  for mit in it do sqchecker(mit^);
+  it.release();
 
   // here, we collected all monsters and players in `wgunHitHeap` and `wgunHitTime`
   // also, if `wallWasHit` is `true`, then `wallHitX` and `wallHitY` contains spark coords
index 1604055c028f6620f115998343a90966a458eb5d..ae67f034aa60363ec362b8b04b4a6ff2f4bec870 100644 (file)
@@ -90,6 +90,39 @@ type
     // get pointer for the given mark
     // WARNING! pointer can become invalid after next call to `alloc()`!
     function getPtr (amark: PoolMark): Pointer; inline;
+    function curPtr (): Pointer; inline;
+  end;
+
+
+type
+  generic PoolIter<T> = record
+  public
+    type Ptr = ^T;
+    type MyType = specialize PoolIter<T>;
+
+  private
+    mMark: PoolMark;
+    mCount: Integer;
+    mCurrent: Integer;
+    mFinished: Boolean;
+
+  public
+    constructor Create (dummy: Boolean); // idiotic FPC doesn't support arg-less ctors for rectord
+    procedure startIt (); inline; // automatically called by ctor; does NO checks!
+    procedure finishIt (); inline; // sets count
+
+    procedure rewind (); inline;
+    function length (): Integer; inline;
+    procedure release (); inline; // reset pool
+
+    function moveNext (): Boolean; inline;
+    function getCurrent (): Ptr; inline;
+    function getEnumerator (): MyType; inline;
+
+    function first (): Ptr; inline;
+
+  public
+    property current: Ptr read getCurrent;
   end;
 
 
@@ -193,6 +226,94 @@ begin
 end;
 
 
+function TPoolMarkRelease.curPtr (): Pointer; inline;
+begin
+  result := Pointer(PAnsiChar(mMemory)+mUsed);
+end;
+
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+constructor PoolIter.Create (dummy: Boolean);
+begin
+  startIt();
+end;
+
+
+procedure PoolIter.startIt (); inline; // automatically called by ctor; does NO checks!
+begin
+  mMark := framePool.mark();
+  mCount := 0;
+  mCurrent := -1;
+  mFinished := false;
+end;
+
+
+procedure PoolIter.finishIt (); inline; // sets count
+begin
+  if (mFinished) then raise Exception.Create('double fatality');
+  if (mMark = -1) then raise Exception.Create('void fatality');
+  mFinished := true;
+  mCount := Integer(PtrUInt(framePool.curPtr)-PtrUInt(framePool.getPtr(mMark))) div Integer(sizeof(T));
+  if (mCount < 0) then raise Exception.Create('wutafu?');
+end;
+
+
+procedure PoolIter.rewind (); inline;
+begin
+  if (mMark = -1) then raise Exception.Create('void rewind');
+  mCurrent := -1;
+end;
+
+
+function PoolIter.length (): Integer; inline;
+begin
+  //if (mCurrent+1 >= 0) and (mCurrent+1 < mCount) then result := mCount-(mCurrent+1) else result := 0;
+  result := mCount;
+end;
+
+
+procedure PoolIter.release (); inline; // reset pool
+begin
+  if (mMark = -1) then raise Exception.Create('double release');
+  framePool.release(mMark);
+  mMark := -1;
+  mCount := 0;
+  mCurrent := -1;
+  mFinished := false;
+end;
+
+
+function PoolIter.moveNext (): Boolean; inline;
+begin
+  if (mMark = -1) then raise Exception.Create('void moveNext()');
+  if (not mFinished) then raise Exception.Create('moveNext() on unfinished');
+  Inc(mCurrent);
+  result := (mCurrent < mCount);
+end;
+
+
+function PoolIter.getCurrent (): Ptr; inline;
+begin
+  if (mCurrent < 0) or (mCurrent >= mCount) then raise Exception.Create('getCurrent() range error');
+  result := Ptr(framePool.getPtr(mMark+mCurrent*Integer(sizeof(T))));
+end;
+
+
+function PoolIter.getEnumerator (): PoolIter; inline;
+begin
+  result := self;
+end;
+
+
+function PoolIter.first (): Ptr; inline;
+begin
+  if (mMark = -1) then raise Exception.Create('void moveNext()');
+  if (not mFinished) then raise Exception.Create('moveNext() on unfinished');
+  result := Ptr(framePool.getPtr(mMark));
+end;
+
+
 // ////////////////////////////////////////////////////////////////////////// //
 {$IFDEF USE_MEMPOOL}
 uses