LINUX.ORG.RU

Сообщения wandrien

 

projman (текстовый редактор)

ProjMan (aka «Tcl/Tk Project Manager») is an editor for programming in TCL/Tk and other languages. It includes a file manager; a source editor with syntax highlighting and code navigation; Git support.

Контекст:

Какой редактор кода или IDE вы используете? (комментарий)

@svk28: Есть, как-то тут в галерее показывал https://git.nuk-svk.ru/svk/projman . Киллер-фич никаких, даже наоборот, обычный редактор с многолетней историей - дорог мне как память :) ну и пишу потихоньку (очень потихоньку).

Дело было вечером, делать было нечего. Я увидел указанный пост и решил JFF покодить на Tcl.

Немножко причесал баги и добавил фич. В планах еще что-нибудь впилить интересное.

Подробнее:

 , projman, ,

wandrien
()

Не было печали, но пришел glycin

Заметил, что моём файловом менеджере диалог «Свойства файла» стал открываться с задержкой в полсекунды.

Если запустить приложение с export G_MESSAGES_DEBUG=all, то в эти полсекунды имеем вот такую красоту на 360 строк: https://pastebin.com/G0ivjKnz

Если закомментировать вот эту строку то задержка исчезает. Можно считать, что причина локализована. Теперь это нужно как-то чинить.

Могу сказать спасибо Гному и всему опенсорцу за то, что не устают давать мне причины тренироваться в написании мультипоточного и асинхронного кода, чтобы уметь обходить тормоза во фреймфорках и библиотеках. И отдельное спасибо Расту, на котором собственно glycin и реализован.

Работаем дальше.

 , glycin, ,

wandrien
()

Только у меня с huggingface модели не скачиваются или у всех?

Провайдер Билайн.

Соединение зависает после получения 16 килобайт:

$ wget 'https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf'
--2025-12-06 15:53:16--  https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf
Загружен сертификат CA «/etc/ssl/certs/ca-certificates.crt»
Распознаётся huggingface.co (huggingface.co)… 65.9.46.59, 65.9.46.41, 65.9.46.54, ...
Подключение к huggingface.co (huggingface.co)|65.9.46.59|:443... соединение установлено.
HTTP-запрос отправлен. Ожидание ответа… 302 Found
Адрес: https://cas-bridge.xethub.hf.co/xet-bridge-us/<....> [переход]
--2025-12-06 15:53:17--  https://cas-bridge.xethub.hf.co/xet-bridge-us/<....>
Распознаётся cas-bridge.xethub.hf.co (cas-bridge.xethub.hf.co)… 65.9.46.15, 65.9.46.42, 65.9.46.47, ...
Подключение к cas-bridge.xethub.hf.co (cas-bridge.xethub.hf.co)|65.9.46.15|:443... соединение установлено.
HTTP-запрос отправлен. Ожидание ответа… 200 OK
Длина: 806058240 (769M)
Сохранение в: ‘gemma-3-1b-it-Q4_K_M.gguf.2’

gemma-3-1b-it-Q4_K_M.gguf.2               0%[                     ]  16,00K  --.-KB/s    ост 3d 6h  ^C

 

wandrien
()

Один день из копроэкономики

Процитирую сообщение, которое сегодня отправил клиенту. Комментарии излишни, наверное. И так всё ясно.


Взял только первые два числа от IP, в топе такие значения получаются:

   4903 42.81
   5446 40.79
   6473 142.147
   6831 42.187
   7347 84.37
   7564 207.241
   9946 65.21
  10110 20.171
  10678 47.246
  37377 8.217
  59520 202.76
  65096 43.173
 201283 216.73
 217590 146.174
 247401 66.249

Проанализировал принадлежность IP и user agent-ы.

66.249 - боты Google.

146.174 - имитирует органическую посещаемость, UA реальных браузеров. Вот только диапазон принадлежит HuaweiCloud.
Забанил весь диапазон IP.

216.73 - ClaudeBot, сегодня ранее уже заблокировал его.

43.173 - диапазон принадлежит компании https://ru.wikipedia.org/wiki/Tencent Все UA почти одинаковые, с небольшими вариациями. Основной UA этот:
Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.114 Safari/537.36
Забанил весь диапазон IP.

202.76 - имитирует органическую посещаемость, но диапазон принадлежит HuaweiCloud.
Забанил весь диапазон IP.

8.217 - UA: AliyunSecBot/Aliyun (AliyunSecBot@service.alibaba.com)
Забанил весь диапазон IP.

47.246 - имитирует органическую посещаемость. Все 10678 были вчера, сегодня обращений ноль. Диапазон адресов принадлежит Alibaba Cloud LLC
Забанил весь диапазон IP.

20.171 - GPTBot, сегодня ранее уже заблокировал его.

65.21 - AwarioBot, сегодня ранее уже заблокировал его.

207.241 - Бот сайта http://archive.org/
Его банить рука не поднялась, единственный полезный сервис на фоне этих наглых ботов китайских нейросеток. Да и нагрузки от него не много.


Отдельная проблема с ботами Гугла. Если взять статистику по поисковым ботам, то окажется, Google создаёт нагрузку в 20 выше, чем Yandex:

  10917 +http://www.bing.com/bingbot.htm
  12092 +http://www.apple.com/go/applebot
  12313 +http://yandex.com/bots
 249190 +http://www.google.com/bot.html

Возможно, Google тоже решил «выкачать весь интернет» для нейронок. И делает это под теми же самыми IP и UA, что и бот поисковой системы. Чтобы веб-мастер не мог просто взять и заблокировать его, если не хочет остаться без присутствия в поисковой выдаче.

 , ,

wandrien
()

Страдаю на Tcl/Tk

Немного о качестве батареек в Tcl/Tk:

  • Модуль cmdline в Tcllib писал наркоман, иначе не скажешь. Для вменяемого парсинга опций комадной строки пришлось брать сторонний модуль и доводить его напильником.
  • Поддержка статуса окна maximized есть под виндой и макосью, но нет под юниксами. EWMH для авторов tk ничего не значит. Порылся еще, через wm attributes . -zoomed 1 работает вроде. Но не через wm state.
  • Есть процедура regexp, но нет процедуры для квотирования строки для формирования регэкспов. Эту функцию ты должен написать сам.
  • Нет встроенной процедуры для «вернуть значение переменной, если она существует, иначе вернуть указанное значение». Её ты тоже должен написать сам.

Конкретно самого языка:

  • Возможности метапрограммирования это хорошо.
  • Если писать по уму, то всё надо обвешивать тестами еще сильнее, чем в питоне. Один лишний / пропущенный символ, и программа будет без диагностик просто обрабатывать чушь. Но так как я работаю с уже имеющимся кодом, в котором не было тестов, то пока забил.

Продолжаю наблюдения. Советы приветствуются.

Алсо, cast @Shadow

 ,

wandrien
()

Какая же шляпа Андроид

Ей-богу, я не понимаю, почему настолько плохо.


Концепцию «работы с файлами» или «работы с документами» разрабы приложений целенаправленно игнорируют. С точки зрения разработчика, ты корпоративный раб, который должен «пользоваться приложением» и приносить прибыль, а не с какими-то там своими файлами работать.

Открыть два каталога в разных окнах? Или хотя бы в разных вкладках одного окна?

Или поставить одно видео на паузу и запустить другое?

Или две картинки одновременно редактировать?

