189 lines
4.0 KiB
ObjectPascal
189 lines
4.0 KiB
ObjectPascal
unit trace_m;
|
|
|
|
interface
|
|
|
|
uses creature_m, math_m;
|
|
|
|
const
|
|
PreviousTraceIdx = 3;
|
|
TraceSymbol = '+';
|
|
|
|
type
|
|
tracePtr = ^trace;
|
|
|
|
trace = record
|
|
x, y: integer;
|
|
prev: tracePtr
|
|
end;
|
|
|
|
function FindIndex(var t: tracePtr; x, y, curIdx: integer): integer;
|
|
function GetLength(var t: tracePtr): integer;
|
|
function IsOnTrace(var cr: creature; t: tracePtr): boolean;
|
|
function IsOnTrace(x, y: integer; t: tracePtr): boolean;
|
|
function
|
|
TraceCrossed(prevX, prevY: integer; var cr: creature; t: tracePtr): boolean;
|
|
procedure ChangeHamsterTrace(var h: creature; var t: tracePtr);
|
|
procedure DecreaseTrace(var hamster: creature; var t: tracePtr);
|
|
procedure DeleteTrace(var t: tracePtr);
|
|
procedure GetStart(var traceStart: tracePtr; t: tracePtr);
|
|
procedure IncreaseTrace(var hamster: creature; var t: tracePtr);
|
|
procedure Pop(var t: tracePtr);
|
|
|
|
implementation
|
|
|
|
uses arena_graphics_m;
|
|
|
|
function GetLength(var t: tracePtr): integer;
|
|
begin
|
|
if t = nil then
|
|
GetLength := 0
|
|
else
|
|
GetLength := 1 + GetLength(t^.prev)
|
|
end;
|
|
|
|
procedure GetStart(var traceStart: tracePtr; t: tracePtr);
|
|
begin
|
|
while t <> nil do
|
|
begin
|
|
if t^.prev = nil then
|
|
traceStart := t;
|
|
t := t^.prev
|
|
end
|
|
end;
|
|
|
|
procedure DeleteTrace(var t: tracePtr);
|
|
var
|
|
tmpT: tracePtr;
|
|
begin
|
|
while t <> nil do
|
|
begin
|
|
tmpT := t^.prev;
|
|
dispose(t);
|
|
t := tmpT
|
|
end
|
|
end;
|
|
|
|
function FindIndex(var t: tracePtr; x, y, curIdx: integer): integer;
|
|
begin
|
|
if t = nil then
|
|
FindIndex := -1
|
|
else
|
|
if (t^.x = x) and (t^.y = y) then
|
|
FindIndex := curIdx
|
|
else
|
|
FindIndex := FindIndex(t^.prev, x, y, curIdx + 1)
|
|
end;
|
|
|
|
function IsOnTrace(x, y: integer; t: tracePtr): boolean;
|
|
begin
|
|
if t = nil then
|
|
IsOnTrace := false
|
|
else
|
|
if (t^.x = x) and (t^.y = y) then
|
|
IsOnTrace := true
|
|
else
|
|
IsOnTrace := IsOnTrace(x, y, t^.prev)
|
|
end;
|
|
|
|
procedure Add(var t: tracePtr; x, y: integer);
|
|
var
|
|
nextTrace: tracePtr;
|
|
begin
|
|
new(nextTrace);
|
|
nextTrace^.x := x;
|
|
nextTrace^.y := y;
|
|
nextTrace^.prev := t;
|
|
t := nextTrace
|
|
end;
|
|
|
|
procedure Pop(var t: tracePtr);
|
|
var
|
|
tmpPrev: tracePtr;
|
|
begin
|
|
tmpPrev := t^.prev;
|
|
dispose(t);
|
|
t := tmpPrev
|
|
end;
|
|
|
|
function IsOnTrace(var cr: creature; t: tracePtr): boolean;
|
|
begin
|
|
IsOnTrace := IsOnTrace(cr.curX, cr.curY, t)
|
|
end;
|
|
|
|
procedure AddStepTrace(var h: creature; var t: tracePtr);
|
|
var
|
|
nextX, nextY, dX, dY: integer;
|
|
begin
|
|
dX := Signum(h.curX, t^.x);
|
|
dY := Signum(h.curY, t^.y);
|
|
nextX := t^.x + dX;
|
|
nextY := t^.y + dY;
|
|
Add(t, nextX, nextY)
|
|
end;
|
|
|
|
procedure AddFirstTrace(var hamster: creature; var t: tracePtr);
|
|
var
|
|
traceX, traceY, dX, dY: integer;
|
|
begin
|
|
dX := Signum(hamster.curX - hamster.dX, hamster.curX) * hamster.movespeed;
|
|
dY := Signum(hamster.curY - hamster.dY, hamster.curY) * hamster.movespeed;
|
|
traceX := hamster.curX + dX;
|
|
traceY := hamster.curY + dY;
|
|
Add(t, traceX, traceY)
|
|
end;
|
|
|
|
procedure IncreaseTrace(var hamster: creature; var t: tracePtr);
|
|
var
|
|
i: integer;
|
|
begin
|
|
if t = nil then
|
|
AddFirstTrace(hamster, t);
|
|
for i := 1 to hamster.movespeed do
|
|
AddStepTrace(hamster, t)
|
|
end;
|
|
|
|
procedure DecreaseTrace(var hamster: creature; var t: tracePtr);
|
|
var
|
|
i: integer;
|
|
begin
|
|
for i := 1 to hamster.movespeed do
|
|
Pop(t);
|
|
if GetLength(t) = 1 then
|
|
Pop(t)
|
|
end;
|
|
|
|
procedure ChangeHamsterTrace(var h: creature; var t: tracePtr);
|
|
begin
|
|
if IsOnTrace(h, t) then
|
|
begin
|
|
EraseStepTrace(h, t);
|
|
DecreaseTrace(h, t)
|
|
end
|
|
else
|
|
begin
|
|
IncreaseTrace(h, t)
|
|
end
|
|
end;
|
|
|
|
function
|
|
TraceCrossed(prevX, prevY: integer; var cr: creature; t: tracePtr): boolean;
|
|
var
|
|
dX, dY: integer;
|
|
begin
|
|
dX := Signum(cr.curX, prevX);
|
|
dY := Signum(cr.curY, prevY);
|
|
while (prevX <> cr.curX) and (prevY <> cr.curY) do
|
|
begin
|
|
if IsOnTrace(prevX, prevY, t) then
|
|
begin
|
|
TraceCrossed := true;
|
|
exit
|
|
end;
|
|
prevX := prevX + dX;
|
|
prevY := prevY + dY
|
|
end;
|
|
TraceCrossed := false
|
|
end;
|
|
|
|
end.
|