278 lines
6.7 KiB
ObjectPascal
278 lines
6.7 KiB
ObjectPascal
|
|
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.
|