unit graphics_m; interface uses arena_m, creature_m, hamster_m, trace_m; procedure DrawAfterStep(var hamster: creature; var t: tracePtr; var a: arena); procedure DrawAfterStep(var cr: creature; var a: arena); procedure DrawArenaBorders(var a: arena); procedure DrawArenaCell(arenaX, arenaY: integer; symbol: char); procedure DrawArenaEdges; procedure DrawCreature(var cr: creature); procedure DrawLevel; procedure EraseTrace(var hamster: creature; t: tracePtr); function IsTerminalValid: boolean; procedure PrintTerminalHelp; implementation uses crt, math_m; const InterfaceH = 6; CellSize = 2; BorderSize = 1; ScreenW = (ArenaW - 1) * CellSize + BorderSize * 2; { 79 } ScreenH = (ArenaH + InterfaceH) * CellSize + BorderSize; WidthCoefficient = 2; InterfaceBarH = ScreenW - ArenaH * CellSize - BorderSize * 2; { 14 } function IsTerminalValid: boolean; begin IsTerminalValid := (ScreenWidth >= ScreenW) and (ScreenHeight >= ScreenH) end; procedure PrintTerminalHelp; begin writeln('Increase your terminal size and try again.'); if ScreenWidth < ScreenW then begin writeln('Your terminal width: ', ScreenWidth, '. Required: ', ScreenW, '.') end; if ScreenHeight < ScreenH then begin writeln('Your terminal height: ', ScreenHeight, '. Required: ', ScreenH, '.') end end; procedure DrawLineX(x, y, len: integer); var i: integer; begin GotoXY(x, y); for i := 1 to len do write(BorderSymbol); GotoXY(1, 1) end; procedure DrawLineY(x, y, len: integer); var i: integer; begin for i := 1 to len do begin GotoXY(x, y + i - 1); write(BorderSymbol) end; GotoXY(1, 1) end; procedure DrawRectangle(x0, y0, h, w: integer); var i: integer; begin DrawLineX(x0, y0, w); for i := 1 to h - 2 do begin GotoXY(x0, y0 + i); write(BorderSymbol); GotoXY(x0 + w - 1, y0 + i); write(BorderSymbol) end; DrawLineX(x0, y0 + h - 1, w); GotoXY(1, 1) end; procedure DrawInterface; var cellW: integer = ScreenW div 3; begin DrawLineX(1, InterfaceBarH, ScreenW * WidthCoefficient); DrawLineY(cellW * WidthCoefficient, 1, InterfaceBarH); DrawLineY(cellW * 2 * WidthCoefficient + 1, 1, InterfaceBarH) end; procedure DrawLevel; begin DrawRectangle(1, 1, ScreenH, ScreenW * WidthCoefficient); DrawInterface end; procedure DrawArenaCell(arenaX, arenaY: integer; symbol: char); var i, screenX, screenY: integer; begin screenX := BorderSize + (arenaX - 1) * CellSize * WidthCoefficient; screenY := InterfaceBarH + (arenaY - 1) * CellSize; GotoXY(screenX, screenY); for i := 1 to CellSize * WidthCoefficient do write(symbol); GotoXY(screenX, screenY + 1); { later change to nested for } for i := 1 to CellSize * WidthCoefficient do write(symbol); GotoXY(1, 1) end; procedure DrawArenaEdges; begin DrawRectangle(1, InterfaceBarH, ScreenH - InterfaceBarH + 1, ScreenW * WidthCoefficient) end; procedure DrawLeftEdge(y: integer); var terminalY: integer; begin y := Clamp(y, 1, ArenaH); terminalY := InterfaceBarH + (y - 1) * CellSize; DrawLineY(1, terminalY, CellSize) end; procedure DrawRightEdge(y: integer); var terminalY: integer; begin y := Clamp(y, 1, ArenaH); terminalY := InterfaceBarH + (y - 1) * CellSize; DrawLineY(ScreenW * WidthCoefficient, terminalY, CellSize) end; procedure DrawUpperEdge(x: integer); var terminalX, sizeX: integer; begin x := Clamp(x, 1, ArenaW); terminalX := (x - 1) * CellSize * WidthCoefficient + 1; sizeX := CellSize * WidthCoefficient; DrawLineX(terminalX, InterfaceBarH, sizeX) end; procedure DrawLowerEdge(x: integer); var terminalX, sizeX: integer; begin x := Clamp(x, 1, ArenaW); terminalX := (x - 1) * CellSize * WidthCoefficient + 1; sizeX := CellSize * WidthCoefficient; DrawLineX(terminalX, InterfaceBarH + ArenaH * CellSize - 1, sizeX) end; procedure DrawArenaBorders(var a: arena); var i, j: integer; begin for i := 1 to ArenaH do for j := 1 to ArenaW do if a.borders[j][i] then DrawArenaCell(j, i, BorderSymbol) end; procedure EraseTrace(var hamster: creature; t: tracePtr); var i: integer; begin for i := 1 to HamsterDelta do begin DrawArenaCell(t^.x, t^.y, ArenaSymbol); t := t^.prev end; if GetLength(t) = 1 then begin if IsOnEdge(hamster) then DrawArenaCell(t^.x, t^.y, ArenaSymbol) else DrawArenaCell(t^.x, t^.y, BorderSymbol) end end; procedure EraseCell(x, y: integer); begin DrawArenaCell(x, y, ArenaSymbol) end; procedure DrawEdge(x, y: integer; var a: arena); begin if a.captured[x][y] then DrawArenaCell(x, y, CaptureSymbol) else DrawArenaCell(x, y, ArenaSymbol); if x = 1 then DrawLeftEdge(y); if x = ArenaW then DrawRightEdge(y); if y = 1 then DrawUpperEdge(x); if y = ArenaH then DrawLowerEdge(x) end; procedure DrawCreature(var cr: creature); begin DrawArenaCell(cr.curX, cr.curY, cr.symbol) end; procedure DrawPreviousCell(var hamster: creature; var t: tracePtr; var a: arena); var prevX, prevY: integer; begin prevX := hamster.curX - hamster.dX; prevY := hamster.curY - hamster.dY; if t = nil then DrawEdge(prevX, prevY, a); if (a.borders[prevX][prevY]) and (t = nil) then DrawArenaCell(prevX, prevY, BorderSymbol) end; procedure DrawStepTrace(t: tracePtr); var i: integer; begin for i := 1 to HamsterDelta do begin t := t^.prev; DrawArenaCell(t^.x, t^.y, TraceSymbol) end end; procedure DrawAfterStep(var hamster: creature; var t: tracePtr; var a: arena); var prevX, prevY: integer; begin prevX := hamster.curX - hamster.dX; prevY := hamster.curY - hamster.dY; if IsOnEdge(prevX, prevY) and a.captured[prevX][prevY] then DrawArenaCell(prevX, prevY, CaptureSymbol) else if IsOnBorder(prevX, prevY, a) then DrawArenaCell(prevX, prevY, BorderSymbol) else DrawArenaCell(prevX, prevY, ArenaSymbol); if t <> nil then DrawStepTrace(t); DrawCreature(hamster); DrawPreviousCell(hamster, t, a) end; procedure DrawAfterStep(var cr: creature; var a: arena); var prevX, prevY: integer; begin prevX := cr.curX - cr.dX; prevY := cr.curY - cr.dY; if IsOnEdge(prevX, prevY) and a.captured[prevX][prevY] then DrawArenaCell(prevX, prevY, CaptureSymbol) else if IsOnBorder(prevX, prevY, a) then DrawArenaCell(prevX, prevY, BorderSymbol) else DrawArenaCell(prevX, prevY, ArenaSymbol); DrawCreature(cr) end; end.