{"id":380071,"date":"2024-06-27T09:04:11","date_gmt":"2024-06-27T09:04:11","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=380071"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=380071","title":{"rendered":"<span>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0438\u0433\u0440\u0443, \u0441\u043b\u043e\u0432\u043d\u043e \u043d\u0430 \u0434\u0432\u043e\u0440\u0435 1987 \u0433\u043e\u0434<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041d\u0435\u0434\u0430\u0432\u043d\u043e \u044f \u043d\u0430\u0442\u043a\u043d\u0443\u043b\u0441\u044f \u043d\u0430\u00a0\u0443\u0434\u0438\u0432\u0438\u0432\u0448\u0435\u0435 \u043c\u0435\u043d\u044f <a href=\"https:\/\/tech.lgbt\/@nina_kali_nina\/112594910070716090\">\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435<\/a>. \u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u00ab\u0421\u0430\u043f\u0451\u0440\u00bb \u043e\u0442\u00a0Microsoft \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0440\u0435\u043a\u043b\u0430\u043c\u0443, \u043f\u043b\u0430\u0442\u043d\u044b\u0435 \u043e\u043f\u0446\u0438\u0438 \u0438 \u0432\u0435\u0441\u0438\u0442 235\u00a0\u041c\u0411, \u0442\u0440\u0435\u0431\u0443\u044f \u043d\u0435\u00a0\u043c\u0435\u043d\u044c\u0448\u0435 500\u00a0\u041c\u0411 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u044b. \u0414\u0430, \u0432\u044b \u043d\u0435\u00a0\u043e\u0441\u043b\u044b\u0448\u0430\u043b\u0438\u0441\u044c. \u0423\u00a0\u043d\u044b\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u00ab\u0421\u0430\u043f\u0451\u0440\u0430\u00bb \u0435\u0441\u0442\u044c \u0440\u0435\u043a\u043b\u0430\u043c\u043d\u043e\u0435 \u043e\u043a\u043e\u0448\u043a\u043e \u0441\u0431\u043e\u043a\u0443, \u0430\u00a0\u0435\u0449\u0451 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0440\u0435\u043a\u043b\u0430\u043c\u0443 \u0434\u043b\u044f\u00a0\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0431\u043e\u043d\u0443\u0441\u043e\u0432 \u0432\u00a0\u0438\u0433\u0440\u0435. <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/eee\/129\/a60\/eee129a6064dcfca824a01339476a822.png\" width=\"1663\" height=\"1247\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/eee\/129\/a60\/eee129a6064dcfca824a01339476a822.png\"\/><\/figure>\n<p>\u0418 \u0442\u043e\u0433\u0434\u0430 \u044f \u043f\u043e\u0434\u0443\u043c\u0430\u043b, \u0447\u0442\u043e\u00a0\u0431\u044b\u043b\u043e\u00a0\u0431\u044b \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u00a0\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c. \u0412\u043e\u0441\u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u0443\u043b\u044c\u0442\u043e\u0432\u0443\u044e \u0432\u0438\u0434\u0435\u043e\u0438\u0433\u0440\u0443 \u00ab\u0421\u0430\u043f\u0451\u0440\u00bb \u0441\u00a0\u043d\u0443\u043b\u044f. \u0421\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0433\u0430\u0431\u0430\u0439\u0442 \u0431\u0443\u0434\u0435\u0442 \u0432\u0435\u0441\u0438\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u0430\u044f \u0438\u0433\u0440\u0430? \u041d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044d\u0442\u043e \u0441\u043b\u043e\u0436\u043d\u043e? \u041c\u043e\u0436\u0435\u0442\u00a0\u043b\u0438 \u043b\u044e\u0431\u0438\u0442\u0435\u043b\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0437\u0430\u00a0\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u043e\u0432?<\/p>\n<p>\u0413\u0435\u0439\u043c\u043f\u043b\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u043c. Enter \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0438\u0433\u0440\u0443, \u0430  \u0434\u043b\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u044f\u0447\u0435\u0439\u043a\u0438 \u043f\u043e\u0434\u00a0\u043a\u0443\u0440\u0441\u043e\u0440\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0436\u0430\u0442\u044c \u043b\u044e\u0431\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443 \u043c\u044b\u0448\u0438.<\/p>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/667d0d6bee68229db64cfa01\" data-style=\"\" id=\"667d0d6bee68229db64cfa01\" width=\"\"><\/div>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/76b\/9fd\/e6a\/76b9fde6a711ce0e536eb06abd799f8e.png\" width=\"1443\" height=\"785\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/76b\/9fd\/e6a\/76b9fde6a711ce0e536eb06abd799f8e.png\"\/><\/figure>\n<p>\u0412\u00a0\u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0439 \u0444\u0430\u0439\u043b \u043e\u0431\u044a\u0451\u043c\u043e\u043c ~ 300\u00a0\u041a\u0431\u0430\u0439\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u00a0\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043c ~ 1\u00a0\u041c\u0431 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438. \u042d\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0432\u00a0\u0442\u044b\u0441\u044f\u0447\u0443 \u0440\u0430\u0437 \u043c\u0435\u043d\u044c\u0448\u0435, \u0447\u0435\u043c \u0443\u00a0Microsoft. \u0418 \u044d\u0442\u043e \u0432\u0441\u0435\u0433\u043e\u00a0\u043b\u0438\u0448\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0442\u0435\u043d \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430. <\/p>\n<p>\u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0432\u00a0\u0442\u043e\u043c, \u0447\u0442\u043e\u00a0\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043a\u0440\u043e\u0448\u0435\u0447\u043d\u044b\u043c \u0438 \u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u044b\u043c: \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0435 \u0441\u00a0\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u043c\u0438 \u0431\u0438\u0442\u0430\u043c\u0438 libC, \u043e\u043d\u043e \u043c\u043e\u0436\u0435\u0442\u00a0\u0431\u044b\u0442\u044c \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0432\u00a0\u043b\u044e\u0431\u043e\u0439 Unix \u0438 \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u043f\u043e\u0432\u0441\u044e\u0434\u0443, \u0438 \u043e\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430\u00a0\u043b\u044e\u0431\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435 (\u0441 \u0442\u043e\u0439\u00a0\u0436\u0435 \u041e\u0421\/\u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043e\u0439). \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f \u0434\u0430\u0436\u0435 \u043d\u0430\u00a0\u0441\u0442\u0430\u0440\u044b\u0445 Linux 20-\u043b\u0435\u0442\u043d\u0435\u0439 \u0434\u0430\u0432\u043d\u043e\u0441\u0442\u0438. <\/p>\n<p>\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0438\u0433\u0440\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f <a href=\"https:\/\/github.com\/gaultier\/minesweeper-from-scratch\">\u0437\u0434\u0435\u0441\u044c<\/a>. \u041d\u043e\u00a0\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043d\u0430\u0448 \u043a\u043e\u0434.<\/p>\n<h3>\u0427\u0442\u043e \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c<\/h3>\n<p>11-\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 X \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u043d\u0430\u00a0\u0441\u0432\u0435\u0442 \u0432 1987\u00a0\u0433\u043e\u0434\u0443 \u0438 \u0441\u00a0\u0442\u0435\u0445 \u043f\u043e\u0440 \u043d\u0435\u00a0\u043c\u0435\u043d\u044f\u043b\u0430\u0441\u044c. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043d\u0430\u00a0\u0434\u0435\u0441\u044f\u0442\u044c \u043b\u0435\u0442 \u0440\u0430\u043d\u044c\u0448\u0435 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043e\u0432, \u0435\u0433\u043e \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0430\u00a0\u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043d\u0435\u00a0\u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u0430\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u044b\u043c \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c. \u0422\u0435\u043c \u043d\u0435\u00a0\u043c\u0435\u043d\u0435\u0435, \u043e\u043d \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u043e\u0432\u0441\u044e\u0434\u0443. \u0412\u00a0\u043b\u044e\u0431\u043e\u0439 Unix \u0435\u0441\u0442\u044c X\u2011\u0441\u0435\u0440\u0432\u0435\u0440, \u0434\u0430\u0436\u0435 \u0432\u00a0macOS \u0441\u00a0XQuartz, \u0438 \u0442\u0435\u043f\u0435\u0440\u044c Windows \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 Linux \u0441\u00a0\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c \u0432\u043d\u0443\u0442\u0440\u0438 WALL! X11\u00a0\u0435\u0449\u0451 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u00a0\u0431\u044b\u043b \u0442\u0430\u043a\u0438\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c. <\/p>\n<p>\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442, \u0430\u00a0\u043f\u043e\u0440\u043e\u0433 \u0432\u0445\u043e\u0434\u0430 \u043d\u0435\u0432\u044b\u0441\u043e\u043a: \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u043a\u0435\u0442, \u0438 \u043c\u044b \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u044b. \u0410\u00a0\u0434\u043b\u044f 2D\u2011\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0435\u00a0\u043d\u0443\u0436\u043d\u043e\u00a0\u0431\u044b\u0442\u044c \u043c\u0430\u0441\u0442\u0435\u0440\u043e\u043c Vulkan \u0438\u043b\u0438\u00a0\u0434\u0430\u0436\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441\u00a0\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043e\u043c. \u0427\u0435\u0440\u0442 \u0432\u043e\u0437\u044c\u043c\u0438, \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0434\u0430\u0436\u0435 \u0431\u0435\u0437\u00a0\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430!<\/p>\n<p>\u0412\u00a0\u043d\u0430\u0448\u0438 \u0434\u043d\u0438 \u0432\u0441\u0435, \u043a\u0442\u043e \u043f\u0438\u0448\u0435\u0442 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 <s>\u0447\u0440\u0435\u0437\u043c\u0435\u0440\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u044b<\/s>\u0445 \u0443\u0432\u0430\u0436\u0430\u0435\u043c\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a libX11\u00a0\u0438 libxcb \u0438 \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u044f Qt \u0438 SDL.<\/p>\n<p>\u0412\u043e\u0442 \u0447\u0442\u043e\u00a0\u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c:<\/p>\n<ul>\n<li>\n<p>\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u043e\u043a\u043d\u043e<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 (\u043e\u0434\u0438\u043d \u0441\u043f\u0440\u0430\u0439\u0442 \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438)<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u0438 \u0441\u043f\u0440\u0430\u0439\u0442\u0430 \u0432\u00a0\u043e\u043a\u043d\u0435<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u00a0\u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u044b\/\u043c\u044b\u0448\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0441\u0451. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435: \u043a\u0430\u0436\u0434\u044b\u0439 \u0448\u0430\u0433\u00a0\u2014 \u044d\u0442\u043e 1\u20133\u00a0\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f X11, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c,\u00a0\u2014 \u044d\u0442\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043b\u0430\u0432\u0438\u0448 \u0438 \u043c\u044b\u0448\u0438.<\/p>\n<p>\u041f\u0438\u0441\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u043d\u0430 <a href=\"https:\/\/odin-lang.org\/\">\u044f\u0437\u044b\u043a\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Odin<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f. \u041d\u043e\u00a0\u0435\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c C \u0438\u043b\u0438\u00a0\u0447\u0442\u043e\u2011\u0442\u043e \u0435\u0449\u0435, \u0434\u0435\u0440\u0437\u0430\u0439\u0442\u0435. \u0412\u0441\u0435, \u0447\u0442\u043e\u00a0\u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e,\u00a0\u2014 \u044d\u0442\u043e \u0443\u043c\u0435\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0441\u043e\u043a\u0435\u0442 Unix, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043f\u043e\u00a0\u043d\u0435\u043c\u0443 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0432\u00a0\u043f\u0430\u043c\u044f\u0442\u044c. \u0414\u043b\u044f\u00a0\u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u043e\u0440\u043c\u0430\u0442 PNG, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0432\u00a0\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 Odin \u0435\u0441\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 PNG. \u041d\u043e\u00a0\u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u043e\u0440\u043c\u0430\u0442 PPM (\u044f \u043f\u0440\u043e\u0434\u0435\u043b\u044b\u0432\u0430\u043b <a href=\"https:\/\/gaultier.github.io\/blog\/wayland_from_scratch.html\">\u043d\u0435\u0447\u0442\u043e \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0435<\/a> \u0441\u00a0Wayland), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043b\u0435\u0433\u043a\u043e \u043f\u043e\u0434\u0434\u0430\u0451\u0442\u0441\u044f \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u043c\u0443 \u0430\u043d\u0430\u043b\u0438\u0437\u0443. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 Odin \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0438 \u0442\u043e, \u0438 \u0434\u0440\u0443\u0433\u043e\u0435 \u0432\u00a0\u0441\u0432\u043e\u0435\u0439 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435, \u0432\u044b\u0431\u043e\u0440 \u043d\u0435\u00a0\u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. \u042f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0441\u044f \u043d\u0430\u00a0PNG, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043e\u043d \u0431\u043e\u043b\u0435\u0435 \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0447\u0435\u043d. <\/p>\n<p>\u041c\u043d\u043e\u0433\u0438\u0435 \u0432\u0435\u0449\u0438 \u0432\u00a0X11\u00a0\u043d\u0435\u00a0\u0437\u0430\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b. \u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f\u00a0X11, \u0434\u0430\u0436\u0435 \u0441\u00a0\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043c\u043e\u0436\u0435\u0442 \u0441\u0442\u0430\u0442\u044c \u0445\u043e\u0440\u043e\u0448\u0438\u043c \u0443\u0447\u0435\u0431\u043d\u044b\u043c \u043f\u043e\u0441\u043e\u0431\u0438\u0435\u043c. \u041d\u0443, \u0438\u043b\u0438\u00a0\u0432\u0430\u043c \u043c\u043e\u0436\u0435\u0442\u00a0\u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043a\u0430\u043a\u00a0\u043f\u0440\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0442\u043e\u0442 \u0438\u043b\u0438\u00a0\u0438\u043d\u043e\u0439 \u0442\u0440\u044e\u043a \u0441\u00a0\u043a\u043e\u0434\u043e\u043c. <\/p>\n<h3>\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f<\/h3>\n<p>\u0412\u00a0\u044d\u0442\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 X. \u042d\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441\u00a0\u0442\u0435\u043c, \u0447\u0442\u043e\u00a0\u043f\u0440\u0438\u00a0\u0440\u0430\u0431\u043e\u0442\u0435 \u043f\u043e\u0434\u00a0Wayland \u0441\u00a0XWayland \u0432\u00a0\u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\u0445 \u0440\u0430\u0431\u043e\u0447\u0435\u0433\u043e \u0441\u0442\u043e\u043b\u0430, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a\u00a0Gnome, \u043d\u0430\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e.<\/p>\n<p>\u042d\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043b\u0438\u043d\u043e\u0439 16\u00a0\u0431\u0430\u0439\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432\u00a0\u0444\u0430\u0439\u043b\u0435 \u0432\u00a0\u0434\u043e\u043c\u0430\u0448\u043d\u0435\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0435\u0433\u043e \u0432\u00a0\u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u043f\u043e\u0441\u044b\u043b\u0430\u0435\u043c X\u2011\u0441\u0435\u0440\u0432\u0435\u0440\u0443.<\/p>\n<p>\u042d\u0442\u043e\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <code>MIT-MAGIC-COOKIE-1<\/code>.<\/p>\n<p>\u0417\u0430\u0433\u0432\u043e\u0437\u0434\u043a\u0430 \u0432\u00a0\u0442\u043e\u043c, \u0447\u0442\u043e\u00a0\u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0434\u043b\u044f\u00a0\u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u0432 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u0441\u0435\u0442\u0435\u0432\u044b\u0445 \u0445\u043e\u0441\u0442\u043e\u0432. \u041f\u043e\u043c\u043d\u0438\u0442\u0435, X11\u00a0\u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f\u00a0\u0440\u0430\u0431\u043e\u0442\u044b \u043f\u043e\u00a0\u0441\u0435\u0442\u0438. \u041e\u0434\u043d\u0430\u043a\u043e \u0437\u0434\u0435\u0441\u044c \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043f\u0438\u0441\u044c \u0434\u043b\u044f\u00a0localhost.<\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043f\u043e\u0434\u0443\u043c\u0430\u0442\u044c, \u043f\u043e\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f. \u0412\u00a0\u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c \u0442\u043e, \u0447\u0442\u043e\u00a0\u0434\u0435\u043b\u0430\u0435\u0442 <code>libXau<\/code>. \u0418\u0437\u00a0\u0435\u0433\u043e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438:<\/p>\n<pre><code>The .Xauthority file is a binary file consisting of a sequence of entries in the following format: 2 bytesFamily value (second byte is as in protocol HOST) 2 bytesaddress length (always MSB first) A byteshost address (as in protocol HOST) 2 bytesdisplay \"number\" length (always MSB first) S bytesdisplay \"number\" string 2 bytesname length (always MSB first) N bytesauthorization name string 2 bytesdata length (always MSB first) D bytesauthorization data string<\/code><\/pre>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0438\u043f\u044b \u0438 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b:  <\/p>\n<pre><code>AUTH_ENTRY_FAMILY_LOCAL: u16 : 1 AUTH_ENTRY_MAGIC_COOKIE: string : \"MIT-MAGIC-COOKIE-1\"  AuthToken :: [16]u8  AuthEntry :: struct { family:    u16, auth_name: []u8, auth_data: []u8, }<\/code><\/pre>\n<p>\u041c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u043f\u043e\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0442. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043a\u0430\u0436\u0434\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c:<\/p>\n<pre><code>read_x11_auth_entry :: proc(buffer: ^bytes.Buffer) -> (AuthEntry, bool) { entry := AuthEntry{}  { n_read, err := bytes.buffer_read(buffer, mem.ptr_to_bytes(&amp;entry.family)) if err == .EOF {return {}, false}  assert(err == .None) assert(n_read == size_of(entry.family)) }  address_len: u16 = 0 { n_read, err := bytes.buffer_read(buffer, mem.ptr_to_bytes(&amp;address_len)) assert(err == .None)  address_len = bits.byte_swap(address_len) assert(n_read == size_of(address_len)) }  address := make([]u8, address_len) { n_read, err := bytes.buffer_read(buffer, address) assert(err == .None) assert(n_read == cast(int)address_len) }  display_number_len: u16 = 0 { n_read, err := bytes.buffer_read(buffer, mem.ptr_to_bytes(&amp;display_number_len)) assert(err == .None)  display_number_len = bits.byte_swap(display_number_len) assert(n_read == size_of(display_number_len)) }  display_number := make([]u8, display_number_len) { n_read, err := bytes.buffer_read(buffer, display_number) assert(err == .None) assert(n_read == cast(int)display_number_len) }  auth_name_len: u16 = 0 { n_read, err := bytes.buffer_read(buffer, mem.ptr_to_bytes(&amp;auth_name_len)) assert(err == .None)  auth_name_len = bits.byte_swap(auth_name_len) assert(n_read == size_of(auth_name_len)) }  entry.auth_name = make([]u8, auth_name_len) { n_read, err := bytes.buffer_read(buffer, entry.auth_name) assert(err == .None) assert(n_read == cast(int)auth_name_len) }  auth_data_len: u16 = 0 { n_read, err := bytes.buffer_read(buffer, mem.ptr_to_bytes(&amp;auth_data_len)) assert(err == .None)  auth_data_len = bits.byte_swap(auth_data_len) assert(n_read == size_of(auth_data_len)) }  entry.auth_data = make([]u8, auth_data_len) { n_read, err := bytes.buffer_read(buffer, entry.auth_data) assert(err == .None) assert(n_read == cast(int)auth_data_len) }  return entry, true }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0444\u0430\u0439\u043b\u0435, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0439\u0442\u0438 \u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u0430:<\/p>\n<pre><code>load_x11_auth_token :: proc(allocator := context.allocator) -> (token: AuthToken, ok: bool) { context.allocator = allocator defer free_all(allocator)  filename_env := os.get_env(\"XAUTHORITY\")  filename := len(filename_env) != 0 \\ ? filename_env \\ : filepath.join([]string{os.get_env(\"HOME\"), \".Xauthority\"})  data := os.read_entire_file_from_filename(filename) or_return  buffer := bytes.Buffer{} bytes.buffer_init(&amp;buffer, data[:])   for { auth_entry := read_x11_auth_entry(&amp;buffer) or_break  if auth_entry.family == AUTH_ENTRY_FAMILY_LOCAL &amp;&amp;    slice.equal(auth_entry.auth_name, transmute([]u8)AUTH_ENTRY_MAGIC_COOKIE) &amp;&amp;    len(auth_entry.auth_data) == size_of(AuthToken) {  mem.copy_non_overlapping( raw_data(&amp;token), raw_data(auth_entry.auth_data), size_of(AuthToken), ) return token, true } }      \/\/ Did not find a fitting token. return {}, false }<\/code><\/pre>\n<p>\u0423 Odin \u0435\u0441\u0442\u044c \u0445\u043e\u0440\u043e\u0448\u0435\u0435 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0440\u0430\u043d\u043d\u0435\u0433\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u043e\u0448\u0438\u0431\u043e\u043a:\u00a0<code>or_return<\/code>, \u0447\u0442\u043e \u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442\u043d\u043e\u00a0<code>?<\/code>\u0432 Rust \u0438\u043b\u0438\u00a0<code>try <\/code>\u0432 Zig. \u0422\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0438 \u0441\u00a0<code>or_break<\/code>.<\/p>\n<p>\u0418 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0435\u0433\u043e \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0432\u00a0<code>main<\/code>:<\/p>\n<pre><code>main :: proc() { auth_token, _ := load_x11_auth_token(context.temp_allocator) }<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043c\u044b \u043d\u0435\u00a0\u043d\u0430\u0448\u043b\u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430, \u043d\u0435\u00a0\u0431\u0435\u0434\u0430, \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u043c \u0441\u00a0\u043f\u0443\u0441\u0442\u044b\u043c.<\/p>\n<p>\u041e\u0434\u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f \u0432\u0435\u0449\u044c: \u0432\u00a0Odin, \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e Zig, \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c,\u00a0\u0436\u0435\u043b\u0430\u044e\u0449\u0438\u043c \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c. \u041e\u0434\u043d\u0430\u043a\u043e, \u0432\u00a0\u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442\u00a0Zig, \u0432\u00a0Odin \u0435\u0441\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043c\u0435\u043d\u0435\u0435 \u0443\u0442\u043e\u043c\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c (\u0438, \u043a\u0430\u043a\u00a0\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0435, \u0431\u043e\u043b\u0435\u0435 \u043d\u0435\u044f\u0432\u043d\u044b\u043c), \u043f\u043e\u00a0\u0441\u0443\u0442\u0438, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u0432\u00a0\u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c.<\/p>\n<p>Odin \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043b\u044e\u0431\u0435\u0437\u0435\u043d, \u0447\u0442\u043e\u0431\u044b \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043d\u0430\u043c \u0434\u0432\u0430 \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0440\u0430\u0437\u0443: \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u043e\u0431\u0449\u0435\u0433\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0439 \u0430\u0440\u0435\u043d\u0443.<\/p>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0437\u0430\u043f\u0438\u0441\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043c\u043e\u0433\u0443\u0442\u00a0\u0431\u044b\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438, \u043d\u0430\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432\u044b\u0434\u0435\u043b\u044f\u0442\u044c \u043c\u0435\u0441\u0442\u043e\u00a0\u2014 \u0441\u0442\u0435\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0430\u043a\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430.\u00a0\u0411\u044b\u043b\u043e\u00a0\u0431\u044b \u043f\u0440\u0438\u0441\u043a\u043e\u0440\u0431\u043d\u043e \u043f\u0435\u0440\u0435\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u0442\u0435\u043a \u0438\u0437\u2011\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u00a0\u0438\u043c\u044f \u0445\u043e\u0441\u0442\u0430 \u0432\u00a0\u044d\u0442\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0434\u043b\u0438\u043d\u043d\u044b\u043c.<\/p>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432\u044b \u0441\u043a\u0430\u0436\u0435\u0442\u0435, \u0447\u0442\u043e \u0432\u0441\u0451 \u044d\u0442\u043e \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u0441\u044f \u0432\u00a0\u0441\u0442\u0435\u043a\u0435. \u0414\u0430, \u043d\u043e\u00a0\u044d\u0442\u043e\u00a0\u0431\u044b\u043b\u0430 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u0430\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u0434\u0445\u043e\u0434 Odin \u043a\u00a0\u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u043f\u0430\u043c\u044f\u0442\u044c\u044e.<\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u043c\u044b \u043d\u0435 \u0445\u043e\u0442\u0438\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u043f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f 16-\u0431\u0430\u0439\u0442\u043e\u0432\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c <code>defer free_all(allocator)<\/code>. \u042d\u0442\u043e \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c \u043f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u0438 \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0430\u0442\u044c \u043f\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043a\u0430\u0436\u0434\u043e\u0435 \u043f\u043e\u043b\u0435. \u041c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0430\u0435\u043c \u0432\u0441\u044e \u0430\u0440\u0435\u043d\u0443 \u043e\u0434\u043d\u0438\u043c \u043c\u0430\u0445\u043e\u043c (\u043d\u043e \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u0430\u044f \u043f\u0430\u043c\u044f\u0442\u044c \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u043f\u043e\u0437\u0436\u0435).<\/p>\n<p>\u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u044d\u0442\u043e\u0439 \u0430\u0440\u0435\u043d\u044b \u0437\u0430\u0434\u0430\u0451\u0442 \u0432\u0435\u0440\u0445\u043d\u044e\u044e \u0433\u0440\u0430\u043d\u0438\u0446\u0443 (\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0433\u0430\u0431\u0430\u0439\u0442) \u043d\u0430\u00a0\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f. \u0422\u0430\u043a \u0447\u0442\u043e\u00a0\u0435\u0441\u043b\u0438 \u043e\u0434\u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c \u0432\u00a0\u0444\u0430\u0439\u043b\u0435 \u043e\u0433\u0440\u043e\u043c\u043d\u0430 \u0438\u043b\u0438\u00a0\u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0430, \u043c\u044b \u0442\u043e\u0447\u043d\u043e \u043d\u0435\u00a0\u0441\u043c\u043e\u0436\u0435\u043c \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442 \u043f\u0430\u043c\u044f\u0442\u0438. \u042d\u0442\u043e \u0445\u043e\u0440\u043e\u0448\u0430\u044f \u043d\u043e\u0432\u043e\u0441\u0442\u044c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e\u00a0\u0432\u00a0\u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u041e\u0421 \u043d\u0430\u0447\u043d\u0451\u0442 \u0441\u0432\u043e\u043f\u0438\u043d\u0433 \u043a\u0430\u043a\u00a0\u0441\u0443\u043c\u0430\u0441\u0448\u0435\u0434\u0448\u0430\u044f \u0438 \u0431\u0443\u0434\u0435\u0442 \u0443\u0431\u0438\u0432\u0430\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b. \u041f\u043e\u00a0\u043c\u043e\u0435\u043c\u0443 \u043e\u043f\u044b\u0442\u0443, \u043e\u0431\u044b\u0447\u043d\u043e \u044d\u0442\u043e \u0443\u0431\u0438\u0432\u0430\u0435\u0442 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440 \u043e\u043a\u043e\u043d\/\u0440\u0430\u0431\u043e\u0447\u0435\u0433\u043e \u0441\u0442\u043e\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0449\u0435\u043b\u0447\u043a\u043e\u043c \u0422\u0430\u043d\u043e\u0441\u0430 \u0438\u0441\u043f\u0430\u0440\u044f\u0435\u0442 \u0432\u0441\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0435 \u043e\u043a\u043d\u0430. \u041e\u0447\u0435\u043d\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0441\u00a0\u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u041e\u0421, \u0438 \u0443\u0436\u0430\u0441\u043d\u043e \u0441\u00a0\u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0432\u0435\u0440\u0445\u043d\u044e\u044e \u0433\u0440\u0430\u043d\u0438\u0446\u0443 \u043d\u0430\u00a0\u0432\u0441\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438 \u0432\u0430\u0448\u0435\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b.<\/p>\n<p>\u0412\u00a0\u0446\u0435\u043b\u043e\u043c \u044f \u043d\u0430\u0445\u043e\u0436\u0443 \u043f\u043e\u0434\u0445\u043e\u0434 Odin \u043e\u0447\u0435\u043d\u044c \u044d\u043b\u0435\u0433\u0430\u043d\u0442\u043d\u044b\u043c. \u041e\u0431\u044b\u0447\u043d\u043e \u044f \u0445\u043e\u0447\u0443 \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0440\u0443\u0433\u043e\u0439 \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u0432\u00a0\u0434\u0430\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043d\u043e\u00a0\u0442\u0430\u043a\u0436\u0435, \u0435\u0441\u043b\u0438 \u043c\u043d\u0435 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e, \u043e\u043d \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0438 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440.<\/p>\n<h3>\u041e\u0442\u043a\u0440\u044b\u0442\u0438\u0435 \u043e\u043a\u043d\u0430<\/h3>\n<p>\u0417\u0434\u0435\u0441\u044c \u0432\u0441\u0451 \u043f\u043e\u0447\u0442\u0438 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435,  \u0447\u0442\u043e \u0438 \u0432\u044b\u0448\u0435, \u0442\u0430\u043a \u0447\u0442\u043e \u044f \u0431\u0443\u0434\u0443 \u043a\u0440\u0430\u0442\u043e\u043a.<\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0442\u043a\u0440\u043e\u0435\u043c \u0441\u043e\u043a\u0435\u0442 \u0434\u043e\u043c\u0435\u043d\u0430 UNIX:<\/p>\n<pre><code>connect_x11_socket :: proc() -> os.Socket { SockaddrUn :: struct #packed { sa_family: os.ADDRESS_FAMILY, sa_data:   [108]u8, }  socket, err := os.socket(os.AF_UNIX, os.SOCK_STREAM, 0) assert(err == os.ERROR_NONE)  possible_socket_paths := [2]string{\"\/tmp\/.X11-unix\/X0\", \"\/tmp\/.X11-unix\/X1\"} for &amp;socket_path in possible_socket_paths { addr := SockaddrUn { sa_family = cast(u16)os.AF_UNIX, } mem.copy_non_overlapping(&amp;addr.sa_data, raw_data(socket_path), len(socket_path))  err = os.connect(socket, cast(^os.SOCKADDR)&amp;addr, size_of(addr)) if (err == os.ERROR_NONE) {return socket} }  os.exit(1) }<\/code><\/pre>\n<p>\u041c\u044b \u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u043f\u0443\u0442\u0435\u0439 \u0434\u043b\u044f \u0441\u043e\u043a\u0435\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u0430.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0435 \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0431\u0449\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u043e\u043c X11:<\/p>\n<pre><code>Screen :: struct #packed { id:             u32, colormap:       u32, white:          u32, black:          u32, input_mask:     u32, width:          u16, height:         u16, width_mm:       u16, height_mm:      u16, maps_min:       u16, maps_max:       u16, root_visual_id: u32, backing_store:  u8, save_unders:    u8, root_depth:     u8, depths_count:   u8, }  ConnectionInformation :: struct { root_screen:      Screen, resource_id_base: u32, resource_id_mask: u32, }<\/code><\/pre>\n<p>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b #packed  \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u043c \u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430, \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043c\u043e\u0436\u0435\u0442 \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u043b\u044f\u043c\u0438.<\/p>\n<p>\u041e\u0434\u043d\u0430 \u0432\u0435\u0449\u044c, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0443\u0436\u043d\u043e \u0437\u043d\u0430\u0442\u044c \u043e X11: \u0432\u0441\u0435, \u0447\u0442\u043e \u043c\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c, \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043e \u0434\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430, \u043a\u0440\u0430\u0442\u043d\u043e\u0433\u043e 4 \u0431\u0430\u0439\u0442\u0430\u043c. \u041c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a\u0430 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0444\u043e\u0440\u043c\u0443\u043b\u0443 <code>((i32)x + 3) &amp; -4<\/code>\u00a0 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u044e\u043d\u0438\u0442-\u0442\u0435\u0441\u0442\u043e\u043c \u043d\u0430 \u0432\u0441\u044f\u043a\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439:<\/p>\n<pre><code>round_up_4 :: #force_inline proc(x: u32) -> u32 { mask: i32 = -4 return transmute(u32)((transmute(i32)x + 3) &amp; mask) }  @(test) test_round_up_4 :: proc(_: ^testing.T) { assert(round_up_4(0) == 0) assert(round_up_4(1) == 4) assert(round_up_4(2) == 4) assert(round_up_4(3) == 4) assert(round_up_4(4) == 4) assert(round_up_4(5) == 8) assert(round_up_4(6) == 8) assert(round_up_4(7) == 8) assert(round_up_4(8) == 8) }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0435 \u0441 \u043c\u0430\u0440\u043a\u0435\u0440\u043e\u043c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0432\u043d\u0443\u0442\u0440\u0438. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 <code>writev<\/code>, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0431\u0443\u0444\u0435\u0440\u043e\u0432 \u0440\u0430\u0437\u043d\u043e\u0439 \u0434\u043b\u0438\u043d\u044b \u0437\u0430 \u043e\u0434\u0438\u043d \u0432\u044b\u0437\u043e\u0432.<\/p>\n<p>\u041f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043f\u0440\u0438\u0441\u044b\u043b\u0430\u0435\u0442 \u043d\u0430\u043c \u0441\u0435\u0440\u0432\u0435\u0440, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0435\u0439:<\/p>\n<pre><code>x11_handshake :: proc(socket: os.Socket, auth_token: ^AuthToken) -> ConnectionInformation { Request :: struct #packed { endianness:             u8, pad1:                   u8, major_version:          u16, minor_version:          u16, authorization_len:      u16, authorization_data_len: u16, pad2:                   u16, }  request := Request { endianness             = 'l', major_version          = 11, authorization_len      = len(AUTH_ENTRY_MAGIC_COOKIE), authorization_data_len = size_of(AuthToken), }   { padding := [2]u8{0, 0} n_sent, err := linux.writev( cast(linux.Fd)socket, []linux.IO_Vec { {base = &amp;request, len = size_of(Request)}, {base = raw_data(AUTH_ENTRY_MAGIC_COOKIE), len = len(AUTH_ENTRY_MAGIC_COOKIE)}, {base = raw_data(padding[:]), len = len(padding)}, {base = raw_data(auth_token[:]), len = len(auth_token)}, }, ) assert(err == .NONE) assert( n_sent == size_of(Request) + len(AUTH_ENTRY_MAGIC_COOKIE) + len(padding) + len(auth_token), ) }  StaticResponse :: struct #packed { success:       u8, pad1:          u8, major_version: u16, minor_version: u16, length:        u16, }  static_response := StaticResponse{} { n_recv, err := os.recv(socket, mem.ptr_to_bytes(&amp;static_response), 0) assert(err == os.ERROR_NONE) assert(n_recv == size_of(StaticResponse)) assert(static_response.success == 1) }   recv_buf: [1 &lt;&lt; 15]u8 = {} { assert(len(recv_buf) >= cast(u32)static_response.length * 4)  n_recv, err := os.recv(socket, recv_buf[:], 0) assert(err == os.ERROR_NONE) assert(n_recv == cast(u32)static_response.length * 4) }   DynamicResponse :: struct #packed { release_number:              u32, resource_id_base:            u32, resource_id_mask:            u32, motion_buffer_size:          u32, vendor_length:               u16, maximum_request_length:      u16, screens_in_root_count:       u8, formats_count:               u8, image_byte_order:            u8, bitmap_format_bit_order:     u8, bitmap_format_scanline_unit: u8, bitmap_format_scanline_pad:  u8, min_keycode:                 u8, max_keycode:                 u8, pad2:                        u32, }  read_buffer := bytes.Buffer{} bytes.buffer_init(&amp;read_buffer, recv_buf[:])  dynamic_response := DynamicResponse{} { n_read, err := bytes.buffer_read(&amp;read_buffer, mem.ptr_to_bytes(&amp;dynamic_response)) assert(err == .None) assert(n_read == size_of(DynamicResponse)) }   \/\/ Skip over the vendor information. bytes.buffer_next(&amp;read_buffer, cast(int)round_up_4(cast(u32)dynamic_response.vendor_length)) \/\/ Skip over the format information (each 8 bytes long). bytes.buffer_next(&amp;read_buffer, 8 * cast(int)dynamic_response.formats_count)  screen := Screen{} { n_read, err := bytes.buffer_read(&amp;read_buffer, mem.ptr_to_bytes(&amp;screen)) assert(err == .None) assert(n_read == size_of(screen)) }  return( ConnectionInformation { resource_id_base = dynamic_response.resource_id_base, resource_id_mask = dynamic_response.resource_id_mask, root_screen = screen, } \\ ) }<\/code><\/pre>\n<p>\u0418 \u0442\u0435\u043f\u0435\u0440\u044c <code>main<\/code>\u00a0  \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f:<\/p>\n<pre><code>main :: proc() { auth_token, _ := load_x11_auth_token(context.temp_allocator) socket := connect_x11_socket() connection_information := x11_handshake(socket, &amp;auth_token) }<\/code><\/pre>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430. \u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043c\u044b \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0434\u043b\u044f \u043d\u0435\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435. \u0412\u043f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u0441\u044b\u043b\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0443:<\/p>\n<pre><code>next_x11_id :: proc(current_id: u32, info: ConnectionInformation) -> u32 { return 1 + ((info.resource_id_mask &amp; (current_id)) | info.resource_id_base) }<\/code><\/pre>\n<p>\u041f\u043e\u0440\u0430 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442:<\/p>\n<pre><code>x11_create_graphical_context :: proc(socket: os.Socket, gc_id: u32, root_id: u32) { opcode: u8 : 55 FLAG_GC_BG: u32 : 8 BITMASK: u32 : FLAG_GC_BG VALUE1: u32 : 0x00_00_ff_00  Request :: struct #packed { opcode:   u8, pad1:     u8, length:   u16, id:       u32, drawable: u32, bitmask:  u32, value1:   u32, } request := Request { opcode   = opcode, length   = 5, id       = gc_id, drawable = root_id, bitmask  = BITMASK, value1   = VALUE1, }  { n_sent, err := os.send(socket, mem.ptr_to_bytes(&amp;request), 0) assert(err == os.ERROR_NONE) assert(n_sent == size_of(Request)) } } <\/code><\/pre>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043e\u043a\u043d\u043e. \u041c\u044b \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0439:<\/p>\n<ul>\n<li>\n<p><code>Exposure<\/code>: \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u0448\u0435 \u043e\u043a\u043d\u043e \u0441\u0442\u0430\u043d\u0435\u0442 \u0432\u0438\u0434\u0438\u043c\u044b\u043c<\/p>\n<\/li>\n<li>\n<p><code>KEY_PRESS<\/code>: \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043a\u043b\u0430\u0432\u0438\u0448\u0438 \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u044b<\/p>\n<\/li>\n<li>\n<p><code>KEY_RELEASE<\/code>: \u043a\u043e\u0433\u0434\u0430 \u043a\u043b\u0430\u0432\u0438\u0448\u0430 \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u044b \u043e\u0442\u043f\u0443\u0449\u0435\u043d\u0430<\/p>\n<\/li>\n<li>\n<p><code>BUTTON_PRESS<\/code>: \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043a\u043d\u043e\u043f\u043a\u0438 \u043c\u044b\u0448\u0438<\/p>\n<\/li>\n<li>\n<p><code>BUTTON_RELEASE<\/code>: \u043a\u043e\u0433\u0434\u0430 \u043a\u043d\u043e\u043f\u043a\u0430 \u043c\u044b\u0448\u0438 \u043e\u0442\u043f\u0443\u0449\u0435\u043d\u0430<\/p>\n<\/li>\n<\/ul>\n<p>\u041c\u044b \u0442\u0430\u043a\u0436\u0435 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u0446\u0432\u0435\u0442 \u0444\u043e\u043d\u0430. \u041f\u0443\u0441\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u0436\u0451\u043b\u0442\u044b\u0439. \u042d\u0442\u043e \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043c\u044b \u0437\u0430\u043a\u0440\u043e\u0435\u043c \u0432\u0441\u0435 \u0447\u0430\u0441\u0442\u0438 \u043e\u043a\u043d\u0430 \u043d\u0430\u0448\u0438\u043c\u0438 \u0430\u0441\u0441\u0435\u0442\u0430\u043c\u0438.  <\/p>\n<pre><code>x11_create_window :: proc( socket: os.Socket, window_id: u32, parent_id: u32, x: u16, y: u16, width: u16, height: u16, root_visual_id: u32, ) { FLAG_WIN_BG_PIXEL: u32 : 2 FLAG_WIN_EVENT: u32 : 0x800 FLAG_COUNT: u16 : 2 EVENT_FLAG_EXPOSURE: u32 = 0x80_00 EVENT_FLAG_KEY_PRESS: u32 = 0x1 EVENT_FLAG_KEY_RELEASE: u32 = 0x2 EVENT_FLAG_BUTTON_PRESS: u32 = 0x4 EVENT_FLAG_BUTTON_RELEASE: u32 = 0x8 flags: u32 : FLAG_WIN_BG_PIXEL | FLAG_WIN_EVENT depth: u8 : 24 border_width: u16 : 0 CLASS_INPUT_OUTPUT: u16 : 1 opcode: u8 : 1 BACKGROUND_PIXEL_COLOR: u32 : 0x00_ff_ff_00  Request :: struct #packed { opcode:         u8, depth:          u8, request_length: u16, window_id:      u32, parent_id:      u32, x:              u16, y:              u16, width:          u16, height:         u16, border_width:   u16, class:          u16, root_visual_id: u32, bitmask:        u32, value1:         u32, value2:         u32, } request := Request { opcode         = opcode, depth          = depth, request_length = 8 + FLAG_COUNT, window_id      = window_id, parent_id      = parent_id, x              = x, y              = y, width          = width, height         = height, border_width   = border_width, class          = CLASS_INPUT_OUTPUT, root_visual_id = root_visual_id, bitmask        = flags, value1         = BACKGROUND_PIXEL_COLOR, value2         = EVENT_FLAG_EXPOSURE | EVENT_FLAG_BUTTON_RELEASE | EVENT_FLAG_BUTTON_PRESS | EVENT_FLAG_KEY_PRESS | EVENT_FLAG_KEY_RELEASE, }  { n_sent, err := os.send(socket, mem.ptr_to_bytes(&amp;request), 0) assert(err == os.ERROR_NONE) assert(n_sent == size_of(Request)) } }<\/code><\/pre>\n<p>\u041c\u044b \u0440\u0435\u0448\u0430\u0435\u043c, \u0447\u0442\u043e \u0432 \u043d\u0430\u0448\u0435\u0439 \u0438\u0433\u0440\u0435 \u0431\u0443\u0434\u0435\u0442 16 \u0441\u0442\u0440\u043e\u043a \u0438 16 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432, \u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0430\u0441\u0441\u0435\u0442 \u0438\u043c\u0435\u0435\u0442 \u0440\u0430\u0437\u043c\u0435\u0440 16&#215;16 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439.<\/p>\n<p><code>main<\/code> \u0442\u0435\u043f\u0435\u0440\u044c:<\/p>\n<pre><code>ENTITIES_ROW_COUNT :: 16 ENTITIES_COLUMN_COUNT :: 16 ENTITIES_WIDTH :: 16 ENTITIES_HEIGHT :: 16  main :: proc() { auth_token, _ := load_x11_auth_token(context.temp_allocator) socket := connect_x11_socket() connection_information := x11_handshake(socket, &amp;auth_token)  gc_id := next_x11_id(0, connection_information) x11_create_graphical_context(socket, gc_id, connection_information.root_screen.id)  window_id := next_x11_id(gc_id, connection_information) x11_create_window( socket, window_id, connection_information.root_screen.id, 200, 200, ENTITIES_COLUMN_COUNT * ENTITIES_WIDTH, ENTITIES_ROW_COUNT * ENTITIES_HEIGHT, connection_information.root_screen.root_visual_id, ) }<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u044b \u043e\u043a\u043d\u0430 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u043e\u0439: \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u0442\u0430\u0439\u043b\u043e\u0432\u043e\u043c \u043e\u043a\u043e\u043d\u043d\u043e\u043c \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0435. \u041c\u044b \u043d\u0435 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c \u044d\u0442\u043e\u0442 \u0441\u043b\u0443\u0447\u0430\u0439 \u0437\u0434\u0435\u0441\u044c, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0430\u043a\u0442\u0438\u0432\u044b \u0438\u043c\u0435\u044e\u0442 \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0441\u043b\u0435\u0434\u0438\u043b\u0438 \u0437\u0430 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u0442\u043e \u0441\u0435\u0439\u0447\u0430\u0441 \u0432\u044b \u0443\u0432\u0438\u0434\u0438\u0442\u0435&#8230; \u043d\u0438\u0447\u0435\u0433\u043e. \u042d\u0442\u043e \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442\u044c X11 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0430\u0448\u0435 \u043e\u043a\u043d\u043e \u043f\u0440\u0438\u00a0<code>map_window<\/code>\u0432\u044b\u0437\u043e\u0432\u0435:<\/p>\n<pre><code>x11_map_window :: proc(socket: os.Socket, window_id: u32) { opcode: u8 : 8  Request :: struct #packed { opcode:         u8, pad1:           u8, request_length: u16, window_id:      u32, } request := Request { opcode         = opcode, request_length = 2, window_id      = window_id, } { n_sent, err := os.send(socket, mem.ptr_to_bytes(&amp;request), 0) assert(err == os.ERROR_NONE) assert(n_sent == size_of(Request)) }  }<\/code><\/pre>\n<p>\u0418 \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u044d\u0442\u043e:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b88\/1b8\/0b3\/b881b80b34b60f0fa386245612448e29.png\" width=\"452\" height=\"491\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b88\/1b8\/0b3\/b881b80b34b60f0fa386245612448e29.png\"\/><\/figure>\n<p>\u041f\u043e\u0440\u0430 \u0437\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0441\u0430\u043c\u043e\u0439 \u0438\u0433\u0440\u043e\u0439.<\/p>\n<h3>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0430\u0441\u0441\u0435\u0442\u043e\u0432<\/h3>\n<p>\u041a\u0430\u043a\u0430\u044f \u0438\u0433\u0440\u0430 \u0431\u0435\u0437 \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0445 \u043a\u0430\u0440\u0442\u0438\u043d\u043e\u043a,\u00a0<s>\u0447\u0435\u0441\u0442\u043d\u043e \u044d\u043a\u0441\u043f\u0440\u043e\u0440\u0438\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043e\u0442\u043a\u0443\u0434\u0430-\u0442\u043e \u0438\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430<\/s>?<\/p>\n<p>\u0412\u043e\u0442 \u043d\u0430\u0448 \u0441\u043f\u0440\u0430\u0439\u0442, \u0432\u0441\u0435 \u043d\u0430\u0448\u0438 \u0430\u0441\u0441\u0435\u0442\u044b \u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/da4\/a1e\/9fc\/da4a1e9fcd3a46663cd3bd0c80f44704.png\" width=\"144\" height=\"91\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/da4\/a1e\/9fc\/da4a1e9fcd3a46663cd3bd0c80f44704.png\"\/><\/figure>\n<p>\u0423\u00a0Odin \u0435\u0441\u0442\u044c \u0445\u043e\u0440\u043e\u0448\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f\u00a0\u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u00a0\u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0439 \u0444\u0430\u0439\u043b, \u0447\u0442\u043e\u00a0\u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0438 \u0443\u0441\u043a\u043e\u0440\u044f\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e: <\/p>\n<pre><code>png_data := #load(\"sprite.png\") sprite, err := png.load_from_bytes(png_data, {}) assert(err == nil)<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u043e\u0442 \u0432\u00a0\u0447\u0451\u043c \u0437\u0430\u0433\u0432\u043e\u0437\u0434\u043a\u0430: \u0444\u043e\u0440\u043c\u0430\u0442 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f X11\u00a0\u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u00a0\u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0441\u043f\u0440\u0430\u0439\u0442\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0431\u0430\u0439\u0442\u044b \u043c\u0435\u0441\u0442\u0430\u043c\u0438: <\/p>\n<pre><code>sprite_data := make([]u8, sprite.height * sprite.width * 4)  \/\/ Convert the image format from the sprite (RGB) into the X11 image format (BGRX). for i := 0; i &lt; sprite.height * sprite.width - 3; i += 1 { sprite_data[i * 4 + 0] = sprite.pixels.buf[i * 3 + 2] \/\/ R -> B sprite_data[i * 4 + 1] = sprite.pixels.buf[i * 3 + 1] \/\/ G -> G sprite_data[i * 4 + 2] = sprite.pixels.buf[i * 3 + 0] \/\/ B -> R sprite_data[i * 4 + 3] = 0 \/\/ pad }<\/code><\/pre>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u00a0<code>A<\/code>\u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0443 \u043d\u0430\u0441 \u043d\u0435\u0442 \u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0441\u0442\u0438.  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043f\u0430\u043c\u044f\u0442\u0438 (\u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439), \u043a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430? \u041a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u043c\u043e\u0434\u0435\u043b\u0438 X11 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u043d\u0430 \u043b\u044e\u0431\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435 \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u043c \u043a\u043e\u043d\u0446\u0435 \u0441\u0432\u0435\u0442\u0430.<\/p>\n<p>\u0412 X11 \u0435\u0441\u0442\u044c \u0442\u0440\u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0432\u044b\u0437\u043e\u0432\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439:\u00a0<code>CreatePixmap<\/code>\u0438\u00a0<code>PutImage<\/code>. <code>Pixmap<\/code>\u2014 \u0432\u043d\u0435\u044d\u043a\u0440\u0430\u043d\u043d\u044b\u0439 \u0431\u0443\u0444\u0435\u0440 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f.\u00a0<code>PutImage<\/code>\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043b\u0438\u0431\u043e \u0432 \u043f\u0438\u043a\u0441\u043c\u0430\u043f, \u043b\u0438\u0431\u043e \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u043e\u043a\u043d\u043e (\u00abdrawable\u00bb \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 X11).\u00a0<code>CopyArea<\/code>\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442 \u043e\u0434\u0438\u043d \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e drawable \u0432 \u0434\u0440\u0443\u0433\u043e\u0439.  <\/p>\n<p>\u041f\u043e \u043c\u043e\u0435\u043c\u0443 \u0441\u043a\u0440\u043e\u043c\u043d\u043e\u043c\u0443 \u043c\u043d\u0435\u043d\u0438\u044e, \u0432\u0441\u0451 \u043d\u0435 \u0442\u0430\u043a.\u00a0<code>CreatePixmap<\/code>\u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u043b \u0431\u044b\u0442\u044c \u0432\u044b\u0437\u0432\u0430\u043d\u00a0<code>CreateOffscreenImageBuffer<\/code>\u0438\u00a0<code>PutImage<\/code>\u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u043b \u0431\u044b\u0442\u044c\u00a0<code>UploadImageData<\/code>.\u00a0<code>CopyArea<\/code>: \u0437\u0434\u0435\u0441\u044c \u0432\u0441\u0451 \u043a\u0440\u0443\u0442\u043e, \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u0430\u043a \u0435\u0441\u0442\u044c.<\/p>\n<p>\u041c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u00a0<code>PutImage<\/code>, \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0432\u0435\u0434\u0435\u043d \u0432\u0435\u0441\u044c \u0441\u043f\u0440\u0430\u0439\u0442 (\u0437\u0434\u0435\u0441\u044c \u043d\u0435\u0442 \u043f\u043e\u043b\u0435\u0439 \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f). \u041c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0433\u043e \u0447\u0430\u0441\u0442\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432\u00a0<code>PutImage<\/code>, \u043d\u043e \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<p>\u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043e\u0434\u0438\u043d \u0440\u0430\u0437, \u0432\u043d\u0435 \u044d\u043a\u0440\u0430\u043d\u0430, \u043e\u0434\u043d\u0438\u043c \u0432\u044b\u0437\u043e\u0432\u043e\u043c <code>PutImage<\/code>, \u0430 \u0437\u0430\u0442\u0435\u043c \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0447\u0430\u0441\u0442\u0438 \u0432 \u043e\u043a\u043d\u043e. \u0412\u043e\u0442 \u043a\u0430\u043a \u044d\u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c:<\/p>\n<ul>\n<li>\n<p><code>CreatePixmap<\/code><\/p>\n<\/li>\n<li>\n<p><code>PutImage<\/code> \u0434\u043b\u044f\u00a0\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u00a0pixmap\u00a0\u2014 \u0432\u00a0\u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u00a0\u043e\u043a\u043d\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435\u00a0\u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f, \u0432\u0441\u0435 \u043f\u043e\u2011\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0437\u0430\u00a0\u043f\u0440\u0435\u0434\u0435\u043b\u0430\u043c\u0438 \u044d\u043a\u0440\u0430\u043d\u0430<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 \u043d\u0430\u0448\u0435\u0439 \u0438\u0433\u0440\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u0434\u0435\u0448\u0451\u0432\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 <code>CopyArea<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442 \u0447\u0430\u0441\u0442\u044c pixmap \u0432\u00a0\u043e\u043a\u043d\u043e\u00a0\u2014 \u0442\u0435\u043f\u0435\u0440\u044c \u0435\u0433\u043e \u0432\u0438\u0434\u043d\u043e!<\/p>\n<\/li>\n<\/ul>\n<p>X-\u0441\u0435\u0440\u0432\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 GPU \u0432\u044b\u0437\u043e\u0432\u043e\u043c <code>PutImage<\/code> \u00a0<code> <\/code> (\u044d\u0442\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438). \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e\u00a0\u0432\u044b\u0437\u043e\u0432\u044b<code>CopyArea<\/code>\u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u044b X-\u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u044b GPU \u0434\u043b\u044f \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0431\u0443\u0444\u0435\u0440\u0430 GPU \u0432 \u0434\u0440\u0443\u0433\u043e\u0439: \u044d\u0442\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e! \u0414\u0430\u043d\u043d\u044b\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044e\u0442\u0441\u044f \u043d\u0430 GPU \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0438 \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u0442\u0430\u043c \u0434\u043e \u043a\u043e\u043d\u0446\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b.<\/p>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0435 X \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u043d\u043e (\u0442\u0430\u043c \u0441\u043a\u0430\u0437\u0430\u043d\u043e: &#171;\u043c\u043e\u0436\u0435\u0442 \u0438\u043b\u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 [&#8230;]&#187;), \u043d\u043e \u044d\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f \u0438\u0434\u0435\u044f, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0443\u0436\u043d\u043e \u0438\u043c\u0435\u0442\u044c \u0432 \u0432\u0438\u0434\u0443. <\/p>\n<p>\u0415\u0449\u0451 \u043e\u0434\u043d\u0430 \u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f \u0438\u0434\u0435\u044f \u2014 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442, \u043a\u043e\u0433\u0434\u0430 X-\u0441\u0435\u0440\u0432\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e \u0441\u0435\u0442\u0438: \u041c\u044b \u0445\u043e\u0442\u0438\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u043c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0430 \u0437\u0430\u0442\u0435\u043c \u0432\u044b\u0434\u0430\u0442\u044c \u0434\u0435\u0448\u0451\u0432\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b <code>CopyArea<\/code>, \u043a\u0430\u0436\u0434\u0430\u044f \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0432\u0441\u0435\u0433\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u0430\u0439\u0442.<\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u044d\u0442\u043e:<\/p>\n<pre><code>x11_create_pixmap :: proc( socket: os.Socket, window_id: u32, pixmap_id: u32, width: u16, height: u16, depth: u8, ) { opcode: u8 : 53  Request :: struct #packed { opcode:         u8, depth:          u8, request_length: u16, pixmap_id:      u32, drawable_id:    u32, width:          u16, height:         u16, }  request := Request { opcode         = opcode, depth          = depth, request_length = 4, pixmap_id      = pixmap_id, drawable_id    = window_id, width          = width, height         = height, }  { n_sent, err := os.send(socket, mem.ptr_to_bytes(&amp;request), 0) assert(err == os.ERROR_NONE) assert(n_sent == size_of(Request)) } }  x11_put_image :: proc( socket: os.Socket, drawable_id: u32, gc_id: u32, width: u16, height: u16, dst_x: u16, dst_y: u16, depth: u8, data: []u8, ) { opcode: u8 : 72  Request :: struct #packed { opcode:         u8, format:         u8, request_length: u16, drawable_id:    u32, gc_id:          u32, width:          u16, height:         u16, dst_x:          u16, dst_y:          u16, left_pad:       u8, depth:          u8, pad1:           u16, }  data_length_padded := round_up_4(cast(u32)len(data))  request := Request { opcode         = opcode, format         = 2, \/\/ ZPixmap request_length = cast(u16)(6 + data_length_padded \/ 4), drawable_id    = drawable_id, gc_id          = gc_id, width          = width, height         = height, dst_x          = dst_x, dst_y          = dst_y, depth          = depth, } { padding_len := data_length_padded - cast(u32)len(data)  n_sent, err := linux.writev( cast(linux.Fd)socket, []linux.IO_Vec { {base = &amp;request, len = size_of(Request)}, {base = raw_data(data), len = len(data)}, {base = raw_data(data), len = cast(uint)padding_len}, }, ) assert(err == .NONE) assert(n_sent == size_of(Request) + len(data) + cast(int)padding_len) } }  x11_copy_area :: proc( socket: os.Socket, src_id: u32, dst_id: u32, gc_id: u32, src_x: u16, src_y: u16, dst_x: u16, dst_y: u16, width: u16, height: u16, ) { opcode: u8 : 62 Request :: struct #packed { opcode:         u8, pad1:           u8, request_length: u16, src_id:         u32, dst_id:         u32, gc_id:          u32, src_x:          u16, src_y:          u16, dst_x:          u16, dst_y:          u16, width:          u16, height:         u16, }  request := Request { opcode         = opcode, request_length = 7, src_id         = src_id, dst_id         = dst_id, gc_id          = gc_id, src_x          = src_x, src_y          = src_y, dst_x          = dst_x, dst_y          = dst_y, width          = width, height         = height, } { n_sent, err := os.send(socket, mem.ptr_to_bytes(&amp;request), 0) assert(err == os.ERROR_NONE) assert(n_sent == size_of(Request)) } }<\/code><\/pre>\n<p>\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u043e\u0437\u044c\u043c\u0451\u043c\u0441\u044f \u0437\u0430 <code>main<\/code>:  <\/p>\n<pre><code>img_depth: u8 = 24 pixmap_id := next_x11_id(window_id, connection_information) x11_create_pixmap( socket, window_id, pixmap_id, cast(u16)sprite.width, cast(u16)sprite.height, img_depth, )  x11_put_image( socket, pixmap_id, gc_id, sprite_width, sprite_height, 0, 0, img_depth, sprite_data, )      \/\/ Let's render two different assets: an exploded mine and an idle mine. x11_copy_area( socket, pixmap_id, window_id, gc_id, 32, \/\/ X coordinate on the sprite sheet. 40, \/\/ Y coordinate on the sprite sheet. 0, \/\/ X coordinate on the window. 0, \/\/ Y coordinate on the window. 16, \/\/ Width. 16, \/\/ Height. ) x11_copy_area( socket, pixmap_id, window_id, gc_id, 64, 40, 16, 0, 16, 16, )<\/code><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/88f\/c53\/6e2\/88fc536e2065b0627eac2d76bafd0e81.png\" width=\"284\" height=\"322\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/88f\/c53\/6e2\/88fc536e2065b0627eac2d76bafd0e81.png\"\/><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0438\u0433\u0440\u043e\u0432\u044b\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u0445.  <\/p>\n<h3>\u0418\u0433\u0440\u043e\u0432\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438<\/h3>\n<p>\u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u0436\u0434\u0430\u044f \u0438\u0437 \u043d\u0438\u0445 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0443\u0447\u0430\u0441\u0442\u043e\u043a \u0441\u043f\u0440\u0430\u0439\u0442\u043e\u0432\u043e\u0433\u043e \u043b\u0438\u0441\u0442\u0430 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c 16&#215;16. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c\u0441\u044f \u0441 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c:<\/p>\n<pre><code>Position :: struct { x: u16, y: u16, }  Entity_kind :: enum { Covered, Uncovered_0, Uncovered_1, Uncovered_2, Uncovered_3, Uncovered_4, Uncovered_5, Uncovered_6, Uncovered_7, Uncovered_8, Mine_exploded, Mine_idle, }  ASSET_COORDINATES: [Entity_kind]Position = { .Uncovered_0 = {x = 0 * 16, y = 22}, .Uncovered_1 = {x = 1 * 16, y = 22}, .Uncovered_2 = {x = 2 * 16, y = 22}, .Uncovered_3 = {x = 3 * 16, y = 22}, .Uncovered_4 = {x = 4 * 16, y = 22}, .Uncovered_5 = {x = 5 * 16, y = 22}, .Uncovered_6 = {x = 6 * 16, y = 22}, .Uncovered_7 = {x = 7 * 16, y = 22}, .Uncovered_8 = {x = 8 * 16, y = 22}, .Covered = {x = 0, y = 38}, .Mine_exploded = {x = 32, y = 40}, .Mine_idle = {x = 64, y = 40}, }<\/code><\/pre>\n<p>\u0418 \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0451, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e, \u0432 \u043e\u0434\u043d\u0443 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c\u00a0<code>Scene<\/code>:  <\/p>\n<pre><code>Scene :: struct { window_id:              u32, gc_id:                  u32, sprite_pixmap_id:       u32, displayed_entities:     [ENTITIES_ROW_COUNT * ENTITIES_COLUMN_COUNT]Entity_kind, mines:                  [ENTITIES_ROW_COUNT * ENTITIES_COLUMN_COUNT]bool, }<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0432\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 \u2014\u00a0<code>displayed_entities<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442, \u043a\u0430\u043a\u0438\u0435 \u0430\u0441\u0441\u0435\u0442\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u0438\u043d\u0430 \u043b\u0438\u0431\u043e \u0441\u043f\u0440\u044f\u0442\u0430\u043d\u0430, \u043b\u0438\u0431\u043e \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u0430 \u0438 \u0432\u0437\u043e\u0440\u0432\u0430\u043d\u0430, \u0435\u0441\u043b\u0438 \u0438\u0433\u0440\u043e\u043a \u043d\u0430\u0436\u0430\u043b \u043d\u0430 \u043d\u0435\u0451, \u043b\u0438\u0431\u043e \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u0430 \u0438 \u043f\u0440\u043e\u0441\u0442\u0430\u0438\u0432\u0430\u0435\u0442, \u0435\u0441\u043b\u0438 \u0438\u0433\u0440\u043e\u043a \u0443\u0433\u0430\u0434\u0430\u043b \u0435\u0451 \u043c\u0435\u0441\u0442\u043e\u043d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435.<\/p>\n<p>\u0412\u0442\u043e\u0440\u043e\u0439 \u2014\u00a0<code>mines<\/code>\u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442, \u0433\u0434\u0435 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u043c\u0438\u043d\u044b. \u042d\u0442\u043e \u043c\u043e\u0433\u043b\u043e \u0431\u044b\u0442\u044c \u0431\u0438\u0442\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435 \u0434\u043b\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0430, \u043d\u043e \u044f \u043d\u0435 \u0441\u0442\u0430\u043b \u0437\u0430\u043c\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f. <\/p>\n<p>\u0412 <code>main<\/code> \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u0443\u044e \u0441\u0446\u0435\u043d\u0443 \u0438 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0441\u0442\u0430\u0432\u0438\u043c \u043c\u0438\u043d\u044b:<\/p>\n<pre><code>scene := Scene { window_id              = window_id, gc_id                  = gc_id, sprite_pixmap_id       = pixmap_id, } reset(&amp;scene)<\/code><\/pre>\n<p>\u041c\u044b \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043b\u0438 \u044d\u0442\u0443 \u043b\u043e\u0433\u0438\u043a\u0443 \u0432 <code>reset<\/code>\u00a0, \u0447\u0442\u043e\u0431\u044b \u0438\u0433\u0440\u043e\u043a \u043c\u043e\u0433 \u043b\u0435\u0433\u043a\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0438\u0433\u0440\u0443 \u043e\u0434\u043d\u0438\u043c \u043d\u0430\u0436\u0430\u0442\u0438\u0435\u043c \u043a\u043b\u0430\u0432\u0438\u0448\u0438:<\/p>\n<pre><code>reset :: proc(scene: ^Scene) { for &amp;entity in scene.displayed_entities { entity = .Covered }  for &amp;mine in scene.mines { mine = rand.choice([]bool{true, false, false, false}) } }<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c 1\/4, \u0447\u0442\u043e \u0432 \u044f\u0447\u0435\u0439\u043a\u0435 \u0435\u0441\u0442\u044c \u043c\u0438\u043d\u0430. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0433\u043e\u0442\u043e\u0432\u044b \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0443 (\u043f\u043e\u043a\u0430 \u0447\u0442\u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e) \u0441\u0446\u0435\u043d\u0443:<\/p>\n<pre><code>render :: proc(socket: os.Socket, scene: ^Scene) { for entity, i in scene.displayed_entities { rect := ASSET_COORDINATES[entity] row, column := idx_to_row_column(i)  x11_copy_area( socket, scene.sprite_pixmap_id, scene.window_id, scene.gc_id, rect.x, rect.y, cast(u16)column * ENTITIES_WIDTH, cast(u16)row * ENTITIES_HEIGHT, ENTITIES_WIDTH, ENTITIES_HEIGHT, ) } }<\/code><\/pre>\n<p>\u0418 \u0432\u043e\u0442 \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/dda\/10f\/ae6\/dda10fae6ee9ff82e0bece0817b514ff.png\" width=\"284\" height=\"322\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/dda\/10f\/ae6\/dda10fae6ee9ff82e0bece0817b514ff.png\"\/><\/figure>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0448\u0430\u0433 \u2013 \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f.  <\/p>\n<h3>\u0420\u0435\u0430\u043a\u0446\u0438\u044f \u043d\u0430 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u044b \u0438 \u043c\u044b\u0448\u0438<\/h3>\n<p>\u041b\u043e\u0433\u0438\u043a\u0430 \u043f\u0440\u043e\u0441\u0442\u0430\u044f. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043e\u0436\u0438\u0434\u0430\u0435\u043c, &#8212; \u044d\u0442\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u044b \u0438 \u043c\u044b\u0448\u0438, \u0438\u043c\u0435\u044e\u0449\u0438\u0435 \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 32 \u0431\u0430\u0439\u0442\u0430, \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0440\u043e\u0432\u043d\u043e 32 \u0431\u0430\u0439\u0442\u0430 \u0432 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0435\u043c \u0440\u0435\u0436\u0438\u043c\u0435.  \u041f\u0435\u0440\u0432\u044b\u0439 \u0431\u0430\u0439\u0442 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u0442\u0438\u043f \u0441\u043e\u0431\u044b\u0442\u0438\u044f:<\/p>\n<pre><code>wait_for_x11_events :: proc(socket: os.Socket, scene: ^Scene) { GenericEvent :: struct #packed { code: u8, pad:  [31]u8, } assert(size_of(GenericEvent) == 32)  KeyReleaseEvent :: struct #packed { code:            u8, detail:          u8, sequence_number: u16, time:            u32, root_id:         u32, event:           u32, child_id:        u32, root_x:          u16, root_y:          u16, event_x:         u16, event_y:         u16, state:           u16, same_screen:     bool, pad1:            u8, } assert(size_of(KeyReleaseEvent) == 32)  ButtonReleaseEvent :: struct #packed { code:        u8, detail:      u8, seq_number:  u16, timestamp:   u32, root:        u32, event:       u32, child:       u32, root_x:      u16, root_y:      u16, event_x:     u16, event_y:     u16, state:       u16, same_screen: bool, pad1:        u8, } assert(size_of(ButtonReleaseEvent) == 32)  EVENT_EXPOSURE: u8 : 0xc EVENT_KEY_RELEASE: u8 : 0x3 EVENT_BUTTON_RELEASE: u8 : 0x5  KEYCODE_ENTER: u8 : 36  for { generic_event := GenericEvent{} n_recv, err := os.recv(socket, mem.ptr_to_bytes(&amp;generic_event), 0) if err == os.EPIPE || n_recv == 0 { os.exit(0) \/\/ The end. }  assert(err == os.ERROR_NONE) assert(n_recv == size_of(GenericEvent))  switch generic_event.code { case EVENT_EXPOSURE: render(socket, scene)  case EVENT_KEY_RELEASE: event := transmute(KeyReleaseEvent)generic_event if event.detail == KEYCODE_ENTER { reset(scene) render(socket, scene) }  case EVENT_BUTTON_RELEASE: event := transmute(ButtonReleaseEvent)generic_event on_cell_clicked(event.event_x, event.event_y, scene) render(socket, scene) } } }<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0440\u0430\u0432\u043d\u043e\u00a0<code>Exposed<\/code>, \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 (\u044d\u0442\u043e \u043d\u0430\u0448 \u043f\u0435\u0440\u0432\u044b\u0439 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433, \u043a\u043e\u0433\u0434\u0430 \u043e\u043a\u043d\u043e \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0432\u0438\u0434\u0438\u043c\u044b\u043c \u2014 \u0438\u043b\u0438 \u0435\u0441\u043b\u0438 \u043e\u043a\u043d\u043e \u0431\u044b\u043b\u043e \u0441\u0432\u0451\u0440\u043d\u0443\u0442\u043e, \u0430 \u0437\u0430\u0442\u0435\u043c \u0441\u043d\u043e\u0432\u0430 \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0432\u0438\u0434\u0438\u043c\u044b\u043c).  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043b\u0430\u0432\u0438\u0448\u0430 <code>Enter<\/code>, \u043c\u044b \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438\u0433\u0440\u044b \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433. X11 \u0440\u0430\u0437\u043b\u0438\u0447\u0430\u0435\u0442 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0438 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043a\u043b\u0430\u0432\u0438\u0448\u0438 \u043d\u0430 \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u0435, \u043d\u043e \u0437\u0434\u0435\u0441\u044c \u044d\u0442\u043e \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f (\u0438\u043b\u0438, \u044f \u0431\u044b \u0441\u043a\u0430\u0437\u0430\u043b, \u0432 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0438\u0433\u0440: \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u043b\u0430\u0432\u0438\u0448\u0438, \u0430 \u043d\u0435 \u0442\u043e, \u0441 \u0447\u0435\u043c \u0435\u0435 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c).<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0436\u0430\u0442\u0438\u0435 \u0438 \u043e\u0442\u043f\u0443\u0441\u043a\u0430\u043d\u0438\u0435 \u043a\u043d\u043e\u043f\u043a\u0438 \u043c\u044b\u0448\u0438, \u043c\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0438\u0433\u0440\u043e\u0432\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0439\u0442\u0438 \u044f\u0447\u0435\u0439\u043a\u0443 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433.<\/p>\n<p>\u0412\u043e\u0442 \u0438 \u0432\u0441\u0451.<\/p>\n<h3>\u041b\u043e\u0433\u0438\u043a\u0430 \u0438\u0433\u0440\u044b: \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u044c \u044f\u0447\u0435\u0439\u043a\u0443<\/h3>\n<p>\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c: \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438\u0433\u0440\u044b.<\/p>\n<p>\u041d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044f \u043f\u043e\u043c\u043d\u044e, \u043f\u0440\u0438 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u043d\u0438\u0438 \u044f\u0447\u0435\u0439\u043a\u0438 \u043c\u044b \u0438\u043c\u0435\u0435\u043c \u0434\u0432\u0430 \u0441\u043b\u0443\u0447\u0430\u044f:<\/p>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u043c\u0438\u043d\u0430, \u043c\u044b \u043f\u0440\u043e\u0438\u0433\u0440\u0430\u043b\u0438<\/p>\n<\/li>\n<li>\n<p> \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u043d\u0435 \u043c\u0438\u043d\u0430, \u043c\u044b \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u044d\u0442\u0443 \u044f\u0447\u0435\u0439\u043a\u0443 \u0438 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0435 \u044f\u0447\u0435\u0439\u043a\u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0437\u0430\u043b\u0438\u0432\u043a\u0438. \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u043c\u044b \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0437\u0430\u043c\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u044f\u0447\u0435\u0439\u043a\u0438. \u041d\u0435\u043e\u0442\u043a\u0440\u044b\u0442\u0430\u044f \u044f\u0447\u0435\u0439\u043a\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044f\u0447\u0435\u0435\u043a \u043f\u043e\u0441\u043e\u0441\u0435\u0434\u0441\u0442\u0432\u0443 \u0437\u0430\u043c\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e (\u0435\u0441\u043b\u0438 0, \u0442\u043e \u044f\u0447\u0435\u0439\u043a\u0430 \u043f\u0443\u0441\u0442\u0430\u044f, \u0447\u0438\u0441\u043b\u043e \u043d\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f).<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435, \u0447\u0442\u043e \u043c\u0435\u043d\u044f \u0441\u043c\u0443\u0442\u0438\u043b\u043e, \u044d\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u043c\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c 8 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0445 \u044f\u0447\u0435\u0435\u043a \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0447\u0451\u0442\u0430 \u043c\u0438\u043d, \u043d\u043e \u043f\u0440\u0438 \u0437\u0430\u043b\u0438\u0432\u043a\u0435 \u043f\u043e\u0441\u0435\u0449\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e 4 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0435 \u044f\u0447\u0435\u0439\u043a\u0438: \u0432\u0432\u0435\u0440\u0445, \u0432\u043f\u0440\u0430\u0432\u043e, \u0432\u043d\u0438\u0437, \u0432\u043b\u0435\u0432\u043e, \u0430 \u043d\u0435 \u0441\u043e\u0441\u0435\u0434\u0435\u0439 \u043f\u043e \u0434\u0438\u0430\u0433\u043e\u043d\u0430\u043b\u0438. \u0412 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0437\u0430\u043b\u0438\u0432\u043a\u0430 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u0438\u044e \u0432\u0441\u0435\u0445 \u044f\u0447\u0435\u0435\u043a \u0432 \u0438\u0433\u0440\u0435 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e.<\/p>\n<p>\u0422\u0430\u043a \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043c\u044b\u0448\u0438 \u0432 \u043e\u043a\u043d\u0435 \u0432 \u0438\u043d\u0434\u0435\u043a\u0441\/\u0441\u0442\u0440\u043e\u043a\u0443\/\u0441\u0442\u043e\u043b\u0431\u0435\u0446 \u044f\u0447\u0435\u0439\u043a\u0438 \u0432 \u043d\u0430\u0448\u0435\u0439 \u0441\u0435\u0442\u043a\u0435:<\/p>\n<pre><code>row_column_to_idx :: #force_inline proc(row: int, column: int) -> int { return cast(int)row * ENTITIES_COLUMN_COUNT + cast(int)column }  locate_entity_by_coordinate :: proc(win_x: u16, win_y: u16) -> (idx: int, row: int, column: int) { column = cast(int)win_x \/ ENTITIES_WIDTH row = cast(int)win_y \/ ENTITIES_HEIGHT  idx = row_column_to_idx(row, column)  return idx, row, column }<\/code><\/pre>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u043b\u043e\u0433\u0438\u043a\u0430 \u0438\u0433\u0440\u044b:  <\/p>\n<pre><code>on_cell_clicked :: proc(x: u16, y: u16, scene: ^Scene) { idx, row, column := locate_entity_by_coordinate(x, y)  mined := scene.mines[idx]  if mined { scene.displayed_entities[idx] = .Mine_exploded \/\/ Lose. uncover_all_cells(&amp;scene.displayed_entities, &amp;scene.mines, .Mine_exploded) } else { visited := [ENTITIES_COLUMN_COUNT * ENTITIES_ROW_COUNT]bool{} uncover_cells_flood_fill(row, column, &amp;scene.displayed_entities, &amp;scene.mines, &amp;visited)  \/\/ Win. if count_remaining_goals(scene.displayed_entities, scene.mines) == 0 { uncover_all_cells(&amp;scene.displayed_entities, &amp;scene.mines, .Mine_idle) } } }<\/code><\/pre>\n<p>\u0426\u0435\u043b\u044c \u2014 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0442\u044c \u0432\u0441\u0435 \u044f\u0447\u0435\u0439\u043a\u0438 \u0431\u0435\u0437 \u043c\u0438\u043d. \u041c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0447\u0451\u0442\u0447\u0438\u043a \u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0442\u044c \u0435\u0433\u043e, \u043d\u043e \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043a\u0430\u043d\u0438\u0440\u0443\u044e \u0441\u0435\u0442\u043a\u0443, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0441\u0447\u0438\u0442\u0430\u0442\u044c, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043d\u0435\u043f\u043e\u043a\u0440\u044b\u0442\u044b\u0445 \u044f\u0447\u0435\u0435\u043a \u0431\u0435\u0437 \u043c\u0438\u043d\u044b \u043f\u043e\u0434 \u043d\u0435\u0439 (\u0432\u00a0<code>count_remaining_goals<\/code>). \u041d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0440\u0438\u0441\u043a\u0430 \u0440\u0430\u0441\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u0438\u0433\u0440\u044b \u0438 \u0442\u0435\u043c, \u0447\u0442\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435, \u043d\u0435\u0442.<\/p>\n<p><code>uncover_all_cells<\/code>\u0431\u0435\u0437\u043e\u0433\u043e\u0432\u043e\u0440\u043e\u0447\u043d\u043e \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0432\u0441\u044e \u0441\u0435\u0442\u043a\u0443, \u043a\u043e\u0433\u0434\u0430 \u0438\u0433\u0440\u043e\u043a \u0432\u044b\u0438\u0433\u0440\u0430\u043b \u0438\u043b\u0438 \u043f\u0440\u043e\u0438\u0433\u0440\u0430\u043b. \u041d\u0430\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0437\u043e\u0440\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u0438\u043d\u044b, \u043a\u043e\u0433\u0434\u0430 \u0438\u0433\u0440\u043e\u043a \u043f\u0440\u043e\u0438\u0433\u0440\u0430\u043b, \u0438 \u0434\u0435\u0430\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d \u0432\u044b\u0438\u0433\u0440\u0430\u043b.<\/p>\n<p><code>uncover_cells_flood_fill<\/code>\u044d\u0442\u043e \u0441\u0430\u043c\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435. \u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e, \u0438 \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e\u043a\u0440\u0430\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u0441\u0435\u0449\u0435\u043d\u0438\u044f \u043e\u0434\u043d\u0438\u0445 \u0438 \u0442\u0435\u0445 \u0436\u0435 \u044f\u0447\u0435\u0435\u043a \u0438 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u044f \u0432 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e, \u043c\u044b \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u043c, \u043a\u0430\u043a\u0438\u0435 \u044f\u0447\u0435\u0439\u043a\u0438 \u0431\u044b\u043b\u0438 \u043f\u043e\u0441\u0435\u0449\u0435\u043d\u044b:<\/p>\n<pre><code>uncover_cells_flood_fill :: proc( row: int, column: int, displayed_entities: ^[ENTITIES_COLUMN_COUNT * ENTITIES_ROW_COUNT]Entity_kind, mines: ^[ENTITIES_ROW_COUNT * ENTITIES_COLUMN_COUNT]bool, visited: ^[ENTITIES_COLUMN_COUNT * ENTITIES_ROW_COUNT]bool, ) { i := row_column_to_idx(row, column) if visited[i] {return}  visited[i] = true  \/\/ Do not uncover covered mines. if mines[i] {return}  if displayed_entities[i] != .Covered {return}  \/\/ Uncover cell.  mines_around_count := count_mines_around_cell(row, column, mines[:]) assert(mines_around_count &lt;= 8)  displayed_entities[i] = cast(Entity_kind)(cast(int)Entity_kind.Uncovered_0 + mines_around_count)  \/\/ Uncover neighbors.  \/\/ Up. if !(row == 0) { uncover_cells_flood_fill(row - 1, column, displayed_entities, mines, visited) }  \/\/ Right if !(column == (ENTITIES_COLUMN_COUNT - 1)) { uncover_cells_flood_fill(row, column + 1, displayed_entities, mines, visited) }  \/\/ Bottom. if !(row == (ENTITIES_ROW_COUNT - 1)) { uncover_cells_flood_fill(row + 1, column, displayed_entities, mines, visited) }  \/\/ Left. if !(column == 0) { uncover_cells_flood_fill(row, column - 1, displayed_entities, mines, visited) } }<\/code><\/pre>\n<p>\u0422\u0443\u0442 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u044e\u0430\u043d\u0441\u043e\u0432, \u043d\u043e \u0432 \u0446\u0435\u043b\u043e\u043c \u0432\u0441\u0451 \u0433\u043e\u0442\u043e\u0432\u043e. \u0412\u0441\u0435\u0433\u043e 1000 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430 \u0431\u0435\u0437 \u0432\u0441\u044f\u043a\u0438\u0445 \u0443\u0445\u0438\u0449\u0440\u0435\u043d\u0438\u0439 \u0438 \u0437\u0430\u0443\u043c\u043d\u044b\u0445 \u0448\u0442\u0443\u0447\u0435\u043a.<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/af7\/cce\/dfc\/af7ccedfc498236d1fe23bbe67b50de4.png\" width=\"452\" height=\"491\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/af7\/cce\/dfc\/af7ccedfc498236d1fe23bbe67b50de4.png\"\/><\/figure>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>X11 \u0443\u0441\u0442\u0430\u0440\u0435\u043b \u0438 \u043d\u0435\u0443\u0434\u043e\u0431\u0435\u043d, \u043d\u043e \u0432 \u0446\u0435\u043b\u043e\u043c \u043d\u0435\u043f\u043b\u043e\u0445. \u041a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u0443\u0434\u0443\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0435 \u043e\u043a\u043d\u0430, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438 \u0442. \u0434., \u043e \u043d\u0451\u043c \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0431\u044b\u0442\u044c, \u0438 \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u0442\u044c \u0432\u0441\u0435 \u043d\u0430\u0448\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0438\u0433\u0440\u0435. \u042d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0446\u0435\u043d\u043d\u043e. \u0421\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u0432 \u0438 \u0441\u0440\u0435\u0434 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043c\u043e\u0433\u0443\u0442 \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435?<\/p>\n<p>\u041c\u043d\u0435 \u0442\u0430\u043a\u0436\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f, \u0447\u0442\u043e \u043e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u043b\u044e\u0431\u044b\u043c \u044f\u0437\u044b\u043a\u043e\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0441 \u043b\u044e\u0431\u044b\u043c \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0441\u0442\u0435\u043a\u043e\u043c. \u041d\u0435 \u043d\u0443\u0436\u043d\u043e \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043f\u0440\u0438\u0432\u044f\u0437\u043e\u043a, \u043d\u0438\u043a\u0430\u043a\u0438\u0445 FFI, \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u0430\u0439\u0442 \u043f\u043e \u0441\u043e\u043a\u0435\u0442\u0443. \u0412\u044b \u0434\u0430\u0436\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0432 Bash (\u043d\u0435 \u0438\u0441\u043a\u0443\u0448\u0430\u0439\u0442\u0435 \u043c\u0435\u043d\u044f!).<\/p>\n<p>\u042f \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0432\u0435\u0449\u0435\u0439 \u0438\u0437 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0439 \u0438\u0433\u0440\u044b, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0444\u043b\u0430\u0433\u0430 \u043d\u0430 \u043a\u043b\u0435\u0442\u043a\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439, \u043a\u0430\u043a \u0432\u044b \u043f\u043e\u0434\u043e\u0437\u0440\u0435\u0432\u0430\u0435\u0442\u0435, \u0435\u0441\u0442\u044c \u043c\u0438\u043d\u0430. \u041d\u0435 \u0441\u0442\u0435\u0441\u043d\u044f\u0439\u0442\u0435\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e, \u044d\u0442\u043e \u043d\u0435 \u0442\u0430\u043a\u0430\u044f \u0443\u0436 \u0442\u0440\u0443\u0434\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u043a\u0430.<\/p>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u0447\u0442\u043e \u0432\u0430\u043c \u0431\u044b\u043b\u043e \u0442\u0430\u043a \u0436\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043a\u0430\u043a \u0438 \u043c\u043d\u0435!  <\/p>\n<details class=\"spoiler\">\n<summary>\u0412\u0435\u0441\u044c \u043a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>package main  import \"core:bytes\" import \"core:image\/png\" import \"core:math\/bits\" import \"core:math\/rand\" import \"core:mem\" import \"core:os\" import \"core:path\/filepath\" import \"core:slice\" import \"core:sys\/linux\" import \"core:testing\"  TILE_WIDTH :: 16 TILE_HEIGHT :: 16  Position :: struct { x: u16, y: u16, }  Entity_kind :: enum { Covered, Uncovered_0, Uncovered_1, Uncovered_2, Uncovered_3, Uncovered_4, Uncovered_5, Uncovered_6, Uncovered_7, Uncovered_8, Mine_exploded, Mine_idle, }  ASSET_COORDINATES: [Entity_kind]Position = { .Uncovered_0 = {x = 0 * 16, y = 22}, .Uncovered_1 = {x = 1 * 16, y = 22}, .Uncovered_2 = {x = 2 * 16, y = 22}, .Uncovered_3 = {x = 3 * 16, y = 22}, .Uncovered_4 = {x = 4 * 16, y = 22}, .Uncovered_5 = {x = 5 * 16, y = 22}, .Uncovered_6 = {x = 6 * 16, y = 22}, .Uncovered_7 = {x = 7 * 16, y = 22}, .Uncovered_8 = {x = 8 * 16, y = 22}, .Covered = {x = 0, y = 38}, .Mine_exploded = {x = 32, y = 40}, .Mine_idle = {x = 64, y = 40}, }  AuthToken :: [16]u8  AuthEntry :: struct { family:    u16, auth_name: []u8, auth_data: []u8, }  Screen :: struct #packed { id:             u32, colormap:       u32, white:          u32, black:          u32, input_mask:     u32, width:          u16, height:         u16, width_mm:       u16, height_mm:      u16, maps_min:       u16, maps_max:       u16, root_visual_id: u32, backing_store:  u8, save_unders:    u8, root_depth:     u8, depths_count:   u8, }  ConnectionInformation :: struct { root_screen:      Screen, resource_id_base: u32, resource_id_mask: u32, }   AUTH_ENTRY_FAMILY_LOCAL: u16 : 1 AUTH_ENTRY_MAGIC_COOKIE: string : \"MIT-MAGIC-COOKIE-1\"  round_up_4 :: #force_inline proc(x: u32) -> u32 { mask: i32 = -4 return transmute(u32)((transmute(i32)x + 3) &amp; mask) }  read_x11_auth_entry :: proc(buffer: ^bytes.Buffer) -> (AuthEntry, bool) { entry := AuthEntry{}  { n_read, err := bytes.buffer_read(buffer, mem.ptr_to_bytes(&amp;entry.family)) if err == .EOF {return {}, false}  assert(err == .None) assert(n_read == size_of(entry.family)) }  address_len: u16 = 0 { n_read, err := bytes.buffer_read(buffer, mem.ptr_to_bytes(&amp;address_len)) assert(err == .None)  address_len = bits.byte_swap(address_len) assert(n_read == size_of(address_len)) }  address := make([]u8, address_len) { n_read, err := bytes.buffer_read(buffer, address) assert(err == .None) assert(n_read == cast(int)address_len) }  display_number_len: u16 = 0 { n_read, err := bytes.buffer_read(buffer, mem.ptr_to_bytes(&amp;display_number_len)) assert(err == .None)  display_number_len = bits.byte_swap(display_number_len) assert(n_read == size_of(display_number_len)) }  display_number := make([]u8, display_number_len) { n_read, err := bytes.buffer_read(buffer, display_number) assert(err == .None) assert(n_read == cast(int)display_number_len) }  auth_name_len: u16 = 0 { n_read, err := bytes.buffer_read(buffer, mem.ptr_to_bytes(&amp;auth_name_len)) assert(err == .None)  auth_name_len = bits.byte_swap(auth_name_len) assert(n_read == size_of(auth_name_len)) }  entry.auth_name = make([]u8, auth_name_len) { n_read, err := bytes.buffer_read(buffer, entry.auth_name) assert(err == .None) assert(n_read == cast(int)auth_name_len) }  auth_data_len: u16 = 0 { n_read, err := bytes.buffer_read(buffer, mem.ptr_to_bytes(&amp;auth_data_len)) assert(err == .None)  auth_data_len = bits.byte_swap(auth_data_len) assert(n_read == size_of(auth_data_len)) }  entry.auth_data = make([]u8, auth_data_len) { n_read, err := bytes.buffer_read(buffer, entry.auth_data) assert(err == .None) assert(n_read == cast(int)auth_data_len) }   return entry, true }  load_x11_auth_token :: proc(allocator := context.allocator) -> (token: AuthToken, ok: bool) { context.allocator = allocator defer free_all(allocator)  filename_env := os.get_env(\"XAUTHORITY\")  filename := len(filename_env) != 0 \\ ? filename_env \\ : filepath.join([]string{os.get_env(\"HOME\"), \".Xauthority\"})  data := os.read_entire_file_from_filename(filename) or_return  buffer := bytes.Buffer{} bytes.buffer_init(&amp;buffer, data[:])   for { auth_entry := read_x11_auth_entry(&amp;buffer) or_break  if auth_entry.family == AUTH_ENTRY_FAMILY_LOCAL &amp;&amp;    slice.equal(auth_entry.auth_name, transmute([]u8)AUTH_ENTRY_MAGIC_COOKIE) &amp;&amp;    len(auth_entry.auth_data) == size_of(AuthToken) {  mem.copy_non_overlapping( raw_data(&amp;token), raw_data(auth_entry.auth_data), size_of(AuthToken), ) return token, true } }  \/\/ Did not find a fitting token. return {}, false }  connect_x11_socket :: proc() -> os.Socket { SockaddrUn :: struct #packed { sa_family: os.ADDRESS_FAMILY, sa_data:   [108]u8, }  socket, err := os.socket(os.AF_UNIX, os.SOCK_STREAM, 0) assert(err == os.ERROR_NONE)  possible_socket_paths := [2]string{\"\/tmp\/.X11-unix\/X0\", \"\/tmp\/.X11-unix\/X1\"} for &amp;socket_path in possible_socket_paths { addr := SockaddrUn { sa_family = cast(u16)os.AF_UNIX, } mem.copy_non_overlapping(&amp;addr.sa_data, raw_data(socket_path), len(socket_path))  err = os.connect(socket, cast(^os.SOCKADDR)&amp;addr, size_of(addr)) if (err == os.ERROR_NONE) {return socket} }  os.exit(1) }   x11_handshake :: proc(socket: os.Socket, auth_token: ^AuthToken) -> ConnectionInformation {  Request :: struct #packed { endianness:             u8, pad1:                   u8, major_version:          u16, minor_version:          u16, authorization_len:      u16, authorization_data_len: u16, pad2:                   u16, }  request := Request { endianness             = 'l', major_version          = 11, authorization_len      = len(AUTH_ENTRY_MAGIC_COOKIE), authorization_data_len = size_of(AuthToken), }   { padding := [2]u8{0, 0} n_sent, err := linux.writev( cast(linux.Fd)socket, []linux.IO_Vec { {base = &amp;request, len = size_of(Request)}, {base = raw_data(AUTH_ENTRY_MAGIC_COOKIE), len = len(AUTH_ENTRY_MAGIC_COOKIE)}, {base = raw_data(padding[:]), len = len(padding)}, {base = raw_data(auth_token[:]), len = len(auth_token)}, }, ) assert(err == .NONE) assert( n_sent == size_of(Request) + len(AUTH_ENTRY_MAGIC_COOKIE) + len(padding) + len(auth_token), ) }  StaticResponse :: struct #packed { success:       u8, pad1:          u8, major_version: u16, minor_version: u16, length:        u16, }  static_response := StaticResponse{} { n_recv, err := os.recv(socket, mem.ptr_to_bytes(&amp;static_response), 0) assert(err == os.ERROR_NONE) assert(n_recv == size_of(StaticResponse)) assert(static_response.success == 1) }   recv_buf: [1 &lt;&lt; 15]u8 = {} { assert(len(recv_buf) >= cast(u32)static_response.length * 4)  n_recv, err := os.recv(socket, recv_buf[:], 0) assert(err == os.ERROR_NONE) assert(n_recv == cast(u32)static_response.length * 4) }   DynamicResponse :: struct #packed { release_number:              u32, resource_id_base:            u32, resource_id_mask:            u32, motion_buffer_size:          u32, vendor_length:               u16, maximum_request_length:      u16, screens_in_root_count:       u8, formats_count:               u8, image_byte_order:            u8, bitmap_format_bit_order:     u8, bitmap_format_scanline_unit: u8, bitmap_format_scanline_pad:  u8, min_keycode:                 u8, max_keycode:                 u8, pad2:                        u32, }  read_buffer := bytes.Buffer{} bytes.buffer_init(&amp;read_buffer, recv_buf[:])  dynamic_response := DynamicResponse{} { n_read, err := bytes.buffer_read(&amp;read_buffer, mem.ptr_to_bytes(&amp;dynamic_response)) assert(err == .None) assert(n_read == size_of(DynamicResponse)) }   \/\/ Skip over the vendor information. bytes.buffer_next(&amp;read_buffer, cast(int)round_up_4(cast(u32)dynamic_response.vendor_length)) \/\/ Skip over the format information (each 8 bytes long). bytes.buffer_next(&amp;read_buffer, 8 * cast(int)dynamic_response.formats_count)  screen := Screen{} { n_read, err := bytes.buffer_read(&amp;read_buffer, mem.ptr_to_bytes(&amp;screen)) assert(err == .None) assert(n_read == size_of(screen)) }  return (ConnectionInformation { resource_id_base = dynamic_response.resource_id_base, resource_id_mask = dynamic_response.resource_id_mask, root_screen = screen, }) }  next_x11_id :: proc(current_id: u32, info: ConnectionInformation) -> u32 { return 1 + ((info.resource_id_mask &amp; (current_id)) | info.resource_id_base) }  x11_create_graphical_context :: proc(socket: os.Socket, gc_id: u32, root_id: u32) { opcode: u8 : 55 FLAG_GC_BG: u32 : 8 BITMASK: u32 : FLAG_GC_BG VALUE1: u32 : 0x00_00_ff_00  Request :: struct #packed { opcode:   u8, pad1:     u8, length:   u16, id:       u32, drawable: u32, bitmask:  u32, value1:   u32, } request := Request { opcode   = opcode, length   = 5, id       = gc_id, drawable = root_id, bitmask  = BITMASK, value1   = VALUE1, }  { n_sent, err := os.send(socket, mem.ptr_to_bytes(&amp;request), 0) assert(err == os.ERROR_NONE) assert(n_sent == size_of(Request)) } }  x11_create_window :: proc( socket: os.Socket, window_id: u32, parent_id: u32, x: u16, y: u16, width: u16, height: u16, root_visual_id: u32, ) { FLAG_WIN_BG_PIXEL: u32 : 2 FLAG_WIN_EVENT: u32 : 0x800 FLAG_COUNT: u16 : 2 EVENT_FLAG_EXPOSURE: u32 = 0x80_00 EVENT_FLAG_KEY_PRESS: u32 = 0x1 EVENT_FLAG_KEY_RELEASE: u32 = 0x2 EVENT_FLAG_BUTTON_PRESS: u32 = 0x4 EVENT_FLAG_BUTTON_RELEASE: u32 = 0x8 flags: u32 : FLAG_WIN_BG_PIXEL | FLAG_WIN_EVENT depth: u8 : 24 border_width: u16 : 0 CLASS_INPUT_OUTPUT: u16 : 1 opcode: u8 : 1 BACKGROUND_PIXEL_COLOR: u32 : 0x00_ff_ff_00  Request :: struct #packed { opcode:         u8, depth:          u8, request_length: u16, window_id:      u32, parent_id:      u32, x:              u16, y:              u16, width:          u16, height:         u16, border_width:   u16, class:          u16, root_visual_id: u32, bitmask:        u32, value1:         u32, value2:         u32, } request := Request { opcode         = opcode, depth          = depth, request_length = 8 + FLAG_COUNT, window_id      = window_id, parent_id      = parent_id, x              = x, y              = y, width          = width, height         = height, border_width   = border_width, class          = CLASS_INPUT_OUTPUT, root_visual_id = root_visual_id, bitmask        = flags, value1         = BACKGROUND_PIXEL_COLOR, value2         = EVENT_FLAG_EXPOSURE | EVENT_FLAG_BUTTON_RELEASE | EVENT_FLAG_BUTTON_PRESS | EVENT_FLAG_KEY_PRESS | EVENT_FLAG_KEY_RELEASE, }  { n_sent, err := os.send(socket, mem.ptr_to_bytes(&amp;request), 0) assert(err == os.ERROR_NONE) assert(n_sent == size_of(Request)) } }  x11_map_window :: proc(socket: os.Socket, window_id: u32) { opcode: u8 : 8  Request :: struct #packed { opcode:         u8, pad1:           u8, request_length: u16, window_id:      u32, } request := Request { opcode         = opcode, request_length = 2, window_id      = window_id, } { n_sent, err := os.send(socket, mem.ptr_to_bytes(&amp;request), 0) assert(err == os.ERROR_NONE) assert(n_sent == size_of(Request)) }  }  x11_put_image :: proc( socket: os.Socket, drawable_id: u32, gc_id: u32, width: u16, height: u16, dst_x: u16, dst_y: u16, depth: u8, data: []u8, ) { opcode: u8 : 72  Request :: struct #packed { opcode:         u8, format:         u8, request_length: u16, drawable_id:    u32, gc_id:          u32, width:          u16, height:         u16, dst_x:          u16, dst_y:          u16, left_pad:       u8, depth:          u8, pad1:           u16, }  data_length_padded := round_up_4(cast(u32)len(data))  request := Request { opcode         = opcode, format         = 2, \/\/ ZPixmap request_length = cast(u16)(6 + data_length_padded \/ 4), drawable_id    = drawable_id, gc_id          = gc_id, width          = width, height         = height, dst_x          = dst_x, dst_y          = dst_y, depth          = depth, } { padding_len := data_length_padded - cast(u32)len(data)  n_sent, err := linux.writev( cast(linux.Fd)socket, []linux.IO_Vec { {base = &amp;request, len = size_of(Request)}, {base = raw_data(data), len = len(data)}, {base = raw_data(data), len = cast(uint)padding_len}, }, ) assert(err == .NONE) assert(n_sent == size_of(Request) + len(data) + cast(int)padding_len) } }  render :: proc(socket: os.Socket, scene: ^Scene) { for entity, i in scene.displayed_entities { rect := ASSET_COORDINATES[entity] row, column := idx_to_row_column(i)  x11_copy_area( socket, scene.sprite_pixmap_id, scene.window_id, scene.gc_id, rect.x, rect.y, cast(u16)column * ENTITIES_WIDTH, cast(u16)row * ENTITIES_HEIGHT, ENTITIES_WIDTH, ENTITIES_HEIGHT, ) } }  ENTITIES_ROW_COUNT :: 16 ENTITIES_COLUMN_COUNT :: 16 ENTITIES_WIDTH :: 16 ENTITIES_HEIGHT :: 16  Scene :: struct { window_id:          u32, gc_id:              u32, sprite_pixmap_id:   u32, displayed_entities: [ENTITIES_ROW_COUNT * ENTITIES_COLUMN_COUNT]Entity_kind, \/\/ TODO: Bitfield? mines:              [ENTITIES_ROW_COUNT * ENTITIES_COLUMN_COUNT]bool, }  wait_for_x11_events :: proc(socket: os.Socket, scene: ^Scene) { GenericEvent :: struct #packed { code: u8, pad:  [31]u8, } assert(size_of(GenericEvent) == 32)  KeyReleaseEvent :: struct #packed { code:            u8, detail:          u8, sequence_number: u16, time:            u32, root_id:         u32, event:           u32, child_id:        u32, root_x:          u16, root_y:          u16, event_x:         u16, event_y:         u16, state:           u16, same_screen:     bool, pad1:            u8, } assert(size_of(KeyReleaseEvent) == 32)  ButtonReleaseEvent :: struct #packed { code:        u8, detail:      u8, seq_number:  u16, timestamp:   u32, root:        u32, event:       u32, child:       u32, root_x:      u16, root_y:      u16, event_x:     u16, event_y:     u16, state:       u16, same_screen: bool, pad1:        u8, } assert(size_of(ButtonReleaseEvent) == 32)  EVENT_EXPOSURE: u8 : 0xc EVENT_KEY_RELEASE: u8 : 0x3 EVENT_BUTTON_RELEASE: u8 : 0x5  KEYCODE_ENTER: u8 : 36  for { generic_event := GenericEvent{} n_recv, err := os.recv(socket, mem.ptr_to_bytes(&amp;generic_event), 0) if err == os.EPIPE || n_recv == 0 { os.exit(0) \/\/ The end. }  assert(err == os.ERROR_NONE) assert(n_recv == size_of(GenericEvent))  switch generic_event.code { case EVENT_EXPOSURE: render(socket, scene)  case EVENT_KEY_RELEASE: event := transmute(KeyReleaseEvent)generic_event if event.detail == KEYCODE_ENTER { reset(scene) render(socket, scene) }  case EVENT_BUTTON_RELEASE: event := transmute(ButtonReleaseEvent)generic_event on_cell_clicked(event.event_x, event.event_y, scene) render(socket, scene) } } }  reset :: proc(scene: ^Scene) { for &amp;entity in scene.displayed_entities { entity = .Covered }  for &amp;mine in scene.mines { mine = rand.choice([]bool{true, false, false, false}) } }  x11_copy_area :: proc( socket: os.Socket, src_id: u32, dst_id: u32, gc_id: u32, src_x: u16, src_y: u16, dst_x: u16, dst_y: u16, width: u16, height: u16, ) { opcode: u8 : 62 Request :: struct #packed { opcode:         u8, pad1:           u8, request_length: u16, src_id:         u32, dst_id:         u32, gc_id:          u32, src_x:          u16, src_y:          u16, dst_x:          u16, dst_y:          u16, width:          u16, height:         u16, }  request := Request { opcode         = opcode, request_length = 7, src_id         = src_id, dst_id         = dst_id, gc_id          = gc_id, src_x          = src_x, src_y          = src_y, dst_x          = dst_x, dst_y          = dst_y, width          = width, height         = height, } { n_sent, err := os.send(socket, mem.ptr_to_bytes(&amp;request), 0) assert(err == os.ERROR_NONE) assert(n_sent == size_of(Request)) } }  on_cell_clicked :: proc(x: u16, y: u16, scene: ^Scene) { idx, row, column := locate_entity_by_coordinate(x, y)  mined := scene.mines[idx]  if mined { scene.displayed_entities[idx] = .Mine_exploded \/\/ Lose. uncover_all_cells(&amp;scene.displayed_entities, &amp;scene.mines, .Mine_exploded) } else { visited := [ENTITIES_COLUMN_COUNT * ENTITIES_ROW_COUNT]bool{} uncover_cells_flood_fill(row, column, &amp;scene.displayed_entities, &amp;scene.mines, &amp;visited)  \/\/ Win. if count_remaining_goals(scene.displayed_entities, scene.mines) == 0 { uncover_all_cells(&amp;scene.displayed_entities, &amp;scene.mines, .Mine_idle) } } }  count_remaining_goals :: proc( displayed_entities: [ENTITIES_COLUMN_COUNT * ENTITIES_ROW_COUNT]Entity_kind, mines: [ENTITIES_COLUMN_COUNT * ENTITIES_ROW_COUNT]bool, ) -> int {  covered := 0  for entity in displayed_entities { covered += cast(int)(entity == .Covered) }  mines_count := 0  for mine in mines { mines_count += cast(int)mine }  return covered - mines_count }  uncover_all_cells :: proc( displayed_entities: ^[ENTITIES_COLUMN_COUNT * ENTITIES_ROW_COUNT]Entity_kind, mines: ^[ENTITIES_ROW_COUNT * ENTITIES_COLUMN_COUNT]bool, shown_mine: Entity_kind, ) { for &amp;entity, i in displayed_entities { if mines[i] { entity = shown_mine } else { row, column := idx_to_row_column(i) mines_around_count := count_mines_around_cell(row, column, mines[:]) assert(mines_around_count &lt;= 8)  entity = cast(Entity_kind)(cast(int)Entity_kind.Uncovered_0 + mines_around_count) } } }  uncover_cells_flood_fill :: proc( row: int, column: int, displayed_entities: ^[ENTITIES_COLUMN_COUNT * ENTITIES_ROW_COUNT]Entity_kind, mines: ^[ENTITIES_ROW_COUNT * ENTITIES_COLUMN_COUNT]bool, visited: ^[ENTITIES_COLUMN_COUNT * ENTITIES_ROW_COUNT]bool, ) { i := row_column_to_idx(row, column) if visited[i] {return}  visited[i] = true  \/\/ Do not uncover covered mines. if mines[i] {return}  if displayed_entities[i] != .Covered {return}  \/\/ Uncover cell.  mines_around_count := count_mines_around_cell(row, column, mines[:]) assert(mines_around_count &lt;= 8)  displayed_entities[i] = cast(Entity_kind)(cast(int)Entity_kind.Uncovered_0 + mines_around_count)  \/\/ Uncover neighbors.  \/\/ Up. if !(row == 0) { uncover_cells_flood_fill(row - 1, column, displayed_entities, mines, visited) }  \/\/ Right if !(column == (ENTITIES_COLUMN_COUNT - 1)) { uncover_cells_flood_fill(row, column + 1, displayed_entities, mines, visited) }  \/\/ Bottom. if !(row == (ENTITIES_ROW_COUNT - 1)) { uncover_cells_flood_fill(row + 1, column, displayed_entities, mines, visited) }  \/\/ Left. if !(column == 0) { uncover_cells_flood_fill(row, column - 1, displayed_entities, mines, visited) } }  idx_to_row_column :: #force_inline proc(i: int) -> (int, int) { column := i % ENTITIES_COLUMN_COUNT row := i \/ ENTITIES_ROW_COUNT  return row, column }  row_column_to_idx :: #force_inline proc(row: int, column: int) -> int { return cast(int)row * ENTITIES_COLUMN_COUNT + cast(int)column }  count_mines_around_cell :: proc(row: int, column: int, displayed_entities: []bool) -> int { \/\/ TODO: Pad the border to elide all bound checks?  up_left := row == 0 || column == 0 \\ ? false \\ : displayed_entities[row_column_to_idx(row - 1, column - 1)] up := row == 0 ? false : displayed_entities[row_column_to_idx(row - 1, column)] up_right := row == 0 || column == (ENTITIES_COLUMN_COUNT - 1) \\ ? false \\ : displayed_entities[row_column_to_idx(row - 1, column + 1)] right := column == (ENTITIES_COLUMN_COUNT - 1) \\ ? false \\ : displayed_entities[row_column_to_idx(row, column + 1)] bottom_right := row == (ENTITIES_ROW_COUNT - 1) || column == (ENTITIES_COLUMN_COUNT - 1) \\ ? false \\ : displayed_entities[row_column_to_idx(row + 1, column + 1)] bottom := row == (ENTITIES_ROW_COUNT - 1) \\ ? false \\ : displayed_entities[row_column_to_idx(row + 1, column)] bottom_left := column == 0 || row == (ENTITIES_COLUMN_COUNT - 1) \\ ? false \\ : displayed_entities[row_column_to_idx(row + 1, column - 1)] left := column == 0 ? false : displayed_entities[row_column_to_idx(row, column - 1)]   return( cast(int)up_left + cast(int)up + cast(int)up_right + cast(int)right + cast(int)bottom_right + cast(int)bottom + cast(int)bottom_left + cast(int)left \\ ) }  locate_entity_by_coordinate :: proc(win_x: u16, win_y: u16) -> (idx: int, row: int, column: int) { column = cast(int)win_x \/ ENTITIES_WIDTH row = cast(int)win_y \/ ENTITIES_HEIGHT  idx = row_column_to_idx(row, column)  return idx, row, column }  x11_create_pixmap :: proc( socket: os.Socket, window_id: u32, pixmap_id: u32, width: u16, height: u16, depth: u8, ) { opcode: u8 : 53  Request :: struct #packed { opcode:         u8, depth:          u8, request_length: u16, pixmap_id:      u32, drawable_id:    u32, width:          u16, height:         u16, }  request := Request { opcode         = opcode, depth          = depth, request_length = 4, pixmap_id      = pixmap_id, drawable_id    = window_id, width          = width, height         = height, }  { n_sent, err := os.send(socket, mem.ptr_to_bytes(&amp;request), 0) assert(err == os.ERROR_NONE) assert(n_sent == size_of(Request)) } }  main :: proc() { png_data := #load(\"sprite.png\") sprite, err := png.load_from_bytes(png_data, {}) assert(err == nil) sprite_data := make([]u8, sprite.height * sprite.width * 4)  \/\/ Convert the image format from the sprite (RGB) into the X11 image format (BGRX). for i := 0; i &lt; sprite.height * sprite.width - 3; i += 1 { sprite_data[i * 4 + 0] = sprite.pixels.buf[i * 3 + 2] \/\/ R -> B sprite_data[i * 4 + 1] = sprite.pixels.buf[i * 3 + 1] \/\/ G -> G sprite_data[i * 4 + 2] = sprite.pixels.buf[i * 3 + 0] \/\/ B -> R sprite_data[i * 4 + 3] = 0 \/\/ pad }  auth_token, _ := load_x11_auth_token(context.temp_allocator)  socket := connect_x11_socket() connection_information := x11_handshake(socket, &amp;auth_token)  gc_id := next_x11_id(0, connection_information) x11_create_graphical_context(socket, gc_id, connection_information.root_screen.id)  window_id := next_x11_id(gc_id, connection_information) x11_create_window( socket, window_id, connection_information.root_screen.id, 200, 200, ENTITIES_COLUMN_COUNT * ENTITIES_WIDTH, ENTITIES_ROW_COUNT * ENTITIES_HEIGHT, connection_information.root_screen.root_visual_id, )  img_depth: u8 = 24 pixmap_id := next_x11_id(window_id, connection_information) x11_create_pixmap( socket, window_id, pixmap_id, cast(u16)sprite.width, cast(u16)sprite.height, img_depth, ) scene := Scene { window_id        = window_id, gc_id            = gc_id, sprite_pixmap_id = pixmap_id, } reset(&amp;scene)  x11_put_image( socket, scene.sprite_pixmap_id, scene.gc_id, cast(u16)sprite.width, cast(u16)sprite.height, 0, 0, img_depth, sprite_data, )  x11_map_window(socket, window_id)  wait_for_x11_events(socket, &amp;scene) }   @(test) test_round_up_4 :: proc(_: ^testing.T) { assert(round_up_4(0) == 0) assert(round_up_4(1) == 4) assert(round_up_4(2) == 4) assert(round_up_4(3) == 4) assert(round_up_4(4) == 4) assert(round_up_4(5) == 8) assert(round_up_4(6) == 8) assert(round_up_4(7) == 8) assert(round_up_4(8) == 8) }  @(test) test_count_mines_around_cell :: proc(_: ^testing.T) { { mines := [ENTITIES_ROW_COUNT * ENTITIES_COLUMN_COUNT]bool{} mines[row_column_to_idx(0, 0)] = true mines[row_column_to_idx(0, 1)] = true mines[row_column_to_idx(0, 2)] = true mines[row_column_to_idx(1, 2)] = true mines[row_column_to_idx(2, 2)] = true mines[row_column_to_idx(2, 1)] = true mines[row_column_to_idx(2, 0)] = true mines[row_column_to_idx(1, 0)] = true  assert(count_mines_around_cell(1, 1, mines[:]) == 8) } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041a\u0441\u0442\u0430\u0442\u0438, \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u00ab\u0421\u0430\u043f\u0451\u0440\u00bb, \u0435\u0441\u0442\u044c \u0435\u0449\u0451 \u043e\u0434\u043d\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0430\u00a0\u044d\u0442\u0443 \u0442\u0435\u043c\u0443. <a href=\"https:\/\/habr.com\/ru\/companies\/cloud4y\/articles\/487052\/\">Kaboom: \u043d\u0435\u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0441\u0430\u043f\u0451\u0440<\/a>. \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430\u00a0\u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435! \u0412\u0430\u0448 <a href=\"https:\/\/www.cloud4y.ru\/\">Cloud4Y<\/a>. <\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/824610\/\"> https:\/\/habr.com\/ru\/articles\/824610\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041d\u0435\u0434\u0430\u0432\u043d\u043e \u044f \u043d\u0430\u0442\u043a\u043d\u0443\u043b\u0441\u044f \u043d\u0430\u00a0\u0443\u0434\u0438\u0432\u0438\u0432\u0448\u0435\u0435 \u043c\u0435\u043d\u044f <a href=\"https:\/\/tech.lgbt\/@nina_kali_nina\/112594910070716090\">\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435<\/a>. \u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u00ab\u0421\u0430\u043f\u0451\u0440\u00bb \u043e\u0442\u00a0Microsoft \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0440\u0435\u043a\u043b\u0430\u043c\u0443, \u043f\u043b\u0430\u0442\u043d\u044b\u0435 \u043e\u043f\u0446\u0438\u0438 \u0438 \u0432\u0435\u0441\u0438\u0442 235\u00a0\u041c\u0411, \u0442\u0440\u0435\u0431\u0443\u044f \u043d\u0435\u00a0\u043c\u0435\u043d\u044c\u0448\u0435 500\u00a0\u041c\u0411 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u044b. \u0414\u0430, \u0432\u044b \u043d\u0435\u00a0\u043e\u0441\u043b\u044b\u0448\u0430\u043b\u0438\u0441\u044c. \u0423\u00a0\u043d\u044b\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u00ab\u0421\u0430\u043f\u0451\u0440\u0430\u00bb \u0435\u0441\u0442\u044c \u0440\u0435\u043a\u043b\u0430\u043c\u043d\u043e\u0435 \u043e\u043a\u043e\u0448\u043a\u043e \u0441\u0431\u043e\u043a\u0443, \u0430\u00a0\u0435\u0449\u0451 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0440\u0435\u043a\u043b\u0430\u043c\u0443 \u0434\u043b\u044f\u00a0\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0431\u043e\u043d\u0443\u0441\u043e\u0432 \u0432\u00a0\u0438\u0433\u0440\u0435. <\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0418 \u0442\u043e\u0433\u0434\u0430 \u044f \u043f\u043e\u0434\u0443\u043c\u0430\u043b, \u0447\u0442\u043e\u00a0\u0431\u044b\u043b\u043e\u00a0\u0431\u044b \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u00a0\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c. \u0412\u043e\u0441\u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u0443\u043b\u044c\u0442\u043e\u0432\u0443\u044e \u0432\u0438\u0434\u0435\u043e\u0438\u0433\u0440\u0443 \u00ab\u0421\u0430\u043f\u0451\u0440\u00bb \u0441\u00a0\u043d\u0443\u043b\u044f. \u0421\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0433\u0430\u0431\u0430\u0439\u0442 \u0431\u0443\u0434\u0435\u0442 \u0432\u0435\u0441\u0438\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u0430\u044f \u0438\u0433\u0440\u0430? \u041d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044d\u0442\u043e \u0441\u043b\u043e\u0436\u043d\u043e? \u041c\u043e\u0436\u0435\u0442\u00a0\u043b\u0438 \u043b\u044e\u0431\u0438\u0442\u0435\u043b\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0437\u0430\u00a0\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u043e\u0432?<\/p>\n<p>\u0413\u0435\u0439\u043c\u043f\u043b\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u043c. Enter \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0438\u0433\u0440\u0443, \u0430  \u0434\u043b\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u044f\u0447\u0435\u0439\u043a\u0438 \u043f\u043e\u0434\u00a0\u043a\u0443\u0440\u0441\u043e\u0440\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0436\u0430\u0442\u044c \u043b\u044e\u0431\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443 \u043c\u044b\u0448\u0438.<\/p>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/667d0d6bee68229db64cfa01\" data-style=\"\" id=\"667d0d6bee68229db64cfa01\" width=\"\"><\/div>\n<figure class=\"full-width\"><\/figure>\n<p>\u0412\u00a0\u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0439 \u0444\u0430\u0439\u043b \u043e\u0431\u044a\u0451\u043c\u043e\u043c ~ 300\u00a0\u041a\u0431\u0430\u0439\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u00a0\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043c ~ 1\u00a0\u041c\u0431 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438. \u042d\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0432\u00a0\u0442\u044b\u0441\u044f\u0447\u0443 \u0440\u0430\u0437 \u043c\u0435\u043d\u044c\u0448\u0435, \u0447\u0435\u043c \u0443\u00a0Microsoft. \u0418 \u044d\u0442\u043e \u0432\u0441\u0435\u0433\u043e\u00a0\u043b\u0438\u0448\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0442\u0435\u043d \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430. <\/p>\n<p>\u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0432\u00a0\u0442\u043e\u043c, \u0447\u0442\u043e\u00a0\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043a\u0440\u043e\u0448\u0435\u0447\u043d\u044b\u043c \u0438 \u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u044b\u043c: \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0435 \u0441\u00a0\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u043c\u0438 \u0431\u0438\u0442\u0430\u043c\u0438 libC, \u043e\u043d\u043e \u043c\u043e\u0436\u0435\u0442\u00a0\u0431\u044b\u0442\u044c \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0432\u00a0\u043b\u044e\u0431\u043e\u0439 Unix \u0438 \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u043f\u043e\u0432\u0441\u044e\u0434\u0443, \u0438 \u043e\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430\u00a0\u043b\u044e\u0431\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435 (\u0441 \u0442\u043e\u0439\u00a0\u0436\u0435 \u041e\u0421\/\u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043e\u0439). \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f \u0434\u0430\u0436\u0435 \u043d\u0430\u00a0\u0441\u0442\u0430\u0440\u044b\u0445 Linux 20-\u043b\u0435\u0442\u043d\u0435\u0439 \u0434\u0430\u0432\u043d\u043e\u0441\u0442\u0438. <\/p>\n<p>\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0438\u0433\u0440\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f <a href=\"https:\/\/github.com\/gaultier\/minesweeper-from-scratch\">\u0437\u0434\u0435\u0441\u044c<\/a>. \u041d\u043e\u00a0\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043d\u0430\u0448 \u043a\u043e\u0434.<\/p>\n<h3>\u0427\u0442\u043e \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c<\/h3>\n<p>11-\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 X \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u043d\u0430\u00a0\u0441\u0432\u0435\u0442 \u0432 1987\u00a0\u0433\u043e\u0434\u0443 \u0438 \u0441\u00a0\u0442\u0435\u0445 \u043f\u043e\u0440 \u043d\u0435\u00a0\u043c\u0435\u043d\u044f\u043b\u0430\u0441\u044c. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043d\u0430\u00a0\u0434\u0435\u0441\u044f\u0442\u044c \u043b\u0435\u0442 \u0440\u0430\u043d\u044c\u0448\u0435 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043e\u0432, \u0435\u0433\u043e \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0430\u00a0\u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043d\u0435\u00a0\u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u0430\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u044b\u043c \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c. \u0422\u0435\u043c \u043d\u0435\u00a0\u043c\u0435\u043d\u0435\u0435, \u043e\u043d \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u043e\u0432\u0441\u044e\u0434\u0443. \u0412\u00a0\u043b\u044e\u0431\u043e\u0439 Unix \u0435\u0441\u0442\u044c X\u2011\u0441\u0435\u0440\u0432\u0435\u0440, \u0434\u0430\u0436\u0435 \u0432\u00a0macOS \u0441\u00a0XQuartz, \u0438 \u0442\u0435\u043f\u0435\u0440\u044c Windows \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 Linux \u0441\u00a0\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c \u0432\u043d\u0443\u0442\u0440\u0438 WALL! X11\u00a0\u0435\u0449\u0451 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u00a0\u0431\u044b\u043b \u0442\u0430\u043a\u0438\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c. <\/p>\n<p>\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442, \u0430\u00a0\u043f\u043e\u0440\u043e\u0433 \u0432\u0445\u043e\u0434\u0430 \u043d\u0435\u0432\u044b\u0441\u043e\u043a: \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u043a\u0435\u0442, \u0438 \u043c\u044b \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u044b. \u0410\u00a0\u0434\u043b\u044f 2D\u2011\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0435\u00a0\u043d\u0443\u0436\u043d\u043e\u00a0\u0431\u044b\u0442\u044c \u043c\u0430\u0441\u0442\u0435\u0440\u043e\u043c Vulkan \u0438\u043b\u0438\u00a0\u0434\u0430\u0436\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441\u00a0\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043e\u043c. \u0427\u0435\u0440\u0442 \u0432\u043e\u0437\u044c\u043c\u0438, \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0434\u0430\u0436\u0435 \u0431\u0435\u0437\u00a0\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430!<\/p>\n<p>\u0412\u00a0\u043d\u0430\u0448\u0438 \u0434\u043d\u0438 \u0432\u0441\u0435, \u043a\u0442\u043e \u043f\u0438\u0448\u0435\u0442 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 <s>\u0447\u0440\u0435\u0437\u043c\u0435\u0440\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u044b<\/s>\u0445 \u0443\u0432\u0430\u0436\u0430\u0435\u043c\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a libX11\u00a0\u0438 libxcb \u0438 \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u044f Qt \u0438 SDL.<\/p>\n<p>\u0412\u043e\u0442 \u0447\u0442\u043e\u00a0\u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c:<\/p>\n<ul>\n<li>\n<p>\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u043e\u043a\u043d\u043e<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 (\u043e\u0434\u0438\u043d \u0441\u043f\u0440\u0430\u0439\u0442 \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438)<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u0438 \u0441\u043f\u0440\u0430\u0439\u0442\u0430 \u0432\u00a0\u043e\u043a\u043d\u0435<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u00a0\u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u044b\/\u043c\u044b\u0448\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0441\u0451. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435: \u043a\u0430\u0436\u0434\u044b\u0439 \u0448\u0430\u0433\u00a0\u2014 \u044d\u0442\u043e 1\u20133\u00a0\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f X11, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c,\u00a0\u2014 \u044d\u0442\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043b\u0430\u0432\u0438\u0448 \u0438 \u043c\u044b\u0448\u0438.<\/p>\n<p>\u041f\u0438\u0441\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u043d\u0430 <a href=\"https:\/\/odin-lang.org\/\">\u044f\u0437\u044b\u043a\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Odin<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f. \u041d\u043e\u00a0\u0435\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c C \u0438\u043b\u0438\u00a0\u0447\u0442\u043e\u2011\u0442\u043e \u0435\u0449\u0435, \u0434\u0435\u0440\u0437\u0430\u0439\u0442\u0435. \u0412\u0441\u0435, \u0447\u0442\u043e\u00a0\u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e,\u00a0\u2014 \u044d\u0442\u043e \u0443\u043c\u0435\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0441\u043e\u043a\u0435\u0442 Unix, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043f\u043e\u00a0\u043d\u0435\u043c\u0443 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0432\u00a0\u043f\u0430\u043c\u044f\u0442\u044c. \u0414\u043b\u044f\u00a0\u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u043e\u0440\u043c\u0430\u0442 PNG, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0432\u00a0\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 Odin \u0435\u0441\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 PNG. \u041d\u043e\u00a0\u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u043e\u0440\u043c\u0430\u0442 PPM (\u044f \u043f\u0440\u043e\u0434\u0435\u043b\u044b\u0432\u0430\u043b <a href=\"https:\/\/gaultier.github.io\/blog\/wayland_from_scratch.html\">\u043d\u0435\u0447\u0442\u043e \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0435<\/a> \u0441\u00a0Wayland), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043b\u0435\u0433\u043a\u043e \u043f\u043e\u0434\u0434\u0430\u0451\u0442\u0441\u044f \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u043c\u0443 \u0430\u043d\u0430\u043b\u0438\u0437\u0443. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 Odin \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0438 \u0442\u043e, \u0438 \u0434\u0440\u0443\u0433\u043e\u0435 \u0432\u00a0\u0441\u0432\u043e\u0435\u0439 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435, \u0432\u044b\u0431\u043e\u0440 \u043d\u0435\u00a0\u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. \u042f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0441\u044f \u043d\u0430\u00a0PNG, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043e\u043d \u0431\u043e\u043b\u0435\u0435 \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0447\u0435\u043d. <\/p>\n<p>\u041c\u043d\u043e\u0433\u0438\u0435 \u0432\u0435\u0449\u0438 \u0432\u00a0X11\u00a0\u043d\u0435\u00a0\u0437\u0430\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b. \u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f\u00a0X11, \u0434\u0430\u0436\u0435 \u0441\u00a0\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043c\u043e\u0436\u0435\u0442 \u0441\u0442\u0430\u0442\u044c \u0445\u043e\u0440\u043e\u0448\u0438\u043c \u0443\u0447\u0435\u0431\u043d\u044b\u043c \u043f\u043e\u0441\u043e\u0431\u0438\u0435\u043c. \u041d\u0443, \u0438\u043b\u0438\u00a0\u0432\u0430\u043c \u043c\u043e\u0436\u0435\u0442\u00a0\u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043a\u0430\u043a\u00a0\u043f\u0440\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0442\u043e\u0442 \u0438\u043b\u0438\u00a0\u0438\u043d\u043e\u0439 \u0442\u0440\u044e\u043a \u0441\u00a0\u043a\u043e\u0434\u043e\u043c. <\/p>\n<h3>\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f<\/h3>\n<p>\u0412\u00a0\u044d\u0442\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 X. \u042d\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441\u00a0\u0442\u0435\u043c, \u0447\u0442\u043e\u00a0\u043f\u0440\u0438\u00a0\u0440\u0430\u0431\u043e\u0442\u0435 \u043f\u043e\u0434\u00a0Wayland \u0441\u00a0XWayland \u0432\u00a0\u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\u0445 \u0440\u0430\u0431\u043e\u0447\u0435\u0433\u043e \u0441\u0442\u043e\u043b\u0430, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a\u00a0Gnome, \u043d\u0430\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e.<\/p>\n<p>\u042d\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043b\u0438\u043d\u043e\u0439 16\u00a0\u0431\u0430\u0439\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432\u00a0\u0444\u0430\u0439\u043b\u0435 \u0432\u00a0\u0434\u043e\u043c\u0430\u0448\u043d\u0435\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0435\u0433\u043e \u0432\u00a0\u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u043f\u043e\u0441\u044b\u043b\u0430\u0435\u043c X\u2011\u0441\u0435\u0440\u0432\u0435\u0440\u0443.<\/p>\n<p>\u042d\u0442\u043e\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <code>MIT-MAGIC-COOKIE-1<\/code>.<\/p>\n<p>\u0417\u0430\u0433\u0432\u043e\u0437\u0434\u043a\u0430 \u0432\u00a0\u0442\u043e\u043c, \u0447\u0442\u043e\u00a0\u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0434\u043b\u044f\u00a0\u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u0432 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u0441\u0435\u0442\u0435\u0432\u044b\u0445 \u0445\u043e\u0441\u0442\u043e\u0432. \u041f\u043e\u043c\u043d\u0438\u0442\u0435, X11\u00a0\u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f\u00a0\u0440\u0430\u0431\u043e\u0442\u044b \u043f\u043e\u00a0\u0441\u0435\u0442\u0438. \u041e\u0434\u043d\u0430\u043a\u043e \u0437\u0434\u0435\u0441\u044c \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043f\u0438\u0441\u044c \u0434\u043b\u044f\u00a0localhost.<\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043f\u043e\u0434\u0443\u043c\u0430\u0442\u044c, \u043f\u043e\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f. \u0412\u00a0\u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c \u0442\u043e, \u0447\u0442\u043e\u00a0\u0434\u0435\u043b\u0430\u0435\u0442 <code>libXau<\/code>. \u0418\u0437\u00a0\u0435\u0433\u043e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438:<\/p>\n<pre><code>The .Xauthority file is a binary file consisting of a sequence of entries in the following format: 2 bytesFamily value (second byte is as in protocol HOST) 2 bytesaddress length (always MSB first) A byteshost address (as in protocol HOST) 2 bytesdisplay \"number\" length (always MSB first) S bytesdisplay \"number\" string 2 bytesname length (always MSB first) N bytesauthorization name string 2 bytesdata length (always MSB first) D bytesauthorization data string<\/code><\/pre>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0438\u043f\u044b \u0438 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b:  <\/p>\n<pre><code>AUTH_ENTRY_FAMILY_LOCAL: u16 : 1 AUTH_ENTRY_MAGIC_COOKIE: string : \"MIT-MAGIC-COOKIE-1\"  AuthToken :: [16]u8  AuthEntry :: struct { family:    u16, auth_name: []u8, auth_data: []u8, }<\/code><\/pre>\n<p>\u041c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u043f\u043e\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0442. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043a\u0430\u0436\u0434\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c:<\/p>\n<pre><code>read_x11_auth_entry :: proc(buffer: ^bytes.Buffer) -> (AuthEntry, bool) { entry := AuthEntry{}  { n_read, err := bytes.buffer_read(buffer, mem.ptr_to_bytes(&amp;entry.family)) if err == .EOF {return {}, false}  assert(err == .None) assert(n_read == size_of(entry.family)) }  address_len: u16 = 0 { n_read, err := bytes.buffer_read(buffer, mem.ptr_to_bytes(&amp;address_len)) assert(err == .None)  address_len = bits.byte_swap(address_len) assert(n_read == size_of(address_len)) }  address := make([]u8, address_len) { n_read, err := bytes.buffer_read(buffer, address) assert(err == .None) assert(n_read == cast(int)address_len) }  display_number_len: u16 = 0 { n_read, err := bytes.buffer_read(buffer, mem.ptr_to_bytes(&amp;display_number_len)) assert(err == .None)  display_number_len = bits.byte_swap(display_number_len) assert(n_read == size_of(display_number_len)) }  display_number := make([]u8, display_number_len) { n_read, err := bytes.buffer_read(buffer, display_number) assert(err == .None) assert(n_read == cast(int)display_number_len) }  auth_name_len: u16 = 0 { n_read, err := bytes.buffer_read(buffer, mem.ptr_to_bytes(&amp;auth_name_len)) assert(err == .None)  auth_name_len = bits.byte_swap(auth_name_len) assert(n_read == size_of(auth_name_len)) }  entry.auth_name = make([]u8, auth_name_len) { n_read, err := bytes.buffer_read(buffer, entry.auth_name) assert(err == .None) assert(n_read == cast(int)auth_name_len) }  auth_data_len: u16 = 0 { n_read, err := bytes.buffer_read(buffer, mem.ptr_to_bytes(&amp;auth_data_len)) assert(err == .None)  auth_data_len = bits.byte_swap(auth_data_len) assert(n_read == size_of(auth_data_len)) }  entry.auth_data = make([]u8, auth_data_len) { n_read, err := bytes.buffer_read(buffer, entry.auth_data) assert(err == .None) assert(n_read == cast(int)auth_data_len) }  return entry, true }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0444\u0430\u0439\u043b\u0435, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0439\u0442\u0438 \u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u0430:<\/p>\n<pre><code>load_x11_auth_token :: proc(allocator := context.allocator) -> (token: AuthToken, ok: bool) { context.allocator = allocator defer free_all(allocator)  filename_env := os.get_env(\"XAUTHORITY\")  filename := len(filename_env) != 0 \\ ? filename_env \\ : filepath.join([]string{os.get_env(\"HOME\"), \".Xauthority\"})  data := os.read_entire_file_from_filename(filename) or_return  buffer := bytes.Buffer{} bytes.buffer_init(&amp;buffer, data[:])   for { auth_entry := read_x11_auth_entry(&amp;buffer) or_break  if auth_entry.family == AUTH_ENTRY_FAMILY_LOCAL &amp;&amp;    slice.equal(auth_entry.auth_name, transmute([]u8)AUTH_ENTRY_MAGIC_COOKIE) &amp;&amp;    len(auth_entry.auth_data) == size_of(AuthToken) {  mem.copy_non_overlapping( raw_data(&amp;token), raw_data(auth_entry.auth_data), size_of(AuthToken), ) return token, true } }      \/\/ Did not find a fitting token. return {}, false }<\/code><\/pre>\n<p>\u0423 Odin \u0435\u0441\u0442\u044c \u0445\u043e\u0440\u043e\u0448\u0435\u0435 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0440\u0430\u043d\u043d\u0435\u0433\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u043e\u0448\u0438\u0431\u043e\u043a:\u00a0<code>or_return<\/code>, \u0447\u0442\u043e \u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442\u043d\u043e\u00a0<code>?<\/code>\u0432 Rust \u0438\u043b\u0438\u00a0<code>try <\/code>\u0432 Zig. \u0422\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0438 \u0441\u00a0<code>or_break<\/code>.<\/p>\n<p>\u0418 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0435\u0433\u043e \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0432\u00a0<code>main<\/code>:<\/p>\n<pre><code>main :: proc() { auth_token, _ := load_x11_auth_token(context.temp_allocator) }<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043c\u044b \u043d\u0435\u00a0\u043d\u0430\u0448\u043b\u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430, \u043d\u0435\u00a0\u0431\u0435\u0434\u0430, \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u043c \u0441\u00a0\u043f\u0443\u0441\u0442\u044b\u043c.<\/p>\n<p>\u041e\u0434\u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f \u0432\u0435\u0449\u044c: \u0432\u00a0Odin, \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e Zig, \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c,\u00a0\u0436\u0435\u043b\u0430\u044e\u0449\u0438\u043c \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c. \u041e\u0434\u043d\u0430\u043a\u043e, \u0432\u00a0\u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442\u00a0Zig, \u0432\u00a0Odin \u0435\u0441\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043c\u0435\u043d\u0435\u0435 \u0443\u0442\u043e\u043c\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c (\u0438, \u043a\u0430\u043a\u00a0\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0435, \u0431\u043e\u043b\u0435\u0435 \u043d\u0435\u044f\u0432\u043d\u044b\u043c), \u043f\u043e\u00a0\u0441\u0443\u0442\u0438, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u0432\u00a0\u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c.<\/p>\n<p>Odin \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043b\u044e\u0431\u0435\u0437\u0435\u043d, \u0447\u0442\u043e\u0431\u044b \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043d\u0430\u043c \u0434\u0432\u0430 \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0440\u0430\u0437\u0443: \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u043e\u0431\u0449\u0435\u0433\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0439 \u0430\u0440\u0435\u043d\u0443.<\/p>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0437\u0430\u043f\u0438\u0441\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043c\u043e\u0433\u0443\u0442\u00a0\u0431\u044b\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438, \u043d\u0430\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432\u044b\u0434\u0435\u043b\u044f\u0442\u044c \u043c\u0435\u0441\u0442\u043e\u00a0\u2014 \u0441\u0442\u0435\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0430\u043a\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430.\u00a0\u0411\u044b\u043b\u043e\u00a0\u0431\u044b \u043f\u0440\u0438\u0441\u043a\u043e\u0440\u0431\u043d\u043e \u043f\u0435\u0440\u0435\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u0442\u0435\u043a \u0438\u0437\u2011\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u00a0\u0438\u043c\u044f \u0445\u043e\u0441\u0442\u0430 \u0432\u00a0\u044d\u0442\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0434\u043b\u0438\u043d\u043d\u044b\u043c.<\/p>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432\u044b \u0441\u043a\u0430\u0436\u0435\u0442\u0435, \u0447\u0442\u043e \u0432\u0441\u0451 \u044d\u0442\u043e \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u0441\u044f \u0432\u00a0\u0441\u0442\u0435\u043a\u0435. \u0414\u0430, \u043d\u043e\u00a0\u044d\u0442\u043e\u00a0\u0431\u044b\u043b\u0430 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u0430\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u0434\u0445\u043e\u0434 Odin \u043a\u00a0\u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u043f\u0430\u043c\u044f\u0442\u044c\u044e.<\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u043c\u044b \u043d\u0435 \u0445\u043e\u0442\u0438\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u043f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f 16-\u0431\u0430\u0439\u0442\u043e\u0432\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c <code>defer free_all(allocator)<\/code>. \u042d\u0442\u043e \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c \u043f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u0438 \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0430\u0442\u044c \u043f\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043a\u0430\u0436\u0434\u043e\u0435 \u043f\u043e\u043b\u0435. \u041c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0430\u0435\u043c \u0432\u0441\u044e \u0430\u0440\u0435\u043d\u0443 \u043e\u0434\u043d\u0438\u043c \u043c\u0430\u0445\u043e\u043c (\u043d\u043e \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u0430\u044f \u043f\u0430\u043c\u044f\u0442\u044c \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u043f\u043e\u0437\u0436\u0435).<\/p>\n<p>\u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u044d\u0442\u043e\u0439 \u0430\u0440\u0435\u043d\u044b \u0437\u0430\u0434\u0430\u0451\u0442 \u0432\u0435\u0440\u0445\u043d\u044e\u044e \u0433\u0440\u0430\u043d\u0438\u0446\u0443 (\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0433\u0430\u0431\u0430\u0439\u0442) \u043d\u0430\u00a0\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f. \u0422\u0430\u043a \u0447\u0442\u043e\u00a0\u0435\u0441\u043b\u0438 \u043e\u0434\u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c \u0432\u00a0\u0444\u0430\u0439\u043b\u0435 \u043e\u0433\u0440\u043e\u043c\u043d\u0430 \u0438\u043b\u0438\u00a0\u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0430, \u043c\u044b \u0442\u043e\u0447\u043d\u043e \u043d\u0435\u00a0\u0441\u043c\u043e\u0436\u0435\u043c \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442 \u043f\u0430\u043c\u044f\u0442\u0438. \u042d\u0442\u043e \u0445\u043e\u0440\u043e\u0448\u0430\u044f \u043d\u043e\u0432\u043e\u0441\u0442\u044c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e\u00a0\u0432\u00a0\u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u041e\u0421 \u043d\u0430\u0447\u043d\u0451\u0442 \u0441\u0432\u043e\u043f\u0438\u043d\u0433<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-380071","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/380071","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=380071"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/380071\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=380071"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=380071"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=380071"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}