Загрузка данных


@echo off
chcp 65001 >nul
set "SELF=%~f0"
powershell -NoProfile -ExecutionPolicy Bypass -Command "$f=[IO.File]::ReadAllText($env:SELF,[Text.Encoding]::UTF8); Invoke-Expression ($f -split ('#===PS'+'_CODE==='))[1]"
exit /b
#===PS_CODE===
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::CursorVisible = $false
$Host.UI.RawUI.WindowTitle = "CYBER GALAXY: OVERDRIVE"

$ESC = [char]27
$W = 64
$H = 24
$grid = New-Object char[] ($W * $H)
$cols = New-Object int[] ($W * $H)
$rnd = New-Object System.Random

function Set-Cell([int]$x, [int]$y, [char]$ch, [int]$c) {
    if ($x -ge 0 -and $x -lt $W -and $y -ge 0 -and $y -lt $H) {
        $idx = $y * $W + $x
        $script:grid[$idx] = $ch
        $script:cols[$idx] = $c
    }
}

function Draw-Text([int]$x, [int]$y, [string]$text, [int]$c) {
    for ($i = 0; $i -lt $text.Length; $i++) {
        Set-Cell ($x + $i) $y $text[$i] $c
    }
}

function Spawn-Explosion([double]$ex, [double]$ey, [int]$count) {
    $chars = @('*', '+', '.', 'o', 'x')
    $pcols = @(93, 91, 33, 31, 97)
    for ($i = 0; $i -lt $count; $i++) {
        $ang = $rnd.NextDouble() * 6.283
        $spd = 0.3 + $rnd.NextDouble() * 1.2
        [void]$particles.Add(@{
            x = $ex; y = $ey
            vx = [Math]::Cos($ang) * $spd * 1.6
            vy = [Math]::Sin($ang) * $spd
            life = $rnd.Next(5, 14)
            ch = $chars[$rnd.Next($chars.Count)]
            c = $pcols[$rnd.Next($pcols.Count)]
        })
    }
}

