source: tags/1.3.1/AI/StdAI/Pile.pas

Last change on this file was 289, checked in by chronos, 3 years ago
  • Modified: Code formatted using JEDI code formatter.
  • Modified: Protocol copied from main game.
  • Modified: Added Barbarina into project tree.
File size: 3.0 KB
Line 
1{single instance priority queue
2main parts contributed by Rassim Eminli}
3
4{$INCLUDE Switches.inc}
5
6unit Pile;
7
8interface
9
10procedure Create(Size: integer);
11procedure Free;
12procedure Empty;
13function Put(Item, Value: integer): boolean;
14function TestPut(Item, Value: integer): boolean;
15function Get(var Item, Value: integer): boolean;
16
17
18implementation
19
20const
21 MaxSize = 9600;
22
23type
24 TheapItem = record
25 Item: integer;
26 Value: integer;
27 end;
28
29var
30 bh: array[0..MaxSize - 1] of TheapItem;
31 Ix: array[0..MaxSize - 1] of integer;
32 n, CurrentSize: integer;
33{$IFDEF DEBUG}InUse: boolean;{$ENDIF}
34
35
36procedure Create(Size: integer);
37begin
38 {$IFDEF DEBUG}
39 assert(not InUse, 'Pile is a single instance class, ' +
40 'no multiple usage possible. Always call Pile.Free after use.');
41{$ENDIF}
42 assert(Size <= MaxSize);
43 if (n <> 0) or (Size > CurrentSize) then
44 begin
45 FillChar(Ix, Size * sizeOf(integer), 255);
46 n := 0;
47 end;
48 CurrentSize := Size;
49 {$IFDEF DEBUG}
50 InUse := True;
51{$ENDIF}
52end;
53
54procedure Free;
55begin
56 {$IFDEF DEBUG}
57 assert(InUse);
58 InUse := False;
59{$ENDIF}
60end;
61
62procedure Empty;
63begin
64 if n <> 0 then
65 begin
66 FillChar(Ix, CurrentSize * sizeOf(integer), 255);
67 n := 0;
68 end;
69end;
70
71//Parent(i) = (i-1)/2.
72function Put(Item, Value: integer): boolean; //O(lg(n))
73var
74 i, j: integer;
75begin
76 assert(Item < CurrentSize);
77 i := Ix[Item];
78 if i >= 0 then
79 begin
80 if bh[i].Value <= Value then
81 begin
82 Result := False;
83 exit;
84 end;
85 end
86 else
87 begin
88 i := n;
89 Inc(n);
90 end;
91
92 while i > 0 do
93 begin
94 j := (i - 1) shr 1; //Parent(i) = (i-1)/2
95 if Value >= bh[j].Value then
96 break;
97 bh[i] := bh[j];
98 Ix[bh[i].Item] := i;
99 i := j;
100 end;
101 // Insert the new Item at the insertion point found.
102 bh[i].Value := Value;
103 bh[i].Item := Item;
104 Ix[bh[i].Item] := i;
105 Result := True;
106end;
107
108function TestPut(Item, Value: integer): boolean;
109var
110 i: integer;
111begin
112 assert(Item < CurrentSize);
113 i := Ix[Item];
114 Result := (i < 0) or (bh[i].Value > Value);
115end;
116
117//Left(i) = 2*i+1.
118//Right(i) = 2*i+2 => Left(i)+1
119function Get(var Item, Value: integer): boolean; //O(lg(n))
120var
121 i, j: integer;
122 last: TheapItem;
123begin
124 if n = 0 then
125 begin
126 Result := False;
127 exit;
128 end;
129
130 Item := bh[0].Item;
131 Value := bh[0].Value;
132
133 Ix[Item] := -1;
134
135 Dec(n);
136 if n > 0 then
137 begin
138 last := bh[n];
139 i := 0;
140 j := 1;
141 while j < n do
142 begin
143 // Right(i) = Left(i)+1
144 if (j < n - 1) and (bh[j].Value > bh[j + 1].Value) then
145 Inc(j);
146 if last.Value <= bh[j].Value then
147 break;
148
149 bh[i] := bh[j];
150 Ix[bh[i].Item] := i;
151 i := j;
152 j := j shl 1 + 1; //Left(j) = 2*j+1
153 end;
154
155 // Insert the root in the correct place in the heap.
156 bh[i] := last;
157 Ix[last.Item] := i;
158 end;
159 Result := True;
160end;
161
162initialization
163 n := 0;
164 CurrentSize := 0;
165 {$IFDEF DEBUG}
166 InUse := False;
167{$ENDIF}
168end.
Note: See TracBrowser for help on using the repository browser.