НЕТ.

Этот же рак проникает на дескопты. В Telegram на дектопе есть просмотрищик картинок и видео, но открыть параллельно несколько файлов - невозможно. Впрочем, Telegram на обеих платформах - это отдельный рак, про который можно написать несколько тысяч символов бомбёжки. У них на каждой платформе свои уникальные мозговыносящие баги.


Приложение Ютуба. Если из списка видео на канале запустить видео, а потом вернуться назад, то с некоторой вероятностью произойдёт одно из следущего:

  • Список видео будет в той же позиции, как и было.
  • Позиция в списке сбросится в начало списка.
  • Вместо списка видео отобразится главная вкладка канала.

Я думал, что на старом телефоне не хватает памяти или типа того. Но когда я в прошлом году купил новый телефон, там оказалась такая же шляпа.

Этот баг существует столько, сколько я вообще помню существование приложения ютуба. Я не понимаю, почему в 2025-м нельзя без багов сохранить и восстановиить состояние UI. Или это какой-то хитрый план, хз.


Вы не можете управлять значением mtime у файла. Если вы закачали файлы с компьютера, попрощайтесь с датами модификации.

В качестве особого издевательства - приложение галереи сортирует фото по mtime, а не по дате снимка. НЕКОТОРЫЕ приложения галереи могут сортировать и по дате из EXIF.


Организовать галерею иерархически? НЕТ. Слишком сложно. Вдруг пользователь сначала начнёт сортировать свои фото, а потом и вовсе начнет ДУМАТЬ. Нам умные не нужны.


Производитель моего телефона своё приложение назвал «Галерея AI». AI в галерее не обнаружено. Зато обнаружено отсутствие группировки снимков по датам в альбомах. Всё сплошной лентой, даты угадывай сам.

Также производитель считает, что рисовать в файловом менеджере белые скруглённые прямоугольники на светло-сером фоне с гигантскими отступами - это хороший UI: https://postimg.cc/zy1Nnw9M

Никаких настроек ничего вообще в этих приложениях нет.


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

Если есть какой-то опенсорсный видеоплеер без рекламы, который умеет просто работать, посоветуйте, плиз. Моя планка ожиданий настолько низкая, что я просто хочу чтобы программа умела выполнять свою единственную базовую функцию.


Внезапно, опенсорное некоммерческое приложение Галереи из F-Droid - есть настройки по количеству столбцов и параметрам группировки:

А что, так можно было что ли??? (c)
Оказывается, что если делать приложения, думая о людях, а не о бабках, то получается даже ничего.

В качестве креативного решения для этой недоработки Гугл собирается F-Droid уничтожить.


Шторка в современных версиях Андроида это какая-то UI- и UX-катастрофа: https://postimg.cc/JsW8b39Y

У меня ноль идей, как индустрия дошла до такого убожества после всех этих десятилетий опыта в сфере UX. Понятно одно: экономически выгодно делать как можно больше говна каждый год, а какое там качество - какая разница, если у пользователей нет выбора.

Да, шторку поменять нельзя, она не считается приложением. Я бы с удовольствием пользовался шторкой от древнего Wileyfox Swift 2X.


В немалом количестве приложений доминирует концепция «навалить как можно больше непонятных иконок». Какие-то неведомые закорючки без какой-либо подсказки, что сейчас произойдёт. То ли текст скопируется, то ли флешка отформатируется.

Некоторые разработчики честно пытаются вместить в смартфон более-менее развитое приложение с кучей фич. В итоге по экрану разбросано несколько панелей с закорючками и несколько меню по углам, в которые хаотично рассованы команды. Выглядит страшно, пользоваться ужасно, но реально спасибо за то, что они хотя бы пытаются, в отличие от абсолютно анскильных приложений от всех остальных.


Размеры софта. Рандомные примеры:

  • «Сервисы Google Play» - 1 ГБ, из которых 360 МБ - приложение, остальное «данные».
  • Авито - 700 МБ без кэша.
  • Zoom - 700 МБ без кэша.
  • Gboard - 400 МБ, из которых 180 МБ - «приложение».
  • Магнит - 230 МБ без кэша.
  • Фонарик - 70 МБ!!!

Глядя на то как растут аппетиты, я начинаю сомневаться, что 0.5 ТБ памяти хватит на всё время жизни устройства. Слота под SD-карту в телефоне теперь нет, как и во всех моделях, кроме самых бюджетных.

Если вы хотите пускать Linux-юзерленд под Андроидом, то еще не забудьте, что в Линуксе теперь тоже аппетиты приложений к накопителю растут конскими темпами. Особенно после начала Rust-лихорадки.


Мне кажется, этот перечень херни бесконечно можно продолжать.

P.S. Свеженькое:

Google меняет политику публикации исправлений уязвимостей в Android

Отныне Google изначально предоставляет исправления безопасности для Android исключительно OEM-производителям по закрытым каналам с соглашением о неразглашении, обязующем их не раскрывать исходный код с применением предоставленных патчей на срок 3 месяца с момента получения. В течение этого времени возможно распространение исключительно бинарных сборок с включением исправления.

 ,

wandrien
()

Lua Shell

Контест этого топика: Леннарт теперь до эмуляторов терминала добрался (комментарий)

@EXL:

Лучше бы Lennart взялся за Bash.

@wandrien:

Там только выкинуть целиком. Я вот хочу попытаться для lua сделать обвязку для скриптинга уровня оболочки. Подобные либы на Lua есть, но качество и объем фич мне не нравится. Надо лучше. Тебе бы был интересен такой проект?


Итак, вот моя идея в общих чертах. Составные части, на которых основываться:

https://github.com/BanceDev/lush
Низкое качество сборочного скрипта. Вероятно, и кода тоже. Интересует идея в первую очередь.

https://github.com/mna/luashell
Ключевое, что нам нужно. Взять за основу. Но:

  • Нужны полнофункциональные средства перенаправления ввода-вывода, заменить эту часть API. Под капотом, вероятно. придётся делать полноценную обработку fork - настройка процесса - exec.
  • test() должен быть вменяемый, а не парсить строку по пробелам. Просто алиас для sh.cmd("test", ...).exec()
  • Форк процесса без exec в качестве элемента пайплайна на уровне API
  • Как расширение предыдущего - обёртка а ля sh.echo("text").

В качестве базового API взять https://25thandclement.com/~william/projects/lunix.html вместо https://github.com/luaposix/luaposix

Также рассмотреть для включения и/или как источник идей:


Общая идея:

  • Lua + lunix — получаем возможность писать на Луа «приложения как на Си под libc».
  • Сверху на это - форкнутый и допиленный luashell. Это ключевое.
  • Далее QoL вещи: lua-path, argparse, функции для парсинга и форматирвоания времени, функции для JSON.
  • Далее - разработать интерактивный режим для использования в качестве командной оболочки.

Продукт компилируется в статический бинарь с musl и/или cosmopolitan libc и получаем «вечный» shell. При этом весьма компактный.

 , , ,

wandrien
()

Леннарт теперь до эмуляторов терминала добрался

После очередного обновления systemd я обнаружил, что при входе в учетную запись рута под одним из эмуляторов терминала отображается вот такая абракадабра:

]8003;start=18dcf83c-b8a1-49a6-a824-d7a793edfd2c;user=root;hostname=aquila;machineid=609fc63f07736a785af67b1600000438;bootid=6bd8c743-1bf9-4965-88f0-5326eca7fc15;pid=661805;type=shell;cwd=/root[root@aquila ~]# 

