-
Notifications
You must be signed in to change notification settings - Fork 0
/
POSTS.PAS
138 lines (109 loc) · 2.31 KB
/
POSTS.PAS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
unit Posts;
interface
type Post = record
X, Y: Word;
Free: Boolean;
end;
PostPtr = ^Post;
PostListPtr = ^PostList;
PostList = record
Current: PostPtr;
Next: PostListPtr;
end;
PostListPtrPtr = ^PostListPtr;
var AllPosts, OccupiedPosts: PostListPtr;
function NumOccupied: Byte;
procedure AddPost(P: PostPtr);
procedure AddOccupied(P: PostPtr);
procedure RemoveOccupied(P: PostPtr);
procedure ClearOccupied;
function RandomPost: PostListPtr;
function RandomOccupied: PostListPtr;
implementation
uses Utils;
function _DynLength(Start: PostListPtrPtr): Byte;
var N: Byte;
Node: PostListPtr;
begin
N := 0;
Node := Start^;
while Node <> nil do
begin
Node := Node^.Next;
Inc(N);
end;
_DynLength := N;
end;
function NumOccupied: Byte;
begin
NumOccupied := _DynLength(@OccupiedPosts);
end;
procedure _AddNodeToStart(Start: PostListPtrPtr; P: PostPtr);
var Node: PostListPtr;
begin
New(Node);
Node^.Current := P;
Node^.Next := Start^;
Start^ := Node;
end;
procedure AddPost(P: PostPtr);
begin
_AddNodeToStart(@AllPosts, P);
end;
procedure AddOccupied(P: PostPtr);
begin
P^.Free := False;
_AddNodeToStart(@OccupiedPosts, P);
end;
procedure _RemoveFromStart;
var _N: PostListPtr;
begin
OccupiedPosts^.Current^.Free := True;
_N := OccupiedPosts;
OccupiedPosts := OccupiedPosts^.Next;
Dispose(_N);
end;
procedure RemoveOccupied(P: PostPtr);
var Node, _N: PostListPtr;
begin
if OccupiedPosts^.Current = P then
_RemoveFromStart
else
begin
P^.Free := True;
Node := OccupiedPosts;
while Node^.Next^.Current <> P do Node := Node^.Next;
_N := Node^.Next;
Node^.Next := Node^.Next^.Next;
Dispose(_N);
end;
end;
procedure ClearOccupied;
begin
while OccupiedPosts <> nil do _RemoveFromStart;
end;
function _PickRandom(Start: PostListPtrPtr): PostListPtr;
var N: Byte;
Node: PostListPtr;
begin
Node := Start^;
N := Random(_DynLength(Start));
while N > 0 do
begin
Node := Node^.Next;
Dec(N);
end;
_PickRandom := Node;
end;
function RandomPost: PostListPtr;
begin
RandomPost := _PickRandom(@AllPosts);
end;
function RandomOccupied: PostListPtr;
begin
RandomOccupied := _PickRandom(@OccupiedPosts);
end;
begin
AllPosts := nil;
OccupiedPosts := nil;
end.