source: trunk/Packages/TemplateGenerics/Generic/GenericMatrix.inc

Last change on this file was 58, checked in by chronos, 23 months ago
  • Fixed: Rock drawing issue for player on the righ or bottom side.
File size: 16.0 KB
Line 
1{$IFDEF INTERFACE}
2
3 TGMatrix = class;
4
5 TGMatrixSortCompare = function(const Item1, Item2: TGMatrixItem): Integer of object;
6 TGMatrixToStringConverter = function(Item: TGMatrixItem): string;
7 TGMatrixFromStringConverter = function(Text: string): TGMatrixItem;
8 TGMatrixRow = array of TGMatrixItem;
9 TGMatrixMerge = function(Item1, Item2: TGMatrixItem): TGMatrixItem of object;
10
11 TGMatrixIndex = record
12 X: TGMatrixIndexX;
13 Y: TGMatrixIndexY;
14 end;
15
16 // TGMatrix<TGMatrixIndex, TGMatrixIndex, TGMatrixItem> = class
17 TGMatrix = class
18 private
19 FItems: array of array of TGMatrixItem;
20 FCount: TGMatrixIndex;
21 function GetItemXY(X: TGMatrixIndexX; Y: TGMatrixIndexY): TGMatrixItem;
22 function GetItem(Index: TGMatrixIndex): TGMatrixItem;
23 function GetCapacity: TGMatrixIndex;
24 function GetLast: TGMatrixItem;
25 function GetFirst: TGMatrixItem;
26 procedure SetCapacity(const AValue: TGMatrixIndex);
27 procedure SetLast(AValue: TGMatrixItem);
28 procedure SetFirst(AValue: TGMatrixItem);
29 procedure PutItemXY(X: TGMatrixIndexX; Y: TGMatrixIndexY; const AValue: TGMatrixItem); virtual;
30 procedure PutItem(Index: TGMatrixIndex; const AValue: TGMatrixItem); virtual;
31 procedure SetCount(const AValue: TGMatrixIndex);
32 procedure CheckRange(X: TGMatrixIndexX; Y: TGMatrixIndexY); inline;
33 public
34 constructor Create; virtual;
35 function Add(Item: TGMatrixItem): TGMatrixIndex;
36 procedure AddMatrix(Values: array of TGMatrixRow);
37 procedure AddList(List: TGMatrix);
38 procedure Assign(Source: TGMatrix);
39 procedure Clear; virtual;
40 procedure Contract;
41 function CreateIndex(X: TGMatrixIndexY; Y: TGMatrixIndexX): TGMatrixIndex;
42 procedure Delete(Index: TGMatrixIndex); virtual;
43 procedure DeleteItems(Index, Count: TGMatrixIndex);
44 function EqualTo(List: TGMatrix): Boolean;
45 procedure Expand;
46 function Extract(Item: TGMatrixItem): TGMatrixItem;
47 procedure Exchange(Index1, Index2: TGMatrixIndex);
48 property First: TGMatrixItem read GetFirst write SetFirst;
49 procedure FillAll(Value: TGMatrixItem);
50 procedure Fill(Start, Count: TGMatrixIndex; Value: TGMatrixItem);
51 function Implode(RowSeparator, ColSeparator: string; Converter: TGMatrixToStringConverter): string;
52 procedure Explode(Text, Separator: string; Converter: TGMatrixFromStringConverter; SlicesCount: Integer = -1);
53 function IndexOf(Item: TGMatrixItem; Start: TGMatrixIndex): TGMatrixIndex;
54 function IndexOfList(List: TGMatrix; Start: TGMatrixIndex): TGMatrixIndex;
55 procedure Insert(Index: TGMatrixIndex; Item: TGMatrixItem);
56 procedure InsertList(Index: TGMatrixIndex; List: TGMatrix);
57 procedure InsertArray(Index: TGMatrixIndex; Values: array of TGMatrixItem);
58 procedure Move(CurIndex, NewIndex: TGMatrixIndex);
59 procedure MoveItems(CurIndex, NewIndex, Count: TGMatrixIndex);
60 procedure Merge(Index: TGMatrixIndex; Source: TGMatrix; Proc: TGMatrixMerge);
61 procedure Replace(Index: TGMatrixIndex; Source: TGMatrix);
62 function Remove(Item: TGMatrixItem): TGMatrixIndex;
63 procedure Reverse;
64 procedure ReverseHorizontal;
65 procedure ReverseVertical;
66 procedure Sort(Compare: TGMatrixSortCompare);
67 procedure SetArray(Values: array of TGMatrixItem);
68 property Count: TGMatrixIndex read FCount write SetCount;
69 property Capacity: TGMatrixIndex read GetCapacity write SetCapacity;
70 property ItemsXY[X: TGMatrixIndexX; Y: TGMatrixIndexY]: TGMatrixItem
71 read GetItemXY write PutItemXY; default;
72 property Items[Index: TGMatrixIndex]: TGMatrixItem
73 read GetItem write PutItem;
74 property Last: TGMatrixItem read GetLast write SetLast;
75 end;
76
77{$UNDEF INTERFACE}
78{$ENDIF}
79
80{$IFDEF IMPLEMENTATION_USES}
81
82uses
83 RtlConsts;
84
85resourcestring
86 SMatrixIndexError = 'Matrix index error [X: %d, Y: %d]';
87
88{$UNDEF IMPLEMENTATION_USES}
89{$ENDIF}
90
91{$IFDEF IMPLEMENTATION}
92
93{ TGMatrix }
94
95procedure TGMatrix.Replace(Index: TGMatrixIndex; Source: TGMatrix);
96var
97 X: TGMatrixIndexX;
98 Y: TGMatrixIndexY;
99begin
100 Y := 0;
101 while Y < Source.Count.Y do begin
102 X := 0;
103 while X < Source.Count.X do begin
104 ItemsXY[Index.X + X, Index.Y + Y] := Source.ItemsXY[X, Y];
105 X := X + 1;
106 end;
107 Y := Y + 1;
108 end;
109end;
110
111procedure TGMatrix.Merge(Index: TGMatrixIndex; Source: TGMatrix; Proc: TGMatrixMerge);
112var
113 X: TGMatrixIndexX;
114 Y: TGMatrixIndexY;
115begin
116 Y := 0;
117 while Y < Source.Count.Y do begin
118 X := 0;
119 while X < Source.Count.X do begin
120 ItemsXY[Index.X + X, Index.Y + Y] := Proc(ItemsXY[Index.X + X, Index.Y + Y], Source.ItemsXY[X, Y]);
121 X := X + 1;
122 end;
123 Y := Y + 1;
124 end;
125end;
126
127function TGMatrix.CreateIndex(X: TGMatrixIndexY; Y: TGMatrixIndexX): TGMatrixIndex;
128begin
129 Result.X := X;
130 Result.Y := Y;
131end;
132
133function TGMatrix.GetCapacity: TGMatrixIndex;
134begin
135 Result.Y := Length(FItems);
136 if Result.Y > 0 then Result.X := Length(FItems[0]) else Result.X := 0;
137end;
138
139procedure TGMatrix.SetCapacity(const AValue: TGMatrixIndex);
140var
141 Y: TGMatrixIndexY;
142begin
143 if (Capacity.X <> AValue.X) and (Capacity.Y <> AValue.Y) then begin
144 SetLength(FItems, AValue.Y);
145 Y := 0;
146 while Y < Length(FItems) do begin
147 SetLength(FItems[Y], AValue.X);
148 Y := Y + 1;
149 end;
150
151 { SetLength(FItems, AValue.Y, AValue.X);}
152 end;
153end;
154
155function TGMatrix.GetItemXY(X: TGMatrixIndexX; Y: TGMatrixIndexY): TGMatrixItem;
156begin
157 CheckRange(X, Y);
158 Result := FItems[Y, X];
159end;
160
161function TGMatrix.GetItem(Index: TGMatrixIndex): TGMatrixItem;
162begin
163 CheckRange(Index.X, Index.Y);
164 Result := FItems[Index.Y, Index.X];
165end;
166
167procedure TGMatrix.PutItemXY(X: TGMatrixIndexX; Y: TGMatrixIndexY; const AValue: TGMatrixItem);
168begin
169 CheckRange(X, Y);
170 FItems[Y, X] := AValue;
171end;
172
173procedure TGMatrix.PutItem(Index: TGMatrixIndex; const AValue: TGMatrixItem);
174begin
175 CheckRange(Index.X, Index.Y);
176 FItems[Index.Y, Index.X] := AValue;
177end;
178
179procedure TGMatrix.SetCount(const AValue: TGMatrixIndex);
180begin
181 Capacity := AValue;
182 FCount := AValue;
183end;
184
185procedure TGMatrix.CheckRange(X: TGMatrixIndexX; Y: TGMatrixIndexY);
186begin
187 if (X < 0) or (X >= Count.X) or
188 (Y < 0) or (Y >= Count.Y) then
189 raise EListError.CreateFmt(SMatrixIndexError, [X, Y]);
190end;
191
192procedure TGMatrix.Assign(Source: TGMatrix);
193var
194 Index: TGMatrixIndex;
195begin
196 Count := Source.Count;
197 Index.Y := 0;
198 while Index.Y < Count.Y do begin
199 Index.X := 0;
200 while Index.X < Count.X do begin
201 Items[Index] := Source.Items[Index];
202 Index.X := Index.X + 1;
203 end;
204 Index.Y := Index.Y + 1;
205 end;
206end;
207
208procedure TGMatrix.Expand;
209var
210 IncSize: TGMatrixIndex;
211 NewCapacity: TGMatrixIndex;
212begin
213 if (FCount.X = Capacity.X) then begin
214 IncSize.X := 4;
215 if Capacity.X > 3 then IncSize.X := IncSize.X + 4;
216 if Capacity.X > 8 then IncSize.X := IncSize.X + 8;
217 if Capacity.X > 63 then IncSize.X := IncSize.X + Capacity.X shr 2;
218 NewCapacity.X := Capacity.X + IncSize.X;
219 end;
220 if (FCount.Y = Capacity.Y) then begin
221 IncSize.Y := 4;
222 if Capacity.Y > 3 then IncSize.Y := IncSize.Y + 4;
223 if Capacity.Y > 8 then IncSize.Y := IncSize.Y + 8;
224 if Capacity.Y > 63 then IncSize.Y := IncSize.Y + Capacity.Y shr 2;
225 NewCapacity.Y := Capacity.Y + IncSize.Y;
226 end;
227 Capacity := NewCapacity;
228end;
229
230procedure TGMatrix.Contract;
231var
232 NewCapacity: TGMatrixIndex;
233begin
234 if (Capacity.X > 256) and (FCount.X < Capacity.X shr 2) then
235 begin
236 NewCapacity.X := Capacity.X shr 1;
237 end;
238 if (Capacity.Y > 256) and (FCount.Y < Capacity.Y shr 2) then
239 begin
240 NewCapacity.Y := Capacity.Y shr 1;
241 end;
242 Capacity := NewCapacity;
243end;
244
245function TGMatrix.Extract(Item: TGMatrixItem): TGMatrixItem;
246var
247 I: TGMatrixIndex;
248begin
249(* I := IndexOf(Item);
250 if I >= 0 then begin
251 Result := Item;
252 Delete(I);
253 end else
254 raise EListError.CreateFmt(SListIndexError, [0]);
255 *)
256end;
257
258function TGMatrix.IndexOf(Item: TGMatrixItem; Start: TGMatrixIndex): TGMatrixIndex;
259begin
260(* Result := Start;
261 while (Result < FCount) and
262 not CompareMem(Addr(FItems[Result]), Addr(Item), SizeOf(TGMatrixItem)) do
263 Result := Result + 1;
264 if Result = FCount then Result := -1;
265 *)
266end;
267
268procedure TGMatrix.Insert(Index: TGMatrixIndex; Item: TGMatrixItem);
269begin
270(* if (Index < 0) or (Index > FCount ) then
271 raise EListError.CreateFmt(SListIndexError, [Index]);
272 if FCount = Capacity then Expand;
273 if Index < FCount then
274 System.Move(FItems[Index], FItems[Index + 1], (FCount - Index) * SizeOf(TGMatrixItem));
275 FItems[Index] := Item;
276 FCount := FCount + 1;
277 *)
278end;
279
280procedure TGMatrix.InsertList(Index: TGMatrixIndex; List: TGMatrix);
281var
282 I: TGMatrixIndex;
283begin
284(* I := 0;
285 while (I < List.Count) do begin
286 Insert(Index + I, List[I]);
287 I := I + 1;
288 end;
289 *)
290end;
291
292function TGMatrix.IndexOfList(List: TGMatrix; Start: TGMatrixIndex): TGMatrixIndex;
293var
294 I: TGMatrixIndex;
295begin
296(* if List.Count > 0 then begin
297 Result := IndexOf(List[0], Start);
298 if Result <> -1 then begin
299 I := 1;
300 while I < List.Count do begin
301 if not CompareMem(Addr(FItems[Result + I]), Addr(List.FItems[I]), SizeOf(TGMatrixItem)) then begin
302 Result := -1;
303 Break;
304 end;
305 I := I + 1;
306 end;
307 end;
308 end else Result := -1;
309 *)
310end;
311
312function TGMatrix.GetLast: TGMatrixItem;
313begin
314(* if FCount = 0 then
315 raise EListError.CreateFmt(SListIndexError, [0])
316 else
317 Result := Items[FCount - 1];
318 *)
319end;
320
321procedure TGMatrix.SetLast(AValue: TGMatrixItem);
322begin
323(* if FCount = 0 then
324 raise EListError.CreateFmt(SListIndexError, [0])
325 else
326 Items[FCount - 1] := AValue;
327 *)
328end;
329
330function TGMatrix.GetFirst: TGMatrixItem;
331begin
332(* if FCount = 0 then
333 raise EListError.CreateFmt(SListIndexError, [0])
334 else
335 Result := Items[0];
336 *)
337end;
338
339procedure TGMatrix.SetFirst(AValue: TGMatrixItem);
340begin
341(* if FCount = 0 then
342 raise EListError.CreateFmt(SListIndexError, [0])
343 else
344 Items[0] := AValue;
345 *)
346end;
347
348procedure TGMatrix.Move(CurIndex, NewIndex: TGMatrixIndex);
349var
350 Temp: TGMatrixItem;
351begin
352(* if ((CurIndex < 0) or (CurIndex > Count - 1)) then
353 raise EListError.CreateFmt(SListIndexError, [CurIndex]);
354 if ((NewIndex < 0) or (NewIndex > Count -1)) then
355 raise EListError.CreateFmt(SlistIndexError, [NewIndex]);
356 Temp := FItems[CurIndex];
357 if NewIndex > CurIndex then begin
358 System.Move(FItems[CurIndex + 1], FItems[CurIndex], (NewIndex - CurIndex) * SizeOf(TGMatrixItem));
359 end else
360 if NewIndex < CurIndex then begin
361 System.Move(FItems[NewIndex], FItems[NewIndex + 1], (CurIndex - NewIndex) * SizeOf(TGMatrixItem));
362 end;
363 FItems[NewIndex] := Temp;
364 //Delete(CurIndex);
365 //Insert(NewIndex, Temp);*)
366end;
367
368procedure TGMatrix.MoveItems(CurIndex, NewIndex, Count: TGMatrixIndex);
369var
370 S: Integer;
371 D: Integer;
372begin
373(* if CurIndex < NewIndex then begin
374 S := CurIndex + Count - 1;
375 D := NewIndex + Count - 1;
376 while S >= CurIndex do begin
377 Move(S, D);
378 S := S - 1;
379 D := D - 1;
380 end;
381 end else
382 if CurIndex > NewIndex then begin
383 S := CurIndex;
384 D := NewIndex;
385 while S < (CurIndex + Count) do begin
386 Move(S, D);
387 S := S + 1;
388 D := D + 1;
389 end;
390 end;*)
391end;
392
393function TGMatrix.Remove(Item: TGMatrixItem): TGMatrixIndex;
394begin
395(* Result := IndexOf(Item);
396 if Result <> -1 then
397 Delete(Result); *)
398end;
399
400function TGMatrix.EqualTo(List: TGMatrix): Boolean;
401var
402 I: TGMatrixIndex;
403begin
404(* Result := Count = List.Count;
405 if Result then begin
406 I := 0;
407 while I < Count do begin
408 if not CompareMem(Addr(FItems[I]), Addr(List.FItems[I]), SizeOf(TGMatrixItem)) then begin
409 Result := False;
410 Break;
411 end;
412 I := I + 1;
413 end;
414 end; *)
415end;
416
417procedure TGMatrix.Reverse;
418var
419 X: TGMatrixIndexX;
420 Y: TGMatrixIndexY;
421begin
422 Y := 0;
423 while Y < (Count.Y - 1) do begin
424 X := 1 + Y;
425 while X < Count.X do begin
426 Exchange(CreateIndex(X, Y), CreateIndex(Y, X));
427 X := X + 1;
428 end;
429 Y := Y + 1;
430 end;
431end;
432
433procedure TGMatrix.ReverseHorizontal;
434var
435 X: TGMatrixIndexX;
436 Y: TGMatrixIndexY;
437begin
438 Y := 0;
439 while Y < Count.Y do begin
440 X := 0;
441 while X < (Count.X div 2) do begin
442 Exchange(CreateIndex(X, Y), CreateIndex(Count.X - 1 - X, Y));
443 X := X + 1;
444 end;
445 Y := Y + 1;
446 end;
447end;
448
449procedure TGMatrix.ReverseVertical;
450var
451 X: TGMatrixIndexX;
452 Y: TGMatrixIndexY;
453begin
454 X := 0;
455 while X < Count.X do begin
456 Y := 0;
457 while Y < (Count.Y div 2) do begin
458 Exchange(CreateIndex(X, Y), CreateIndex(X, Count.Y - 1 - Y));
459 Y := Y + 1;
460 end;
461 X := X + 1;
462 end;
463end;
464
465procedure TGMatrix.Sort(Compare: TGMatrixSortCompare);
466begin
467(* if FCount > 1 then
468 QuickSort(0, FCount - 1, Compare); *)
469end;
470
471procedure TGMatrix.AddMatrix(Values: array of TGMatrixRow);
472var
473 I: TGMatrixIndex;
474begin
475(* I := 0;
476 while I <= High(Values) do begin
477 Add(Values[I]);
478 I := I + 1;
479 end; *)
480end;
481
482procedure TGMatrix.SetArray(Values: array of TGMatrixItem);
483var
484 I: TGMatrixIndex;
485begin
486(* Clear;
487 I := 0;
488 while I <= High(Values) do begin
489 Add(Values[I]);
490 I := I + 1;
491 end; *)
492end;
493
494procedure TGMatrix.InsertArray(Index: TGMatrixIndex; Values: array of TGMatrixItem);
495var
496 I: TGMatrixIndex;
497begin
498(* I := 0;
499 while I <= High(Values) do begin
500 Insert(Index + I, Values[I]);
501 I := I + 1;
502 end; *)
503end;
504
505function TGMatrix.Implode(RowSeparator, ColSeparator: string; Converter: TGMatrixToStringConverter): string;
506var
507 Y: TGMatrixIndexY;
508 X: TGMatrixIndexX;
509begin
510 Result := '';
511 Y := 0;
512 while Y < Count.Y do begin
513 X := 0;
514 while X < Count.X do begin
515 Result := Result + Converter(ItemsXY[X, Y]);
516 if X < (Count.X - 1) then
517 Result := Result + ColSeparator;
518 X := X + 1;
519 end;
520 if Y < (Count.Y - 1) then
521 Result := Result + RowSeparator;
522 Y := Y + 1;
523 end;
524end;
525
526procedure TGMatrix.Explode(Text, Separator: string; Converter: TGMatrixFromStringConverter; SlicesCount: Integer = -1);
527begin
528(* Clear;
529 while (Pos(Separator, Text) > 0) and
530 ((Count < (SlicesCount - 1)) or (SlicesCount = -1)) do begin
531 Add(Converter(Copy(Text, 1, Pos(Separator, Text) - 1)));
532 System.Delete(Text, 1, Pos(Separator, Text) + Length(Separator) - 1);
533 end;
534 Add(Converter(Text)); *)
535end;
536
537function TGMatrix.Add(Item: TGMatrixItem): TGMatrixIndex;
538begin
539(* if FCount = Capacity then
540 Self.Expand;
541 FItems[FCount] := Item;
542 Result := FCount;
543 FCount := FCount + 1; *)
544end;
545
546procedure TGMatrix.AddList(List: TGMatrix);
547var
548 I: TGMatrixIndex;
549begin
550(* I := 0;
551 while I < List.Count do begin
552 Add(List[I]);
553 I := I + 1;
554 end; *)
555end;
556
557constructor TGMatrix.Create;
558begin
559 SetLength(FItems, 0, 0);
560 FCount := CreateIndex(0, 0);
561end;
562
563procedure TGMatrix.Clear;
564begin
565 Count := CreateIndex(0, 0);
566 Capacity := CreateIndex(0, 0);
567end;
568
569procedure TGMatrix.Delete(Index: TGMatrixIndex);
570begin
571(* if (Index < 0) or (Index >= FCount) then
572 raise EListError.CreateFmt(SListIndexError, [Index]);
573 FCount := FCount - 1;
574 System.Move(FItems[Index + 1], FItems[Index], (FCount - Index) * SizeOf(TGMatrixItem));
575 Contract;
576 *)
577end;
578
579procedure TGMatrix.DeleteItems(Index, Count: TGMatrixIndex);
580var
581 I: TGMatrixIndex;
582begin
583(* I := Index;
584 while I < (Index + Count) do begin
585 Delete(Index);
586 I := I + 1;
587 end;
588 *)
589end;
590
591procedure TGMatrix.Fill(Start, Count: TGMatrixIndex; Value: TGMatrixItem);
592var
593 X: TGMatrixIndexX;
594 Y: TGMatrixIndexY;
595begin
596 Y := Start.Y;
597 while Y < Start.Y + Count.Y do begin
598 X := Start.X;
599 while X < Start.X + Count.X do begin
600 ItemsXY[X, Y] := Value;
601 X := X + 1;
602 end;
603 Y := Y + 1;
604 end;
605end;
606
607procedure TGMatrix.FillAll(Value: TGMatrixItem);
608begin
609 Fill(CreateIndex(0, 0), CreateIndex(Count.X - 1, Count.Y - 1), Value);
610end;
611
612procedure TGMatrix.Exchange(Index1, Index2: TGMatrixIndex);
613var
614 Temp: TGMatrixItem;
615begin
616 if (Index1.X < 0) or (Index1.X >= Count.X) or
617 (Index1.Y < 0) or (Index1.Y >= Count.Y) then
618 raise EListError.CreateFmt(SMatrixIndexError, [Index1.X, Index1.Y]);
619 if (Index2.X < 0) or (Index2.X >= Count.X) or
620 (Index2.Y < 0) or (Index2.Y >= Count.Y) then
621 raise EListError.CreateFmt(SMatrixIndexError, [Index2.X, Index2.Y]);
622 Temp := FItems[Index1.Y, Index1.X];
623 FItems[Index1.Y, Index1.X] := FItems[Index2.Y, Index2.X];
624 FItems[Index2.Y, Index2.X] := Temp;
625end;
626
627{$UNDEF IMPLEMENTATION}
628{$ENDIF}
Note: See TracBrowser for help on using the repository browser.