Конкретно у меня - проблема со старой версией vte, на которой работают эмуляторы терминала, собранные под gtk2.

Поиск виновника привёл меня к следующим файлам:

/usr/lib/systemd/profile.d/70-systemd-shell-extra.sh
/usr/lib/systemd/profile.d/80-systemd-osc-context.sh

Потом к этому багрепорту: https://github.com/systemd/systemd/issues/39133

К этому: https://bugs.kde.org/show_bug.cgi?id=500842

И наконец к сути: https://github.com/systemd/systemd/blob/main/docs/OSC_CONTEXT.md

Машинный перевод для тех, кто плохо понимает английский: https://translate.google.com/?sl=en&tl=ru&text=https%3A%2F%2Fgithub.com%2Fsystemd%2Fsystemd%2Fblob%2Fmain%2Fdocs%2FOSC_CONTEXT.md&op=translate

В целом идея мне показалась не особо полезной, но направление мысли мне понравилось. Более содержательное общение приложения с эмулятором терминала - это хорошо. Я всегда приветствую развитие протоколов обмена обмена данными с терминалом.

 , , ,

wandrien
()

Количество исходных пакетов в Arch

Не знаю, зачем вам эта информация, но вот вам статистика:

В Arch сейчас 12196 исходных пакетов - рецептов сборки.

Из них 249 пакетов имеют префикс lib32- - относятся к поддержке 32-битного юзерспейса.

Количество пакетов, имеющих префикс конкретного ЯП:

   1840 python-
   1170 haskell-
    635 perl-
     60 cargo-
     30 ocaml-

P.S.: Статистика построена на основе этого оглавления, по которому работает билд-ферма: https://gitlab.archlinux.org/archlinux/packaging/state

 

wandrien
()

Simple File Info

В рамках работы над SDE реализовал следующий скрипт.

Simple File Info — программа для отображения расширенной информации о файле. Реализована как переносимый POSIX sh-скрипт.

О программе Simple File Info

Программа отображает диалоговое окно с различной информацией о файле, получаемой из инструментов mimetype, file, exiftool, mediainfo, gio info.

Предназначена для использования с легковесными файловыми менеджерами, у которых нет отображения подобной расширенной информации, но есть возможность добавлять кастомные команды для обработки файлов.

К программе прилагается desktop-файл, чтобы все ФМ, поддерживающие обработку привязки приложений и файлов, могли отображать пункт вызова программы в меню «Открыть с помощью».

Более подробно об отображаемой информации:

В типичной Unix-like системе присутствует два механизма идентификации типа файла: первый на основе базы данных MimeInfo, второй на основе базы данных для утилиты file.

Большинство приложений с графическим интерфейсом используют идентификацию типа файла через MimeInfo.
Многие скрипты для терминала используют идентификацию через file.

Если у вас в системе установлены команды mimetype и file, Simple File Info включит информацию о типе файла в отчёт.

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

  • mediainfo - программа для отображения метаинформации об аудио- и видео-файлах, кроме того, она умеет извлекать метаданные из изображений.

  • gio - модульный фреймфорк для виртуализованной файловой системы, используемый многими графическими программами.

Если у вас в системе установлены команды exiftool, mediainfo, gio, информация из этих программ будет включена в отчёт.

Отображение информации

Для отображения информации используется один из следующих инструментов:

  GXMESSAGE YAD XDIALOG ZENITY XMESSAGE

Simple File Info пытается использовать инструменты в указанном порядке, пока не найдёт установленный и рабочий инструмент.

Чтобы переопределить порядок поиска инструментов, задайте переменную окружения SIMPLE_FILE_INFO_DIALOG_TOOLS. Например:

  export SIMPLE_FILE_INFO_DIALOG_TOOLS='YAD ZENITY GXMESSAGE'

Проблемы/недоработки инструментов отображения диалогов:

  yad
  Не выставляет разумные размер окна и положение окна.

  zenity
  Не выставляет разумные размер окна и положение окна.
  Нет возможности менять иконку в заголовке окна.
  Look & feel в стиле GNOME не соответствует задумке данной программы.

  Xdialog
  Опция --fixed-font не работает на моей машине. Требуется дальнейшее изучение проблемы.
  Отображает себя на "основном" мониторе, а не на мониторе с активным окном.
  Нет возможности менять иконку в заголовке окна.

  xmessage
  Нет поддержки копирования текста в буфера обмена CLIPBOARD, только в PRIMARY.
  Нет возможности менять иконку в заголовке окна.
  Нет возможности переноса длинных строк.
  Нет поддержки юникода.

  gxmessage
  Нет возможности менять иконку в заголовке окна.

Вызов программы

Использование:

  simple-file-info [команда] файлы...

Команды:
  --show-report   - Открыть окно с отчётом по указанным файлам.
                    Если файлов перечислено больше одного, для каждого будет
                    открыто отдельное окно.
  --print-report  - Вывести отчёт по файлам в stdout.
  --show-help     - Открыть окно с данной справкой.
  --help          - Вывести в stdout данную справку и выйти.
  --version       - Вывести в stdout версию программы и выйти.
  --license       - Вывести в stdout информацию о лицензии прогарммы и выйти.
  --desktop-entry - Вывести в stdout содержимое desktop-файла.
  --check-tools   - Вывести в stdout отладочный отчёт о работе внешних утилит.

Если команда не указана, по умолчанию выполняется команда --show-report.

TODO

  • Добавить поддержку определяемых пользователем действий-кнопок
  • Добавить поддержку определяемых пользователем обработчиков внутри generate_report
  • Добавить умный рассчёт размера и позиции окна для yad и zenity

 , , ,

wandrien
()

Потеря открытых вкладок

Вчера произошло странное.

После очередного запуска firefox, он не восстановил содержимое окон.

Открывает нужное количество окон, но вместо реальных вкладок там отображается одна пустая вкладка, а вместо реального заголовка окна а ля «Mozilla Firefox» отображается надпись «Безымянное окно».

Попытки подсунуть одну из резервных копий файла sessionstore, которые Firefox бэкапит автоматически, успеха не дали.

Выглядит это так:

  • Сносим sessionstore.jsonlz4 и sessionstore-backups.
  • Запускаем firefox. Открывается пустой сеанс, и можно пользоваться браузером как обычно. При перезапусках сеанс сохраняется и восстанавливается без сбоев.
  • Кладём в качестве sessionstore.jsonlz4 резервную копию.
  • Запускаем firefox. Открываются те самые 50 пустых окон «Безымянное окно».

При этом если распаковать резервную копию, там валидный json, который можно прочитать и вытащить оттуда состояние сеанса. Но FF с ним работать отказывается.

Попытки нагуглить проблему результатов не дали.

Теперь мне предстоит разобрать 1385 ссылок, которые ранее были вкладками в 58-ми окнах браузера.

Попутно я еще решил разобрать бардак в Opera, где открыто еще 359 вкладок.

Пока что я осилил разобрать штук 50.

 , ,

wandrien
()

SSD труп?

Купил новый SSD в начале лета. Почти им не пользовался. Ситуация:

