diff --git a/src/Makefile b/src/Makefile index 2728f7e..6d021fa 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,14 +1,15 @@ FPC = fpc + CONVBANNERS_SRC = convbanners.pas BANNERS_SRC = completed.txt exit.txt keys.txt paused.txt menu.txt \ - level.txt gameover.txt + level.txt gameover.txt -GAME_SRC = _banners_m.pas arena_graphics_m.pas arena_m.pas \ +GAME_SRC = _autobanners_m.pas arena_graphics_m.pas arena_m.pas \ ascii_arts_m.pas cell_m.pas creature_m.pas enemy_packs_m.pas \ game_m.pas ghost_m.pas gohamster.pas graphics_m.pas hamster_m.pas \ - keys_m.pas level_m.pas math_m.pas sun_m.pas sun_fields_m.pas \ - trace_m.pas snake_m.pas snake_fields_m.pas drop_m.pas drop_fields_m.pas + keys_m.pas level_m.pas math_m.pas sun_m.pas trace_m.pas snake_m.pas \ + drop_m.pas all: gohamster @@ -18,11 +19,11 @@ play: gohamster gohamster: $(GAME_SRC) $(FPC) $@.pas -_banners_m.pas: convbanners $(BANNERS_SRC) +_autobanners_m.pas: convbanners $(BANNERS_SRC) ./convbanners convbanners: $(CONVBANNERS_SRC) $(FPC) $@.pas clean: - rm *.o *.ppu convbanners _banners_m.pas gohamster + rm *.o *.ppu convbanners _autobanners_m.pas gohamster diff --git a/src/arena_graphics_m.pas b/src/arena_graphics_m.pas index aa81090..b3e90cd 100644 --- a/src/arena_graphics_m.pas +++ b/src/arena_graphics_m.pas @@ -2,7 +2,7 @@ unit arena_graphics_m; interface -uses arena_m, creature_m, trace_m, level_m, _banners_m; +uses arena_m, creature_m, trace_m, level_m, _autobanners_m; const ArenaSymbol = ' '; @@ -28,6 +28,7 @@ procedure DrawScore(s: integer); procedure EraseStepTrace(var hamster: creature; a: tracePtr); procedure EraseLifesNumber(n: integer); procedure EraseTrace(tp: tracePtr; var a: arena); +procedure RedrawInterfaceArea(x: integer; t: creatureType); implementation @@ -58,9 +59,9 @@ const HamsterLifeY = 5; DecimalBase = 10; PauseXPadding = 3 * WidthCoefficient; - PauseX = (ScreenW * WidthCoefficient - PauseWidth) div 2; + PauseX = (ScreenW * WidthCoefficient - PauseBannerW) div 2; PauseYPadding = 1; - PauseY = (ScreenH - PauseHeight) div 2; + PauseY = (ScreenH - PauseBannerH) div 2; InterfaceArenaCellX1 = 15; InterfaceArenaCellX2 = 29; @@ -80,13 +81,16 @@ const lY: 0; rX: 0; rY: GhostHeight div CellSize ), ( - lX: 0; lY: 0; rX: 0; rY: 0 + lX: -SunWidth div CellSize div WidthCoefficient; + lY: -SunHeight div CellSize; rX: 0; rY: 0 ), ( - lX: 0; lY: 0; rX: 0; rY: 0 + lX: -SnakeWidth div CellSize div WidthCoefficient; + lY: -SnakeHeight div CellSize; rX: 0; rY: 1 ), ( - lX: 0; lY: 0; rX: 0; rY: 0 + lX: -DropWidth div CellSize div WidthCoefficient; + lY: -DropHeight div CellSize; rX: 0; rY: 1 ) ); @@ -184,24 +188,63 @@ begin DrawFieldCell(x - 1, -1, ' ') end; -procedure RedrawInterfaceArea(x: integer); +procedure EraseSunInterface(x: integer); begin - EraseHamsterInterface(x); - if (x = 1) or (x = 2) then - DrawLineY(1, InterfaceBarH - HamsterHeight, - HamsterHeight, BorderSymbol) - else - if x = InterfaceArenaCellX1 then - DrawLineY(InterfaceCellW * WidthCoefficient, - InterfaceBarH - HamsterHeight, HamsterHeight, BorderSymbol) - else - if x = InterfaceArenaCellX2 then - DrawLineY(InterfaceCellW * 2 * WidthCoefficient + 1, - InterfaceBarH - HamsterHeight, HamsterHeight, BorderSymbol) - else - if x = ArenaW then - DrawLineY(ArenaW * CellSize * WidthCoefficient, - InterfaceBarH - HamsterHeight, HamsterHeight, BorderSymbol) + if x <= 0 then + exit; + DrawFieldCell(x, 0, ' '); + DrawFieldCell(x - 1, 0, ' ') +end; + +procedure RedrawEnemyInterfaceArea(x: integer); +var + h: integer = SunHeight div 2; +begin + EraseSunInterface(x); + if (x = 1) or (x = 2) then + DrawLineY(1, InterfaceBarH - h, h, BorderSymbol) + else + if (x = InterfaceArenaCellX1) or (x = InterfaceArenaCellX1 + -1) then + DrawLineY(InterfaceCellW * WidthCoefficient, + InterfaceBarH - h, h, BorderSymbol) + else + if (x = InterfaceArenaCellX2) or (x = InterfaceArenaCellX2 - 1) then + DrawLineY(InterfaceCellW * 2 * WidthCoefficient + 1, + InterfaceBarH - h, h, BorderSymbol) + else + if x = ArenaW then + DrawLineY(ArenaW * CellSize * WidthCoefficient, + InterfaceBarH - h, h, BorderSymbol) +end; + +procedure RedrawHamsterInterfaceArea(x: integer); +begin + EraseHamsterInterface(x); + if (x = 1) or (x = 2) then + DrawLineY(1, InterfaceBarH - HamsterHeight, + HamsterHeight, BorderSymbol) + else + if x = InterfaceArenaCellX1 then + DrawLineY(InterfaceCellW * WidthCoefficient, + InterfaceBarH - HamsterHeight, HamsterHeight, BorderSymbol) + else + if x = InterfaceArenaCellX2 then + DrawLineY(InterfaceCellW * 2 * WidthCoefficient + 1, + InterfaceBarH - HamsterHeight, HamsterHeight, BorderSymbol) + else + if x = ArenaW then + DrawLineY(ArenaW * CellSize * WidthCoefficient, + InterfaceBarH - HamsterHeight, HamsterHeight, BorderSymbol) +end; + +procedure RedrawInterfaceArea(x: integer; t: creatureType); +begin + case t of + creatureHamster: + RedrawHamsterInterfaceArea(x); + creatureSun, creatureSnake, creatureDrop: + RedrawEnemyInterfaceArea(x) + end end; procedure RedrawArea(var a: arena; arenaX, arenaY: integer; t: creatureType); @@ -217,8 +260,6 @@ begin if (arenaX + j > 0) and (arenaX + j < ArenaW + 1) and (arenaY + i > 0) and (arenaY + i < ArenaH + 1) then begin - if (t = creatureHamster) and (arenaY + i = 1) then - RedrawInterfaceArea(arenaX + j); DrawArenaCell(arenaX + j, arenaY + i, a) end end @@ -232,6 +273,8 @@ begin {Later move to erase hamster} arenaX := h.curX - h.dX; arenaY := h.curY - h.dY; + if arenaY = 1 then + RedrawInterfaceArea(arenaX, h.t); RedrawArea(a, arenaX, arenaY, h.t); if t <> nil then DrawTrace(t); @@ -262,14 +305,15 @@ procedure DrawPause; begin EraseRectangle(PauseX - PauseXPadding, PauseY - PauseYPadding, - PauseWidth + PauseXPadding * 2, - PauseHeight + PauseYPadding * 2 + 1); + PauseBannerW + PauseXPadding * 2, + PauseBannerH + PauseYPadding * 2 + 1); DrawRectangle(PauseX - PauseXPadding, PauseY - PauseYPadding, - PauseHeight + PauseYPadding * 2 + 1, - PauseWidth + PauseXPadding * 2, + PauseBannerH + PauseYPadding * 2 + 1, + PauseBannerW + PauseXPadding * 2, BorderSymbol); - DrawBannerImage(PauseX, PauseY, PauseHeight, PauseAscii) + DrawBannerImage(PauseX, PauseY, PauseBannerH, PauseBanner); + GotoXY(1, 1) end; procedure DrawTrace(a: tracePtr); @@ -358,8 +402,8 @@ procedure ErasePause; begin EraseRectangle(PauseX - PauseXPadding, PauseY - PauseYPadding, - PauseWidth + PauseXPadding * 2, - PauseHeight + PauseYPadding * 2 + 1) + PauseBannerW + PauseXPadding * 2, + PauseBannerH + PauseYPadding * 2 + 1) end; procedure DrawLevelUnpause(var level: levelState); @@ -388,8 +432,7 @@ begin write(symbol) end end - end; - GotoXY(1, 1) + end end; procedure DrawArenaEdges; @@ -515,7 +558,7 @@ end; procedure DrawHamsterRunX(var h: creature); var xIdx: integer; - img: ^CreatureImage; + img: ^creatureImage; begin if h.dX = 0 then exit; @@ -532,7 +575,7 @@ end; procedure DrawHamsterRunY(var h: creature); var yIdx: integer; - img: ^CreatureImage; + img: ^creatureImage; begin if h.dY = 0 then exit; @@ -558,7 +601,8 @@ begin DrawHamsterRunX(h) else if h.dY <> 0 then - DrawHamsterRunY(h) + DrawHamsterRunY(h); + GotoXY(1, 1) end; procedure DrawGhost(var g: creature); @@ -574,23 +618,41 @@ end; procedure DrawSun(var g: creature); var - asciiIdx: integer; + asciiIdx, h: integer; + img: ^creatureImage; begin - asciiIdx := g.curX div g.moveSpeed mod SunRunN + 1; + if g.rageMode then + begin + img := @(GoidaSunAscii); + h := GoidaSunHeight + end + else + begin + asciiIdx := g.curX div g.moveSpeed mod SunRunN + 1; + img := @(SunAscii[asciiIdx]); + h := SunHeight + end; DrawFieldAscii(g.curX - SunWidth div WidthCoefficient div 2, - g.curY - SunHeight div 2 + 1, - SunHeight, SunWidth, SunAscii[asciiIdx]) - + g.curY - h div 2 + 1, h, SunWidth, img^) end; -{ -procedure DrawEnemy(var e: creature); +procedure DrawSnake(var g: creature); var asciiIdx: integer; begin - asciiIdx := e.curX div e.moveSpeed mod; + asciiIdx := g.curX div g.moveSpeed mod SnakeRunN + 1; + DrawFieldAscii(g.curX - SnakeWidth div WidthCoefficient div 2, + g.curY - SnakeHeight div 2 + 1, + SnakeHeight, SnakeWidth, SnakeAscii[asciiIdx]) + +end; + +procedure DrawDrop(var g: creature); +begin + DrawFieldAscii(g.curX - DropWidth div WidthCoefficient div 2, + g.curY - DropHeight div 2 + 1, DropHeight, + DropWidth, DropAscii) end; -} procedure DrawCreature(var cr: creature); begin @@ -600,7 +662,11 @@ begin creatureGhost: DrawGhost(cr); creatureSun: - DrawSun(cr) + DrawSun(cr); + creatureSnake: + DrawSnake(cr); + creatureDrop: + DrawDrop(cr) end end; diff --git a/src/arena_m.pas b/src/arena_m.pas index b4219aa..451affd 100644 --- a/src/arena_m.pas +++ b/src/arena_m.pas @@ -2,7 +2,7 @@ unit arena_m; interface -uses creature_m, trace_m; +uses creature_m, cell_m, trace_m; const ArenaH = 33; @@ -32,13 +32,11 @@ procedure MakeEnemySteps(var a: arena; var h: creature; procedure MakeHamsterStep(var h: creature; var t: tracePtr; var a: arena); procedure SetArenaBorder(var t: tracePtr; var a: arena); procedure TurnStubbornEnemies(var a: arena; var e: creatureList); -procedure MakeStep(var a: arena; var cr: creature); - - +procedure MakeStep(var a: arena; var enemy: creature); implementation -uses arena_graphics_m, cell_m, crt, graphics_m, math_m, Math; +uses arena_graphics_m, crt, graphics_m, snake_m, drop_m, math_m, Math; const MaxTurnAttempts = 3; @@ -413,29 +411,14 @@ begin DrawAfterHamsterStep(h, t, a) end; -function GhostShouldTurn(var g: creature; var a: arena): boolean; -var - nextX, nextY: integer; -begin - nextX := g.curX + g.dX; - nextY := g.curY + g.dY; - GhostShouldTurn := StepBeyondEdge(g) or - a.borders[g.curY][g.curX] and a.captured[nextY][nextX] -end; - -function SunShouldTurn(var g: creature; var a: arena): boolean; -begin - SunShouldTurn := true -end; - -function VerticalBorder(nextX, nextY: integer; var a: arena): boolean; +function VerticalBorder(var a: arena; nextX, nextY: integer): boolean; begin VerticalBorder := a.borders[nextY][nextX] and (a.borders[nextY - 1][nextX] or a.borders[nextY + 1][nextX]) end; -function HorizontalBorder(nextX, nextY: integer; var a: arena): boolean; +function HorizontalBorder(var a: arena; nextX, nextY: integer): boolean; begin HorizontalBorder := a.borders[nextY][nextX] and @@ -444,30 +427,39 @@ end; function IsCorner(x, y: integer; var a: arena): boolean; begin - IsCorner := HorizontalBorder(x, y, a) and VerticalBorder(x, y, a) + IsCorner := HorizontalBorder(a, x, y) and VerticalBorder(a, x, y) end; -procedure TurnGhost(var g: creature; var a: arena); +procedure TpDrop(var a: arena; var e: creature); +var + nx, ny: integer; begin - if (OnEdgeX(g.curX) or VerticalBorder(g.curX, g.curY, a)) then - g.dX := g.dX * -1; - if (OnEdgeY(g.curY) or HorizontalBorder(g.curX, g.curY, a)) then - g.dY := g.dY * -1 + while true do + begin + nx := RandomLR(1, ArenaW); + ny := RandomLR(1, ArenaH); + if not a.captured[ny][nx] then + break + end; + e.curX := nx; + e.curY := ny end; -procedure TurnSun(var g: creature; var a: arena); -begin -end; - -procedure MakeEnemyStep(var a: arena; var e, h: creature; t: tracePtr); +procedure MakeEnemyStep(var a: arena; var e, hamster: creature; t: tracePtr); var prevX, prevY: integer; begin + if (e.t = creatureDrop) and (e.beforeTransform = 0) then + begin + TpDrop(a, e); + exit + end; + prevX := e.curX; prevY := e.curY; MakeStep(a, e); if TraceCrossed(prevX, prevY, e, t) then - h.alive := false + hamster.alive := false end; procedure KillCapturedEnemies(var a: arena; var e: creatureList); @@ -483,24 +475,95 @@ begin end end; +procedure TurnOtherwise(var a: arena; var g: creature); +begin + if (OnEdgeX(g.curX) or VerticalBorder(a, g.curX, g.curY)) then + g.dX := g.dX * -1; + if (OnEdgeY(g.curY) or HorizontalBorder(a, g.curX, g.curY)) then + g.dY := g.dY * -1 +end; + +procedure SetVerticalMove(var g: creature; ms: integer); +begin + g.dX := 0; + g.dY := ms; + if RandomBool then + g.dY := -g.dY +end; + +procedure SetHorizontalMove(var g: creature; ms: integer); +begin + g.dX := ms; + g.dY := 0; + if RandomBool then + g.dX := -g.dX +end; + +procedure TurnToDiagonal(var g: creature; ms: integer); +begin + if (g.dX <> 0) and (g.dY <> 0) then + begin + g.dX := -g.dX; + g.dY := -g.dY + end + else + begin + g.dX := ms; + if RandomBool then + g.dX := -g.dX; + g.dY := ms; + if RandomBool then + g.dY := -g.dY + end +end; + +procedure EightDimensionTurn(var a: arena; var g: creature; + var diagonalMove: boolean; ms: integer); +begin + if RandomBool then + diagonalMove := not diagonalMove; + if diagonalMove then + begin + TurnToDiagonal(g, ms) + end + else + begin + if OnEdgeX(g.curX) or VerticalBorder(a, g.curX, g.curY) then + SetVerticalMove(g, ms) + else + SetHorizontalMove(g, ms) + end +end; + procedure TurnEnemy(var cr: creature; var a: arena); begin case cr.t of creatureGhost: - TurnGhost(cr, a); + TurnOtherwise(a, cr); creatureSun: - TurnGhost(cr, a) + TurnOtherwise(a, cr); + creatureSnake, creatureDrop: + begin + if cr.t = creatureSnake then + EightDimensionTurn(a, cr, cr.diagonalMove, SnakeMovespeed) + else + EightDimensionTurn(a, cr, cr.diagonalMove, DropMovespeed) + end; end end; -function EnemyShouldTurn(var cr: creature; var a: arena): boolean; +function EnemyShouldTurn(var e: creature; var a: arena): boolean; +var + oldX, oldY, newX, newY: integer; begin - case cr.t of - creatureGhost: - EnemyShouldTurn := GhostShouldTurn(cr, a); - creatureSun: - EnemyShouldTurn := GhostShouldTurn(cr, a) - end + oldX := e.curX; + oldY := e.curY; + MakeStep(a, e); + newX := e.curX; + newY := e.curY; + e.curX := oldX; + e.curY := oldY; + EnemyShouldTurn := (oldX = newX) and (oldY = newY) end; procedure TurnStubbornEnemies(var a: arena; var e: creatureList); @@ -529,6 +592,8 @@ begin tmp := e.first; while tmp <> nil do begin + if tmp^.cr^.curY = 1 then + RedrawInterfaceArea(tmp^.cr^.curX, tmp^.cr^.t); if tmp^.cr^.alive and not EnemyShouldTurn(tmp^.cr^, a) then RedrawArea(a, tmp^.cr^.curX, tmp^.cr^.curY, tmp^.cr^.t); tmp := tmp^.next @@ -549,19 +614,19 @@ begin end end; -procedure MakeStep(var a: arena; var cr: creature); +procedure MakeStep(var a: arena; var enemy: creature); var absDx, absDy, maxD, stepX, stepY, i, nX, nY: integer; begin - absDx := Abs(cr.dX); - absDy := Abs(cr.dY); + absDx := Abs(enemy.dX); + absDy := Abs(enemy.dY); maxD := Max(absDx, absDy); - stepX := Signum(cr.dX, 0); - stepY := Signum(cr.dY, 0); + stepX := Signum(enemy.dX, 0); + stepY := Signum(enemy.dY, 0); for i := 1 to maxD do begin - nX := cr.curX + stepX; - nY := cr.curY + stepY; + nX := enemy.curX + stepX; + nY := enemy.curY + stepY; if a.captured[nY][nX] or (nX < 1) or (nX > ArenaW) or (nY < 1) or (nY > ArenaH) then begin @@ -569,8 +634,8 @@ begin end else begin - cr.curX := nX; - cr.curY := nY + enemy.curX := nX; + enemy.curY := nY end end end; diff --git a/src/ascii_arts_m.pas b/src/ascii_arts_m.pas index d69aca0..4339388 100644 --- a/src/ascii_arts_m.pas +++ b/src/ascii_arts_m.pas @@ -244,7 +244,7 @@ const ) ); - SunHeight = 5; + SunHeight = 4; SunWidth = 7; SunRunN = 2; SunAscii: array[1..SunRunN] of CreatureImage = ( @@ -253,28 +253,55 @@ const ' / \', '<|o o|>', ' \_^_/', - ' V' + '' ), ( ' _A_', ' / \', - '{|o o|}', + '{-o o-}', ' \_^_/', - ' v' - ) - ); - - RageSunHeight = 4; - RageSunRunN = 1; - RageSunAscii: array[1..RageSunRunN] of CreatureImage = ( - ( - ' ___', - ' / Z \', - '||> <||', - ' \___/', '' ) ); + GoidaSunHeight = 4; + GoidaSunAscii: CreatureImage = ( + ' ___', + ' / Z \', + '||> <||', + ' \___/', + '' + ); + + SnakeHeight = 5; + SnakeWidth = 7; + SnakeRunN = 2; + SnakeAscii: array[1..SnakeRunN] of CreatureImage = ( + ( + ' /v\ ', + '3 |o |', + '\\ \ / ', + ' \\_\\ ', + ' \_// ' + ), + ( + ' /v\ ', + ' o ', + '\\ \ / ', + ' ', + ' \_// ' + ) + ); + + DropHeight = 5; + DropWidth = 7; + DropAscii: CreatureImage = ( + ' _', + ' / \', + ' / \', + '/ 0_0 \', + '\_____/' + ); + implementation end. diff --git a/src/completed.txt b/src/completed.txt index 797d631..9210d62 100644 --- a/src/completed.txt +++ b/src/completed.txt @@ -1,3 +1,5 @@ +GameCompleteScoreWidth 50 +== BANNER START == ' _____ _ _ _ ', ' / ____| | | | | | |', '| | __ __ _ _ __ ___ ___ ___ ___ _ __ ___ _ __ | | ___| |_ ___| |', diff --git a/src/convbanners.pas b/src/convbanners.pas index b5faf75..48ae793 100644 --- a/src/convbanners.pas +++ b/src/convbanners.pas @@ -1,28 +1,40 @@ program convbanners; +uses Math; + const - BannerModuleName = '_banners_m.pas'; - GameCompleteFile = 'completed.txt'; - ExitFile = 'exit.txt'; - KeysFile = 'keys.txt'; + + AutobannerModuleName = '_autobanners_m.pas'; + + BannerStartS = '== BANNER START =='; + BannersN = 7; MenuFile = 'menu.txt'; - GameOverFile = 'gameover.txt'; - PausedFile = 'paused.txt'; LevelFile = 'level.txt'; + PauseFile = 'paused.txt'; + GameOverFile = 'gameover.txt'; + GameCompleteFile = 'completed.txt'; + KeyInfoFile = 'keys.txt'; + ExitFile = 'exit.txt'; + BannerFiles: array[1..BannersN] of string = ( + MenuFile, LevelFile, PauseFile, GameOverFile, + GameCompleteFile, KeyInfoFile, ExitFile + ); + + MenuVarsPrefix = 'MenuBanner'; + LevelVarsPrefix = 'LevelAnnounceBanner'; + PauseVarsPrefix = 'PauseBanner'; + GameOverVarsPrefix = 'GameOverBanner'; + GameCompleteVarsPrefix = 'GameCompleteBanner'; + KeysVarsPrefix = 'KeysInfoBanner'; + ExitVarsPrefix = 'ExitBanner'; + VarsPrefixes: array[1..BannersN] of string = ( + MenuVarsPrefix, LevelVarsPrefix, PauseVarsPrefix, GameOverVarsPrefix, + GameCompleteVarsPrefix, KeysVarsPrefix, ExitVarsPrefix + ); + + DecimalBase = 10; AfterImageLinesN = 2; - - ModuleBeginH = 13; - -{ -const - MaxBannerWidth = KeyInfoWidth; - MaxBannerHeight = KeyInfoHeight; -type - BannerImage = array[1..MaxBannerHeight] of string[MaxBannerWidth]; -} - - ModuleBegin: array[1..ModuleBeginH] of string = ( '{ ************************************************** }', '{ ************************************************** }', @@ -33,104 +45,19 @@ type '{ *** *** }', '{ ************************************************** }', '{ ************************************************** }', - 'unit _banners_m;', + 'unit _autobanners_m;', '', 'interface', - 'const' - ); - - KeyInfoCodeH = 10; - BannersKeyInfo: array[1..KeyInfoCodeH] of string = ( - 'KeyInfoHeight = 42;', - 'KeyInfoWidth = 98;', - 'MaxBannerHeight = KeyInfoHeight;', - 'MaxBannerWidth = KeyInfoWidth;', - 'type', - 'BannerImage = array[1..MaxBannerHeight] of string[MaxBannerWidth];', - 'const', - 'KeyInfoScreen: BannerImage = (', - ');', '' ); - { - KeyInfoCodeH = 5; - BannersKeyInfo: array[1..KeyInfoCodeH] of string = ( - 'KeyInfoHeight = 42;', - 'KeyInfoWidth = 98;', - 'KeyInfoScreen: BannerImage = (', - ');', - '' - ); - } + BannerImageTypeStr = + 'BannerImage = array[1..MaxBannerHeight] of string[MaxBannerWidth];'; - ExitCodeH = 6; - BannersExit: array[1..ExitCodeH] of string = ( - 'ExitScreenHeight = 16;', - 'ExitWidth = 70;', - 'ExitHeight = 8;', - 'ExitScreen: BannerImage = (', - ');', - '' - ); - - PauseCodeH = 5; - BannersPause: array[1..PauseCodeH] of string = ( - 'PauseHeight = 22;', - 'PauseWidth = 76;', - 'PauseAscii: BannerImage = (', - ');', - '' - ); - - CompleteCodeH = 6; - BannersGameComplete: array[1..CompleteCodeH] of string = ( - 'GameCompleteHeight = 14;', - 'GameCompleteWidth = 74;', - 'GameCompleteScoreWidth = 50;', - 'GameComplete: BannerImage = (', - ');', - '' - ); - - MenuCodeH = 11; - BannersMenu: array[1..MenuCodeH] of string = ( - 'GameMenuHeight = 36;', - 'GameNameHeight = 6;', - 'GameNameWidth = 58;', - 'NewGameHeight = 6;', - 'HighScoreHeight = 8;', - 'MenuInfoHeight = 8;', - 'ContinueHeight = 6;', - 'ContinueWidth = 41;', - 'GameMenuScreen: BannerImage = (', - ');', - '' - ); - - GameOverCodeH = 5; - BannersGameOver: array[1..GameOverCodeH] of string = ( - 'GameOverHeight = 40;', - 'GameOverWidth = 63;', - 'GameOverScreen: BannerImage = (', - ');', - '' - ); - - LevelCodeH = 5; - BannersLevel: array[1..LevelCodeH] of string = ( - 'LevelAnnounceHeight = 6;', - 'LevelAnnounceWidth = 24;', - 'LevelAnnounce: BannerImage = (', - ');', - '' - ); - - ModuleEndH = 3; + ModuleEndH = 2; ModuleEnd: array[1..ModuleEndH] of string = ( 'implementation', - 'end.', - '' + 'end.' ); procedure AppendText(var f: text; var t: array of string; h: integer); @@ -141,55 +68,185 @@ begin writeln(f, t[i - 1]) end; -procedure ConcatenateFiles(var fTo: text; var filename: string); +function ParsedStrLength(var s: string): integer; var + res: integer = 0; + backtickCnt: integer = 0; + i, sLen: integer; +begin + sLen := Length(s); + res := sLen; + for i := 1 to Length(s) do + if s[i] = '''' then + backtickCnt := backtickCnt + 1; + if s[sLen] = ',' then + res := res - 1; + res := res - 2; {Subtract first and last '} + backtickCnt := backtickCnt - 2; {Subtract first and last '} + ParsedStrLength := res - (backtickCnt div 2) +end; + +procedure GetMaxBannersDimensions(var h, w: integer); +var + i, len: integer; + curH: integer = 0; + t: text; ln: string; - fFrom: text; + isBanner: boolean = false; begin - assign(fFrom, fileName); - reset(fFrom); - while not eof(fFrom) do + h := 0; + w := 0; + for i := 1 to BannersN do begin - readln(fFrom, ln); - writeln(fTo, ln) + curH := 0; + isBanner := false; + assign(t, BannerFiles[i]); + reset(t); + while not eof(t) do + begin + readln(t, ln); + if not isBanner then + begin + isBanner := (ln = BannerStartS); + continue + end; + curH := curH + 1; + len := ParsedStrLength(ln); + w := Max(w, len); + if len > 0 then + h := max(h, curH) + end end end; -procedure AppendAsciiBanner(var f: text; var t: array of string; - h: integer; fileName: string); -var - i: integer; +procedure AppendMaxBannersDimensions(var t: text; maxH, maxW: integer); begin - for i := 1 to h do + writeln(t, 'MaxBannerHeight = ', maxH, ';'); + writeln(t, 'MaxBannerWidth = ', maxW, ';'); + writeln(t, '') +end; + +procedure AppendBannersType(var t: text); +begin + writeln(t, 'type'); + writeln(t, BannerImageTypeStr); + writeln(t, '') +end; + +procedure GetBannerDimensions(var fileName: string; var h, w: integer); +var + sLen: integer; + hNow: integer = 0; + fileFrom: text; + ln: string; + isBanner: boolean = false; +begin + w := 0; + h := 0; + assign(fileFrom, fileName); + reset(fileFrom); + while not eof(fileFrom) do begin - writeln(f, t[i - 1]); - if i = h - AfterImageLinesN then - ConcatenateFiles(f, fileName) + readln(fileFrom, ln); + if not isBanner then + begin + isBanner := (ln = BannerStartS); + continue + end; + sLen := ParsedStrLength(ln); + w := Max(w, sLen); + hNow := hNow + 1; + if sLen > 0 then + h := hNow end end; -procedure CreateBannerModule; +procedure ParseNum(var ln, res: string; idx: integer); var + i, n: integer; +begin + n := Length(ln); + for i := idx to n do + begin + if (ln[i] <= '0') or (ln[i] >= '9') then + begin + res := copy(ln, idx, i - 1); + break + end; + if i = n then + res := copy(ln, idx, i) + end +end; + +procedure TryAddConst(var fileTo: text; var ln: string); +var + idx: integer = 1; + lenS: integer; + num: string; + constName: string = ''; +begin + lenS := Length(ln); + while (idx <= lenS) do + begin + if ln[idx] = ' ' then + break; + idx := idx + 1 + end; + if (idx >= lenS) or (idx = 1) then + exit; + constName := copy(ln, 1, idx - 1); + ParseNum(ln, num, idx + 1); + writeln(fileTo, constName, ' = ', num, ';') +end; + +procedure AppendBanner(var fileTo: text; var fileName, varPrefix: string); +var + w, h: integer; + isBanner: boolean = false; + fileFrom: text; + ln: string; +begin + GetBannerDimensions(fileName, h, w); + writeln(fileTo, varPrefix, 'H = ', h, ';'); + writeln(fileTo, varPrefix, 'W = ', w, ';'); + assign(fileFrom, fileName); + reset(fileFrom); + while not isBanner do + begin + readln(fileFrom, ln); + isBanner := (ln = BannerStartS); + if not isBanner and (Length(ln) > 0) then + TryAddConst(fileTo, ln) + end; + writeln(fileTo, varPrefix, ': BannerImage = ('); + while not eof(fileFrom) do + begin + readln(fileFrom, ln); + writeln(fileTo, ln) + end; + writeln(fileTo, ');'); + writeln(fileTo, ''); +end; + +procedure CreateAutobannerModule; +var + i, maxH, maxW: integer; newModule: text; begin - assign(newModule, BannerModuleName); + assign(newModule, AutobannerModuleName); rewrite(newModule); AppendText(newModule, ModuleBegin, ModuleBeginH); - AppendAsciiBanner(newModule, BannersKeyInfo, KeyInfoCodeH, KeysFile); - AppendAsciiBanner(newModule, BannersExit, ExitCodeH, ExitFile); - AppendAsciiBanner(newModule, BannersPause, PauseCodeH, PausedFile); - AppendAsciiBanner(newModule, BannersGameComplete, CompleteCodeH, - GameCompleteFile); - AppendAsciiBanner(newModule, BannersMenu, MenuCodeH, MenuFile); - AppendAsciiBanner(newModule, BannersGameOver, GameOverCodeH, GameOverFile); - - AppendAsciiBanner(newModule, BannersLevel, LevelCodeH, LevelFile); - + writeln(newModule, 'const'); + GetMaxBannersDimensions(maxH, maxW); + AppendMaxBannersDimensions(newModule, maxH, maxW); + AppendBannersType(newModule); + writeln(newModule, 'const'); + for i := 1 to BannersN do + AppendBanner(newModule, BannerFiles[i], VarsPrefixes[i]); AppendText(newModule, ModuleEnd, ModuleEndH); close(newModule) end; begin - CreateBannerModule + CreateAutobannerModule end. - diff --git a/src/creature_m.pas b/src/creature_m.pas index 3208c92..48e4966 100644 --- a/src/creature_m.pas +++ b/src/creature_m.pas @@ -2,8 +2,6 @@ unit creature_m; interface -uses sun_fields_m, snake_fields_m, drop_fields_m; - type creatureType = (creatureHamster, creatureGhost, creatureSun, creatureSnake, creatureDrop); @@ -14,9 +12,13 @@ type curX, curY, dX, dY, moveSpeed, animation: integer; alive: boolean; t: creatureType; - sunf: sunStatePtr; - snakef: snakeStatePtr; - dropf: dropStatePtr; + + rageMode: boolean; {for sun } + bigStep: boolean; {for sun } + beforeTransform: integer; {for sun and drop } + diagonalMove: boolean; {for snake and drop} + beforeReverse: integer; {for snake and drop} + end; creatureItemPtr = ^creatureItem; @@ -72,15 +74,6 @@ begin lst.first := lst.first^.next; if lst.first = nil then lst.last := nil; - - if tmp^.cr^.t = creatureSun then - dispose(tmp^.cr^.sunf) - else - if tmp^.cr^.t = creatureSnake then - dispose(tmp^.cr^.snakef) - else - if tmp^.cr^.t = creatureDrop then - dispose(tmp^.cr^.dropF); dispose(tmp^.cr); dispose(tmp); lst.len := lst.len - 1 diff --git a/src/drop_m.pas b/src/drop_m.pas index 24d180a..f81ca1c 100644 --- a/src/drop_m.pas +++ b/src/drop_m.pas @@ -4,12 +4,49 @@ interface uses creature_m; -procedure UpdateDropState(var cr: creature); +procedure UpdateDropState(var d: creature); +procedure InitRandomDrop(var s: creature); + +const + DropMovespeed = 2; implementation -procedure UpdateDropState(var cr: creature); +uses arena_m, Math, math_m; + +const + MinToTp = 10; + MaxToTp = 75; + +procedure InitDrop(var s: creature; x, y, sigdx, sigdy: integer); begin + s.t := creatureDrop; + s.curX := x; + s.curY := y; + s.dX := DropMovespeed * sigdx; + s.dY := DropMovespeed * sigdy; + s.alive := true; + s.moveSpeed := DropMovespeed; + s.beforeTransform := RandomLR(MinToTp, MaxToTp); + s.diagonalMove := false +end; + +procedure InitRandomDrop(var s: creature); +var + x, y, sigdx, sigdy: integer; +begin + sigdx := IfThen(RandomBool, 1, -1); + sigdy := IfThen(RandomBool, 1, -1); + x := RandomLR(2, ArenaW - 1); + y := RandomLR(2, ArenaH - 1); + InitDrop(s, x, y, sigdx, sigdy) +end; + +procedure UpdateDropState(var d: creature); +begin + if d.beforeTransform = 0 then + d.beforeTransform := RandomLR(MinToTp, MaxToTp); + d.beforeTransform := d.beforeTransform - 1 end; end. diff --git a/src/enemy_packs_m.pas b/src/enemy_packs_m.pas index 5acff49..873ee7f 100644 --- a/src/enemy_packs_m.pas +++ b/src/enemy_packs_m.pas @@ -13,31 +13,21 @@ procedure AppendEnemies(var lst: creatureList; t: enemyPackType); implementation -uses ghost_m, sun_m; +uses ghost_m, sun_m, snake_m, drop_m; const - { - LevelGhostN: array[enemyPackType] of integer = ( - 4, 4, 2, 4, 4, 2, 4, 2, 4, 4 - ); - } - LevelGhostN: array[enemyPackType] of integer = ( 4, 4, 2, 4, 4, 2, 4, 2, 4, 4 ); LevelSunN: array[enemyPackType] of integer = ( 0, 1, 4, 2, 0, 2, 2, 2, 2, 0 ); - - - { - LevelSnakeN: array[enemyPackType] of integer = ( - 0, 0, 0, 1, 2, 2, 2, 4, 2, 2 - ); - LevelDropN: array[enemyPackType] of integer = ( - 0, 0, 0, 0, 2, 2, 1, 1, 2, 4 - ); - } + LevelSnakeN: array[enemyPackType] of integer = ( + 0, 0, 0, 1, 2, 2, 2, 4, 2, 2 + ); + LevelDropN: array[enemyPackType] of integer = ( + 0, 0, 0, 0, 2, 2, 1, 1, 2, 4 + ); procedure AppendRandomGhosts(var lst: creatureList; t: enemyPackType); var @@ -66,11 +56,29 @@ begin end; procedure AppendRandomSnakes(var lst: creatureList; t: enemyPackType); +var + i: integer; + c: creaturePtr; begin + for i := 1 to LevelSnakeN[t] do + begin + new(c); + InitRandomSnake(c^); + AppendCreature(lst, c) + end end; procedure AppendRandomDrops(var lst: creatureList; t: enemyPackType); +var + i: integer; + c: creaturePtr; begin + for i := 1 to LevelDropN[t] do + begin + new(c); + InitRandomDrop(c^); + AppendCreature(lst, c) + end end; procedure AppendEnemies(var lst: creatureList; t: enemyPackType); diff --git a/src/exit.txt b/src/exit.txt index 5169dc1..42f674e 100644 --- a/src/exit.txt +++ b/src/exit.txt @@ -1,3 +1,6 @@ +ExitHeight 8 + +== BANNER START == ' ______ _ _ _ _ ___', '| ____| (_) | | | | | |__ \', '| |__ __ ___| |_ | |_| |__ ___ __ _ __ _ _ __ ___ ___ ) |', diff --git a/src/game_m.pas b/src/game_m.pas index 1bd1a25..030a2b6 100644 --- a/src/game_m.pas +++ b/src/game_m.pas @@ -1,4 +1,3 @@ -{ MainLoop -- main loop } unit game_m; interface @@ -23,8 +22,7 @@ type procedure InitGame(var g: gameState); procedure MainLoop(var g: gameState); -procedure NextExitState(var g: gameState); -procedure PreviousExitState(var g: gameState); +procedure ChangeOtherExitState(var g: gameState); implementation @@ -33,11 +31,11 @@ uses arena_m, arena_graphics_m, crt, creature_m, graphics_m, hamster_m, const KeyDelayMs = 25; - MoveDelayMs = 120; + MoveDelayMs = 125; EraseLifeThreshold = 10; AnnounceDelayMs = 1500; LevelCompleteDelayMs = 1500; - LevelCount = 2; + LevelCount = 20; StartLifeN = 3; procedure DecreaseLife(var life: integer); @@ -117,7 +115,7 @@ begin EraseGameOver; if g.curState = gameLevelAnnounce then begin - InitLevel(level, enemyPack1) + InitLevel(level, g.enemyPack) end else begin @@ -140,17 +138,17 @@ end; procedure GameNextLevel(var g: gameState; var level: levelState); begin - g.level := g.level + 1; DisposeCreatureList(level.enemyList); - if g.level > LevelCount then + if g.level = LevelCount then begin g.levelInited := false; - g.curState := gameComplete - end - else - begin - g.curState := gameLevelComplete - end + g.curState := gameComplete; + exit + end; + g.level := g.level + 1; + g.curState := gameLevelComplete; + if g.level mod 2 = 1 then + g.enemyPack := succ(g.enemyPack) end; procedure GameKillHamster(var g: gameState; var level: levelState); @@ -186,9 +184,7 @@ begin TurnStubbornEnemies(level.a, level.enemyList); EraseEnemies(level.a, level.enemyList); MakeEnemySteps(level.a, level.h, level.t, level.enemyList); - UpdateEnemyStates(level.enemyList); - DrawAliveEnemies(level.enemyList) end; @@ -242,7 +238,7 @@ begin g.score := 0 end; g.curState := gameLevelLoop; - InitLevel(level, enemyPack1); + InitLevel(level, g.enemyPack); DrawLevel(level, g.life, g.score); LevelLoop(g, level) end; @@ -273,6 +269,7 @@ begin if (g.curState = gameMenu) and not prevMenu then begin DrawMenu(g); + GotoXY(1, 1); prevMenu := true end; delay(KeyDelayMs); @@ -294,6 +291,7 @@ var i: integer; begin DrawAnnounce(g.level); + GotoXY(1, 1); for i := 1 to AnnounceDelayMs div KeyDelayMs do begin delay(KeyDelayMs); @@ -371,23 +369,12 @@ begin gameComplete: RunGameCompleteState(g, level) end; - EraseAll + clrscr end; -procedure NextExitState(var g: gameState); +procedure ChangeOtherExitState(var g: gameState); begin - if not g.curExit then - g.curExit := true - else - g.curExit := false -end; - -procedure PreviousExitState(var g: gameState); -begin - if g.curExit then - g.curExit := false - else - g.curExit := true + g.curExit := not g.curExit end; end. diff --git a/src/gameover.txt b/src/gameover.txt index 9e3d03e..27ba170 100644 --- a/src/gameover.txt +++ b/src/gameover.txt @@ -1,3 +1,4 @@ +== BANNER START == ' _____ __ __ ______ ', ' / ____| /\ | \/ | ____|', ' | | __ / \ | \ / | |__ ', diff --git a/src/ghost_m.pas b/src/ghost_m.pas index 40055d8..8f16b78 100644 --- a/src/ghost_m.pas +++ b/src/ghost_m.pas @@ -24,8 +24,7 @@ begin g.dX := GhostStartDX * sigdx; g.dY := GhostStartDY * sigdy; g.moveSpeed := GhostMovespeed; - g.alive := true; - g.animation := 1; + g.alive := true end; procedure InitRandomGhost(var g: creature); diff --git a/src/gohamster.pas b/src/gohamster.pas index 93e7cfd..f978224 100644 --- a/src/gohamster.pas +++ b/src/gohamster.pas @@ -33,9 +33,8 @@ begin PrintTerminalHelp; exit end; - clrscr; InitGame(g); - EraseAll; + clrscr; MainLoop(g) end. diff --git a/src/graphics_m.pas b/src/graphics_m.pas index b5d38a9..98f4038 100644 --- a/src/graphics_m.pas +++ b/src/graphics_m.pas @@ -2,7 +2,7 @@ unit graphics_m; interface -uses arena_m, creature_m, trace_m, game_m, level_m, _banners_m, ascii_arts_m; +uses arena_m, creature_m, trace_m, game_m, level_m, _autobanners_m, ascii_arts_m; const BorderSize = 1; @@ -28,7 +28,6 @@ procedure DrawNumber(x, y: integer; n: longint); procedure DrawRectangle(x0, y0, h, w: integer; ch: char); procedure DrawMenuState(s: menuState); procedure DrawMenu(var g: gameState); -procedure EraseAll; procedure EraseAnnounce(lvl: integer); procedure EraseExit; procedure EraseExitState(b: boolean); @@ -45,7 +44,7 @@ implementation uses crt, math_m; const - AnnounceY = (ScreenH - LevelAnnounceHeight) div 2; + AnnounceY = (ScreenH - LevelAnnounceBannerH) div 2; BigLetterWidth = 8; BorderN = 2; DecimalDelimiter = 10; @@ -55,34 +54,47 @@ const MenuHeightPadding = 2; MenuInfoY = NewGameY + NewGameHeight + MenuHeightPadding; ContinueY = MenuInfoY + MenuInfoHeight; - ExitGameY = (ScreenH - ExitScreenHeight) div 2 - MenuHeightPadding; + ExitGameY = (ScreenH - ExitBannerH) div 2 - MenuHeightPadding; ExitYesY = ExitGameY + ExitHeight - 1 + MenuHeightPadding; ExitHamsterY = ExitYesY; GameNameX = ScreenW * WidthCoefficient div 3 + 4; - MenuWidthPadding = 4; - MenuHamsterX = GameNameX - HamsterWidth - MenuWidthPadding; + MenuPaddingX = 4; + MenuHamsterX = GameNameX - HamsterWidth - MenuPaddingX; ExitYesX = MenuHamsterX; ExitNoX = ScreenW * WidthCoefficient - ExitYesX - NoWidth; - GameOverX = (ScreenW * WidthCoefficient - GameNameWidth) div 2; - GameOverY = (ScreenH - GameOverHeight) div 2; - HamsterNoX = ExitNoX - HamsterWidth - MenuWidthPadding; - HamsterYesX = ExitYesX - HamsterWidth - MenuWidthPadding; - KeyInfoX = (ScreenW * WidthCoefficient - KeyInfoWidth) div 2; - KeyInfoY = (ScreenH - KeyInfoHeight) div 2; + GameOverX = (ScreenW * WidthCoefficient - GameOverBannerW) div 2; + GameOverY = (ScreenH - GameOverBannerH) div 2; + HamsterNoX = ExitNoX - HamsterWidth - MenuPaddingX; + HamsterYesX = ExitYesX - HamsterWidth - MenuPaddingX; + KeyInfoX = (ScreenW * WidthCoefficient - KeysInfoBannerW) div 2; + KeyInfoY = (ScreenH - KeysInfoBannerH) div 2; LetterWidth = 5; LevelNumberMargin = 3; - GameCompleteX = (ScreenW * WidthCoefficient - GameCompleteWidth) div 2; - GameCompleteY = (ScreenH - GameCompleteHeight) div 2; + GameCompleteX = (ScreenW * WidthCoefficient - GameCompleteBannerW) div 2; + GameCompleteY = (ScreenH - GameCompleteBannerH) div 2; GameCompleteScoreX = GameCompleteX + GameCompleteScoreWidth + 3; GameCompleteScoreY = GameCompleteY + 9; - EndOfLine = 256; + MaxStringLen = 255; var firstMenuDraw: boolean = true; +function CountLeadSpaces(var s: string): integer; +var + i, res: integer; +begin + res := 0; + for i := 1 to Length(s) do + if s[i] <> ' ' then + break + else + res := res + 1; + CountLeadSpaces := res +end; + procedure PrintStringScreen(x, y, dy: integer; var s: string); var - cutLen: integer; + cutLen, leadSpaces: integer; sCopy: string; begin if y + dy - 1 > ScreenH then @@ -91,15 +103,22 @@ begin begin cutLen := x * -1 + 1; GotoXY(1, y + dy - 1); - sCopy := copy(s, cutLen, EndOfLine); + sCopy := copy(s, cutLen, MaxStringLen); write(sCopy) end else begin - GotoXY(x, y + dy - 1); - write(s) - end; - GotoXY(1, 1) + leadSpaces := CountLeadSpaces(s); + GotoXY(x + leadSpaces, y + dy - 1); + sCopy := copy(s, leadSpaces + 1, MaxStringLen); + write(sCopy) + end +end; + +procedure PrintDigitS(x, y, dy: integer; var s: string); +begin + GotoXY(x, y + dy - 1); + write(s) end; procedure DrawCreatureImage(x, y, h: integer; var a: CreatureImage); @@ -123,7 +142,7 @@ var i: integer; begin for i := 1 to h do - PrintStringScreen(x, y, i, a[i]) + PrintDigitS(x, y, i, a[i]) end; procedure DrawDigit(x, y, digit: integer); @@ -145,19 +164,22 @@ procedure DrawExit(var g: gameState); var realX: integer = ScreenW * WidthCoefficient; begin - DrawBannerImage((realX - ExitWidth) div 2, ExitGameY, - ExitScreenHeight, ExitScreen); - DrawExitState(g.curExit) + DrawBannerImage((realX - ExitBannerW) div 2, ExitGameY, + ExitBannerH, ExitBanner); + DrawExitState(g.curExit); + GotoXY(1, 1) end; procedure DrawGameOver; begin - DrawBannerImage(GameOverX, GameOverY, GameOverHeight, GameOverScreen) + DrawBannerImage(GameOverX, GameOverY, GameOverBannerH, GameOverBanner); + GotoXY(1, 1) end; procedure DrawKeyInfo; begin - DrawBannerImage(KeyInfoX, KeyInfoY, KeyInfoHeight, KeyInfoScreen) + DrawBannerImage(KeyInfoX, KeyInfoY, KeysInfoBannerH, KeysInfoBanner); + GotoXY(1, 1) end; procedure DrawLineX(x, y, len: integer; ch: char); @@ -166,8 +188,7 @@ var begin GotoXY(x, y); for i := 1 to len do - write(ch); - GotoXY(1, 1) + write(ch) end; procedure DrawLineY(x, y, len: integer; ch: char); @@ -178,8 +199,7 @@ begin begin GotoXY(x, y + i - 1); write(ch) - end; - GotoXY(1, 1) + end end; procedure DrawMenuState(s: menuState); @@ -209,8 +229,7 @@ begin GotoXY(x0 + w - 1, y0 + i); write(ch) end; - DrawLineX(x0, y0 + h - 1, w, ch); - GotoXY(1, 1) + DrawLineX(x0, y0 + h - 1, w, ch) end; procedure DrawMenu(var g: gameState); @@ -222,7 +241,7 @@ begin DrawRectangle(1, 1, ScreenH, ScreenW * WidthCoefficient, BorderSymbol); firstMenuDraw := not firstMenuDraw end; - DrawBannerImage(GameNameX, y, GameMenuHeight, GameMenuScreen); + DrawBannerImage(GameNameX, y, MenuBannerH, MenuBanner); if not g.levelInited then DrawLineX(GameNameX, ContinueY + ContinueHeight div 2, ContinueWidth, '-'); @@ -231,15 +250,15 @@ end; procedure FillRectangle(x, y, w, h: integer; ch: char); var - i, j: integer; + i: integer; + s: string; begin + s := StringOfChar(ch, w); for i := 0 to h - 1 do begin GotoXY(x, y + i); - for j := 0 to w - 1 do - write(ch) - end; - GotoXY(1, 1) + write(s) + end end; procedure EraseRectangle(x, y, w, h: integer); @@ -247,36 +266,32 @@ begin FillRectangle(x, y, w, h, ' ') end; -procedure EraseAll; -begin - EraseRectangle(1, 1, ScreenW * WidthCoefficient, ScreenH) -end; - procedure EraseExit; begin EraseRectangle(HamsterYesX, ExitGameY, - ExitWidth + HamsterWidth + MenuWidthPadding, - ExitScreenHeight + MenuHeightPadding + YesHeight) + ExitBannerW + HamsterWidth + MenuPaddingX, + ExitBannerH + MenuHeightPadding + YesHeight) end; procedure EraseExitState(b: boolean); +var + x: integer; begin if b then - EraseRectangle(HamsterYesX, ExitHamsterY, - HamsterWidth, HamsterHeight) + x := HamsterYesX else - EraseRectangle(HamsterNoX, ExitHamsterY, - HamsterWidth, HamsterHeight) + x := HamsterNoX; + EraseRectangle(x, ExitHamsterY, HamsterWidth, HamsterHeight) end; procedure EraseGameOver; begin - EraseRectangle(GameOverX, GameOverY, GameOverWidth, GameOverHeight) + EraseRectangle(GameOverX, GameOverY, GameOverBannerW, GameOverBannerH) end; procedure EraseKeyInfo; begin - EraseRectangle(KeyInfoX, KeyInfoY, KeyInfoWidth, KeyInfoHeight) + EraseRectangle(KeyInfoX, KeyInfoY, KeysInfoBannerW, KeysInfoBannerH) end; procedure EraseLevel; @@ -290,7 +305,7 @@ end; procedure EraseMenu; begin EraseRectangle(MenuHamsterX, GameNameY, - GameNameWidth + HamsterWidth + MenuWidthPadding, + MenuBannerW + HamsterWidth + MenuPaddingX, ScreenH - GameNameY * 2) end; @@ -306,7 +321,7 @@ begin menuContinue: EraseRectangle(MenuHamsterX, ContinueY + 1, HamsterWidth, HamsterHeight) - end + end end; type @@ -387,12 +402,12 @@ var digitCnt: integer = 0; begin digitCnt := CountDigits(lvl); - w := LevelAnnounceWidth + LevelNumberMargin + + w := LevelAnnounceBannerW + LevelNumberMargin + DigitWidth * digitCnt + DigitSpaceWidth * (digitCnt - 1); x := (ScreenW * WidthCoefficient - w) div 2; - DrawBannerImage(x, AnnounceY, LevelAnnounceHeight, LevelAnnounce); - DrawNumber(x + LevelAnnounceWidth + LevelNumberMargin, AnnounceY + 1, lvl) - + DrawBannerImage(x, AnnounceY, LevelAnnounceBannerH, LevelAnnounceBanner); + DrawNumber(x + LevelAnnounceBannerW + LevelNumberMargin, + AnnounceY + 1, lvl) end; procedure EraseAnnounce(lvl: integer); @@ -400,16 +415,16 @@ var w, x, digitCnt: integer; begin digitCnt := CountDigits(lvl); - w := LevelAnnounceWidth + LevelNumberMargin + + w := LevelAnnounceBannerW + LevelNumberMargin + DigitWidth * digitCnt + DigitSpaceWidth * (digitCnt - 1); x := (ScreenW * WidthCoefficient - w) div 2; - EraseRectangle(x, AnnounceY, w, LevelAnnounceHeight) + EraseRectangle(x, AnnounceY, w, LevelAnnounceBannerH) end; procedure DrawGameComplete(score: integer); begin DrawBannerImage(GameCompleteX, GameCompleteY, - GameCompleteHeight, GameComplete); + GameCompleteBannerH, GameCompleteBanner); DrawNumber(GameCompleteScoreX, GameCompleteScoreY, score) end; diff --git a/src/keys.txt b/src/keys.txt index e580c67..f839a89 100644 --- a/src/keys.txt +++ b/src/keys.txt @@ -1,3 +1,4 @@ +== BANNER START == ' _', ' | |', ' _ __ ___ _____ _____ | | _____ _ _ ___ _', diff --git a/src/keys_m.pas b/src/keys_m.pas index 9896714..5e90d09 100644 --- a/src/keys_m.pas +++ b/src/keys_m.pas @@ -85,8 +85,7 @@ begin GotoXY(2, 60); write(' '); GotoXY(2, 60); - writeln(GetLength(level.t)); - GotoXY(1, 1) + writeln(GetLength(level.t)) end; {DEBUG} if (k = ArrowLeftOrd) or (k = ArrowRightOrd) or (k = ArrowUpOrd) or @@ -194,10 +193,8 @@ end; procedure ChangeExitState(k: integer; var g: gameState); begin case k of - ArrowRightOrd: - NextExitState(g); - ArrowLeftOrd: - PreviousExitState(g) + ArrowRightOrd, ArrowLeftOrd: + ChangeOtherExitState(g) end end; @@ -280,7 +277,8 @@ begin HandleGameOverKey(g, k); gameComplete: HandleGameCompleteKey(g, k) - end + end; + GotoXY(1, 1) end; end. diff --git a/src/level.txt b/src/level.txt index 93b79d2..a9139cd 100644 --- a/src/level.txt +++ b/src/level.txt @@ -1,3 +1,4 @@ +== BANNER START == ' _ _ ', '| | | |', '| | _____ _____| |', diff --git a/src/menu.txt b/src/menu.txt index 36e8bf7..4c8003e 100644 --- a/src/menu.txt +++ b/src/menu.txt @@ -1,3 +1,11 @@ +GameNameHeight 6 +NewGameHeight 6 +MenuInfoHeight 8 +HighScoreHeight 8 +ContinueHeight 6 +ContinueWidth 41 + +== BANNER START == ' _____ _ _ _ _', ' / ____| | | | | | | | |', '| | __ ___ | | | |__| | __ _ _ __ ___ ___| |_ ___ _ __', diff --git a/src/paused.txt b/src/paused.txt index dbd1917..3409385 100644 --- a/src/paused.txt +++ b/src/paused.txt @@ -1,3 +1,4 @@ +== BANNER START == ' _', ' | |', ' _ __ __ _ _ _ ___ ___ __| |', @@ -17,7 +18,7 @@ ' __ _ __ _ _ _ _| |_ | |_ ___ _ __ ___ ___ _ __ _ _', ' / _` | ______ / _` | | | | | __| | __/ _ \ | ''_ ` _ \ / _ \ ''_ \| | | |', '| (_| | |______| | (_| | |_| | | |_ | || (_) | | | | | | | __/ | | | |_| |', -' \__, | \__, |\__,_|_|\__| \__\___/ |_| |_| |_|\___|_| '' |_|\__,_|', +' \__, | \__, |\__,_|_|\__| \__\___/ |_| |_| |_|\___|_| |_|\__,_|', '====| |= | |', ' |_| |_|', '', diff --git a/src/snake_m.pas b/src/snake_m.pas index cc85524..1e8046c 100644 --- a/src/snake_m.pas +++ b/src/snake_m.pas @@ -4,12 +4,53 @@ interface uses creature_m; -procedure UpdateSnakeState(var cr: creature); +procedure UpdateSnakeState(var s: creature); +procedure InitRandomSnake(var s: creature); + +const + SnakeMovespeed = 2; implementation -procedure UpdateSnakeState(var cr: creature); +uses arena_m, Math, math_m; + +const + MinToReverse = 2; + MaxToReverse = 75; + +procedure InitSnake(var s: creature; x, y, sigdx, sigdy: integer); begin + s.t := creatureSnake; + s.curX := x; + s.curY := y; + s.dX := SnakeMovespeed * sigdx; + s.dY := SnakeMovespeed * sigdy; + s.alive := true; + s.moveSpeed := SnakeMovespeed; + s.beforeReverse := RandomLR(MinToReverse, MaxToReverse); + s.diagonalMove := false +end; + +procedure InitRandomSnake(var s: creature); +var + x, y, sigdx, sigdy: integer; +begin + sigdx := IfThen(RandomBool, 1, -1); + sigdy := IfThen(RandomBool, 1, -1); + x := RandomLR(2, ArenaW - 1); + y := RandomLR(2, ArenaH - 1); + InitSnake(s, x, y, sigdx, sigdy) +end; + +procedure UpdateSnakeState(var s: creature); +begin + s.beforeReverse := s.beforeReverse - 1; + if s.beforeReverse = 0 then + begin + s.beforeReverse := RandomLR(MinToReverse, MaxToReverse); + s.dX := s.dX * -1; + s.dY := s.dY * -1 + end end; end. diff --git a/src/sun_m.pas b/src/sun_m.pas index 15be5d4..d5ff7d9 100644 --- a/src/sun_m.pas +++ b/src/sun_m.pas @@ -5,7 +5,7 @@ interface uses creature_m; procedure InitRandomSun(var s: creature); -procedure UpdateSunState(var cr: creature); +procedure UpdateSunState(var s: creature); implementation @@ -14,31 +14,27 @@ uses arena_m, Math, math_m; const SunSlowMovespeed = 1; SunFastMovespeed = 2; - SunRageMovespeed = 4; - + SunGoidaMovespeed = 3; SunStartDX = SunSlowMovespeed; SunStartDY = SunSlowMovespeed; SunSymbol = 's'; - MinToRageSwitch = 15; - MaxToRageSwitch = 25; - + MinToGoidaSwitch = 25; + MaxToGoidaSwitch = 35; MinToNormSwitch = 5; - MaxToNormSwitch = 15; + MaxToNormSwitch = 30; -procedure InitSun(var g: creature; x, y, sigdx, sigdy: integer); +procedure InitSun(var s: creature; x, y, sigdx, sigdy: integer); begin - g.t := creatureSun; - g.curX := x; - g.curY := y; - g.dX := SunStartDX * sigdx; - g.dY := SunStartDY * sigdy; - g.movespeed := SunSlowMovespeed; - g.alive := true; - g.animation := 1; - new(g.sunf); - g.sunf^.bigStep:= true; - g.sunf^.rageMode := false; - g.sunf^.beforeRageSwitch := RandomLR(MinToRageSwitch, MaxToRageSwitch);; + s.t := creatureSun; + s.curX := x; + s.curY := y; + s.dX := SunStartDX * sigdx; + s.dY := SunStartDY * sigdy; + s.alive := true; + s.moveSpeed := SunFastMovespeed; + s.bigStep:= true; + s.rageMode := false; + s.beforeTransform := RandomLR(MinToGoidaSwitch, MaxToGoidaSwitch) end; procedure InitRandomSun(var s: creature); @@ -52,46 +48,46 @@ begin InitSun(s, x, y, sigdx, sigdy) end; -procedure SwitchRageMode(var cr: creature); +procedure SwitchGoidaMode(var cr: creature); begin - cr.sunf^.rageMode := not cr.sunf^.rageMode; - if cr.sunf^.rageMode then - cr.sunf^.beforeRageSwitch := RandomLR(MinToNormSwitch, MaxToNormSwitch) + cr.rageMode := not cr.rageMode; + if cr.rageMode then + cr.beforeTransform := RandomLR(MinToNormSwitch, MaxToNormSwitch) else - cr.sunf^.beforeRageSwitch := RandomLR(MinToRageSwitch, MaxToRageSwitch); - if cr.sunf^.rageMode then + cr.beforeTransform := RandomLR(MinToGoidaSwitch, MaxToGoidaSwitch); + if cr.rageMode then begin - cr.dX := Signum(cr.dX, 0) * SunRageMovespeed; - cr.dY := Signum(cr.dY, 0) * SunRageMovespeed + cr.dX := Signum(cr.dX, 0) * SunGoidaMovespeed; + cr.dY := Signum(cr.dY, 0) * SunGoidaMovespeed end else begin cr.dX := Signum(cr.dX, 0) * SunSlowMovespeed; cr.dY := Signum(cr.dY, 0) * SunSlowMovespeed; - cr.sunf^.bigStep := false + cr.bigStep := false end; end; -procedure UpdateSunState(var cr: creature); +procedure UpdateSunState(var s: creature); begin - if cr.sunf^.beforeRageSwitch = 0 then + if s.beforeTransform = 0 then begin - SwitchRageMode(cr); + SwitchGoidaMode(s); exit end; - cr.sunf^.beforeRageSwitch := cr.sunf^.beforeRageSwitch - 1; - if cr.sunf^.rageMode then + s.beforeTransform := s.beforeTransform - 1; + if s.rageMode then exit; - cr.sunf^.bigStep := not cr.sunf^.bigStep; - if cr.sunf^.bigStep then + s.bigStep := not s.bigStep; + if s.bigStep then begin - cr.dX := Signum(cr.dX, 0) * SunFastMovespeed; - cr.dY := Signum(cr.dY, 0) * SunFastMovespeed + s.dX := Signum(s.dX, 0) * SunFastMovespeed; + s.dY := Signum(s.dY, 0) * SunFastMovespeed end else begin - cr.dX := Signum(cr.dX, 0) * SunSlowMovespeed; - cr.dY := Signum(cr.dY, 0) * SunSlowMovespeed + s.dX := Signum(s.dX, 0) * SunSlowMovespeed; + s.dY := Signum(s.dY, 0) * SunSlowMovespeed end end; diff --git a/src/trace_m.pas b/src/trace_m.pas index 2c84073..711ff8b 100644 --- a/src/trace_m.pas +++ b/src/trace_m.pas @@ -18,8 +18,7 @@ type function FindIndex(var t: tracePtr; x, y, curIdx: integer): integer; function GetLength(var t: tracePtr): integer; -function -TraceCrossed(pX, pY: integer; var cr: creature; t: tracePtr): boolean; +function TraceCrossed(pX, pY: integer; var cr: creature; t: tracePtr): boolean; procedure ChangeHamsterTrace(var h: creature; var t: tracePtr); procedure DeleteTrace(var t: tracePtr); procedure GetStart(var traceStart: tracePtr; a: tracePtr); @@ -165,8 +164,7 @@ begin end end; -function -TraceCrossed(pX, pY: integer; var cr: creature; t: tracePtr): boolean; +function TraceCrossed(pX, pY: integer; var cr: creature; t: tracePtr): boolean; var dX, dY, prevX, prevY: integer; begin @@ -184,10 +182,7 @@ begin prevX := prevX + dX; prevY := prevY + dY end; - if IsOnTrace(prevX, prevY, t) then - TraceCrossed := true - else - TraceCrossed := false + TraceCrossed := IsOnTrace(prevX, prevY, t) end; end.