DEADSOFTWARE

did the same thing for binary heap
authorKetmar Dark <ketmar@ketmar.no-ip.org>
Fri, 22 Sep 2017 11:15:34 +0000 (14:15 +0300)
committerKetmar Dark <ketmar@ketmar.no-ip.org>
Fri, 22 Sep 2017 11:16:10 +0000 (14:16 +0300)
src/game/g_map.pas
src/game/g_weapons.pas
src/shared/binheap.pas

index 0dc5090c2f123848164d467cdcdf56745d736529..227835321cad0e6916b103de085d75eb0bafef5f 100644 (file)
@@ -202,6 +202,14 @@ const
   GridDrawableMask = (GridTagBack or GridTagStep or GridTagWall or GridTagDoor or GridTagAcid1 or GridTagAcid2 or GridTagWater or GridTagFore);
 
 
+type
+  TBinHeapPanelDrawCmp = class
+  public
+    class function less (const a, b: TPanel): Boolean; inline;
+  end;
+
+  TBinHeapPanelDraw = specialize TBinaryHeapBase<TPanel, TBinHeapPanelDrawCmp>;
+
 var
   gWalls: TPanelArray;
   gRenderBackgrounds: TPanelArray;
@@ -224,7 +232,7 @@ var
   gdbg_map_use_accel_render: Boolean = true;
   gdbg_map_use_accel_coldet: Boolean = true;
   profMapCollision: TProfiler = nil; //WARNING: FOR DEBUGGING ONLY!
-  gDrawPanelList: TBinaryHeapObj = nil; // binary heap of all walls we have to render, populated by `g_Map_CollectDrawPanels()`
+  gDrawPanelList: TBinHeapPanelDraw = nil; // binary heap of all walls we have to render, populated by `g_Map_CollectDrawPanels()`
 
   gCurrentMap: TDynRecord = nil;
   gCurrentMapFileName: AnsiString = ''; // so we can skip texture reloading
@@ -506,20 +514,16 @@ begin
 end;
 
 
-function dplLess (a, b: TObject): Boolean;
-var
-  pa, pb: TPanel;
+class function TBinHeapPanelDrawCmp.less (const a, b: TPanel): Boolean; inline;
 begin
-  pa := TPanel(a);
-  pb := TPanel(b);
-  if (pa.tag < pb.tag) then begin result := true; exit; end;
-  if (pa.tag > pb.tag) then begin result := false; exit; end;
-  result := (pa.arrIdx < pb.arrIdx);
+  if (a.tag < b.tag) then begin result := true; exit; end;
+  if (a.tag > b.tag) then begin result := false; exit; end;
+  result := (a.arrIdx < b.arrIdx);
 end;
 
 procedure dplClear ();
 begin
-  if (gDrawPanelList = nil) then gDrawPanelList := TBinaryHeapObj.Create(@dplLess) else gDrawPanelList.clear();
+  if (gDrawPanelList = nil) then gDrawPanelList := TBinHeapPanelDraw.Create() else gDrawPanelList.clear();
 end;
 
 
index 3d8b2e9d11e0fbc8ae5540ef1de1b187d24cc50a..5f3f99a2565ec8ec56a67399680ed9ac866071df 100644 (file)
@@ -157,8 +157,13 @@ type
     x, y: Integer;
   end;
 
+  TBinHeapKeyHitTime = class
+  public
+    class function less (const a, b: Integer): Boolean; inline;
+  end;
+
   // indicies in `wgunHitTime` array
-  TBinaryHeapHitTimes = specialize TBinaryHeapBase<Integer>;
+  TBinaryHeapHitTimes = specialize TBinaryHeapBase<Integer, TBinHeapKeyHitTime>;
 
 var
   WaterMap: array of array of DWORD = nil;
@@ -168,7 +173,7 @@ var
   wgunHitTimeUsed: Integer = 0;
 
 
-function hitTimeLess (a, b: Integer): Boolean;
+class function TBinHeapKeyHitTime.less (const a, b: Integer): Boolean;
 var
   hta, htb: PHitTime;
 begin
@@ -1155,7 +1160,7 @@ begin
   g_Texture_CreateWADEx('TEXTURE_SHELL_SHELL', GameWAD+':TEXTURES\ESHELL');
 
   //wgunMonHash := hashNewIntInt();