Model Family:     Apacer AS340/350 SSDs
Device Model:     Apacer AS340 240GB
ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
  1 Raw_Read_Error_Rate     0x0032   100   100   050    Old_age   Always       -       0
  5 Reallocated_Sector_Ct   0x0032   100   100   050    Old_age   Always       -       2
  9 Power_On_Hours          0x0032   100   100   050    Old_age   Always       -       123
 12 Power_Cycle_Count       0x0032   100   100   050    Old_age   Always       -       72
160 Unknown_Attribute       0x0032   100   100   050    Old_age   Always       -       0
161 Unknown_Attribute       0x0033   100   100   050    Pre-fail  Always       -       91
163 Max_Erase_Count         0x0032   100   100   050    Old_age   Always       -       15
164 Average_Erase_Count     0x0032   100   100   050    Old_age   Always       -       2263
165 Unknown_Attribute       0x0032   100   100   050    Old_age   Always       -       11
166 Later_Bad_Block_Count   0x0032   100   100   050    Old_age   Always       -       1
167 SSD_Protect_Mode        0x0032   100   100   050    Old_age   Always       -       6
168 SATA_PHY_Error_Count    0x0032   100   100   050    Old_age   Always       -       5050
169 Unknown_Attribute       0x0032   100   100   050    Old_age   Always       -       100
175 Bad_Cluster_Table_Count 0x0032   100   100   050    Old_age   Always       -       0
176 Erase_Fail_Count_Chip   0x0032   100   100   050    Old_age   Always       -       0
177 Wear_Leveling_Count     0x0032   100   100   050    Old_age   Always       -       0
178 Used_Rsvd_Blk_Cnt_Chip  0x0032   100   100   050    Old_age   Always       -       2
181 Program_Fail_Cnt_Total  0x0032   100   100   050    Old_age   Always       -       0
182 Erase_Fail_Count_Total  0x0032   100   100   050    Old_age   Always       -       0
192 Unexpect_Power_Loss_Ct  0x0032   100   100   050    Old_age   Always       -       28
194 Temperature_Celsius     0x0022   100   100   050    Old_age   Always       -       40
195 Hardware_ECC_Recovered  0x0032   100   100   050    Old_age   Always       -       988957
196 Reallocated_Event_Count 0x0032   100   100   050    Old_age   Always       -       0
197 Current_Pending_Sector  0x0032   100   100   050    Old_age   Always       -       2
198 Offline_Uncorrectable   0x0032   100   100   050    Old_age   Always       -       0
199 UDMA_CRC_Error_Count    0x0032   100   100   050    Old_age   Always       -       0
232 Available_Reservd_Space 0x0032   100   100   050    Old_age   Always       -       91
241 Total_LBAs_Written      0x0030   100   100   050    Old_age   Offline      -       10877
242 Total_LBAs_Read         0x0030   100   100   050    Old_age   Offline      -       39960
245 Unknown_Attribute       0x0032   100   100   050    Old_age   Always       -       19897

Значения Reallocated_Sector_Ct и Current_Pending_Sector пару часов назад показывали 1, сейчас уже 2.

 apacer, ,

wandrien
()

Почему же весь софт такая шляпа

Простите, у меня сгорела жопа.

Полчаса из жизни:

Надо было отредактировать одну картинку, запустил для этого ноут с виндой. Минут 10 любовался на надпись «Очистка. Завершено 0%. Не выключайте компьютер.» Плюнул, взял ноут с Линуксом.

Картинку мне прислали в PDF. Открываю PDF в Libreoffice Draw. Там лист формата A4, на котором вставлена картинка. Тыкаю ПКМ по картинке, выбираю «Save…». Libreoffice Draw предлагает сохранить её с DPI 96, что даёт физический размер изображения около 32x32 сантиметра.

Ну здорово. А взять реальный размер картинки на листе A4, посчитать из этого DPI и предложить по умолчанию адекватное значение DPI — нельзя было?

То есть DPI я должен вычислять сам, видимо. Ну типа, прикладывать линейку к экрану и считать, сколько процентов от отображения листа A4 на экране она занимает? Или как?

Также в меню для картинки есть пункт «Edit with External Tool». Но называется он неправильно. Его правильное название было бы — «Open with External Tool». Потому что он открывает картинку в программе, которая настроена в файловойм менеджере для соответствующего типа файлов. У меня там — просмотрщик картинок.

Ладно. Сохранил. Запускаю GIMP. GIMP версии 3.0 я запускаю первый раз. Он встретил меня диалогом с выбором настроек внешнего вида. То, насколько этот диалог ужасен с точки зрения дизайна UI — не передать словами. Зато переключение вкладок в нём анимированное. И анимация выглядит всрато.

Итак, GIMP запущен. Первое, что меня в нём «порадовало» — всратые менюшки GTK3 без рамок. Менюшки с серым фоном поверх серого содержимого окна. Границ не видно. Найс.

Тут я решил запустить композитный менеджер, чтобы хотя бы у менюшек тени были. Но видимо, не судьба:

$ fastcompmgr -cC 
Another composite manager is already running
Status: 1

При том, что никакой другой композитный менеджер не запущен. Лааадно. С этим разберёмся потом.

Обратно в GIMP. Вот скриншот всего лишь одного окна: https://ibb.co/v6ztVny8

Может я слишком зажрался, но почему всё настолько плохо? Отступы? Расстояния?? Сетка вёрстки? Здравый смысл, в конечном счёте???

 

wandrien
()

Перемножение двух чисел в дополнительном коде с обнаружением переполнения

Вытащу сюда вопрос из темы.

Хочется узнать, какие есть оптимальные алгоритмы перемножения знаковых чисел заданного размера.

Алгоритм, который мне известен:

1. Расширить операнды знаком в 2 раза. 2. Перемножить расширенные операнды алгоритмом беззнакового умножения, получив произведение, которое имеет в 4 раза больше бит, чем исходные операнды. 3. Трактуем произведение как число в дополнительном коде: если полученное значение укладывается в диапазон значений исходного типа, то переполнения нет, если не укладывается — значит переполнение.

Ну то есть, например: для перемножения 256-битных чисел нам придётся оперировать 1024-битным произведением. Что несколько дохрена.

Хочется алгоритм, который не потребует честно вычислять все старшие биты произведения.

(UPD: не, вроде херня какая-то)

 , , ,

wandrien
()

Qod. Опубликовал исходники компилятора, над которым работаю

Финально определился с названием языка, подчистил разные хвосты и написал README. Теперь наконец-то можно посмотреть на нечто большее, чем просто фрагменты кода в постах на форуме: https://github.com/wandrien/qod/

Драфты по дизайну языка пока еще не готовы. Если перед НГ завала работы не будет, то может выложу их в течение пары недель. Черновики пишу на русском, осилить всё чётко сформулировать на английском в разумные сроки я точно не смогу. На русском-то не всегда получается.

Надеюсь, что после публикации материалов по языку, мне щедро насыпят в панамку как конструктивной, так и не очень, критики.

А пока можно посмотреть на сам код вживую.

 , qod, ,

wandrien
()

Понедельник начинается в субботу, а пятница начинается в понедельник

Дорогие теребятки, пишу вам сие письмо из Firefox 67 как из машины времени.

Сейчас буду обновлять Arch, который не обновлялся больше 5 лет. Пожелайте мне удачи. Узнаем, насколько кривые руки у тех, кто ноет, что у них Арч разваливается постоянно.

