Мандельброт на .bat «for fun»

    Вот эта картинка создана .bat файлом:



    Многие не знают, но если приложить немного усилий, то командный процессор MS Windows становится способен на многое. В принципе, это обычный императивный язык программирования, немного со странностями, но именно они превращают программирование на нём в своеобразное развлечение. Многие действия, не предусмотренные в конструкции языка, надо придумать как имитировать, порой какими-то фантастическими способами.

    Например, как сделать паузу на заданное количество секунд? Команда pause тут бессильна. В место неё паузу удобно организовать через ping.
    Пауза на 5 секунд будет выглядеть вот так:
    ping 127.0.0.1 -n 6 -w 1000 > nul

    Вот как узнать, содержит ли строка подстроку? Опять же, на первый взгляд ничего подходящего нет. На помощь приходит замена подстроки в строке:
    set string=SOME TEXT
    if not "%string%"=="%string:TEXT=%" echo YES

    Ещё на .bat можно организовать вычисления с плавающей точкой (изначально плавающая точка не поддерживается), распараллеленные вычисления, синхронизацию между «процессами», распараллеленное вычисление на нескольких компьютерах и т.п. Я как-то раз видел исходники полиморфного(!) вируса, который полностью написан на bat-файле :)

    В общем, время от времени я пишу что-нибудь на .bat, не могу пройти мимо такого вызова :)
    Cейчас выкладываю одну из своих работ: батник, который рендерит множество Мандельброта в bmp.

    @echo off
    set /a xPixels = 180
    set /a yPixels = 120
    set /a xStart = -22000
    set /a yStart = -10000
    set /a xSize = 32000
    set /a ySize = 20000
    set /a maxIter = 32
    call ::make_bmp_header
     
    set /a xStep = xSize/xPixels
    set /a yStep = ySize/yPixels
     
    set /a iy = 0
    :iyLoop
     
      set /a ix = 0
      :ixLoop
     
        set /a x = xStart + ix * xStep
        set /a y = yStart + iy * yStep
        set /a x0 = x
        set /a y0 = y
     
        set /a iteration = 0
       
        :formula
          set /a xtemp = x*x/10000 - y*y/10000 + x0
          set /a y = 2*x*y/10000 + y0
          set /a x = xtemp
          set /a iteration+=1
     
          set /a dist = x*x/10000 + y*y/10000
          if [%iteration%]==[%maxIter%] goto breakFormula
        if /I %dist% LEQ 40000 goto :formula
        :breakFormula
       
        if [%iteration%]==[%maxIter%] (call :plot_black) else (call :plot_color %iteration%)
     
      set /a ix += 1
      if not [%ix%]==[%xPixels%] goto ixLoop
     
      set /a progress = yPixels - iy
      echo.%progress%
     
    set /a iy += 1
    if not [%iy%]==[%yPixels%] goto iyLoop
     
    call ::make_bin
    ren file$ result.bmp
    mspaint result.bmp
    exit/b
     
     
    :plot_black
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    exit/b
     
    :plot_color
    set /a rc=%1*5 + 32
    set /a gc=%1*7 + 6
    set /a bc=128 - (%1*3 + 4)
    call :write_byte %rc%
    call :write_byte %gc%
    call :write_byte %bc%
    exit/b
     
     
    :make_bmp_header
    
    set /a dataSize = xPixels * yPixels * 3 + 54
    set /a dataSize0 = dataSize%%256
    set /a dataSize1 = (dataSize/256)%%256
    set /a dataSize2 = (dataSize/(256*256))%%256
    set /a dataSize3 = (dataSize/(256*256*256))%%256
     
    call :init_bin
     
    call :write_byte 66
    call :write_byte 77
     
    call :write_byte 118
    call :write_byte 56
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 54
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 40
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte %xPixels%
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte %yPixels%
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 1
    call :write_byte 0
    call :write_byte 24
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte %dataSize0%
    call :write_byte %dataSize1%
    call :write_byte %dataSize2%
    call :write_byte %dataSize3%
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
    call :write_byte 0
     
    exit /b
     
     
    :init_bin
    echo.n file$>bin$
    set /a addr=0x0100
    call set "hstr=e "
    call :write_word %addr%
    set mustflush=0
    exit /b
     
    :write_byte
    set /a a=%1
    set hexs=0123456789ABCDEF
    set /a a0=a/16
    set /a a1=a%%16
    call set res= %%hexs:~%a0%,1%%%%hexs:~%a1%,1%%
    set hstr=%hstr%%res%
    set /a addr+=1
    set /a mod16=addr%%16
    set mustflush=1
    if not %mod16%==0 exit /b
    echo.%hstr%>>bin$
    call set "hstr=e "
    call :write_word %addr%
    set mustflush=0
    exit /b
     
    :write_word
    set /a a=%1
    set hexs=0123456789ABCDEF
    set /a a0=a/4096
    set /a a1=a/256%%16
    set /a a2=a/16%%16
    set /a a3=a%%16
    call set res=%%hexs:~%a0%,1%%%%hexs:~%a1%,1%%%%hexs:~%a2%,1%%%%hexs:~%a3%,1%%
    set hstr=%hstr%%res%
    exit /b
     
    :make_bin
    if "%mustflush%"=="1" echo.%hstr%>>bin$
    set /a filesz=addr-0x0100
    echo.r cx>>bin$
    set hstr=
    call :write_word %filesz%
    echo %hstr%>>bin$
    echo.w>>bin$
    echo.q>>bin$
    debug<bin$
    del bin$
    exit /b
    
    
    Поделиться публикацией
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 102
    • +19
      Например, как сделать паузу на заданное количество секунд? Команда pause тут бессильна. В место неё паузу удобно организовать через ping.
      Пауза на 5 секунд будет выглядеть вот так:
      ping 127.0.0.1 -n 6 -w 1000 > nul

      Вот как узнать, содержит ли строка подстроку? Опять же, на первый взгляд ничего подходящего нет. На помощь приходит замена подстроки в строке:
      set string=SOME TEXT
      if not "%string%"=="%string:TEXT=%" echo YES


      да уж… прям через одно место это делается… но радует что есть люди которые умеют выйти из ситуации :)
      • +5
        Особенно интересно делается интерактивность =)
        Когда делал игру «сокобан», приходилось учитывать разные версии командной строки.
        • +3
          переходите на bash :)
          • +8
            а там нужно трудности преодолевать? =)
            • +25
              трудности — да, но не через одно место :)
            • 0
              сам по себе он не столько рулит (хотя конечно несравним с cmd), а вот вместе со стандартным набором консольных утилит… sed+awk это уже очень много.
              • 0
                sed, awk, grep, find… Этот список можно долго продолжать :)
          • 0
            таких людей зовут програмисты!=)
        • +32
          Код сходу непонятен, но чувствую, что круто! +
          • НЛО прилетело и опубликовало эту надпись здесь
          • +1
            Больше всего понравилось: текст habracut`a
            (=
          • 0
            Гениально!!!
            • +14
              плюс вам, тов. Маньяк
              • +1
                Вы это сами всё? Тогда вы большой молодец. Плюс вам.
              • +2
                Черепашка тож много чего нарисовать может…
                • НЛО прилетело и опубликовало эту надпись здесь
                  • 0
                    «logo — это lisp без скобок», прочитал я в ZX-Review.
                  • 0
                    я еще и крестиком вышивать умею!
                  • +1
                    Это, конечно, не тетрис на sed, но всё равно круто.
                    Никогда бы не подумал, что это возможно в принципе.
                    • +12
                      >паузу удобно организовать через ping

                      Майкросовский подход :)
                      • +24
                        Мсье знает толк в извращениях…
                      • +1
                        я программировать начал с bat в досе на 286 в 96 году)) правда недолго) что-то делал интерактивное, но что б такое… я поражен. правда, похоже, за это время функциональность командного процессора несколько возросла.
                        • +1
                          а еще из извращений вспоминаются конфиги с навороченной логикой (менюшки там всякие, арт) для Quake 1 и 2 с их bind'ами и alias'ами :)
                          • +2
                            Ну не такие уж это и извращения. Часто батники как раз использовали для подобных вещей. Чтобы сделать некое подобие «интерфейса для секретарши».
                        • 0
                          А как такой код дебажить? Отладочными принтами, или есть возможность сделать это поудобнее?
                          И как юзать плавающую точку?
                          Да, это пожалуй самое оригинальное извращение из всех о которых я слышал =)
                          • +2
                            >А как такой код дебажить? Отладочными принтами, или есть возможность сделать это поудобнее?
                            Да, отладочными echo.
                            А ещё, если не делать @echo off, то можно видеть какие команды исполняются и с какими параметрами. Для удобства, этот вывод можно перенаправить в файл для дальнейшего изучения.

                            >И как юзать плавающую точку?
                            Надо написать функции для работы с плавающей точкой =)
                            В этой програме я использовал фиксированную точку, 4 десятичных разряда для дробной части.
                          • +1
                            Когда программистам делать нечего :)
                            • +4
                              А вы не директор по ведущим разработкам Мелкософта? =)
                              • +2
                                мандельброт в 61 байт:
                                tinyurl.com/llkbsd
                                • НЛО прилетело и опубликовало эту надпись здесь
                                • +2
                                  Я как-то раз видел исходники полиморфного(!) вируса, который полностью написан на bat-файле

                                  Это не новость для посвящённых. В славные 90-е вирмейкеры куда больше изощрялись, чем сейчас. :)
                                  Интересующиеся могут полистать старые e-zines вирсцены.
                                  • +2
                                    Из российских я там заметил Chaos AD, Infected Voice, MoonBug.
                                    • +2
                                      О да! Infected Voice — помню, помню =)
                                      • 0
                                        еще Infected Moscow помню был один выпуск, а второго вроде бы так и не дождались…
                                        во были времена, когда натыкался на эти выпуски, приятно вспомнить.
                                  • 0
                                    О да! Infected Voice — помню, помню =)
                                    • +3
                                      Не туда ответил %|
                                    • +2
                                      С gamedev.ru

                                      Растеризация треугольника в консоли:
                                      www.everfall.com/paste/id.php?t5ht4mw6kvls

                                      Консольный сокобан:
                                      www.everfall.com/paste/id.php?szlzpnwtsftu
                                      • +2
                                        Это один и тот же автор.
                                        • +5
                                          «Pasted by Imp5»

                                          это автор топика видимо запостил)
                                          • +4
                                            да, это был я
                                            • 0
                                              Хех, вечером по запарке не заметил))
                                          • 0
                                            Под дос был криптор исполняемых файлов написанный на .bat Trap авторства Christoph Gabler, последние версии правда уже полностью на asm вроде перевел.
                                            • 0
                                              круто у Вас на работе. есть чем заняться ;)
                                              • +3
                                                это в свободное время.
                                                «programming for fun»
                                              • +17
                                                Ваша шайтан-программа грузит сеть весьма странным образом %)



                                                Батник был запущен с сетевой расшарки на другом компе. Временных файлов на расшарке я не увидел :)
                                                • +3
                                                  кстати графики сетевой активности тоже можно попорбывать батниками рисовать. должно быть даже проще, но не так эффектно, конечно)
                                                • +1
                                                  Учитывая, что автор интересовался Infected Voice, стоит прогнать машина антивирусом :))
                                                • 0
                                                  дык это ж из-за ping-задержки наверное?
                                                  • +1
                                                    компы в пределах одного роутера, второй комп под линуксом. Обычно задержка очень маленькая. Скорее, дело действительно в механизме исполнения батника. Кстати, батник сразу предупредил, что будет использовать не текущий путь (в расшарке), а c:\windows\.
                                                  • 0
                                                    Вообще этот батник создаёт временные файлы в текущей папке.
                                                    Ещё дело может быть в том, как cmd исполняет батники. Он их читает по командам (из-за этого батники можно менять в процессе исполнения)
                                                    • 0
                                                      временный файл создается, проверил (имя bin$)
                                                    • +10
                                                      Леша — ты опять забыл принять лекарство! =))
                                                      • 0
                                                        Изображение в посте напоминает как раз картику, которую психиатр показывает пациенту и спрашивает что вы на ней видите =)
                                                        Мне напоминает повернутые пики или раздутые трефы
                                                        • +1
                                                          Это не картинка психиатра, там просто маленькая ящерка с выпотрошенными кишочками, которую ест ее мама
                                                        • –2
                                                          :)))))!
                                                        • 0
                                                          У меня эта хрень минут 5 гудела, может потому что виртуалка, но вряд ли. Так что батник для таких вещей — не самый лучший выбор))
                                                          • 0
                                                            у меня уже минут 20
                                                            что я делаю не так?
                                                            • +2
                                                              Freeman85 не жалуется, он хвастается =)
                                                              у меня на ноутбуке тоже где-то 20 минут работает.
                                                              • 0
                                                                Может и 20 минут, я как-то не засекал :) Просто говорю, что долго.
                                                                • 0
                                                                  у меня работает 8 минут, идут цифры от 120 до нуля, потом выдает ошибку что файл с картинкой не найден, что я делаю не так? 0_о
                                                                  Батник в любой папке лежать может?
                                                                  • 0
                                                                    Батник должен быть в папке, которая свободна для записи.

                                                                    Посмотри, чтобы там уже не было result.bmp

                                                                    В строках
                                                                    set /a xPixels = 180
                                                                    set /a yPixels = 120
                                                                    замени разрешение на меньшее, например 8 на 8, чтобы не ждать результата долго.

                                                                    Есть ли у тебя mspaint.exe?

                                                                    Есть ли у тебя команда debug?
                                                          • +4
                                                            Когда я читаю вот такие стать, как ваша, я вдохновляюсь. Очень приятно читать настоящего хакера.

                                                            Заметьте, ни одного заминусованного коммента к статье.
                                                            • +2
                                                              Ваш минусовать начали :D, поднял обратно до нуля.
                                                              • +1
                                                                Я предвидел — меня это не оскорбляет. Спасибо вам, но право не стоило.
                                                            • 0
                                                              Может кто в курсе, есть ли способ прервать выполнение батника для ввода данных и записи в переменную? Не считая сторонних программ которые записывают введенное значение в errolevel?
                                                              • 0
                                                                rem SETLOCAL ENABLEEXTENSIONS
                                                                set /p var=Как Вас зовут?:
                                                                echo Hello, %var%

                                                                если не заработает, раскомментировать первую строчку
                                                                • 0
                                                                  То что надо, спасибо :)
                                                                • 0
                                                                  Если вам надо в определённом месте спросить что-то у пользователя, то вариант от kentaskis должен подойти.
                                                                  Если это нужно сделать в произвольный момент, то к сожалению, я не знаю простых способов.
                                                                • 0
                                                                  Для пауз есть waitfor
                                                                  Ждем Doom на cmd скриптах :)
                                                                  • 0
                                                                    Да, начиная с Vista или 2003, waitfor есть в штатной комплектации.
                                                                  • –8
                                                                    А был ли мальчик? Короче, устал ждать счастья — убил выполнение. Используйте bash, удаляйте cmd.
                                                                    • +2
                                                                      Напишите Мандельброт на bash.
                                                                    • 0
                                                                      А мне вспомнился спектрум, как это не банально. И хоть мое счастливое детство прошло без детища синклера, но позже этот прекрасный компьютер чрезвычайно увлек меня в своем виртуальном (эмулируемом) воплощении. Многое тоже приходилось делать руками, а иногда и особым образом «удалять гланды». Как первому (операции с плавающей точкой, тригонометрия через ряды, умножение с делением, которые Z80 не поддерживал), так и второму (нестандартные видеорежимы, вывод на экран блоками по 8х8, внутри которых можно использовать лишь 2 различных цвета, 3d на такой простенькой машинке) можно было обучиться, читая ZX-прессу, дискмаги и газеты. Среди прочих равных выделялся журнал ZX Format. В нем всегда можно было найти статейку-другую о программировании для speccy. Эх…
                                                                      • +2
                                                                        … и тут все должны прослезиться?
                                                                      • +1
                                                                        Такими темпами скоро варкрафт на бат перепишут )))
                                                                        • 0
                                                                          20 минут и файл размером 180x120px :) Хорошо повеселили
                                                                          • 0
                                                                            пару секунд и



                                                                            Правда в Linux и с помощью специализированной программы Fraqtive.

                                                                            С помощью пинга локалхоста задержки делать + (не могу пока).
                                                                            • 0
                                                                              В универе в курсе Синергетики такие изображения назывались Фракталы. Есть также спец. программы, которые их строят.
                                                                            • 0
                                                                              Например, как сделать паузу на заданное количество секунд?
                                                                              В Windows7, не знаю как в Vista наконецто добавили
                                                                              • +1
                                                                                Извиняюсь за отрывок, случайно отправил
                                                                                Examples:
                                                                                TIMEOUT /?
                                                                                TIMEOUT /T 10
                                                                                TIMEOUT /T 300 /NOBREAK
                                                                                TIMEOUT /T -1

                                                                                Parameter List:
                                                                                /T timeout Specifies the number of seconds to wait.
                                                                                Valid range is -1 to 99999 seconds.

                                                                                /NOBREAK Ignore key presses and wait specified time.

                                                                                /? Displays this help message.

                                                                                NOTE: A timeout value of -1 means to wait indefinitely for a key press.
                                                                                • 0
                                                                                  а я уж думал, что щас картинка 20 на 20 тыс. px вылезет…
                                                                                  • 0
                                                                                    Теперь осталось написать на .bat-файлах веб-сервер
                                                                                    • +1
                                                                                      Люди знают толк в извращениях
                                                                                      • 0
                                                                                        класс :)
                                                                                        вспоминаю молодость :)

                                                                                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.