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] = magnety) Then Exit; If (cstep <> 0) And (g.map[row, col - cstep] = magnetx) 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.