[vadim@rihanna ~]$ last -F reboot | head -3
reboot   system boot  5.1.15-zen1-1-ze Mon Dec  9 22:51:55 2024   still running
reboot   system boot  5.1.15-zen1-1-ze Mon Mar 28 18:30:13 2022 - Mon Mar 28 11:35:41 2022  (-6:54)
reboot   system boot  5.1.15-zen1-1-ze Thu Jul  4 22:37:19 2019 - Thu Jul  4 16:27:51 2019  (-6:09)
[vadim@rihanna ~]$ tail -1 /var/log/pacman.log 
[2019-07-04 15:47] [ALPM] running 'update-desktop-database.hook'...
[vadim@rihanna ~]$ uname -a
Linux rihanna 5.1.15-zen1-1-zen #1 ZEN SMP PREEMPT Tue Jun 25 04:49:28 UTC 2019 x86_64 GNU/Linux
[vadim@rihanna ~]$ pacman -Q glibc
glibc 2.29-3
[vadim@rihanna ~]$ firefox --version 
Mozilla Firefox 67.0.4

А, да. Железо, в которое я сейчас сунул этот HDD:

[vadim@rihanna ~]$ grep 'model name' /proc/cpuinfo 
model name	: Intel(R) Pentium(R) Dual  CPU  E2180  @ 2.00GHz
model name	: Intel(R) Pentium(R) Dual  CPU  E2180  @ 2.00GHz
[vadim@rihanna ~]$ free -m
              total        used        free      shared  buff/cache   available
Mem:           2998         617        1707          36         673        2195
Swap:          8941           0        8941
[vadim@rihanna ~]$ lspci | grep VGA
01:00.0 VGA compatible controller: NVIDIA Corporation G72 [GeForce 7300 LE] (rev a1)

Интересный антиквариат, который я только что купил за 1000 рублей по приколу. Системник собирала компания Нета в 2007-м. Везде наклейки фирменные и т.п. Корпус и мать были довольно неплохи. Корпус в хорошем состоянии, на вторичке такой сам по себе стоит больше тысячи, а тут еще и начинку дали бонусом. Пыли внутри почти нет, кто-то не поленился всё почистить перед продажей, а ведь мог просто на мусорку отнести. Респект парню.

У меня лежит проц, который как раз сюда годится. Core 2 Duo E8300, если не переврал название по памяти. А в материнке есть 4 слота ОЗУ, так что можно поставить 8 гигов. Купил себе конструктор Лего, короче.

Надеюсь, из Нуво и ядра не выкинули поддержку этого GPU. Но гуглить я это конечно же не буду. Узнаю после рестарта.

 , , , ,

wandrien
()

Пилю генератор кода для компилятора

Здравствуйте, теребятки! С вами наша непостоянная рубрика ненормальное программирование.

В качестве пет-проекта я потихоньку пилю собственный Ada-подобный ЯП. Планов на фичи языка очень много, но пока он по фичам не далеко ушел от ранних вариантов сишечки. Однако сегодня не об этом. Сегодня я вам хочу рассказать о генерации кода.

Генерация кода в настоящее время реализована из синтаксического дерева, без трансляции в отдельное представление для оптимизации. Обычно так не делают, так делать неправильно. Но реализовывать полноценную систему анализа графа управления в мои задачи не входило, поэтому я постарался выжать эффективность насколько возможно из трансляции, управляемой синтаксическим деревом.

Сегодня мы посмотрим, что получается, если решать задачу заведомо неподходящим способом.

Некоторые используемые приёмы оптимизации:

  1. Отслеживание, какие константы или значения выражений загружены в регистры и устранение избыточных загрузок.
  2. Переупорядочивание вычисления операндов выражения.
  3. Устранение выдачи неиспользованных меток. (Помогает лучше отслеживать состояние регистров в п.1.)
  4. Устранение избыточных цепочек jmp-ов. (Когда jmp делается на следующий jmp.)

Далее я покажу примеры, как генератор кода устраняет избыточные загрузки значений. Про остальные пункты расскажу как-нибудь в другой раз. (Примерно через никогда.)

Пример 1.

Генератор кода устранил 4 инструкции mov EAX, dword [EBP+8], так как увидел, что значение переменной Index уже загружено в регистр.

Функция:

char @DictGetFullyQualifiedName(word D)
	when D >= nDict:
		StopInternal(__FILE__, __LINE__);

	word Index = Dict[D].FullyQualifiedName;
	when Index != 0:
		return @Char[Index];

	char Buff[nBUFF];
	strbuf buf;
	strbuf_init(@buf, @Buff, nBUFF);
	Dict_MakeFullyQualifiedName(@buf, D);

	Index = SaveString0(@Buff);
	Dict[D].FullyQualifiedName = Index;
	return @Char[Index];
end

Сгенерированный код:

@10342:                                  ; ## DictGetFullyQualifiedName ##
        push    EBP
        mov     EBP,  ESP
        sub     ESP,  144
                                         ; #line compiler_dict.ctxi:84
        mov     EAX,  dword [EBP+8]
        cmp     EAX,  dword [@@DATA+8476676]
        jb      @10343
                                         ; #line compiler_dict.ctxi:85
        push    dword 85
        push    dword @@ROLITERALS+7329
        call    @10235                   ; StopInternal
@10343: 
                                         ; #line compiler_dict.ctxi:87
        mov     EAX,  dword [EBP+8]
        imul    EAX,  77
        mov     EAX,  dword [@@DATA+EAX+776684]
        mov     dword [EBP-4], EAX
                                         ; #line compiler_dict.ctxi:88
                                         ; Node link reuse in CodePrimaryWrapped
        ; Переиспользуется значение Index в регистре EAX
        test    EAX,  EAX
        je      @10346
                                         ; #line compiler_dict.ctxi:89
                                         ; Node link reuse in CodePrimaryWrapped
        ; Переиспользуется значение Index в регистре EAX
        add     EAX,  @@DATA+49288
        leave
        ret     4
@10346: 
                                         ; #line compiler_dict.ctxi:91
                                         ; #line compiler_dict.ctxi:92
                                         ; #line compiler_dict.ctxi:93
        push    dword 128
        lea     EAX,  [EBP-132]
        push    EAX
        lea     EAX,  [EBP-144]
        push    EAX
        call    @10126                   ; strbuf_init
                                         ; #line compiler_dict.ctxi:94
        push    dword [EBP+8]
        lea     EAX,  [EBP-144]
        push    EAX
        call    @10335                   ; Dict_MakeFullyQualifiedName
                                         ; #line compiler_dict.ctxi:96
        lea     EAX,  [EBP-132]
        push    EAX
        call    @10272                   ; SaveString0
        mov     dword [EBP-4], EAX
                                         ; #line compiler_dict.ctxi:97
                                         ; Node link reuse in Code_ASSIGN (1)
        ; Переиспользуется значение Index в регистре EAX
        mov     EBX,  dword [EBP+8]
        imul    EBX,  77
        mov     dword [@@DATA+EBX+776684], EAX
                                         ; #line compiler_dict.ctxi:98
                                         ; Node link reuse in CodePrimaryWrapped
        ; Переиспользуется значение Index в регистре EAX
        add     EAX,  @@DATA+49288
        leave
        ret     4

В этом примере есть интересный фрагмент:

        mov     EAX,  dword [EBP+8]
        cmp     EAX,  dword [@@DATA+8476676]
        jb      @10343
                                         ; #line compiler_dict.ctxi:85
        push    dword 85
        push    dword @@ROLITERALS+7329
        call    @10235                   ; StopInternal
