From: Ketmar Dark Date: Fri, 22 Sep 2017 11:15:34 +0000 (+0300) Subject: did the same thing for binary heap X-Git-Url: http://deadsoftware.ru/gitweb?a=commitdiff_plain;h=ae58c60b09a12df74e69717546235c3e5bf3c992;p=d2df-sdl.git did the same thing for binary heap --- diff --git a/src/game/g_map.pas b/src/game/g_map.pas index 0dc5090..2278353 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -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; + 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; diff --git a/src/game/g_weapons.pas b/src/game/g_weapons.pas index 3d8b2e9..5f3f99a 100644 --- a/src/game/g_weapons.pas +++ b/src/game/g_weapons.pas @@ -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; + TBinaryHeapHitTimes = specialize TBinaryHeapBase; 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(); diff --git a/src/shared/binheap.pas b/src/shared/binheap.pas index 50531ed..ea73c74 100644 --- a/src/shared/binheap.pas +++ b/src/shared/binheap.pas @@ -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 = class(TObject) - private - type - TBinaryHeapLessFn = function (a, b: ITP): Boolean; - + generic TBinaryHeapBase = 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; - TBinaryHeapInt = specialize TBinaryHeapBase; + 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; + TBinaryHeapIntGreat = specialize TBinaryHeapBase; 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;