:outerLoop while ($true) {
    Clear-Host
    $px = 32; $py = 20
    $hp = 100; $ult = 50; $score = 0; $weapon = 1; $wave = 1
    $nextBossScore = 250
    $boss = $null
    $tick = 0

    $bullets   = New-Object System.Collections.ArrayList
    $ebullets  = New-Object System.Collections.ArrayList
    $enemies   = New-Object System.Collections.ArrayList
    $particles = New-Object System.Collections.ArrayList
    $items     = New-Object System.Collections.ArrayList
    $stars     = New-Object System.Collections.ArrayList

    for ($i = 0; $i -lt 38; $i++) {
        [void]$stars.Add(@{
            x = $rnd.Next(1, $W - 1)
            y = $rnd.NextDouble() * ($H - 2) + 1
            spd = if ($i % 3 -eq 0) { 0.45 } else { 0.18 }
            ch = if ($i % 3 -eq 0) { '*' } else { '.' }
            c = if ($i % 3 -eq 0) { 37 } else { 90 }
        })
    }

    # Главный игровой цикл
    while ($hp -gt 0) {
        $sw = [System.Diagnostics.Stopwatch]::StartNew()
        $tick++

        # --- СЧИТЫВАНИЕ УПРАВЛЕНИЯ ---
        $mx = 0; $my = 0; $useUlt = $false
        while ([Console]::KeyAvailable) {
            $k = [Console]::ReadKey($true).Key
            switch ($k) {
                'LeftArrow'  { $mx = -2 }
                'A'          { $mx = -2 }
                'RightArrow' { $mx = 2 }
                'D'          { $mx = 2 }
                'UpArrow'    { $my = -1 }
                'W'          { $my = -1 }
                'DownArrow'  { $my = 1 }
                'S'          { $my = 1 }
                'Spacebar'   { $useUlt = $true }
                'Escape'     { Clear-Host; [Console]::CursorVisible = $true; exit }
            }
        }
        $px = [Math]::Max(3, [Math]::Min($W - 4, $px + $mx))
        $py = [Math]::Max(4, [Math]::Min($H - 3, $py + $my))

        # --- УЛЬТРА-ШТОРМ (ПРОБЕЛ) ---
        if ($useUlt -and $ult -ge 100) {
            $ult = 0
            $ebullets.Clear()
            for ($bx = 2; $bx -lt ($W - 2); $bx += 2) {
                [void]$bullets.Add(@{ x = $bx; y = $py - 1; vx = 0; vy = -1.5; c = 96; ch = '!' })
            }
            Spawn-Explosion $px $py 25
        }

        # --- АВТО-СТРЕЛЬБА КОРАБЛЯ ---
        if ($tick % 4 -eq 0) {
            if ($weapon -eq 1) {
                [void]$bullets.Add(@{ x = $px; y = $py - 1; vx = 0; vy = -1.2; c = 96; ch = '|' })
            } elseif ($weapon -eq 2) {
                [void]$bullets.Add(@{ x = $px - 1; y = $py - 1; vx = 0; vy = -1.2; c = 96; ch = '|' })
                [void]$bullets.Add(@{ x = $px + 1; y = $py - 1; vx = 0; vy = -1.2; c = 96; ch = '|' })
            } elseif ($weapon -eq 3) {
                [void]$bullets.Add(@{ x = $px; y = $py - 1; vx = 0; vy = -1.3; c = 93; ch = '!' })
                [void]$bullets.Add(@{ x = $px - 2; y = $py; vx = -0.25; vy = -1.1; c = 96; ch = '/' })
                [void]$bullets.Add(@{ x = $px + 2; y = $py; vx = 0.25; vy = -1.1; c = 96; ch = '\' })
            } else {
                [void]$bullets.Add(@{ x = $px - 1; y = $py - 1; vx = 0; vy = -1.4; c = 93; ch = '!' })
                [void]$bullets.Add(@{ x = $px + 1; y = $py - 1; vx = 0; vy = -1.4; c = 93; ch = '!' })
                [void]$bullets.Add(@{ x = $px - 2; y = $py; vx = -0.35; vy = -1.2; c = 95; ch = '\' })
                [void]$bullets.Add(@{ x = $px + 2; y = $py; vx = 0.35; vy = -1.2; c = 95; ch = '/' })
            }
        }

        # --- СПАВН ВРАГОВ И БОССА ---
        if ($null -eq $boss -and $score -ge $nextBossScore) {
            $maxB = 40 + $wave * 20
            $boss = @{ x = 32.0; y = 3.0; vx = 0.6; hp = $maxB; maxHp = $maxB }
        }

        $spawnRate = [Math]::Max(8, 22 - $wave * 2)
        if ($null -eq $boss -and ($tick % $spawnRate -eq 0)) {
            $type = if ($rnd.Next(100) -lt 28) { 2 } else { 1 }
            [void]$enemies.Add(@{
                x = [double]$rnd.Next(4, $W - 5)
                y = 2.0
                vx = ($rnd.NextDouble() - 0.5) * 0.5
                vy = if ($type -eq 1) { 0.28 + $wave * 0.03 } else { 0.16 }
                hp = if ($type -eq 1) { 1 + [int]($wave / 3) } else { 4 + $wave }
                type = $type
            })
        }

        # --- ОЧИСТКА БУФЕРА КАДРА ---
        for ($i = 0; $i -lt ($W * $H);$i++) { $grid[$i] = ' '; $cols[$i] = 37 }

        # --- ОБНОВЛЕНИЕ ЗВЕЗД ---
        foreach ($s in$stars) {
            $s.y +=$s.spd
            if ($s.y -ge ($H - 1)) { $s.y = 1.0; $s.x = $rnd.Next(1,$W - 1) }
            Set-Cell ([int]$s.x) ([int]$s.y) $s.ch $s.c
        }

        # --- ОБНОВЛЕНИЕ БОНУСОВ ---
        for ($i =$items.Count - 1; $i -ge 0; $i--) {
            $it =$items[$i]$it.y += 0.25
            $ix = [int][Math]::Round($it.x)
            $iy = [int][Math]::Round($it.y)
            if ([Math]::Abs($ix -$px) -le 2 -and [Math]::Abs($iy -$py) -le 1) {
                if ($it.t -eq 'W') {$weapon = [Math]::Min(4, $weapon + 1);$score += 25 }
                elseif ($it.t -eq '+') { $hp = [Math]::Min(100,$hp + 30) }
                elseif ($it.t -eq 'E') { $ult = [Math]::Min(100,$ult + 50) }
                $items.RemoveAt($i)
                continue
            }
            if ($iy -ge ($H - 1)) {$items.RemoveAt($i); continue }$ic = if ($it.t -eq 'W') { 96 } elseif ($it.t -eq '+') { 92 } else { 93 }
            Draw-Text ($ix - 1) $iy "[$($it.t)]" $ic
        }

        # --- ЛОГИКА БОССА ---
        if ($null -ne$boss) {
            $boss.x +=$boss.vx
            if ($boss.x -le 8 -or $boss.x -ge ($W - 9)) { $boss.vx = -$boss.vx }
            $bx = [int][Math]::Round($boss.x)
            $by = [int][Math]::Round($boss.y)
            Draw-Text ($bx - 6)$by       "╔═══╦═══╦═══╗" 95
            Draw-Text ($bx - 6) ($by + 1) "╚═╦═╩═█═╩═╦═╝" 91
            Draw-Text ($bx - 4) ($by + 2) "V   V   V"     93

            if ($tick % 14 -eq 0) {
                [void]$ebullets.Add(@{ x = $bx - 4; y =$by + 2; vx = 0; vy = 0.65 })
                [void]$ebullets.Add(@{ x =$bx + 4; y = $by + 2; vx = 0; vy = 0.65 })$dx = ($px -$bx) * 0.04
                [void]$ebullets.Add(@{ x =$bx; y = $by + 2; vx =$dx; vy = 0.7 })
            }
        }

        # --- ОБНОВЛЕНИЕ ВРАГОВ ---
        for ($i = $enemies.Count - 1; $i -ge 0; $i--) {$e = $enemies[$i]
            $e.x +=$e.vx
            $e.y +=$e.vy
            if ($e.x -le 3 -or $e.x -ge ($W - 4)) { $e.vx = -$e.vx }
            $ex = [int][Math]::Round($e.x)
            $ey = [int][Math]::Round($e.y)

            if ($ey -ge ($H - 1)) { $enemies.RemoveAt($i); continue }

            # Столкновение с игроком
            if ([Math]::Abs($ex - $px) -le 2 -and [Math]::Abs($ey - $py) -le 1) {$hp -= 20
                Spawn-Explosion $ex$ey 12
                $enemies.RemoveAt($i)
                continue
            }

            # Выстрелы врагов
            if ($e.type -eq 2 -and ($tick % 28 -eq 0)) {
                [void]$ebullets.Add(@{ x = $ex; y =$ey + 1; vx = 0; vy = 0.6 })
            }

            if ($e.type -eq 1) {
                Draw-Text ($ex - 1)$ey "<V>" 91
            } else {
                Draw-Text ($ex - 2)$ey "[=O=]" 95
            }
        }

        # --- ОБНОВЛЕНИЕ ПУЛЬ ИГРОКА ---
        for ($i = $bullets.Count - 1; $i -ge 0; $i--) {$b = $bullets[$i]
            $b.x +=$b.vx
            $b.y +=$b.vy
            $bx = [int][Math]::Round($b.x)
            $by = [int][Math]::Round($b.y)
            if ($by -le 1 -or$bx -le 1 -or $bx -ge ($W - 1)) { $bullets.RemoveAt($i); continue }

            $hit =$false
            # Попадание по боссу
            if ($null -ne$boss) {
                if ([Math]::Abs($bx - $boss.x) -le 6 -and [Math]::Abs($by - ($boss.y + 1)) -le 1) {$boss.hp--
                    Spawn-Explosion $bx$by 3
                    $bullets.RemoveAt($i)
                    if ($boss.hp -le 0) {
                        Spawn-Explosion $boss.x ($boss.y + 1) 40
                        $score += 150$wave++
                        $nextBossScore =$score + 250 + ($wave * 50)
                        [void]$items.Add(@{ x = $boss.x - 2; y =$boss.y; t = 'W' })
                        [void]$items.Add(@{ x = $boss.x + 2; y =$boss.y; t = '+' })
                        $boss =$null
                    }
                    continue
                }
            }

            # Попадание по обычным врагам
            for ($j = $enemies.Count - 1; $j -ge 0; $j--) {$e = $enemies[$j]
                $rad = if ($e.type -eq 1) { 1.8 } else { 2.6 }
                if ([Math]::Abs($bx -$e.x) -le $rad -and [Math]::Abs($by - $e.y) -le 1.0) {$e.hp--
                    $hit =$true
                    Spawn-Explosion $bx$by 3
                    if ($e.hp -le 0) {
                        Spawn-Explosion $e.x $e.y 12
                        $score += if ($e.type -eq 1) { 10 } else { 25 }
                        $ult = [Math]::Min(100,$ult + 6)
                        if ($rnd.Next(100) -lt 22) {$types = @('W', '+', 'E')
                            [void]$items.Add(@{ x = $e.x; y =$e.y; t = $types[$rnd.Next(3)] })
                        }
                        $enemies.RemoveAt($j)
                    }
                    break
                }
            }
            if ($hit) { $bullets.RemoveAt($i); continue }
            Set-Cell $bx$by $b.ch $b.c
        }

        # --- ПУЛИ ВРАГОВ ---
        for ($i = $ebullets.Count - 1; $i -ge 0; $i--) {$eb = $ebullets[$i]
            $eb.x +=$eb.vx
            $eb.y +=$eb.vy
            $bx = [int][Math]::Round($eb.x)
            $by = [int][Math]::Round($eb.y)
            if ($by -ge ($H - 1)) { $ebullets.RemoveAt($i); continue }
            if ([Math]::Abs($bx - $px) -le 2 -and [Math]::Abs($by - $py) -le 1) {$hp -= 12
                Spawn-Explosion $px$py 10
                $ebullets.RemoveAt($i)
                continue
            }
            Set-Cell $bx$by 'v' 91
        }

        # --- ЧАСТИЦЫ ВЗРЫВОВ ---
        for ($i = $particles.Count - 1; $i -ge 0; $i--) {$p = $particles[$i]
            $p.x +=$p.vx
            $p.y +=$p.vy
            $p.life--
            if ($p.life -le 0) { $particles.RemoveAt($i); continue }
            Set-Cell ([int][Math]::Round($p.x)) ([int][Math]::Round($p.y)) $p.ch $p.c
        }

        # --- ОТРИСОВКА ИГРОКА ---
        Draw-Text ($px - 2)$py "<═▲═>" 96
        $flame = if ($tick % 2 -eq 0) { " ^ " } else { " ' " }
        Draw-Text ($px - 1) ($py + 1)$flame 93

        # --- РАМКА И ИНТЕРФЕЙС (HUD) ---
        Draw-Text 0 0 ("╔" + ("═" * ($W - 2)) + "╗") 36
        Draw-Text 0 ($H - 1) ("╚" + ("═" * ($W - 2)) + "╝") 36
        for ($ry = 1; $ry -lt ($H - 1);$ry++) {
            Set-Cell 0 $ry '║' 36
            Set-Cell ($W - 1)$ry '║' 36
        }

        $hpBlocks = [Math]::Max(0, [int]($hp / 10))
        $hpBar = ("█" * $hpBlocks) + ("░" * (10 - $hpBlocks))$ultBlocks = [Math]::Max(0, [int]($ult / 10))$ultBar = ("█" * $ultBlocks) + ("░" * (10 - $ultBlocks))

        $topHud = " СЧЕТ: $($score.ToString('00000')) │ ВОЛНА: $wave │ ОРУЖИЕ: УР.$weapon "
        Draw-Text 2 0 $topHud 97

        if ($null -ne$boss) {
            $bBlocks = [Math]::Max(0, [int](($boss.hp / $boss.maxHp) * 10))$bBar = "БОСС:[" + ("█" * $bBlocks) + ("░" * (10 - $bBlocks)) + "]"
            Draw-Text ($W - 19) 0$bBar 91
        }

        $hpCol = if ($hp -gt 40) { 92 } else { 91 }
        $ultCol = if ($ult -ge 100) { 93 } else { 96 }
        Draw-Text 2 ($H - 1) " БРОНЯ:[$hpBar] " $hpCol$ultTxt = if ($ult -ge 100) { "УЛЬТА(ПРОБЕЛ):[ГОТОВО!]" } else { "УЛЬТА:[$ultBar]" }
        Draw-Text 26 ($H - 1) $ultTxt$ultCol

        # --- ВЫВОД КАДРА НА ЭКРАН ЗА ОДИН ВЫЗОВ (БЕЗ МЕРЦАНИЯ) ---
        $sb = New-Object System.Text.StringBuilder 4096
        [void]$sb.Append("$ESC[H")
        $lastC = -1
        for ($y = 0; $y -lt$H; $y++) {$rowOff = $y * $W
            for ($x = 0; $x -lt $W; $x++) {
                $c =$cols[$rowOff +$x]
                if ($c -ne$lastC) {
                    [void]$sb.Append("$ESC[$($c)m")
                    $lastC =$c
                }
                [void]$sb.Append($grid[$rowOff +$x])
            }
            if ($y -lt ($H - 1)) { [void]$sb.Append("`r`n") }
        }
        [void]$sb.Append("$ESC[0m")
        [Console]::Write($sb.ToString())

        $el = [int]$sw.ElapsedMilliseconds
        if ($el -lt 32) { [System.Threading.Thread]::Sleep(32 -$el) }
    }

    # --- ЭКРАН ОКОНЧАНИЯ ИГРЫ ---
    [Console]::SetCursorPosition(16, 10)
    Write-Host "$ESC[91m╔══════════════════════════════╗$ESC[0m"
    [Console]::SetCursorPosition(16, 11)
    Write-Host "$ESC[91m║     КОРАБЛЬ УНИЧТОЖЕН!       ║$ESC[0m"
    [Console]::SetCursorPosition(16, 12)
    Write-Host "$ESC[91m║   ИТОГОВЫЙ СЧЕТ: $($score.ToString('000000'))      ║$ESC[0m"
    [Console]::SetCursorPosition(16, 13)
    Write-Host "$ESC[91m║  [R] Заново    [ESC] Выход   ║$ESC[0m"
    [Console]::SetCursorPosition(16, 14)
    Write-Host "$ESC[91m╚══════════════════════════════╝$ESC[0m"

    while ($true) {
        if ([Console]::KeyAvailable) {
            $k = [Console]::ReadKey($true).Key
            if ($k -eq 'R') { continue outerLoop }
            if ($k -eq 'Escape') { Clear-Host; [Console]::CursorVisible =$true; exit }
        }
        [System.Threading.Thread]::Sleep(50)
    }
}