@10343: 
                                         ; #line compiler_dict.ctxi:87
        mov     EAX,  dword [EBP+8]

Здесь также можно было бы устранить повторную загрузку mov EAX, dword [EBP+8], но это пока не реализовано.

  1. Компилятор знает, что StopInternal не возвращает управление.
  2. Единственный переход по метке @10343 выполняется из места, в котором EAX уже содержит нужное значение.
  3. Таким образом вторая загрузка регистра избыточна.
  4. Но чтобы отследить это, необходим продвинутый анализ перехода по меткам, делать который в мои планы пока не входит.

Пример 2.

Вот еще пример устранения загрузок локальной переменной. Генератор кода дважды переиспользует значение переменой L в регистре EAX:

	word L = strlen(@Dst);
	if L > 1 then
		if str_has_char(@fpath_p_dir_separators, Dst[L - 1]) == 0 then
			strn_cat(@Dst, @fpath_p_dir_separator, Size);
		end:if
	end:if
                                         ; #line include/fpath.ctxi:131
        push    dword [EBP+8]
        call    @10013                   ; strlen
        mov     dword [EBP-4], EAX
                                         ; #line include/fpath.ctxi:132
                                         ; Node link reuse in CodePrimaryWrapped
        cmp     EAX,  1
        jbe     @10179
                                         ; #line include/fpath.ctxi:133
                                         ; Node link reuse in CodePrimaryWrapped
        dec     EAX
        add     EAX,  dword [EBP+8]
        mov      AL,  byte  [EAX]
        push    EAX
        push    dword [@@DATA+44]
        call    @10106                   ; str_has_char

Пример 3.

В этом примере генератор кода понимает, что можно повторно использовать константу в EAX, но не понимает, что можно повторно использовать указатель в EBX.

Для оптимизации использования указателя необходим анализ, какие переменные могут измениться при сохранении значения регистра, а какие - не могут. Так как сейчас такой анализ не реализован, то любая запись в память сбрасывает привязку вычисленных выражений.

        mov     EAX,  100000
        mov     EBX,  dword [EBP-8]
        mov     dword [EBX+44], EAX
                                         ; #line compiler_dict.ctxi:117
                                         ; Node link reuse in Code_ASSIGN (1)
        mov     EBX,  dword [EBP-8]
        mov     dword [EBX+32], EAX
                                         ; #line compiler_dict.ctxi:118
                                         ; Node link reuse in Code_ASSIGN (1)
        mov     EBX,  dword [EBP-8]
        mov     dword [EBX+36], EAX
                                         ; #line compiler_dict.ctxi:119
                                         ; Node link reuse in Code_ASSIGN (1)
        mov     EBX,  dword [EBP-8]
        mov     dword [EBX+40], EAX
                                         ; #line compiler_dict.ctxi:120
                                         ; Node link reuse in Code_ASSIGN (1)
        mov     EBX,  dword [EBP-8]
        mov     dword [EBX+12], EAX
                                         ; #line compiler_dict.ctxi:121
                                         ; Node link reuse in Code_ASSIGN (1)
        mov     EBX,  dword [EBP-8]
        mov     dword [EBX+16], EAX
                                         ; #line compiler_dict.ctxi:122
                                         ; Node link reuse in Code_ASSIGN (1)
        mov     EBX,  dword [EBP-8]
        mov     dword [EBX+20], EAX
                                         ; #line compiler_dict.ctxi:123
                                         ; Node link reuse in Code_ASSIGN (1)
        mov     EBX,  dword [EBP-8]
        mov     dword [EBX+24], EAX

Примеры 4, 5, 6.

Устранение загрузок в условных выражениях:

	if rs >= BRACKET_LEX_SIZE | rs < 1 then
		StopInternal(__FILE__, __LINE__);
	end
        mov     EAX,  dword [EBP-8]
        cmp     EAX,  3
        jae     @11156
                                         ; Node link reuse in CodePrimaryWrapped
        cmp     EAX,  1
        jae     @11155
@11156: 
                                         ; #line frontend_syn_brackets.ctxi:40
        push    dword 40
        push    dword @@ROLITERALS+7664
        call    @10235                   ; StopInternal
@11155: 

В теле цикла после проверки условия цикла:

	while i < nOperator do
		word j = i + 1;
		...
        mov     EAX,  dword [EBP-4]
        cmp     EAX,  dword [@@DATA+12180364]
        jae     @11180
                                         ; #line frontend_syn_operators.ctxi:66
                                         ; Node link reuse in CodePrimaryWrapped
        inc     EAX
        mov     dword [EBP-8], EAX
	while i < nOperator do
		if Operator[i].Prio > Prio then
		...
        mov     EAX,  dword [EBP-8]
        cmp     EAX,  dword [@@DATA+12180364]
        jae     @11197
                                         ; #line frontend_syn_operators.ctxi:120
                                         ; Node link reuse in CodePrimaryWrapped
        imul    EAX,  36
        mov     EAX,  dword [@@DATA+EAX+12178080]
        cmp     EAX,  dword [EBP+12]
        jbe     @11198

 , , ,

wandrien
()

Общие сведения о работе терминала

Эту заметку пишу как ответ на коммент в тему Хочу работу с мышкой как в терминале ConEmu Но пишу быстро и по верхам, так что в общий раздел, а не в раздел статьи. Возможно окажется полезным, чтоб ссылаться сюда в случае похожих вопросов у новичков.

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

Ща всё разъясним.

Базово есть такая архитектура:

Приложение-терминал <--> TTY <--> программа, которая хочет общаться через терминал

TTY это компонент ядра. Кроме того, что служит связующим звеном, он также реализует некоторые базовые фичи, которые делают терминал немного «умнее». Дело в том, что исторически терминалы (те самые — физические, аппаратные терминалы) для Unix были концептуально «тупые». То есть умели только выводить текст по командам программы, а также пересылать ей, какие клавиши пользователь нажал. Для некоторых других ОС терминалы были «умные», с продвинутыми средствами работы с данными на стороне терминала. Но в Unix они не применялись. Unix вообще концептуально была про простоту. А ля делай только самое необходимое и не больше.

Так вот TTY реализует некоторые базовые примитивы и алгоритмы для случаев, когда программа не умеет или не предназначена сама работать с терминалом.

Про работу TTY я писал подробную статью, вот тут можно прочитать: https://wandrien.github.io/articles/tty/

Далее.

Если программа хочет сама продвинуто работать с терминалом, она настраивает TTY, чтобы оно ей не мешало, то есть отключает его логику обработки данных частично или полностью. И таким образом работает с терминалом прозрачно, без особого вмешательства TTY.

Кроме того, что программа настроила TTY, ей нужно еще управлять самим терминалом.

Терминал управляется через некоторый протокол. Этих протоколов и их вариаций за историю была чертова уйма. Обычно конкретное приложение-терминал поддерживает некоторый базовый набор + какие-нибудь специфичные для себя фишки. Кто-то меньше, кто-то больше. Например, если внимательно почитать, сколько команд и режимов работы имеет xterm, там можно потеряться. Ну короче зоопарк как с браузерами или как с поддержкой разных фич в видеокартах.

