diff --git a/src/arena_graphics_m.pas b/src/arena_graphics_m.pas new file mode 100644 index 0000000..7a78344 --- /dev/null +++ b/src/arena_graphics_m.pas @@ -0,0 +1,164 @@ +unit arena_graphics_m; + +interface + +uses arena_m, creature_m; + +const + BorderSize = 1; + CellSize = 2; + LifeBarX = 33; + ScreenW = (ArenaW - 1) * CellSize + BorderSize * 2; { 79 } + InterfaceBarH = ScreenW - ArenaH * CellSize - BorderSize * 2; { 14 } + InterfaceCellW = ScreenW div 3; + InterfaceH = 6; + ScreenH = (ArenaH + InterfaceH) * CellSize + BorderSize; + WidthCoefficient = 2; + +procedure DrawArenaBorders(var a: arena); +procedure DrawArenaCell(arenaX, arenaY: integer; symbol: char); +procedure DrawArenaEdges; +procedure DrawEdge(x, y: integer; var a: arena); +procedure DrawLevel; + +implementation + +uses crt, math_m; + +procedure DrawLineX(x, y, len: integer); +var + i: integer; +begin + GotoXY(x, y); + for i := 1 to len do + write(BorderSymbolX); + 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(BorderSymbolY) + 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(BorderSymbolY); + GotoXY(x0 + w - 1, y0 + i); + write(BorderSymbolY) + end; + DrawLineX(x0, y0 + h - 1, w); + GotoXY(1, 1) +end; + +procedure DrawInterface; +begin + DrawLineX(1, InterfaceBarH, ScreenW * WidthCoefficient); + DrawLineY(InterfaceCellW * WidthCoefficient, 1, InterfaceBarH); + DrawLineY(InterfaceCellW * 2 * WidthCoefficient + 1, 1, InterfaceBarH) +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 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 DrawLevel; +begin + DrawRectangle(1, 1, ScreenH, ScreenW * WidthCoefficient); + DrawInterface +end; + +end. diff --git a/src/arena_m.pas b/src/arena_m.pas index 5f5a134..ab625a4 100644 --- a/src/arena_m.pas +++ b/src/arena_m.pas @@ -2,12 +2,14 @@ unit arena_m; interface -uses creature_m, trace_m, hamster_m; +uses creature_m, game_m, trace_m; const ArenaH = 33; ArenaW = 41; CaptureSymbol = '.'; + BorderSymbolX = '|'; {Later can change on '-'} + BorderSymbolY = '|'; BorderSymbol = '|'; ArenaSymbol = ' '; @@ -19,22 +21,22 @@ type end; function ArenaSplited(var h: creature; var t: tracePtr; var a: arena): boolean; -procedure CutSmallerPart(var hamster: creature; var t: tracePtr; var a: arena); function GhostShouldTurn(var g: creature; var a: arena): boolean; function HamsterStepPossible(var h: creature; var t: tracePtr; var a: arena): boolean; -procedure Init(var a: arena); function IsOnBorder(var x, y: integer; var a: arena): boolean; function IsOnEdge(var cr: creature): boolean; function IsOnEdge(x, y: integer): boolean; -procedure MakeEnemyStep(var e: creature; var a: arena); +procedure CutSmallerPart(var hamster: creature; var t: tracePtr; var a: arena); +procedure InitArena(var a: arena); +procedure MakeEnemyStep(var e, h: creature; t: tracePtr; var a: arena); procedure MakeHamsterStep(var h: creature; var t: tracePtr; var a: arena); procedure SetArenaBorder(var t: tracePtr; var a: arena); procedure TurnGhost(var g: creature; var a: arena); implementation -uses cell_m, graphics_m, math_m; +uses arena_graphics_m, cell_m, crt, graphics_m, math_m; procedure Fill(var m: arenaMatrix; val: boolean); var @@ -45,7 +47,7 @@ begin m[i][j] := val end; -procedure Init(var a: arena); +procedure InitArena(var a: arena); begin Fill(a.captured, false); Fill(a.borders, false) @@ -300,12 +302,11 @@ begin DrawArenaBorders(a); DrawArenaEdges; DrawCreature(hamster); - Delete(t) + DeleteTrace(t) end; function -HamsterStepPossible(var h: creature; var t: tracePtr; var a: arena): - boolean; +HamsterStepPossible(var h: creature; var t: tracePtr; var a: arena): boolean; var nextX, nextY, midX, midY: integer; begin @@ -448,10 +449,16 @@ begin end end; -procedure MakeEnemyStep(var e: creature; var a: arena); +procedure MakeEnemyStep(var e, h: creature; t: tracePtr; var a: arena); +var + prevX, prevY: integer; begin + prevX := e.curX; + prevY := e.curY; MakeStep(e); - DrawAfterStep(e, a) + DrawAfterStep(e, a); + if TraceCrossed(prevX, prevY, e, t) then + h.alive := false end; end. diff --git a/src/creature_m.pas b/src/creature_m.pas index 7e83012..e5a4ed3 100644 --- a/src/creature_m.pas +++ b/src/creature_m.pas @@ -4,26 +4,30 @@ interface type creature = record - curX, curY, dX, dY: integer; - symbol: char + curX, curY, dX, dY, moveSpeed: integer; + symbol: char; + alive: boolean end; procedure -InitCreature(var cr: creature; curX, curY, dX, dY: integer; symbol: char); +InitCreature(var cr: creature; curX, curY, movespeed: integer; symbol: char); +procedure KillCreature(var cr: creature); procedure StopCreature(var cr: creature); procedure MakeStep(var cr: creature); implementation -uses arena_m, math_m; +uses arena_graphics_m, arena_m, math_m; procedure -InitCreature(var cr: creature; curX, curY, dX, dY: integer; symbol: char); +InitCreature(var cr: creature; curX, curY, movespeed: integer; symbol: char); begin cr.curX := curX; cr.curY := curY; - cr.dX := dX; - cr.dY := dY; + cr.dX := 0; + cr.dY := 0; + cr.movespeed := moveSpeed; + cr.alive := true; cr.symbol := symbol end; @@ -39,4 +43,10 @@ begin cr.curY := Clamp(cr.curY + cr.dY, 1, ArenaH) end; +procedure KillCreature(var cr: creature); +begin + cr.alive := false; + DrawArenaCell(cr.curX, cr.curY, CaptureSymbol) +end; + end. diff --git a/src/game_m.pas b/src/game_m.pas new file mode 100644 index 0000000..0a2c8f5 --- /dev/null +++ b/src/game_m.pas @@ -0,0 +1,45 @@ +unit game_m; + +interface + +type + gameState = record + score, life, speedBonus, slowBonus: integer; + paused, level, hamsterAlive: boolean; + end; + +procedure DecreaseLife(var g: gameState); +procedure GameOver(var g: gameState); +procedure InitGame(var g: gameState); + +implementation + +uses graphics_m; + +const + StartScore = 0; + StartLifes = 3; + BonusTurns = 45; + StartSpeedBonus = 0; + StartSlowBonus = 0; + +procedure InitGame(var g: gameState); +begin + g.score := StartScore; + g.life := StartLifes; + g.speedBonus := StartSpeedBonus; + g.slowBonus := StartSlowBonus; + g.hamsterAlive := true +end; + +procedure DecreaseLife(var g: gameState); +begin + g.life := g.life - 1; + DrawLifes(g) +end; + +procedure GameOver(var g: gameState); +begin +end; + +end. diff --git a/src/ghost_m.pas b/src/ghost_m.pas index 6593b4b..7395024 100644 --- a/src/ghost_m.pas +++ b/src/ghost_m.pas @@ -7,9 +7,9 @@ uses creature_m; const GhostStartX = 5; GhostStartY = 5; - GhostDelta = 1; - GhostStartDX = GhostDelta; - GhostStartDY = GhostDelta; + GhostMovespeed = 1; + GhostStartDX = GhostMovespeed; + GhostStartDY = GhostMovespeed; GhostSymbol = 'g'; procedure InitGhost(var g: creature); @@ -18,8 +18,9 @@ implementation procedure InitGhost(var g: creature); begin - InitCreature(g, GhostStartX, GhostStartY, - GhostStartDX, GhostStartDY, GhostSymbol) + InitCreature(g, GhostStartX, GhostStartY, GhostMovespeed, GhostSymbol); + g.dX := GhostStartDX; + g.dY := GhostStartDY end; end. diff --git a/src/gohamster.pas b/src/gohamster.pas index 5e4274c..55adaab 100644 --- a/src/gohamster.pas +++ b/src/gohamster.pas @@ -1,6 +1,6 @@ program go_hamster; -uses crt, arena_m, trace_m, creature_m, graphics_m, hamster_m, keys_m, - ghost_m, debug_m; +uses crt, arena_m, arena_graphics_m, trace_m, creature_m, graphics_m, + hamster_m, keys_m, ghost_m, game_m, debug_m; const DelaySizeMs = 100; @@ -11,13 +11,17 @@ var a: arena; t: tracePtr = nil; continueLevel: boolean = true; + game: gameState; begin - Init(a); + InitArena(a); InitHamster(h); InitGhost(g); + InitGame(game); DrawCreature(h); DrawCreature(g); - DrawScore(12345); + DrawScore(game); + DrawLifes(game); + while continueLevel do begin delay(DelaySizeMs); @@ -26,15 +30,31 @@ begin SetArenaBorder(t, a); CutSmallerPart(h, t, a) end; + if g.alive then + MakeEnemyStep(g, h, t, a); + while g.alive and GhostShouldTurn(g, a) do + TurnGhost(g, a); + if not h.alive then + begin + if game.life >= 0 then + begin + DecreaseLife(game); + KillHamster(h, t, a); + h.alive := true + end + else + begin + GameOver(game) + end + end; if keypressed then HandleKey(h, continueLevel, a, t); if not HamsterStepPossible(h, t, a) then StopCreature(h); if not ((h.dX = 0) and (h.dY = 0)) then MakeHamsterStep(h, t, a); - MakeEnemyStep(g, a); - if GhostShouldTurn(g, a) then - TurnGhost(g, a) + if g.alive and a.captured[g.curX][g.curY] then + KillCreature(g) end end; diff --git a/src/graphics_m.pas b/src/graphics_m.pas index 6307153..6627749 100644 --- a/src/graphics_m.pas +++ b/src/graphics_m.pas @@ -2,19 +2,16 @@ unit graphics_m; interface -uses arena_m, creature_m, hamster_m, trace_m; +uses arena_graphics_m, arena_m, creature_m, hamster_m, trace_m, game_m; function IsTerminalValid: boolean; procedure DrawAfterStep(var cr: creature; var a: arena); procedure DrawAfterStep(var hamster: creature; var t: tracePtr; var a: arena); -procedure DrawArenaBorders(var a: arena); -procedure DrawArenaCell(arenaX, arenaY: integer; symbol: char); -procedure DrawArenaEdges; procedure DrawCreature(var cr: creature); -{procedure DrawKills(killCounter: integer);} -procedure DrawScore(s: integer); -procedure DrawLevel; -procedure EraseTrace(var hamster: creature; t: tracePtr); +procedure DrawLifes(var game: GameState); +procedure DrawScore(var game: GameState); +procedure EraseStepTrace(var hamster: creature; t: tracePtr); +procedure EraseTrace(t: tracePtr; var a: arena); procedure PrintTerminalHelp; implementation @@ -22,15 +19,11 @@ implementation uses crt, math_m; const - InterfaceH = 6; - CellSize = 2; - BorderSize = 1; - ScreenW = (ArenaW - 1) * CellSize + BorderSize * 2; { 79 } - ScreenH = (ArenaH + InterfaceH) * CellSize + BorderSize; - InterfaceCellW = ScreenW div 3; - WidthCoefficient = 2; - InterfaceBarH = ScreenW - ArenaH * CellSize - BorderSize * 2; { 14 } LetterWidth = 6; + Notation = 10; + DigitSpaceSize = 1; + InterfaceMarginY = InterfaceBarH div 4 + BorderSize + 1; + InterfaceMarginX = InterfaceCellW div 4; function IsTerminalValid: boolean; begin @@ -52,132 +45,23 @@ begin end end; -procedure DrawLineX(x, y, len: integer); -var - i: integer; +procedure EraseTrace(t: tracePtr; var a: arena); 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 + while t <> nil do begin - GotoXY(x, y + i - 1); - write(BorderSymbol) - end; - GotoXY(1, 1) + if t^.prev = nil then + DrawEdge(t^.x, t^.y, a) + else + DrawArenaCell(t^.x, t^.y, ArenaSymbol); + t := t^.prev + end end; -procedure DrawRectangle(x0, y0, h, w: integer); +procedure EraseStepTrace(var hamster: creature; t: tracePtr); 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; -begin - DrawLineX(1, InterfaceBarH, ScreenW * WidthCoefficient); - DrawLineY(InterfaceCellW * WidthCoefficient, 1, InterfaceBarH); - DrawLineY(InterfaceCellW * 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 + for i := 1 to hamster.movespeed do begin DrawArenaCell(t^.x, t^.y, ArenaSymbol); t := t^.prev @@ -191,27 +75,6 @@ begin 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) @@ -230,7 +93,7 @@ begin DrawArenaCell(prevX, prevY, BorderSymbol) end; -procedure DrawStepTrace(t: tracePtr); +procedure DrawStepTrace(t: tracePtr; hamsterDelta: integer); var i: integer; begin @@ -255,7 +118,7 @@ begin else DrawArenaCell(prevX, prevY, ArenaSymbol); if t <> nil then - DrawStepTrace(t); + DrawStepTrace(t, hamster.movespeed); DrawCreature(hamster); DrawPreviousCell(hamster, t, a) end; @@ -276,19 +139,6 @@ begin DrawCreature(cr) end; -{ -procedure DrawKills(killCounter: integer); -begin - GotoXY(1, 81); - while killCounter <> 0 do - begin - write(killCounter mod 10); - killCounter := killCounter div 10 - end; - GotoXY(1, 1) -end; -} - procedure DrawZero(x, y: integer); begin GotoXY(x, y); @@ -514,9 +364,8 @@ begin end end; -procedure DrawScore(s: integer); +procedure DrawNumber(interfaceX: integer; s: longint); var - killBar: integer = InterfaceCellW * 2 * WidthCoefficient + 1; x, y: integer; i: integer = 0; st: StackInt; @@ -526,17 +375,29 @@ begin StackPush(st, 0); while s <> 0 do begin - StackPush(st, s mod 10); - s := s div 10 + StackPush(st, s mod Notation); + s := s div Notation end; - x := killBar + InterfaceCellW div 4; - y := InterfaceBarH div 4 + BorderSize + 1; + x := interfaceX + InterfaceMarginX; + y := InterfaceMarginY; while st.top <> nil do begin - DrawDigit(x + (LetterWidth + 1) * i, y, st.top^.val); + DrawDigit(x + (LetterWidth + DigitSpaceSize) * i, y, st.top^.val); StackPop(st); i := i + 1 end end; +procedure DrawLifes(var game: GameState); +begin + DrawNumber(LifeBarX, game.life) +end; + +procedure DrawScore(var game: GameState); +var + killBarX: integer = InterfaceCellW * 2 * WidthCoefficient + BorderSize; +begin + DrawNumber(killBarX, game.score) +end; + end. diff --git a/src/hamster_m.pas b/src/hamster_m.pas index fb35c4a..4f80e1f 100644 --- a/src/hamster_m.pas +++ b/src/hamster_m.pas @@ -2,24 +2,49 @@ unit hamster_m; interface -uses creature_m; +uses arena_graphics_m, arena_m, creature_m, trace_m; const HamsterStartX = 5; HamsterStartY = 1; HamsterStartDX = 0; HamsterStartDY = 0; - HamsterDelta = 2; + HamsterMovespeed = 2; HamsterSymbol = 'h'; procedure InitHamster(var h: creature); +procedure KillHamster(var h: creature; var t: tracePtr; var a: arena); implementation +uses graphics_m; + procedure InitHamster(var h: creature); begin InitCreature(h, HamsterStartX, HamsterStartY, - HamsterStartDX, HamsterStartDY, HamsterSymbol) + HamsterMovespeed, HamsterSymbol); + h.dX := HamsterStartDX; + h.dY := HamsterStartDY +end; + +procedure KillHamster(var h: creature; var t: tracePtr; var a: arena); +var + traceStart: tracePtr; +begin + DrawArenaCell(h.curX, h.curY, ArenaSymbol); + EraseTrace(t, a); + if IsOnEdge(h) then + DrawEdge(h.curX, h.curY, a) + else + if a.borders[h.curX][h.curY] then + DrawArenaCell(h.curX, h.curY, BorderSymbol); + GetStart(traceStart, t); + h.curX := traceStart^.x; + h.curY := traceStart^.y; + h.dX := HamsterStartDX; + h.dY := HamsterStartDY; + DeleteTrace(t); + DrawCreature(h) end; end. diff --git a/src/keys_m.pas b/src/keys_m.pas index 932c66a..8ec15e5 100644 --- a/src/keys_m.pas +++ b/src/keys_m.pas @@ -46,13 +46,13 @@ begin h.dY := 0; case keyCode of ArrowLeftOrd: - h.dX := -HamsterDelta; + h.dX := -h.movespeed; ArrowRightOrd: - h.dX := HamsterDelta; + h.dX := h.movespeed; ArrowUpOrd: - h.dY := -HamsterDelta; + h.dY := -h.movespeed; ArrowDownOrd: - h.dY := HamsterDelta; + h.dY := h.movespeed; SpaceOrd: StopCreature(h) end diff --git a/src/math_m.pas b/src/math_m.pas index 17366ae..51ec6ae 100644 --- a/src/math_m.pas +++ b/src/math_m.pas @@ -26,4 +26,11 @@ begin Signum := 0 end; +function Abs(val: integer): integer; +begin + if val < 0 then + val := val * -1; + Abs := val +end; + end. diff --git a/src/trace_m.pas b/src/trace_m.pas index 3f351ed..84ec6da 100644 --- a/src/trace_m.pas +++ b/src/trace_m.pas @@ -2,7 +2,7 @@ unit trace_m; interface -uses creature_m, math_m, hamster_m; +uses creature_m, math_m, game_m; const PreviousTraceIdx = 3; @@ -16,13 +16,17 @@ type prev: tracePtr end; -procedure ChangeHamsterTrace(var h: creature; var t: tracePtr); -procedure DecreaseTrace(var hamster: creature; var t: tracePtr); -procedure Delete(var t: tracePtr); function FindIndex(var t: tracePtr; x, y, curIdx: integer): integer; function GetLength(var t: tracePtr): integer; +function IsOnTrace(var cr: creature; t: tracePtr): boolean; +function IsOnTrace(x, y: integer; t: tracePtr): boolean; +function +TraceCrossed(prevX, prevY: integer; var cr: creature; t: tracePtr): boolean; +procedure ChangeHamsterTrace(var h: creature; var t: tracePtr); +procedure DecreaseTrace(var hamster: creature; var t: tracePtr); +procedure DeleteTrace(var t: tracePtr); +procedure GetStart(var traceStart: tracePtr; t: tracePtr); procedure IncreaseTrace(var hamster: creature; var t: tracePtr); -function IsOnTrace(var cr: creature; var t: tracePtr): boolean; procedure Pop(var t: tracePtr); implementation @@ -37,7 +41,17 @@ begin GetLength := 1 + GetLength(t^.prev) end; -procedure Delete(var t: tracePtr); +procedure GetStart(var traceStart: tracePtr; t: tracePtr); +begin + while t <> nil do + begin + if t^.prev = nil then + traceStart := t; + t := t^.prev + end +end; + +procedure DeleteTrace(var t: tracePtr); var tmpT: tracePtr; begin @@ -60,6 +74,17 @@ begin FindIndex := FindIndex(t^.prev, x, y, curIdx + 1) end; +function IsOnTrace(x, y: integer; t: tracePtr): boolean; +begin + if t = nil then + IsOnTrace := false + else + if (t^.x = x) and (t^.y = y) then + IsOnTrace := true + else + IsOnTrace := IsOnTrace(x, y, t^.prev) +end; + procedure Add(var t: tracePtr; x, y: integer); var nextTrace: tracePtr; @@ -80,15 +105,9 @@ begin t := tmpPrev end; -function IsOnTrace(var cr: creature; var t: tracePtr): boolean; +function IsOnTrace(var cr: creature; t: tracePtr): boolean; begin - if t = nil then - IsOnTrace := false - else - if (t^.x = cr.curX) and (t^.y = cr.curY) then - IsOnTrace := true - else - IsOnTrace := IsOnTrace(cr, t^.prev) + IsOnTrace := IsOnTrace(cr.curX, cr.curY, t) end; procedure AddStepTrace(var h: creature; var t: tracePtr); @@ -106,8 +125,8 @@ procedure AddFirstTrace(var hamster: creature; var t: tracePtr); var traceX, traceY, dX, dY: integer; begin - dX := Signum(hamster.curX - hamster.dX, hamster.curX) * HamsterDelta; - dY := Signum(hamster.curY - hamster.dY, hamster.curY) * HamsterDelta; + dX := Signum(hamster.curX - hamster.dX, hamster.curX) * hamster.movespeed; + dY := Signum(hamster.curY - hamster.dY, hamster.curY) * hamster.movespeed; traceX := hamster.curX + dX; traceY := hamster.curY + dY; Add(t, traceX, traceY) @@ -119,7 +138,7 @@ var begin if t = nil then AddFirstTrace(hamster, t); - for i := 1 to HamsterDelta do + for i := 1 to hamster.movespeed do AddStepTrace(hamster, t) end; @@ -127,7 +146,7 @@ procedure DecreaseTrace(var hamster: creature; var t: tracePtr); var i: integer; begin - for i := 1 to HamsterDelta do + for i := 1 to hamster.movespeed do Pop(t); if GetLength(t) = 1 then Pop(t) @@ -137,7 +156,7 @@ procedure ChangeHamsterTrace(var h: creature; var t: tracePtr); begin if IsOnTrace(h, t) then begin - EraseTrace(h, t); + EraseStepTrace(h, t); DecreaseTrace(h, t) end else @@ -146,4 +165,24 @@ begin end end; +function +TraceCrossed(prevX, prevY: integer; var cr: creature; t: tracePtr): boolean; +var + dX, dY: integer; +begin + dX := Signum(cr.curX, prevX); + dY := Signum(cr.curY, prevY); + while (prevX <> cr.curX) and (prevY <> cr.curY) do + begin + if IsOnTrace(prevX, prevY, t) then + begin + TraceCrossed := true; + exit + end; + prevX := prevX + dX; + prevY := prevY + dY + end; + TraceCrossed := false +end; + end.