-  wgunHitHeap := TBinaryHeapHitTimes.Create(hitTimeLess);
+  wgunHitHeap := TBinaryHeapHitTimes.Create();
 end;
 
 procedure g_Weapon_FreeData();
index 50531ed6f453d79044597739bf48d813dfe96c6f..ea73c746418bc9e2af3f2b95e1ee2ebc6ed40fae 100644 (file)
@@ -20,23 +20,22 @@ unit binheap;
 interface
 
 
+(*
+ * CmpObjT: class that contains class methods:
+ *   class function less (const[ref] a, b: KeyT): Boolean;
+ *)
 type
   // WARNING! don't put structures into heap, use ponters or ids!
-  generic TBinaryHeapBase<ITP> = class(TObject)
-  private
-    type
-      TBinaryHeapLessFn = function (a, b: ITP): Boolean;
-
+  generic TBinaryHeapBase<ITP, CmpObjT> = class(TObject)
   private
     elem: array of ITP;
     elemUsed: Integer;
-    lessfn: TBinaryHeapLessFn;
 
   private
     procedure heapify (root: Integer);
 
   public
-    constructor Create (alessfn: TBinaryHeapLessFn);
+    constructor Create ();
     destructor Destroy (); override;
 
     procedure clear ();
@@ -51,12 +50,20 @@ type
 
 
 type
-  TBinaryHeapObj = specialize TBinaryHeapBase<TObject>;
-  TBinaryHeapInt = specialize TBinaryHeapBase<Integer>;
+  TBinHeapKeyIntLess = class
+  public
+    class function less (const a, b: Integer): Boolean; inline;
+  end;
+
+  TBinHeapKeyIntGreat = class
+  public
+    class function less (const a, b: Integer): Boolean; inline;
+  end;
 
 
-function binHeapNewIntLess (): TBinaryHeapInt;
-function binHeapNewIntGreat (): TBinaryHeapInt;
+type
+  TBinaryHeapIntLess = specialize TBinaryHeapBase<Integer, TBinHeapKeyIntLess>;
+  TBinaryHeapIntGreat = specialize TBinaryHeapBase<Integer, TBinHeapKeyIntGreat>;
 
 
 implementation
@@ -66,19 +73,13 @@ uses
 
 
 // ////////////////////////////////////////////////////////////////////////// //
-function intLess (a, b: Integer): Boolean; begin result := (a < b); end;
-function intGreat (a, b: Integer): Boolean; begin result := (a > b); end;
-
-
-function binHeapNewIntLess (): TBinaryHeapInt; begin result := TBinaryHeapInt.Create(@intLess); end;
-function binHeapNewIntGreat (): TBinaryHeapInt; begin result := TBinaryHeapInt.Create(@intGreat); end;
+class function TBinHeapKeyIntLess.less (const a, b: Integer): Boolean; inline; begin result := (a < b); end;
+class function TBinHeapKeyIntGreat.less (const a, b: Integer): Boolean; inline; begin result := (a > b); end;
 
 
 // ////////////////////////////////////////////////////////////////////////// //
-constructor TBinaryHeapBase.Create (alessfn: TBinaryHeapLessFn);
+constructor TBinaryHeapBase.Create ();
 begin
-  if not assigned(alessfn) then raise Exception.Create('wutafuck?!');
-  lessfn := alessfn;
   SetLength(elem, 128); // 'cause why not?
   elemUsed := 0;
 end;
@@ -107,8 +108,8 @@ begin
     smallest := 2*root+1; // left child
     if (smallest >= elemUsed) then break; // anyway
     right := smallest+1; // right child
-    if not lessfn(elem[smallest], elem[root]) then smallest := root;
-    if (right < elemUsed) and (lessfn(elem[right], elem[smallest])) then smallest := right;
+    if not CmpObjT.less(elem[smallest], elem[root]) then smallest := root;
+    if (right < elemUsed) and (CmpObjT.less(elem[right], elem[smallest])) then smallest := right;
     if (smallest = root) then break;
     // swap
     tmp := elem[root];
@@ -137,7 +138,7 @@ begin
   while (i <> 0) do
   begin
     par := (i-1) div 2; // parent
-    if not lessfn(val, elem[par]) then break;
+    if not CmpObjT.less(val, elem[par]) then break;
     elem[i] := elem[par];
     i := par;
   end;