Для реализации концепции командной строки программы обычно не велосипедят всю логику работы с терминалом с нуля, а берут готовые решения. Часто это библиотека readline. Например, она используется в bash.

В мире BSD-софта вместо readline обычно используется libedit. Ну и еще куча альтернатив есть, как обычно.

Итак, если мы работаем с командным интерпретатором bash, он использует библиотеку readline, реализующую фичи строки ввода, и readline отображает текст в терминале и реагирует на наши команды правки текста.

Если мы работаем с Midnight Commander, то там вместо readline применяется продвинутый тулкит, который реализует окошки, кнопки, поля ввода и так далее.

В zsh, если память не изменяет, используется не readline, а свой отдельный велосипед. (Лень факт-чекать.)

Вот так всё это устроено.

То есть в таких случаях логика работы с вводом пользователя находится в некотором компоненте в составе клиентской программы. А сам терминал тут не особо играет роль.

Теперь к вопросу про мышь, который был в исходном треде.

Если программа не включила в терминале режим передачи событий мыши, то мы видим вот эту простую логику, встроенную в любой терминал, когда можно мышкой выделить текст и скопировать. Если же программа сказала, что хочет сама обрабатывать события мыши, то терминал свою логику выделения текста отключает.

Таким образом получается, что не достаточно сделать так, чтобы мышь работала только в командной строке. Нужно, чтобы приложение еще и «обычную» логику выделения текста как-то у себя поддерживало.

Но! Тут есть обходной путь. Если, например, мы запустим mc и попытаемся выделить текст с нажатой Shift, то увидим, что мышь обрабатывается терминалом, а не mc. Удержание Shift принудительно возвращает обработку мыши в терминал.

Вот вроде и всё, что я хотел вам на эту тему сообщить сегодня. =)

 ,

wandrien
()

Контекстно-зависимость в синтаксисе ЯП

Вот такой чисто теоретический вопрос, навеянный топиком Странная ошибка c шаблоном (или я идиот, или одно из двух)

В C++ одна из особенностей, делающих грамматику контекстно-зависимой — это неоднозначность парсинга выражения

foo<a>(b);

То ли это шаблонная функция foo<a>, вызываемая с аргументом b.

То ли это выражение (foo < a) > b.

Чтобы это понять, компилятор должен иметь доступ к декларации foo.

Как бы вы сделали эту часть грамматики контекстно-свободной, если бы дизайнили ЯП с нуля? Ваши идеи?

 ,

wandrien
()

В этих пикселях на 102.7% больше сюжета, чем...

/Простите, мне некуда это написать, я кроме ЛОРа и еще одного форума нигде не сижу/

Начало игры…

Создаю идеологию из смеси трансгуманизма, ритуализма и кровоедства. Сюжетка – вампирская. На экране выбора пешек сразу прокает сетап: Вампирша 22-х биологических лет возраста и 1941 хронологических. С перком на усердие и огоньками на горном деле, растениеводстве, медицине, общении и умственном труде. А также её дочка 18 лет – трансгуманист, кровожадная, бегун, с огоньками на ближний бой, горное дело и ремесло, да при этом еще и беременная! Сразу жму начать игру, чтобы случайно не рерольнуть такой крутой сетап – у нас тут сразу со старта намечается династия!

Первая осень…

К колонии присоединяется молодая девушка с огоньками в строительстве, искусстве, медицине и умственном труде. Всё бы ничего, вот только она словила комбо перков на дизмораль: завистливость, пессимист, непонятный творец. Оставляю её, хорошие руки и мозги в колонии нужны. Настолько нужны, что у меня нет времени держать её на перевоспитании для смены идеологии. Благо, она частично совместима с моей – в составе есть трансгуманизм и верховенство человека. (И за следующий год времени на перевоспитание так и не найдётся.)

Чуть позже в аварийной капсуле падает её мать. Она боец широкого профиля, крутой медик и строитель. Но снова перки подвели: подавленность и биоконсерватор. А у нас тут планы на тотальную конверсию человеков во всякое.

Решаю вылечить, и если она уйдёт – то выгоню следом и дочь. Но она присоединяется, не успев толком даже полежать в больничке.

Подумываю обеих выгнать позже, когда найду пешек с перками получше. Но тут обнаруживаю, что у этой космической беженки указан бывший муж… тот же чел, что и бывший муж моей вампирши. Что ж. Видимо, Ренди посылает мне знаки. Посмотрим, как с этими двумя игра пойдёт.

Вторая зимовка…

В начале зимы высаживается спящий кластер механоидов с регулятором климата на -10 градусов. Таймер сработает 12-го или 13-го декавраля, перед самым концом зимы. То есть вместо весны меня ждёт вторая зима, а вместо лета – робкая весна и сразу следом снова зима. К такому моя колония не готова, и запасов еды на бесконечную зиму у меня нет.

Корректор климата надо обязательно уничтожить за оставшиеся 2 недели, но у меня нет ни арты, ни дымовых завес для борьбы с туррелями, и даже не открыты нужные технологии. У меня вообще в этом прохождении с наукой не задалось, не смотря на то, что в колонии со старта два хороших исследователя. Но исследовать им некогда. У меня еще даже геотермалка не открыта.

Кластер высадился даже без купольной защиты – мне бы хоть один миномёт и запас боеприпасов.

Решаю смотаться по ближайшим соседям в надежде найти дымовые гранатомёты. Нигде их нет! Делать нечего, покупаю хотя бы автомат отличного качества и некоторое количество брони.

Время постепенно идёт, а что делать с мехами без дымовых завес, я так и не придумал. Вместо этого я безрассудно решаю устроить рейды по открытым точкам, у которых истекает срок. Быстро там, быстро сям, а еще надо успеть до конца зимы поставить колонистам ёлочку, когда все будут на базе вместе. Какая же зима без праздника нового года.

Притаскиваю из рейдов немного лута и двух пленных с огоньками на исследования и общение. В планах завербовать их и посадить на исследования, раз уж мои несостоявшиеся исследователи только успевают служить штурмовиками и строителями.

Зима подходит к концу, а я осознаю, что запасы риса тают слишком быстро – ведь я планировал тихо пересидеть зиму на базе, занимаясь исследованиями, а не носиться по всем окресностям, тратя рис на прокорм животных в пути.

Но вот откладывать дальше некуда – надо хотя бы поставить ёлочку ребятам, а на утро после праздника помолиться и идти в лобовой штурм без дымовой защиты. Какие еще есть варианты? Бросить базу и уйти строить новую, пока еще есть еда. Или тупо пересиживать на месте до лета, экономя жратву и охотясь на диких животных. А там попытаться снова купить дымовухи. Мне не нравится этот вариант, ведь тогда есть риск свариться как лягушка на медленном огне, только вместо огня – холод. Малодушно бросать базу без боя – не нравится еще больше.

Два моих вампира лежат в торпоре, придётся отмечать НГ без них. Ладно, пока все в добром здравии ставим ёлоч… Бзззз! Один чел после похода словил нервный срыв, вернувшись домой холодный и голодный.

Ладно, значит ты не празднуешь, без тебя ставим ёлоч… Бзззз! «Рейд мусорщиков десантируется на вашу базу!»

А ведь.. два моих вампира лежат в торпоре? Чёрт побери! А они двоё сражаются за шестерых.

