2026-02-28 09:28:56 +00:00
|
|
|
program go_hamster;
|
2026-02-28 09:38:37 +00:00
|
|
|
uses crt;
|
|
|
|
|
|
2026-02-28 10:22:41 +00:00
|
|
|
{ Implement figure cuts (check CutField) }
|
|
|
|
|
{ Implement interface }
|
|
|
|
|
{ Implement lifes }
|
|
|
|
|
{ Implement bar }
|
|
|
|
|
{ Implement score }
|
|
|
|
|
{ Implement bonuses }
|
|
|
|
|
{ Implement hamster speed up }
|
|
|
|
|
{ Implement life up }
|
|
|
|
|
{ Implement ghost }
|
|
|
|
|
{ Implement creature death }
|
|
|
|
|
{ Implement enemy slow }
|
|
|
|
|
|
|
|
|
|
{ Implement sun }
|
|
|
|
|
{ Implement snake }
|
|
|
|
|
{ Implement bobr }
|
|
|
|
|
{ Implement hamster animation }
|
|
|
|
|
{ Implement ghost animation }
|
|
|
|
|
{ Implement sun animation }
|
|
|
|
|
{ Implement snake animation }
|
|
|
|
|
{ Implement bobr animation }
|
2026-02-28 10:16:21 +00:00
|
|
|
|
2026-02-28 10:40:16 +00:00
|
|
|
var
|
|
|
|
|
DebugTmp: integer = 2;
|
|
|
|
|
|
2026-02-28 09:38:37 +00:00
|
|
|
const
|
2026-02-28 10:22:41 +00:00
|
|
|
ArenaH = 33;
|
|
|
|
|
ArenaW = 41;
|
|
|
|
|
InterfaceH = 6;
|
2026-02-28 10:16:21 +00:00
|
|
|
CellSize = 2;
|
|
|
|
|
BorderSize = 1;
|
2026-02-28 10:22:41 +00:00
|
|
|
ScreenW = (ArenaW - 1) * CellSize + BorderSize * 2; { 80 }
|
|
|
|
|
ScreenH = (ArenaH + InterfaceH) * CellSize + BorderSize;
|
2026-02-28 09:38:37 +00:00
|
|
|
WidthCoefficient = 2;
|
2026-02-28 10:16:21 +00:00
|
|
|
MinScreenW = ScreenW * WidthCoefficient;
|
2026-02-28 10:22:41 +00:00
|
|
|
InterfaceBarH = ScreenW - ArenaH * CellSize - BorderSize * 2; { 14 }
|
|
|
|
|
BorderSymbol = '#';
|
2026-02-28 10:16:21 +00:00
|
|
|
HamsterSymbol = '*';
|
2026-02-28 10:22:41 +00:00
|
|
|
TraceSymbol = '@';
|
2026-02-28 10:40:16 +00:00
|
|
|
VoidSymbol = '.';
|
2026-02-28 10:22:41 +00:00
|
|
|
DelaySizeMs = 150;
|
|
|
|
|
SpaceOrd = 32;
|
|
|
|
|
EscOrd = 27;
|
|
|
|
|
CtrlCOrd = 3;
|
2026-02-28 10:16:21 +00:00
|
|
|
ArrowLeftOrd = -75;
|
|
|
|
|
ArrowRightOrd = -77;
|
|
|
|
|
ArrowDownOrd = -80;
|
|
|
|
|
ArrowUpOrd = -72;
|
2026-02-28 10:22:41 +00:00
|
|
|
PreviousTraceIdx = 3;
|
|
|
|
|
HamsterDelta = 2;
|
|
|
|
|
DebugMsg = '==============bObr=kUrwa=============';
|
2026-02-28 10:16:21 +00:00
|
|
|
|
|
|
|
|
type
|
2026-02-28 10:22:41 +00:00
|
|
|
creature = record
|
2026-02-28 10:16:21 +00:00
|
|
|
curX, curY, dX, dY: integer;
|
2026-02-28 10:22:41 +00:00
|
|
|
symbol: char
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
tracePtr = ^trace;
|
|
|
|
|
|
|
|
|
|
trace = record
|
2026-02-28 10:40:16 +00:00
|
|
|
x, y: integer;
|
2026-02-28 10:22:41 +00:00
|
|
|
prev: tracePtr
|
2026-02-28 10:16:21 +00:00
|
|
|
end;
|
2026-02-28 09:38:37 +00:00
|
|
|
|
2026-02-28 10:40:16 +00:00
|
|
|
arena = array [1..ArenaW, 1..ArenaH] of boolean;
|
|
|
|
|
|
|
|
|
|
cellItemPtr = ^cellItem;
|
|
|
|
|
|
|
|
|
|
cellItem = record
|
|
|
|
|
x, y: integer;
|
|
|
|
|
next: cellItemPtr
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
QCell = record
|
|
|
|
|
first, last: cellItemPtr
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure DebugCell(curCell: cellItemPtr);
|
|
|
|
|
begin
|
|
|
|
|
GotoXY(2, DebugTmp);
|
|
|
|
|
writeln('Cur X: ', curCell^.x, ' Cur Y: ', curCell^.y);
|
|
|
|
|
DebugTmp := DebugTmp + 1
|
|
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:45:56 +00:00
|
|
|
procedure DebugOrArenas(var a, b: arena);
|
2026-02-28 10:40:16 +00:00
|
|
|
var
|
|
|
|
|
i, j: integer;
|
|
|
|
|
begin
|
|
|
|
|
for i := 1 to ArenaH do
|
|
|
|
|
begin
|
|
|
|
|
for j := 1 to ArenaW do
|
|
|
|
|
if a[j][i] or b[j][i] then
|
|
|
|
|
write(1, ' ')
|
|
|
|
|
else
|
|
|
|
|
write(0, ' ');
|
|
|
|
|
writeln
|
|
|
|
|
end
|
|
|
|
|
end;
|
2026-02-28 10:22:41 +00:00
|
|
|
|
2026-02-28 10:45:56 +00:00
|
|
|
procedure DebugPrintArena(var a: arena);
|
|
|
|
|
var
|
|
|
|
|
i, j: integer;
|
|
|
|
|
begin
|
|
|
|
|
for i := 1 to ArenaH do
|
|
|
|
|
begin
|
|
|
|
|
for j := 1 to ArenaW do
|
|
|
|
|
if a[j][i] then
|
|
|
|
|
write(1, ' ')
|
|
|
|
|
else
|
|
|
|
|
write(0, ' ');
|
|
|
|
|
writeln
|
|
|
|
|
end
|
|
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:16:21 +00:00
|
|
|
function IsTerminalValid: boolean;
|
2026-02-28 09:28:56 +00:00
|
|
|
begin
|
2026-02-28 10:42:30 +00:00
|
|
|
IsTerminalValid := (ScreenWidth >= ScreenW) and (ScreenHeight >= ScreenH)
|
2026-02-28 09:38:37 +00:00
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:16:21 +00:00
|
|
|
procedure PrintTerminalHelp;
|
2026-02-28 09:38:37 +00:00
|
|
|
begin
|
2026-02-28 10:16:21 +00:00
|
|
|
writeln('Increase your terminal size and try again.');
|
2026-02-28 10:22:41 +00:00
|
|
|
if ScreenWidth < ScreenW then
|
2026-02-28 09:38:37 +00:00
|
|
|
begin
|
2026-02-28 10:16:21 +00:00
|
|
|
writeln('Your terminal width: ', ScreenWidth,
|
2026-02-28 10:22:41 +00:00
|
|
|
'. Required: ', ScreenW, '.')
|
2026-02-28 09:38:37 +00:00
|
|
|
end;
|
2026-02-28 10:22:41 +00:00
|
|
|
if ScreenHeight < ScreenH then
|
2026-02-28 09:38:37 +00:00
|
|
|
begin
|
2026-02-28 10:16:21 +00:00
|
|
|
writeln('Your terminal height: ', ScreenHeight,
|
2026-02-28 10:22:41 +00:00
|
|
|
'. Required: ', ScreenH, '.')
|
2026-02-28 09:38:37 +00:00
|
|
|
end
|
|
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:16:21 +00:00
|
|
|
procedure GetKey(var keyCode: integer);
|
|
|
|
|
var
|
2026-02-28 09:38:37 +00:00
|
|
|
c: char;
|
|
|
|
|
begin
|
|
|
|
|
c := ReadKey;
|
|
|
|
|
if c = #0 then
|
|
|
|
|
begin
|
|
|
|
|
c := ReadKey;
|
2026-02-28 10:16:21 +00:00
|
|
|
keyCode := -ord(c)
|
2026-02-28 09:38:37 +00:00
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
2026-02-28 10:16:21 +00:00
|
|
|
keyCode := ord(c)
|
2026-02-28 09:38:37 +00:00
|
|
|
end
|
|
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:16:21 +00:00
|
|
|
procedure DrawLineX(x, y, len: integer);
|
2026-02-28 09:38:37 +00:00
|
|
|
var
|
|
|
|
|
i: integer;
|
|
|
|
|
begin
|
|
|
|
|
GotoXY(x, y);
|
|
|
|
|
for i := 1 to len do
|
2026-02-28 10:22:41 +00:00
|
|
|
write(BorderSymbol);
|
2026-02-28 09:38:37 +00:00
|
|
|
GotoXY(1, 1)
|
|
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:16:21 +00:00
|
|
|
procedure DrawLineY(x, y, len: integer);
|
|
|
|
|
var
|
|
|
|
|
i: integer;
|
2026-02-28 09:38:37 +00:00
|
|
|
begin
|
2026-02-28 10:16:21 +00:00
|
|
|
for i := 1 to len do
|
|
|
|
|
begin
|
|
|
|
|
GotoXY(x, y + i - 1);
|
2026-02-28 10:22:41 +00:00
|
|
|
write(BorderSymbol)
|
2026-02-28 10:16:21 +00:00
|
|
|
end;
|
|
|
|
|
GotoXY(1, 1)
|
2026-02-28 09:38:37 +00:00
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:16:21 +00:00
|
|
|
procedure DrawRectangle(x0, y0, h, w: integer);
|
2026-02-28 09:38:37 +00:00
|
|
|
var
|
|
|
|
|
i: integer;
|
|
|
|
|
begin
|
2026-02-28 10:16:21 +00:00
|
|
|
DrawLineX(x0, y0, w);
|
|
|
|
|
for i := 1 to h - 2 do
|
2026-02-28 09:38:37 +00:00
|
|
|
begin
|
|
|
|
|
GotoXY(x0, y0 + i);
|
2026-02-28 10:22:41 +00:00
|
|
|
write(BorderSymbol);
|
2026-02-28 10:16:21 +00:00
|
|
|
GotoXY(x0 + w - 1, y0 + i);
|
2026-02-28 10:22:41 +00:00
|
|
|
write(BorderSymbol)
|
2026-02-28 09:38:37 +00:00
|
|
|
end;
|
2026-02-28 10:16:21 +00:00
|
|
|
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;
|
|
|
|
|
|
2026-02-28 10:22:41 +00:00
|
|
|
procedure DrawInterface(ScreenH, ScreenW: integer);
|
2026-02-28 10:16:21 +00:00
|
|
|
begin
|
2026-02-28 10:22:41 +00:00
|
|
|
DrawRectangle(1, 1, ScreenH, ScreenW * WidthCoefficient);
|
2026-02-28 09:38:37 +00:00
|
|
|
DrawInterface
|
|
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:40:16 +00:00
|
|
|
procedure FillArena(var a: arena; val: boolean);
|
|
|
|
|
var
|
|
|
|
|
i, j: integer;
|
|
|
|
|
begin
|
|
|
|
|
for i := 1 to ArenaW do
|
|
|
|
|
for j := 1 to ArenaH do
|
|
|
|
|
a[i][j] := val
|
|
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:22:41 +00:00
|
|
|
procedure
|
|
|
|
|
InitiateCreature(var cr: creature; curX, curY, dX, dY: integer; symbol: char);
|
2026-02-28 10:16:21 +00:00
|
|
|
begin
|
2026-02-28 10:22:41 +00:00
|
|
|
cr.curX := curX;
|
|
|
|
|
cr.curY := curY;
|
|
|
|
|
cr.dX := dX;
|
|
|
|
|
cr.dY := dY;
|
|
|
|
|
cr.symbol := symbol
|
2026-02-28 10:16:21 +00:00
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:45:56 +00:00
|
|
|
function IsOnEdge(var cr: creature): boolean;
|
|
|
|
|
begin
|
|
|
|
|
IsOnEdge :=
|
|
|
|
|
(cr.curX = 1) or (cr.curX = ArenaW) or (cr.curY = 1) or
|
|
|
|
|
(cr.curY = ArenaH)
|
|
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:42:30 +00:00
|
|
|
function IsOnBorder(var cr: creature; var borders, captured: arena): boolean;
|
2026-02-28 10:22:41 +00:00
|
|
|
begin
|
|
|
|
|
IsOnBorder :=
|
2026-02-28 10:42:30 +00:00
|
|
|
borders[cr.curX][cr.curY] and (
|
2026-02-28 10:45:56 +00:00
|
|
|
captured[cr.curX - 1][cr.curY + 1] or
|
|
|
|
|
captured[cr.curX - 1][cr.curY - 1] or
|
|
|
|
|
captured[cr.curX + 1][cr.curY + 1] or
|
|
|
|
|
captured[cr.curX + 1][cr.curY - 1]
|
2026-02-28 10:42:30 +00:00
|
|
|
)
|
2026-02-28 10:22:41 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure FillArenaCell(arenaX, arenaY: integer; symbol: char);
|
2026-02-28 10:16:21 +00:00
|
|
|
var
|
2026-02-28 10:22:41 +00:00
|
|
|
i, screenX, screenY: integer;
|
2026-02-28 10:16:21 +00:00
|
|
|
begin
|
2026-02-28 10:22:41 +00:00
|
|
|
screenX := BorderSize + (arenaX - 1) * CellSize * WidthCoefficient;
|
|
|
|
|
screenY := InterfaceBarH + (arenaY - 1) * CellSize;
|
|
|
|
|
GotoXY(screenX, screenY);
|
2026-02-28 10:16:21 +00:00
|
|
|
for i := 1 to CellSize * WidthCoefficient do
|
2026-02-28 10:22:41 +00:00
|
|
|
write(symbol);
|
|
|
|
|
GotoXY(screenX, screenY + 1); { later change to nested for }
|
2026-02-28 10:16:21 +00:00
|
|
|
for i := 1 to CellSize * WidthCoefficient do
|
2026-02-28 10:22:41 +00:00
|
|
|
write(symbol);
|
|
|
|
|
GotoXY(1, 1)
|
|
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:40:16 +00:00
|
|
|
function GetTraceLength(var t: tracePtr): integer;
|
|
|
|
|
begin
|
|
|
|
|
if t = nil then
|
|
|
|
|
GetTraceLength := 0
|
|
|
|
|
else
|
|
|
|
|
GetTraceLength := 1 + GetTraceLength(t^.prev)
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function NewCellItem(x, y: integer): cellItemPtr;
|
2026-02-28 10:22:41 +00:00
|
|
|
var
|
2026-02-28 10:40:16 +00:00
|
|
|
newCell: cellItemPtr;
|
|
|
|
|
begin
|
|
|
|
|
new(newCell);
|
|
|
|
|
newCell^.x := x;
|
|
|
|
|
newCell^.y := y;
|
|
|
|
|
newCell^.next := nil;
|
|
|
|
|
NewCellItem := newCell
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure InitCell(var c: cellItem; x, y: integer);
|
|
|
|
|
begin
|
|
|
|
|
c.x := x;
|
|
|
|
|
c.y := y;
|
|
|
|
|
c.next := nil
|
|
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:45:56 +00:00
|
|
|
procedure GetFiguresCells(var t: tracePtr; var figure1, figure2: cellItem;
|
|
|
|
|
var captured: arena);
|
|
|
|
|
var
|
|
|
|
|
prevTrace: tracePtr;
|
2026-02-28 10:40:16 +00:00
|
|
|
begin
|
2026-02-28 10:45:56 +00:00
|
|
|
prevTrace := t^.prev;
|
|
|
|
|
{if (t^.x = 1) or (t^.x = ArenaW) or
|
|
|
|
|
(t^.y <> 1) and captured[prevTrace^.x][prevTrace^.y - 1] or
|
|
|
|
|
(t^.y <> ArenaH) and captured[prevTrace^.x][prevTrace^.y + 1] then}
|
|
|
|
|
if t^.y = prevTrace^.y then
|
2026-02-28 10:40:16 +00:00
|
|
|
begin
|
2026-02-28 10:45:56 +00:00
|
|
|
InitCell(figure1, prevTrace^.x, prevTrace^.y - 1);
|
|
|
|
|
InitCell(figure2, prevTrace^.x, prevTrace^.y + 1)
|
2026-02-28 10:40:16 +00:00
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
2026-02-28 10:45:56 +00:00
|
|
|
InitCell(figure1, prevTrace^.x - 1, prevTrace^.y);
|
|
|
|
|
InitCell(figure2, prevTrace^.x + 1, prevTrace^.y)
|
2026-02-28 10:40:16 +00:00
|
|
|
end
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure QCellInit(var q: QCell);
|
|
|
|
|
begin
|
|
|
|
|
q.first := nil;
|
|
|
|
|
q.last := nil
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure QCellPush(var q: QCell; var c: cellItem);
|
|
|
|
|
begin
|
|
|
|
|
if q.last = nil then
|
|
|
|
|
begin
|
|
|
|
|
new(q.first);
|
|
|
|
|
q.first^.x := c.x;
|
|
|
|
|
q.first^.y := c.y;
|
|
|
|
|
q.first^.next := nil;
|
|
|
|
|
q.last := q.first
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
new(q.last^.next);
|
|
|
|
|
q.last := q.last^.next;
|
|
|
|
|
q.last^.x := c.x;
|
|
|
|
|
q.last^.y := c.y;
|
|
|
|
|
q.last^.next := nil
|
|
|
|
|
end
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function QCellIsEmpty(var q: QCell): boolean;
|
|
|
|
|
begin
|
|
|
|
|
QCellIsEmpty := (q.last = nil)
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function QCellGet(var q: QCell): cellItemPtr;
|
|
|
|
|
begin
|
|
|
|
|
QCellGet := q.first
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function IsCellFree(x, y: integer; var borders, captured: arena): boolean;
|
|
|
|
|
begin
|
|
|
|
|
IsCellFree :=
|
|
|
|
|
(x <> 0) and (x <> ArenaW + 1) and
|
|
|
|
|
(y <> 0) and (y <> ArenaH + 1) and
|
|
|
|
|
not captured[x][y] and not borders[x][y]
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure QCellPop(var q: QCell);
|
|
|
|
|
var
|
|
|
|
|
removeItem: cellItemPtr;
|
|
|
|
|
begin
|
|
|
|
|
removeItem := QCellGet(q);
|
|
|
|
|
q.first := removeItem^.next;
|
|
|
|
|
if q.first = nil then
|
|
|
|
|
q.last := q.first;
|
|
|
|
|
dispose(removeItem)
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure AddAvailableNeighbours(var q: QCell; var curCell: cellItemPtr;
|
|
|
|
|
var borders, captured: arena);
|
|
|
|
|
var
|
|
|
|
|
addCell: cellItem;
|
|
|
|
|
begin
|
|
|
|
|
if IsCellFree(curCell^.x - 1, curCell^.y, borders, captured) then
|
|
|
|
|
begin
|
|
|
|
|
InitCell(addCell, curCell^.x - 1, curCell^.y);
|
|
|
|
|
captured[addCell.x][addCell.y] := true;
|
|
|
|
|
QCellPush(q, addCell)
|
|
|
|
|
end;
|
|
|
|
|
if IsCellFree(curCell^.x + 1, curCell^.y, borders, captured) then
|
|
|
|
|
begin
|
|
|
|
|
InitCell(addCell, curCell^.x + 1, curCell^.y);
|
|
|
|
|
captured[addCell.x][addCell.y] := true;
|
|
|
|
|
QCellPush(q, addCell)
|
|
|
|
|
end;
|
|
|
|
|
if IsCellFree(curCell^.x, curCell^.y - 1, borders, captured) then
|
|
|
|
|
begin
|
|
|
|
|
InitCell(addCell, curCell^.x, curCell^.y - 1);
|
|
|
|
|
captured[addCell.x][addCell.y] := true;
|
|
|
|
|
QCellPush(q, addCell)
|
|
|
|
|
end;
|
|
|
|
|
if IsCellFree(curCell^.x, curCell^.y + 1, borders, captured) then
|
|
|
|
|
begin
|
|
|
|
|
InitCell(addCell, curCell^.x, curCell^.y + 1);
|
|
|
|
|
captured[addCell.x][addCell.y] := true;
|
|
|
|
|
QCellPush(q, addCell)
|
|
|
|
|
end
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
{ Kind of bfs algorithm. }
|
2026-02-28 10:42:30 +00:00
|
|
|
procedure CaptureFigure(var startCell: cellItem; var capturedN: integer;
|
2026-02-28 10:40:16 +00:00
|
|
|
var borders, captured: arena);
|
|
|
|
|
var
|
|
|
|
|
curCell: cellItemPtr;
|
|
|
|
|
q: QCell;
|
|
|
|
|
begin
|
2026-02-28 10:42:30 +00:00
|
|
|
capturedN := 0;
|
2026-02-28 10:40:16 +00:00
|
|
|
QCellInit(q);
|
|
|
|
|
QCellPush(q, startCell);
|
|
|
|
|
captured[startCell.x][startCell.y] := true;
|
|
|
|
|
while not QCellIsEmpty(q) do
|
|
|
|
|
begin
|
2026-02-28 10:42:30 +00:00
|
|
|
capturedN := capturedN + 1;
|
2026-02-28 10:40:16 +00:00
|
|
|
curCell := QCellGet(q);
|
|
|
|
|
AddAvailableNeighbours(q, curCell, borders, captured);
|
|
|
|
|
{
|
|
|
|
|
clrscr;
|
|
|
|
|
writeln('x: ', curCell^.x, ' y: ', curCell^.y);
|
2026-02-28 10:45:56 +00:00
|
|
|
DebugOrArenas(borders, captured);
|
2026-02-28 10:40:16 +00:00
|
|
|
}
|
|
|
|
|
QCellPop(q)
|
|
|
|
|
end
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function IsCellCaptured(x, y: integer; var captured: arena): boolean;
|
|
|
|
|
begin
|
|
|
|
|
IsCellCaptured :=
|
|
|
|
|
(x <> 0) and (x <> ArenaW + 1) and
|
|
|
|
|
(y <> 0) and (y <> ArenaH + 1) and
|
|
|
|
|
captured[x][y]
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure BfsReleaseCell(x, y: integer; var q: QCell; var captured: arena);
|
|
|
|
|
var
|
|
|
|
|
addCell: cellItem;
|
|
|
|
|
begin
|
|
|
|
|
InitCell(addCell, x, y);
|
|
|
|
|
QCellPush(q, addCell);
|
|
|
|
|
captured[x][y] := false
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure AddCapturedNeighbours(var q: QCell; var curCell: cellItemPtr;
|
|
|
|
|
var captured: arena);
|
|
|
|
|
var
|
|
|
|
|
addCell: cellItem;
|
|
|
|
|
begin
|
|
|
|
|
if IsCellCaptured(curCell^.x - 1, curCell^.y, captured) then
|
|
|
|
|
begin
|
|
|
|
|
InitCell(addCell, curCell^.x - 1, curCell^.y);
|
|
|
|
|
captured[addCell.x][addCell.y] := false;
|
|
|
|
|
QCellPush(q, addCell)
|
|
|
|
|
end;
|
|
|
|
|
if IsCellCaptured(curCell^.x + 1, curCell^.y, captured) then
|
|
|
|
|
begin
|
|
|
|
|
InitCell(addCell, curCell^.x + 1, curCell^.y);
|
|
|
|
|
captured[addCell.x][addCell.y] := false;
|
|
|
|
|
QCellPush(q, addCell)
|
|
|
|
|
end;
|
|
|
|
|
if IsCellCaptured(curCell^.x, curCell^.y - 1, captured) then
|
|
|
|
|
begin
|
|
|
|
|
InitCell(addCell, curCell^.x, curCell^.y - 1);
|
|
|
|
|
captured[addCell.x][addCell.y] := false;
|
|
|
|
|
QCellPush(q, addCell)
|
|
|
|
|
end;
|
|
|
|
|
if IsCellCaptured(curCell^.x, curCell^.y + 1, captured) then
|
|
|
|
|
begin
|
|
|
|
|
InitCell(addCell, curCell^.x, curCell^.y + 1);
|
|
|
|
|
captured[addCell.x][addCell.y] := false;
|
|
|
|
|
QCellPush(q, addCell)
|
|
|
|
|
end
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure ReleaseFigure(var startCell: cellItem; var captured: arena);
|
|
|
|
|
var
|
|
|
|
|
curCell: cellItemPtr;
|
|
|
|
|
q: QCell;
|
|
|
|
|
begin
|
|
|
|
|
QCellInit(q);
|
|
|
|
|
QCellPush(q, startCell);
|
|
|
|
|
while not QCellIsEmpty(q) do
|
|
|
|
|
begin
|
|
|
|
|
curCell := QCellGet(q);
|
|
|
|
|
AddCapturedNeighbours(q, curCell, captured);
|
|
|
|
|
QCellPop(q)
|
|
|
|
|
end
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure FillCaptured(var borders, captured: arena);
|
|
|
|
|
var
|
|
|
|
|
i, j: integer;
|
|
|
|
|
begin
|
|
|
|
|
for i := 1 to ArenaH do
|
|
|
|
|
for j := 1 to ArenaW do
|
2026-02-28 10:42:30 +00:00
|
|
|
if captured[j][i] then
|
2026-02-28 10:40:16 +00:00
|
|
|
FillArenaCell(j, i, VoidSymbol)
|
2026-02-28 10:42:30 +00:00
|
|
|
else
|
|
|
|
|
if borders[j][i] then
|
|
|
|
|
FillArenaCell(j, i, BorderSymbol)
|
2026-02-28 10:40:16 +00:00
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:42:30 +00:00
|
|
|
procedure CutField(var t: tracePtr; var borders, captured: arena);
|
2026-02-28 10:40:16 +00:00
|
|
|
var
|
2026-02-28 10:42:30 +00:00
|
|
|
captured1, captured2: integer;
|
2026-02-28 10:40:16 +00:00
|
|
|
figure1, figure2: cellItem;
|
|
|
|
|
begin
|
2026-02-28 10:45:56 +00:00
|
|
|
GetFiguresCells(t, figure1, figure2, captured);
|
2026-02-28 10:42:30 +00:00
|
|
|
if captured[figure1.x][figure1.y] then
|
|
|
|
|
begin
|
|
|
|
|
CaptureFigure(figure2, captured2, borders, captured)
|
|
|
|
|
end
|
2026-02-28 10:40:16 +00:00
|
|
|
else
|
2026-02-28 10:42:30 +00:00
|
|
|
if captured[figure2.x][figure2.y] then
|
|
|
|
|
begin
|
|
|
|
|
CaptureFigure(figure1, captured1, borders, captured)
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
CaptureFigure(figure1, captured1, borders, captured);
|
|
|
|
|
CaptureFigure(figure2, captured2, borders, captured);
|
|
|
|
|
if captured1 <= captured2 then
|
|
|
|
|
ReleaseFigure(figure2, captured)
|
|
|
|
|
else
|
|
|
|
|
ReleaseFigure(figure1, captured)
|
|
|
|
|
end;
|
2026-02-28 10:40:16 +00:00
|
|
|
|
|
|
|
|
{ Later move to another subroutine }
|
2026-02-28 10:42:30 +00:00
|
|
|
FillCaptured(borders, captured)
|
2026-02-28 10:40:16 +00:00
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:45:56 +00:00
|
|
|
procedure RemoveCutedBorders(var borders, captured: arena);
|
|
|
|
|
var
|
|
|
|
|
i, j: integer;
|
|
|
|
|
begin
|
|
|
|
|
for i := 1 to ArenaH do
|
|
|
|
|
for j := 1 to ArenaW do
|
|
|
|
|
if borders[j][i] and
|
|
|
|
|
(((j = 1) or (i = 1) or captured[j - 1][i - 1] or borders[j - 1][i - 1]) and
|
|
|
|
|
((i = 1) or captured[j + 1][i - 1] or borders[j + 1][i - 1]) and
|
|
|
|
|
((j = 1) or captured[j - 1][i + 1] or borders[j - 1][i + 1]) and
|
|
|
|
|
(captured[j + 1][i + 1] or borders[j + 1][i + 1])) then
|
|
|
|
|
begin
|
|
|
|
|
borders[j][i] := false;
|
|
|
|
|
captured[j][i] := true;
|
|
|
|
|
FillArenaCell(j, i, VoidSymbol)
|
|
|
|
|
end
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure DisposeTraces(var t: tracePtr);
|
2026-02-28 10:40:16 +00:00
|
|
|
var
|
|
|
|
|
tmpT: tracePtr;
|
2026-02-28 10:22:41 +00:00
|
|
|
begin
|
|
|
|
|
while t <> nil do
|
|
|
|
|
begin
|
2026-02-28 10:40:16 +00:00
|
|
|
tmpT := t^.prev;
|
2026-02-28 10:22:41 +00:00
|
|
|
dispose(t);
|
2026-02-28 10:40:16 +00:00
|
|
|
t := tmpT
|
2026-02-28 10:22:41 +00:00
|
|
|
end
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function IsTraceExists(var t: tracePtr; x, y: integer): boolean;
|
|
|
|
|
begin
|
|
|
|
|
if t = nil then
|
|
|
|
|
IsTraceExists := false
|
|
|
|
|
else
|
2026-02-28 10:40:16 +00:00
|
|
|
if (t^.x = x) and (t^.y = y) then
|
2026-02-28 10:22:41 +00:00
|
|
|
IsTraceExists := true
|
|
|
|
|
else
|
|
|
|
|
IsTraceExists := IsTraceExists(t^.prev, x, y)
|
|
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:42:30 +00:00
|
|
|
function FindTraceIdx(var t: tracePtr; x, y, curIdx: integer): integer;
|
2026-02-28 10:22:41 +00:00
|
|
|
begin
|
|
|
|
|
if t = nil then
|
2026-02-28 10:42:30 +00:00
|
|
|
FindTraceIdx := -1
|
2026-02-28 10:22:41 +00:00
|
|
|
else
|
2026-02-28 10:40:16 +00:00
|
|
|
if (t^.x = x) and (t^.y = y) then
|
2026-02-28 10:42:30 +00:00
|
|
|
FindTraceIdx := curIdx
|
2026-02-28 10:22:41 +00:00
|
|
|
else
|
2026-02-28 10:42:30 +00:00
|
|
|
FindTraceIdx := FindTraceIdx(t^.prev, x, y, curIdx + 1)
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function Clamp(val, min, max: integer): integer;
|
|
|
|
|
begin
|
|
|
|
|
Clamp := val;
|
|
|
|
|
if val < min then
|
|
|
|
|
Clamp := min;
|
|
|
|
|
if val > max then
|
|
|
|
|
Clamp := max
|
2026-02-28 10:16:21 +00:00
|
|
|
end;
|
2026-02-28 09:38:37 +00:00
|
|
|
|
2026-02-28 10:40:16 +00:00
|
|
|
function { continue here }
|
|
|
|
|
HamsterMovePossible(var h: creature; var t: tracePtr; var captured: arena):
|
|
|
|
|
boolean;
|
2026-02-28 09:38:37 +00:00
|
|
|
var
|
2026-02-28 10:22:41 +00:00
|
|
|
nextX, nextY, idx: integer;
|
|
|
|
|
begin
|
2026-02-28 10:42:30 +00:00
|
|
|
nextX := Clamp(h.curX + h.dX, 1, ArenaW);
|
|
|
|
|
nextY := Clamp(h.curY + h.dY, 1, ArenaH);
|
|
|
|
|
idx := FindTraceIdx(t, nextX, nextY, 1);
|
|
|
|
|
HamsterMovePossible :=
|
|
|
|
|
(idx <= PreviousTraceIdx) and not captured[nextX][nextY]
|
2026-02-28 10:22:41 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure StopCreature(var cr: creature);
|
|
|
|
|
begin
|
|
|
|
|
cr.dX := 0;
|
|
|
|
|
cr.dY := 0
|
|
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:45:56 +00:00
|
|
|
procedure DrawArenaEdge;
|
2026-02-28 09:38:37 +00:00
|
|
|
begin
|
2026-02-28 10:22:41 +00:00
|
|
|
DrawRectangle(1, InterfaceBarH,
|
|
|
|
|
ScreenH - InterfaceBarH + 1, ScreenW * WidthCoefficient)
|
2026-02-28 10:16:21 +00:00
|
|
|
end;
|
2026-02-28 09:38:37 +00:00
|
|
|
|
2026-02-28 10:45:56 +00:00
|
|
|
procedure DrawArenaBorders(var borders: arena);
|
|
|
|
|
var
|
|
|
|
|
i, j: integer;
|
|
|
|
|
begin
|
|
|
|
|
for i := 1 to ArenaH do
|
|
|
|
|
for j := 1 to ArenaW do
|
|
|
|
|
if borders[j][i] then
|
|
|
|
|
FillArenaCell(j, i, BorderSymbol)
|
|
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:22:41 +00:00
|
|
|
procedure UpdateDelta(keyCode: integer; var cr: creature); { Refactor later }
|
2026-02-28 10:16:21 +00:00
|
|
|
begin
|
|
|
|
|
case keyCode of
|
|
|
|
|
ArrowLeftOrd:
|
|
|
|
|
begin
|
2026-02-28 10:22:41 +00:00
|
|
|
cr.dX := -HamsterDelta;
|
|
|
|
|
cr.dY := 0
|
2026-02-28 10:16:21 +00:00
|
|
|
end;
|
|
|
|
|
ArrowRightOrd:
|
|
|
|
|
begin
|
2026-02-28 10:22:41 +00:00
|
|
|
cr.dX := HamsterDelta;
|
|
|
|
|
cr.dY := 0
|
2026-02-28 10:16:21 +00:00
|
|
|
end;
|
|
|
|
|
ArrowUpOrd:
|
|
|
|
|
begin
|
2026-02-28 10:22:41 +00:00
|
|
|
cr.dX := 0;
|
|
|
|
|
cr.dY := -HamsterDelta
|
2026-02-28 10:16:21 +00:00
|
|
|
end;
|
|
|
|
|
ArrowDownOrd:
|
|
|
|
|
begin
|
2026-02-28 10:22:41 +00:00
|
|
|
cr.dX := 0;
|
|
|
|
|
cr.dY := HamsterDelta
|
|
|
|
|
end;
|
|
|
|
|
SpaceOrd:
|
|
|
|
|
StopCreature(cr)
|
|
|
|
|
end
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure MoveCreature(var cr: creature);
|
|
|
|
|
begin
|
|
|
|
|
cr.curX := Clamp(cr.curX + cr.dX, 1, ArenaW);
|
|
|
|
|
cr.curY := Clamp(cr.curY + cr.dY, 1, ArenaH)
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure AddTrace(var t: tracePtr; nextX, nextY: integer);
|
|
|
|
|
var
|
|
|
|
|
nextTrace: tracePtr;
|
|
|
|
|
begin
|
|
|
|
|
new(nextTrace);
|
2026-02-28 10:40:16 +00:00
|
|
|
nextTrace^.x := nextX;
|
|
|
|
|
nextTrace^.y := nextY;
|
2026-02-28 10:22:41 +00:00
|
|
|
nextTrace^.prev := t;
|
|
|
|
|
t := nextTrace
|
|
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:40:16 +00:00
|
|
|
procedure
|
2026-02-28 10:42:30 +00:00
|
|
|
AddBorderTrace(var t: tracePtr; var hamster: creature; var borders: arena);
|
2026-02-28 10:22:41 +00:00
|
|
|
begin
|
|
|
|
|
if hamster.dX = 2 then
|
|
|
|
|
AddTrace(t, hamster.curX - 2, hamster.curY)
|
|
|
|
|
else
|
|
|
|
|
if hamster.dX = -2 then
|
|
|
|
|
AddTrace(t, hamster.curX + 2, hamster.curY)
|
|
|
|
|
else
|
|
|
|
|
if hamster.dY = 2 then
|
|
|
|
|
AddTrace(t, hamster.curX, hamster.curY - 2)
|
|
|
|
|
else
|
|
|
|
|
AddTrace(t, hamster.curX, hamster.curY + 2);
|
2026-02-28 10:40:16 +00:00
|
|
|
FillArenaCell(t^.x, t^.y, TraceSymbol);
|
2026-02-28 10:42:30 +00:00
|
|
|
borders[t^.x][t^.y] := true
|
2026-02-28 10:22:41 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function IsOnTrace(var t: tracePtr; var cr: creature): boolean;
|
|
|
|
|
begin
|
2026-02-28 10:40:16 +00:00
|
|
|
if t = nil then
|
|
|
|
|
IsOnTrace := false
|
|
|
|
|
else
|
|
|
|
|
if (t^.x = cr.curX) and (t^.y = cr.curY) then
|
|
|
|
|
IsOnTrace := true
|
|
|
|
|
else
|
|
|
|
|
IsOnTrace := IsOnTrace(t^.prev, cr)
|
2026-02-28 10:16:21 +00:00
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:22:41 +00:00
|
|
|
procedure PopTrace(var t: tracePtr);
|
|
|
|
|
var
|
|
|
|
|
tmpPrev: tracePtr;
|
|
|
|
|
begin
|
|
|
|
|
tmpPrev := t^.prev;
|
|
|
|
|
dispose(t);
|
|
|
|
|
t := tmpPrev
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure PopHamsterTrace(var t: tracePtr; var a: arena);
|
|
|
|
|
begin
|
2026-02-28 10:40:16 +00:00
|
|
|
FillArenaCell(t^.x, t^.y, ' ');
|
|
|
|
|
a[t^.x][t^.y] := false;
|
2026-02-28 10:22:41 +00:00
|
|
|
PopTrace(t)
|
|
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:40:16 +00:00
|
|
|
procedure
|
2026-02-28 10:42:30 +00:00
|
|
|
AddHamsterTrace(var t: tracePtr; var h: creature; var borders: arena);
|
2026-02-28 10:22:41 +00:00
|
|
|
var
|
|
|
|
|
nextX, nextY: integer;
|
|
|
|
|
begin
|
2026-02-28 10:40:16 +00:00
|
|
|
if h.curX > t^.x then
|
2026-02-28 10:22:41 +00:00
|
|
|
begin { to right }
|
2026-02-28 10:40:16 +00:00
|
|
|
nextX := t^.x + 1;
|
|
|
|
|
nextY := t^.y
|
2026-02-28 10:22:41 +00:00
|
|
|
end
|
|
|
|
|
else
|
2026-02-28 10:40:16 +00:00
|
|
|
if h.curX < t^.x then
|
2026-02-28 10:22:41 +00:00
|
|
|
begin { to left }
|
2026-02-28 10:40:16 +00:00
|
|
|
nextX := t^.x - 1;
|
|
|
|
|
nextY := t^.y
|
2026-02-28 10:22:41 +00:00
|
|
|
end
|
|
|
|
|
else
|
2026-02-28 10:40:16 +00:00
|
|
|
if h.curY > t^.y then
|
2026-02-28 10:22:41 +00:00
|
|
|
begin { to down }
|
2026-02-28 10:40:16 +00:00
|
|
|
nextX := t^.x;
|
|
|
|
|
nextY := t^.y + 1
|
2026-02-28 10:22:41 +00:00
|
|
|
end
|
|
|
|
|
else
|
2026-02-28 10:40:16 +00:00
|
|
|
if h.curY < t^.y then
|
2026-02-28 10:22:41 +00:00
|
|
|
begin { to up }
|
2026-02-28 10:40:16 +00:00
|
|
|
nextX := t^.x;
|
|
|
|
|
nextY := t^.y - 1
|
2026-02-28 10:22:41 +00:00
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
nextX := h.curX;
|
|
|
|
|
nextY := h.curY
|
|
|
|
|
end;
|
|
|
|
|
AddTrace(t, nextX, nextY);
|
2026-02-28 10:40:16 +00:00
|
|
|
FillArenaCell(t^.x, t^.y, TraceSymbol);
|
2026-02-28 10:42:30 +00:00
|
|
|
borders[t^.x][t^.y] := true
|
2026-02-28 10:22:41 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure
|
|
|
|
|
ChangeHamsterTrace(var t: tracePtr; var h: creature;
|
2026-02-28 10:45:56 +00:00
|
|
|
var borders: arena; var redrawEdge: boolean);
|
2026-02-28 10:22:41 +00:00
|
|
|
var
|
|
|
|
|
i: integer;
|
2026-02-28 10:16:21 +00:00
|
|
|
begin
|
2026-02-28 10:22:41 +00:00
|
|
|
if IsOnTrace(t, h) then
|
|
|
|
|
begin
|
2026-02-28 10:40:16 +00:00
|
|
|
for i := 1 to HamsterDelta do
|
2026-02-28 10:42:30 +00:00
|
|
|
PopHamsterTrace(t, borders);
|
2026-02-28 10:40:16 +00:00
|
|
|
if GetTraceLength(t) = 1 then
|
|
|
|
|
begin
|
2026-02-28 10:42:30 +00:00
|
|
|
PopHamsterTrace(t, borders);
|
2026-02-28 10:45:56 +00:00
|
|
|
redrawEdge := true
|
2026-02-28 10:40:16 +00:00
|
|
|
end
|
2026-02-28 10:22:41 +00:00
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
if t = nil then
|
|
|
|
|
begin
|
2026-02-28 10:42:30 +00:00
|
|
|
AddBorderTrace(t, h, borders);
|
2026-02-28 10:45:56 +00:00
|
|
|
redrawEdge := true
|
2026-02-28 10:22:41 +00:00
|
|
|
end;
|
|
|
|
|
for i := 1 to HamsterDelta do
|
2026-02-28 10:42:30 +00:00
|
|
|
AddHamsterTrace(t, h, borders)
|
2026-02-28 10:22:41 +00:00
|
|
|
end
|
2026-02-28 10:16:21 +00:00
|
|
|
end;
|
|
|
|
|
|
2026-02-28 10:22:41 +00:00
|
|
|
procedure HandleKey(var hamster: creature; var continueLevel: boolean);
|
2026-02-28 10:16:21 +00:00
|
|
|
var
|
|
|
|
|
keyCode: integer;
|
|
|
|
|
begin
|
2026-02-28 10:22:41 +00:00
|
|
|
GetKey(keyCode);
|
|
|
|
|
if (keyCode = ArrowLeftOrd) or (keyCode = ArrowRightOrd) or
|
|
|
|
|
(keyCode = ArrowUpOrd) or (keyCode = ArrowDownOrd) or
|
|
|
|
|
(keyCode = SpaceOrd) then
|
2026-02-28 09:38:37 +00:00
|
|
|
begin
|
2026-02-28 10:22:41 +00:00
|
|
|
UpdateDelta(keyCode, hamster)
|
2026-02-28 09:38:37 +00:00
|
|
|
end;
|
2026-02-28 10:22:41 +00:00
|
|
|
if (keyCode = EscOrd) or (keyCode = CtrlCOrd) then
|
|
|
|
|
continueLevel := false
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure PrintHamsterDebug(var hamster: creature);
|
|
|
|
|
var
|
|
|
|
|
i: integer;
|
|
|
|
|
begin
|
|
|
|
|
GotoXY(2, 2);
|
|
|
|
|
for i := 1 to 20 do
|
|
|
|
|
write(' ');
|
|
|
|
|
GotoXY(2, 2);
|
|
|
|
|
writeln(hamster.curX, ' ', hamster.curY, ' ', hamster.dX, ' ', hamster.dY)
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure RunLevel;
|
|
|
|
|
var
|
|
|
|
|
hamster: creature;
|
2026-02-28 10:42:30 +00:00
|
|
|
captured, borders: arena;
|
2026-02-28 10:22:41 +00:00
|
|
|
hamsterTrace: tracePtr = nil;
|
|
|
|
|
continueLevel: boolean = true;
|
2026-02-28 10:45:56 +00:00
|
|
|
redrawEdge: boolean = false;
|
|
|
|
|
redrawBorders: boolean = false;
|
2026-02-28 10:22:41 +00:00
|
|
|
begin
|
2026-02-28 10:42:30 +00:00
|
|
|
FillArena(captured, false);
|
|
|
|
|
FillArena(borders, false);
|
2026-02-28 10:22:41 +00:00
|
|
|
InitiateCreature(hamster, 5, 1, 0, 0, HamsterSymbol);
|
|
|
|
|
FillArenaCell(hamster.curX, hamster.curY, hamster.symbol);
|
|
|
|
|
while continueLevel do
|
2026-02-28 09:38:37 +00:00
|
|
|
begin
|
|
|
|
|
delay(DelaySizeMs);
|
2026-02-28 10:45:56 +00:00
|
|
|
if (hamsterTrace <> nil) and
|
|
|
|
|
(IsOnBorder(hamster, borders, captured) or IsOnEdge(hamster)) and
|
2026-02-28 10:22:41 +00:00
|
|
|
(hamsterTrace^.prev <> nil) then
|
2026-02-28 09:38:37 +00:00
|
|
|
begin
|
2026-02-28 10:42:30 +00:00
|
|
|
CutField(hamsterTrace, borders, captured);
|
2026-02-28 10:45:56 +00:00
|
|
|
RemoveCutedBorders(borders, captured);
|
|
|
|
|
DisposeTraces(hamsterTrace);
|
|
|
|
|
DrawArenaBorders(borders);
|
|
|
|
|
DrawArenaEdge;
|
|
|
|
|
FillArenaCell(hamster.curX, hamster.curY, hamster.symbol);
|
|
|
|
|
{debug}
|
|
|
|
|
{
|
|
|
|
|
clrscr;
|
|
|
|
|
DebugOrArenas(borders, captured)
|
|
|
|
|
}
|
2026-02-28 10:16:21 +00:00
|
|
|
end;
|
2026-02-28 10:22:41 +00:00
|
|
|
if keypressed then
|
|
|
|
|
HandleKey(hamster, continueLevel);
|
2026-02-28 10:42:30 +00:00
|
|
|
if not HamsterMovePossible(hamster, hamsterTrace, captured) then
|
2026-02-28 10:22:41 +00:00
|
|
|
StopCreature(hamster);
|
|
|
|
|
if (hamster.dX = 0) and (hamster.dY = 0) then
|
|
|
|
|
continue;
|
2026-02-28 10:45:56 +00:00
|
|
|
if not IsOnEdge(hamster) and
|
|
|
|
|
not IsOnBorder(hamster, borders, captured) then
|
|
|
|
|
begin
|
2026-02-28 10:22:41 +00:00
|
|
|
FillArenaCell(hamster.curX, hamster.curY, TraceSymbol)
|
2026-02-28 10:45:56 +00:00
|
|
|
end
|
2026-02-28 10:22:41 +00:00
|
|
|
else
|
2026-02-28 10:45:56 +00:00
|
|
|
begin
|
|
|
|
|
FillArenaCell(hamster.curX, hamster.curY, ' ')
|
|
|
|
|
end;
|
2026-02-28 10:22:41 +00:00
|
|
|
MoveCreature(hamster);
|
2026-02-28 10:45:56 +00:00
|
|
|
if IsOnEdge(hamster) and (hamsterTrace = nil) then
|
|
|
|
|
redrawEdge := true
|
|
|
|
|
else
|
2026-02-28 10:42:30 +00:00
|
|
|
if IsOnBorder(hamster, borders, captured) and (hamsterTrace = nil) then
|
2026-02-28 10:45:56 +00:00
|
|
|
redrawBorders := true
|
2026-02-28 10:22:41 +00:00
|
|
|
else
|
2026-02-28 10:45:56 +00:00
|
|
|
ChangeHamsterTrace(hamsterTrace, hamster, borders, redrawEdge);
|
|
|
|
|
if redrawEdge then
|
|
|
|
|
begin
|
|
|
|
|
DrawArenaEdge;
|
|
|
|
|
redrawEdge := false
|
|
|
|
|
end;
|
|
|
|
|
if redrawBorders then
|
2026-02-28 10:16:21 +00:00
|
|
|
begin
|
2026-02-28 10:45:56 +00:00
|
|
|
DrawArenaBorders(borders);
|
|
|
|
|
redrawBorders := false
|
2026-02-28 10:16:21 +00:00
|
|
|
end;
|
2026-02-28 10:22:41 +00:00
|
|
|
FillArenaCell(hamster.curX, hamster.curY, hamster.symbol)
|
2026-02-28 09:38:37 +00:00
|
|
|
end
|
2026-02-28 10:22:41 +00:00
|
|
|
end;
|
2026-02-28 09:38:37 +00:00
|
|
|
|
2026-02-28 10:22:41 +00:00
|
|
|
begin
|
|
|
|
|
if not IsTerminalValid then
|
|
|
|
|
begin
|
|
|
|
|
PrintTerminalHelp;
|
|
|
|
|
exit
|
|
|
|
|
end;
|
|
|
|
|
clrscr;
|
|
|
|
|
DrawInterface(ScreenH, ScreenW);
|
|
|
|
|
RunLevel;
|
|
|
|
|
end.
|