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.