Мусорщики десантируются прямо на точку, где неприкаянно ходит психанувший колонист. Мне остаётся только беспомощно наблюдать за ним, пока остальные пешки готовятся к обороне. Бесконечно долгие секунды, пока откроются десантные капсулы… Колонист сразу же получает по щщам стальной дубиной и падает – без сознания, но живой. Фух!

Оказывается, за те несколько мгновений, когда сначала видишь тени от садящихся капсул, а потом и сами капсулы, можно о столь многом успеть подумать. И том, что пусть с Маннингом остальные члены колонии не всегда находили общий язык, но все ценили его отличные навыки стрельбы и непререкаемую приверженность нашему учению. Когда-то в самом начале он сам пришел и попросился в колонию как верный последователь нашего дела. А также и о том, что вместе с Маннингом сейчас под десантирующимися капсулами окажется одна из лучших винтовок, и бой придётся принимать не только за минусом трёх бойцов, но и без самого качественного оружия.

Да в рейде-то еще и любовник девчонки, которая сидит у меня в плену. Снова шутки от Ренди.

С трудом отбиваю рейд. Рейд милишный, но их много. В самый критичный момент, когда сокративший дистанцию рейдер под гоу-соком чуть не угрохал мне еще одного колониста, размазываю его в кровавое месиво спеллом крип джойнера.

Остатки рейда бегут. Поля с рисом горят. Два колониста лежат без сознания. База усыпана трупами мусорщиков. Тушу поля, выдыхаю…

А где это любовник… надо посмотреть статы девчонки. Ага, вот он лежит остывает. Не ушел. Еще тридцатника нет, а уже с циррозом печени был. Девчонку не жалко, она ведь тоже не просто так в камере у меня оказалась.

(В этом месте я вспоминаю, как я полгодом ранее пожалел иттакина - вылечил и отпустил. А через неделю он пришел снова в составе другого рейда. Там в землю и лёг.)

Даю полсуток двум раненым немного оклематься, и надо таки поставить ёлочку. Один вампир выходит из спячки. Приходит оптовый торговец, продаю всё ненужное и скупаю мясо. Еда это жизнь! Я бы продал вообще всё, что есть на базе в обмен на большой-большой запас сухих пайков, но у него их нет. И дымового гранатомёта нет.

Ставлю ёлочку. Колонисты собираются на праздник. Проходит несколько секунд:

Бзззз! «Рейд импидов направляется к вашей базе! Враг нападает немедленно!»

Бзззз! «Начинаются сильные заморозки!»

Сразу подряд.

А в составе рейда сын того импида, который у меня сидит в плену уже больше года и служит донором крови вампирам. Отца пришел спасать?

Ладно, какие-то вшивые импиды с луками, всего несколько человек. У меня тут еще и торговец со своей охраной тусит. После мусорщиков под гоу-соком, которые десантировались прямо на голову, импиды это вообще не противник.

Дожидаюсь окончания праздника, выхожу бить импидов. Вместе с охраной торговца легко отбиваем рейд. До края карты успел добежать только старый больной дед. Успел сбежать, потому что сначала до поля битвы дойти не успел.

Среди оставшихся лежать четверо еще живы. С двух снять одежду и оставить истекать кровью в снегу. Третий – тот самый сын, пришедший спасать отца. Захватить и посадить в ту же камеру. Там вы всю свою жизнь и проведёте. Четвёртая… 33 года, «девочка из племени», «беспечный стрелок», «оптимист»… похоже, так бедна, что даже снять с неё нечего. Одета в какие-то лохмотья. Оптимистка, блин… Посреди этого симулятора преступлений против человечности у меня вдруг почему-то дрогнула рука оставить её в снегу. Если выживешь после потери крови и не умрёшь от инфекции, то отпущу.

Бип! «Караван торговцев уходит из-за опасных погодных условий». А почему, снаружи же было -6… в смысле -29? Какой-то лаг в UI, это в холодильнике у меня должно показывать -29…. ЧО РЕАЛЬНО МИНУС ДВАДЦАТЬ ДЕВЯТЬ??? Я смотрю на уведомления, и до меня начинает доходить. Пока я разбирался с импидами, произошло не одно, а два события: три часа назад – начались природные сильные заморозки; час назад – активация искуственной погоды у мехов.

Появляется мстительная мысль, что дед, добежавший до края карты, далеко не убежит. С ранениями и в лёгкой одежде он не сможет выйти за радиус действия контроллёра погоды.

Следом приходит мысль, что и я не смогу. У колонистов не хватает тёплой одежды, я не одевал всех подряд с рассчётом на морозы под -30, поскольку в этих широтах зима не суровая. Излишки вещей и шерсти я просто продавал, а самые недавнюю партию как раз обменял на серебро и автомат отличного качества. Но из серебра не сшить пуховик…

Все посадки мгновенно вымерзают. С грядок пропадает будущая еда, а еда – это жизнь… Правда, есть еще животные в загоне, но насколько их хватит?

Сама база тоже не приспособлена к таким морозам. Правда у меня есть награбленные обогреватели, даже крафтить не придётся. Но нет запаса по мощности, и не везде есть сеть. Срочно отправить часть колонистов ставить пару дополнительных дровяных генераторов и тянуть провода, а другую – пополнять запасы дров?

И снова тот же вопрос, что и ранее, но теперь в острой форме: всё бросить и уходить? отсиживаться на базе, стараясь пережить самый холод? атаковать мехов немедленно?

Тем временем температура в части помещений падает ниже нуля.

Я рассматриваю местность вокруг мехов и нахожу предполагаемое направление атаки, с которого смогу разрушить металлическое заграждение и достреливать до контроллёра погоды, а сам буду находиться вне зоны прострела турелей за горным массивом. Но чтобы туда добраться, нужно сделать большой крюк. Вроде, есть план. Сначала спуллить мехов и уничтожить подвижную силу противника. Затем сделать большую петлю по карте, обходя зоны прострела турелей и горы, чтобы несколько бойцов с винтовками могли дотянуться до контроллёра. Оставив небоеспособных присматривать за пленными, готовлюсь к бою.

Бззз! «Приближаются шамблеры!» …вообще не до вас, ребята зомби… вы там замёрзните как-нибудь в снегах без моего участия, ладно? Еще не хватает классического в такой ситуации «Енот сходит с ума!». Да, Ренди?

Бой проходит относительно удачно. Подвижные дроны уничтожены, двое бойцов – ранены. Тяжело ранена та самая космическая беженка, которую когда-то я хотел выгнать. А сейчас она мой лучший стрелок.

Перед второй фазой боя нужна передышка.

А в это время на базе… у части пленных уже развиваются обморожения. В одной из камер температура упала до -12. В спальне, где весь пол был засажен розами вместо твёрдого настила – вымерли розы. Колонисты тоже плохо переносят холод. Кто был легко одет, к концу боя получили существенную гипотермию. Срочно надо разводить костры, оказывать помощь пленным, думать, как кого переодеть, спасать замерзающих животных в загоне, а все уже на грани нервного срыва и валятся с ног. Одна только дочка главы поселения не унывает и пашет как трактор. Перк кровожадность – сила. После участия в двух мясорубках с кучей убитных врагов, у ней такой запас хорошего настроения, что ничто не может его перебить. А если еще закинуться бодрином, то можно пахать всю ночь и всё утро, пока остальные уже почти сходят с ума.

/здесь пока моё прохождение останавливается/

 ,

wandrien
()

RSS подписка на новые темы