You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

152 lines
3.8 KiB

unit moversProc;
interface
uses dataUnit;
procedure moveMovers(var g: GameState);
implementation
function turnMover(c: char; d: integer): char;
const
period = ord(high(TMoverDir))+1;
var
j, x: integer;
i :TMoverType;
begin
for i := low(TMoverType) to high(TMoverType) do
for j := ord(low(TMoverDir)) to ord(high(TMoverDir)) do
if c = movers[i, TMoverDir(j)] then
begin
x := (j+d) mod period;
Exit(movers[i, TMoverDir(x)]);
end;
Exit(c);
end;
procedure rotateStep(var rstep, cstep: integer; clockWise: boolean);
begin
cstep := cstep + rstep;
rstep := cstep - rstep;
cstep := cstep - rstep;
if clockWise then
cstep := -cstep
else
rstep := -rstep;
end;
procedure moveMover(var g: GameState; row, col, rstep, cstep: integer);
var
rns : integer = 0;
cns : integer = 0;
begin
(* I don't move if I'm cought by a magnet *)
If (rstep <> 0) and (g.map[row - rstep, col] = 'Z') then Exit;
If (cstep <> 0) and (g.map[row, col - cstep] = 'N') then Exit;
(* I don't move beyond the map *)
if (col + cstep > g.mapWidth) or (col + cstep < 1) or
(row + rstep > g.mapHeight) or (row + rstep < 1) then
begin
if g.map[row,col] in pushers then
g.map[row, col] := turnMover(g.map[row,col], 2);
Exit;
end;
(* Turners turn me *)
case g.map[row + rstep, col + cstep] of
'a':
begin
g.map[row, col] := turnMover(g.map[row,col], 1);
rotateStep(rstep, cstep, True);
end;
'c':
begin
g.map[row, col] := turnMover(g.map[row,col], -1);
rotateStep(rstep, cstep, False);
end;
end;
(* Simple movement *)
if g.map[row + rstep, col + cstep] = empty then
begin
g.map[row + rstep, col + cstep] := g.map[row,col];
g.map[row, col] := empty;
Exit;
end;
(* Pushers turn around and push pushables *)
if (g.map[row,col] in pushers) then
begin
if (g.map[row + rstep, col + cstep] in pushable) and
(g.map[row + 2 * rstep, col + 2 * cstep] = empty) then
begin
g.map[row + 2 * rstep, col + 2 * cstep] := g.map[row + rstep, col + cstep];
g.map[row + rstep, col + cstep] := empty;
end;
g.map[row, col] := turnMover(g.map[row,col], 2);
Exit;
end;
(* Gliders slip on slipery things*)
if (g.map[row,col] in gliders) and
(g.map[row + rstep, col + cstep] in slipery) then
begin
if cstep <> 0 then
rns := 2 * random(1) - 1
else
cns := 2 * random(1) - 1;
if (g.map[row + rns, col + cns] = empty) and
(g.map[row + rstep + rns, col + cstep + cns] = empty) then
begin
g.map[row + rstep + rns, col + cstep + cns] := g.map[row,col];
g.map[row, col] := empty;
end
else if (g.map[row - rns, col - cns] = empty) and
(g.map[row + rstep - rns, col + cstep - cns] = empty) then
begin
g.map[row + rstep - rns, col + cstep - cns] := g.map[row,col];
g.map[row, col] := empty;
end;
end;
end;
procedure moveMovers(var g: GameState);
var
idx, row, col, Width, Height: integer;
begin
Width := g.mapWidth;
Height := g.mapHeight;
for idx := 0 to Height * Width - 1 do
begin
(* for up movers *)
row := idx div Width + 1;
col := idx mod Width + 1;
if (g.map[row, col] in UpMovers) then
moveMover(g, row, col, -1, 0);
(* for left movers *)
col := idx div Height + 1;
row := idx mod Height + 1;
if (g.map[row, col] in LeftMovers) then
moveMover(g, row, col, 0, -1);
(* for down movers *)
row := Height - idx div Width + 1;
col := Width - idx mod Width + 1;
if (g.map[row, col] in DownMovers) then
moveMover(g, row, col, 1, 0);
(* for Right movers *)
col := Width - idx div Height + 1;
row := Height - idx mod Height + 1;
if (g.map[row, col] in RightMovers) then
moveMover(g, row, col, 0, 1);
end;
end;
end.