{"id":455339,"date":"2025-04-09T21:02:10","date_gmt":"2025-04-09T21:02:10","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=455339"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=455339","title":{"rendered":"<span>[\u0427\u0430\u0441\u0442\u044c 1.5] \u0414\u0435\u043b\u0430\u0435\u043c \u0441\u0432\u043e\u044e 3D \u0438\u0433\u0440\u0443 \u043d\u0430 Python<\/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<blockquote>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0438 \u043c\u043e\u0436\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f! \u041f\u0438\u0448\u0438\u0442\u0435\u0441\u0432\u043e\u0435 \u043c\u043d\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445!<\/p>\n<\/blockquote>\n<h2>\u0414\u0435\u043b\u0430\u0435\u043c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440!<\/h2>\n<p>\u042f \u0445\u043e\u0447\u0443 \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043a\u0430\u0440\u0442 \u0431\u044b \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0438\u0433\u0440\u044b<strong> &#171;Doom II&#187;<\/strong> \u0442\u0430\u043a \u0447\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 \u0441 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u043c \u0432\u043e\u0442 \u0442\u0430\u043a :<\/p>\n<pre><code class=\"python\">import tkinter as tk from tkinter import filedialog, simpledialog  class MapEditor:     def __init__(self, root):         self.root = root         self.root.title(\"Map Editor\")         self.root.geometry(\"800x600\")                  # \u041d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438         self.width = 10         self.height = 8         self.cell_size = 40         self.zoom = 1.0                  self.init_map()         self.create_widgets()         self.bind_events()         self.draw_map()<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0432 \u044d\u0442\u043e\u043c \u043a\u043e\u0434\u0435 \u043c\u044b :<\/p>\n<ul>\n<li>\n<p>\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043a\u0430\u0440\u0442<\/p>\n<\/li>\n<li>\n<p>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u0439 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043d\u0435\u0435 \u0445\u043e\u043b\u0441\u0442 \u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432:<\/p>\n<pre><code class=\"python\">    def create_widgets(self):         # \u0425\u043e\u043b\u0441\u0442 \u0434\u043b\u044f \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u0430\u0440\u0442\u044b         self.canvas = tk.Canvas(             self.root,              bg='#202020',             cursor=\"crosshair\"         )         self.canvas.pack(fill=tk.BOTH, expand=True)                  # \u041f\u0430\u043d\u0435\u043b\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432         self.toolbar = tk.Frame(self.root)         self.toolbar.pack(fill=tk.X)                  # \u041a\u043d\u043e\u043f\u043a\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f         buttons = [             ('New Map', self.new_map, '#555'),             ('Zoom +', lambda: self.change_zoom(0.1), '#777'),             ('Zoom -', lambda: self.change_zoom(-0.1), '#777'),             ('Save', self.save_map, '#388E3C'),             ('Load', self.load_map, '#1976D2')         ]                  for text, cmd, color in buttons:             btn = tk.Button(                 self.toolbar,                 text=text,                 command=cmd,                 bg=color,                 fg='white',                 padx=8,                 pady=4             )             btn.pack(side=tk.LEFT, padx=2, pady=2)<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u0435:<\/summary>\n<div class=\"spoiler__content\">\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0445\u043e\u043b\u0441\u0442 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043a\u0430\u0440\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0430\u043d\u0435\u043b\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0441 \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0442\u0438\u043b\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<p>\u041d\u0443 \u0447\u0442\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043d\u0430\u0448\u0443 \u043a\u0430\u0440\u0442\u0443 \u0441\u0445\u0435\u043c\u0443 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0430\u043c\u0438\u0445 \u043a\u0430\u0440\u0442! \u041d\u0430\u043f\u043e\u043c\u043d\u044e \u0432\u043e\u0442-\u0442\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0430\u0448\u0430 \u043a\u0430\u0440\u0442\u0430 \u0432 \u0444\u0430\u0439\u043b\u0435 map.txt:<\/p>\n<pre><code>8 WWWWWWWWWW W        W W WW  WW W W WW     W W        W W     WW W W        W WWWWWWWWWW<\/code><\/pre>\n<p>\u0418 \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u043b\u044f \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0442\u0438\u043b\u044f \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0432 <code><strong>ROOM1.map<\/strong><\/code><strong> <\/strong>!<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043f\u043e\u0439\u043b\u0435\u0440<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041a\u0430\u043a \u0432\u044b \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435 \u043f\u043e\u043d\u044f\u043b\u0438 \u044f \u043d\u0430\u0437\u0432\u0430\u043b \u0435\u0433\u043e<code><strong>ROOM1<\/strong><\/code> \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043a\u043e\u043c\u043d\u0430\u0442 \u0438 \u043c\u044b \u0434\u0430\u0436\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0446\u0435\u043b\u043e\u0435 \u043c\u0435\u043d\u044e !<\/p>\n<\/div>\n<\/details>\n<p>\u0412\u043e\u0442 \u0438 \u0441\u0430\u043c \u043a\u043e\u0434 :<\/p>\n<pre><code class=\"python\">    def init_map(self):         \"\"\"\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u043e\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u044b \u0441 \u0433\u0440\u0430\u043d\u0438\u0446\u0430\u043c\u0438\"\"\"         self.map_data = [[' ' for _ in range(self.width)] for _ in range(self.height)]                  # \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0433\u0440\u0430\u043d\u0438\u0446         for x in range(self.width):             self.map_data[0][x] = 'W'             self.map_data[-1][x] = 'W'         for y in range(self.height):             self.map_data[y][0] = 'W'             self.map_data[y][-1] = 'W'      def draw_map(self):         \"\"\"\u041e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0430 \u043a\u0430\u0440\u0442\u044b \u043d\u0430 \u0445\u043e\u043b\u0441\u0442\u0435\"\"\"         self.canvas.delete(\"all\")         cell = self.cell_size * self.zoom                  for y in range(self.height):             for x in range(self.width):                 color = self.get_color(self.map_data[y][x])                 x0 = x * cell                 y0 = y * cell                 self.canvas.create_rectangle(                     x0, y0, x0 + cell, y0 + cell,                     fill=color,                     outline='#333',                     tags=(\"cell\", f\"{x},{y}\")                 )      def get_color(self, cell):         \"\"\"\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0446\u0432\u0435\u0442 \u0434\u043b\u044f \u0442\u0438\u043f\u0430 \u044f\u0447\u0435\u0439\u043a\u0438\"\"\"         return {             'W': '#4A4A4A',  # \u0421\u0442\u0435\u043d\u0430             '.': '#6B6B6B',  # \u041f\u043e\u043b             ' ': '#202020'    # \u041f\u0443\u0441\u0442\u043e\u0442\u0430         }.get(cell, '#202020')<\/code><\/pre>\n<p>\u041d\u0443 \u0447\u0442\u043e-\u0436\u0435 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0432\u044b\u0448\u0435\u0434\u0448\u0438\u0439 \u0443 \u043d\u0430\u0441 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440! \u041d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0449\u0435 \u0447\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u043a\u043e\u0434\u0430 \u0438 \u043c\u0430\u0433\u0438\u0438 <code>\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439<\/code>!<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">    def bind_events(self):         \"\"\"\u041f\u0440\u0438\u0432\u044f\u0437\u043a\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0441\u043e\u0431\u044b\u0442\u0438\u0439\"\"\"         # \u041c\u044b\u0448\u044c         self.canvas.bind(\"&lt;Button-1&gt;\", self.draw)         self.canvas.bind(\"&lt;B1-Motion&gt;\", self.draw)         self.canvas.bind(\"&lt;Button-3&gt;\", self.erase)         self.canvas.bind(\"&lt;B3-Motion&gt;\", self.erase)                  # \u041a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u0430         self.root.bind(\"&lt;plus&gt;\", lambda e: self.change_zoom(0.1))         self.root.bind(\"&lt;minus&gt;\", lambda e: self.change_zoom(-0.1))      def draw(self, event):         \"\"\"\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u041b\u041a\u041c\"\"\"         x, y = self.get_cell_coords(event.x, event.y)         if self.is_valid_cell(x, y):             self.map_data[y][x] = 'W'             self.draw_map()      def erase(self, event):         \"\"\"\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u0442\u0438\u0440\u0430\u043d\u0438\u044f \u041f\u041a\u041c\"\"\"         x, y = self.get_cell_coords(event.x, event.y)         if self.is_valid_cell(x, y):             self.map_data[y][x] = ' '             self.draw_map()<\/code><\/pre>\n<pre><code class=\"python\">    def change_zoom(self, delta):         \"\"\"\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0430\"\"\"         self.zoom = max(0.5, min(2.0, self.zoom + delta))         self.draw_map()      def new_map(self):         \"\"\"\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u044b\"\"\"         new_width = simpledialog.askinteger(\"New Map\", \"Width:\",                                            minvalue=5, maxvalue=50)         new_height = simpledialog.askinteger(\"New Map\", \"Height:\",                                             minvalue=5, maxvalue=50)         if new_width and new_height:             self.width = new_width             self.height = new_height             self.init_map()             self.draw_map()      def save_map(self):         \"\"\"\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043a\u0430\u0440\u0442\u044b \u0432 \u0444\u0430\u0439\u043b\"\"\"         file_path = filedialog.asksaveasfilename(             defaultextension=\".map\",             filetypes=[(\"Map files\", \"*.map\")]         )         if file_path:             with open(file_path, 'w') as f:                 f.write(f\"{self.height}\\n\")                 for row in self.map_data:                     f.write(''.join(row).ljust(self.width, ' ') + '\\n')      def load_map(self):         \"\"\"\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043a\u0430\u0440\u0442\u044b \u0438\u0437 \u0444\u0430\u0439\u043b\u0430\"\"\"         file_path = filedialog.askopenfilename(             filetypes=[(\"Map files\", \"*.map\")]         )         if file_path:             with open(file_path, 'r') as f:                 lines = [line.strip() for line in f.readlines()]                 self.height = int(lines[0])                 self.map_data = [list(line.ljust(self.width, ' ')[:self.width]                                 for line in lines[1:self.height+1]]                 self.draw_map()<\/code><\/pre>\n<\/div>\n<\/details>\n<h2>\u0418\u0442\u043e\u0433!<\/h2>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0441\u0432\u043e\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0443\u0440\u043e\u0432\u043d\u0435\u0439! \u041d\u0443 \u0432\u043e\u0442 \u0438 \u0435\u0433\u043e \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7ac\/f20\/932\/7acf20932ff9fee2356dbb7e167886eb.png\" alt=\"Map editor.\" title=\"Map editor.\" width=\"802\" height=\"632\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/7ac\/f20\/932\/7acf20932ff9fee2356dbb7e167886eb.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7ac\/f20\/932\/7acf20932ff9fee2356dbb7e167886eb.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>Map editor.<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fb3\/a27\/419\/fb3a27419015902c9bb15dfb5d4ff1aa.png\" alt=\"\u0412\u043e\u0442 \u043c\u043e\u044f \u043a\u0430\u0440\u0442\u0430\" title=\"\u0412\u043e\u0442 \u043c\u043e\u044f \u043a\u0430\u0440\u0442\u0430\" width=\"802\" height=\"632\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/fb3\/a27\/419\/fb3a27419015902c9bb15dfb5d4ff1aa.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fb3\/a27\/419\/fb3a27419015902c9bb15dfb5d4ff1aa.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0412\u043e\u0442 \u043c\u043e\u044f \u043a\u0430\u0440\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<details class=\"spoiler\">\n<summary>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u044b<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/613\/c2c\/189\/613c2c18960befa0b4a2788b003bdcc6.gif\" width=\"802\" height=\"632\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/613\/c2c\/189\/613c2c18960befa0b4a2788b003bdcc6.gif 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/613\/c2c\/189\/613c2c18960befa0b4a2788b003bdcc6.gif 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/898\/d99\/afb\/898d99afbcedfc99ae0e6061ed40b49f.gif\" alt=\"\u0414\u0435\u043b\u0430\u044e \u043a\u0430\u0440\u0442\u0443 :)\" title=\"\u0414\u0435\u043b\u0430\u044e \u043a\u0430\u0440\u0442\u0443 :)\" width=\"802\" height=\"632\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/898\/d99\/afb\/898d99afbcedfc99ae0e6061ed40b49f.gif 780w,&#10;       https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/898\/d99\/afb\/898d99afbcedfc99ae0e6061ed40b49f.gif 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0414\u0435\u043b\u0430\u044e \u043a\u0430\u0440\u0442\u0443 \ud83d\ude42<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p><strong>\u041d\u0443 \u0447\u0442\u043e-\u0436\u0435 \u0441\u043f\u0430\u0441\u0438\u0431\u043e \u0438 \u043f\u043e\u043a\u0430!!!<\/strong><\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/898960\/\" rel=\"noopener noreferrer nofollow\">&lt;- \u041f\u0420\u041e\u0428\u041b\u0410\u042f \u0421\u0422\u0410\u0422\u042c<\/a>\u042f<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><\/p>\n<div class=\"tm-article-poll-container\"><!--[--><\/p>\n<div class=\"tm-article-poll tm-article-poll_variant-bordered\">\n<div class=\"tm-notice tm-notice_positive tm-article-poll__notice\"><!----><\/p>\n<div class=\"tm-notice__inner\"><!----><\/p>\n<div class=\"tm-notice__content\" data-test-id=\"notice-content\"><!--[--><span>\u0422\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u0443\u0442 \u0443\u0447\u0430\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0432 \u043e\u043f\u0440\u043e\u0441\u0435. <a rel=\"nofollow\" href=\"\/kek\/v1\/auth\/habrahabr\/?back=\/ru\/articles\/899362\/&#038;hl=ru\">\u0412\u043e\u0439\u0434\u0438\u0442\u0435<\/a>, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430.<\/span><!--]--><\/div>\n<\/div>\n<\/div>\n<p><!--[--><\/p>\n<div class=\"tm-article-poll__header\">\u041e \u0447\u0435\u043c \u043f\u0438\u0441\u0430\u0442\u044c \u0434\u0430\u043b\u0435\u0435?<\/div>\n<div class=\"tm-article-poll__answers\"><!--[--><\/p>\n<div class=\"tm-article-poll__answer\">\n<div class=\"tm-article-poll__answer-data\"><span class=\"tm-article-poll__answer-percent\">0% <\/span><span class=\"tm-article-poll__answer-label\">\u0423\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438!<\/span><span class=\"tm-article-poll__answer-votes\">0<\/span><\/div>\n<div class=\"tm-article-poll__answer-bar\">\n<div class=\"tm-article-poll__answer-progress\" style=\"width: 0%\"><\/div>\n<\/div>\n<\/div>\n<div class=\"tm-article-poll__answer\">\n<div class=\"tm-article-poll__answer-data\"><span class=\"tm-article-poll__answer-percent\">0% <\/span><span class=\"tm-article-poll__answer-label\">\u0414\u0430 \u043d\u0438 \u043e \u0447\u0435\u043c \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0439 \u0441\u0442\u0430\u0442\u044c\u0438!<\/span><span class=\"tm-article-poll__answer-votes\">0<\/span><\/div>\n<div class=\"tm-article-poll__answer-bar\">\n<div class=\"tm-article-poll__answer-progress\" style=\"width: 0%\"><\/div>\n<\/div>\n<\/div>\n<div class=\"tm-article-poll__answer\">\n<div class=\"tm-article-poll__answer-data\"><span class=\"tm-article-poll__answer-percent\">50% <\/span><span class=\"tm-article-poll__answer-label\">\u0422\u0435\u043a\u0441\u0442\u0443\u0440\u043a\u0438!<\/span><span class=\"tm-article-poll__answer-votes\">1<\/span><\/div>\n<div class=\"tm-article-poll__answer-bar\">\n<div class=\"tm-article-poll__answer-progress\" style=\"width: 50%\"><\/div>\n<\/div>\n<\/div>\n<div class=\"tm-article-poll__answer\">\n<div class=\"tm-article-poll__answer-data\"><span class=\"tm-article-poll__answer-percent tm-article-poll__answer-percent_winning\">50% <\/span><span class=\"tm-article-poll__answer-label\">\u0415\u0449\u0435 \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u0434\u043e\u043f.\u0441\u043e\u0444\u0442!<\/span><span class=\"tm-article-poll__answer-votes\">1<\/span><\/div>\n<div class=\"tm-article-poll__answer-bar\">\n<div class=\"tm-article-poll__answer-progress tm-article-poll__answer-progress_winning\" style=\"width: 50%\"><\/div>\n<\/div>\n<\/div>\n<p><!--]--><\/div>\n<div class=\"tm-article-poll__stats\"> \u041f\u0440\u043e\u0433\u043e\u043b\u043e\u0441\u043e\u0432\u0430\u043b\u0438 2 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.    \u0412\u043e\u0437\u0434\u0435\u0440\u0436\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u043d\u0435\u0442. <\/div>\n<p><!--]--><\/div>\n<p><!--]--><\/div>\n<p> \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\/899362\/\"> https:\/\/habr.com\/ru\/articles\/899362\/<\/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<blockquote>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0438 \u043c\u043e\u0436\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f! \u041f\u0438\u0448\u0438\u0442\u0435\u0441\u0432\u043e\u0435 \u043c\u043d\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445!<\/p>\n<\/blockquote>\n<h2>\u0414\u0435\u043b\u0430\u0435\u043c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440!<\/h2>\n<p>\u042f \u0445\u043e\u0447\u0443 \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043a\u0430\u0440\u0442 \u0431\u044b \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0438\u0433\u0440\u044b<strong> &#171;Doom II&#187;<\/strong> \u0442\u0430\u043a \u0447\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 \u0441 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u043c \u0432\u043e\u0442 \u0442\u0430\u043a :<\/p>\n<pre><code class=\"python\">import tkinter as tk from tkinter import filedialog, simpledialog  class MapEditor:     def __init__(self, root):         self.root = root         self.root.title(\"Map Editor\")         self.root.geometry(\"800x600\")                  # \u041d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438         self.width = 10         self.height = 8         self.cell_size = 40         self.zoom = 1.0                  self.init_map()         self.create_widgets()         self.bind_events()         self.draw_map()<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0432 \u044d\u0442\u043e\u043c \u043a\u043e\u0434\u0435 \u043c\u044b :<\/p>\n<ul>\n<li>\n<p>\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043a\u0430\u0440\u0442<\/p>\n<\/li>\n<li>\n<p>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u0439 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043d\u0435\u0435 \u0445\u043e\u043b\u0441\u0442 \u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432:<\/p>\n<pre><code class=\"python\">    def create_widgets(self):         # \u0425\u043e\u043b\u0441\u0442 \u0434\u043b\u044f \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u0430\u0440\u0442\u044b         self.canvas = tk.Canvas(             self.root,              bg='#202020',             cursor=\"crosshair\"         )         self.canvas.pack(fill=tk.BOTH, expand=True)                  # \u041f\u0430\u043d\u0435\u043b\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432         self.toolbar = tk.Frame(self.root)         self.toolbar.pack(fill=tk.X)                  # \u041a\u043d\u043e\u043f\u043a\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f         buttons = [             ('New Map', self.new_map, '#555'),             ('Zoom +', lambda: self.change_zoom(0.1), '#777'),             ('Zoom -', lambda: self.change_zoom(-0.1), '#777'),             ('Save', self.save_map, '#388E3C'),             ('Load', self.load_map, '#1976D2')         ]                  for text, cmd, color in buttons:             btn = tk.Button(                 self.toolbar,                 text=text,                 command=cmd,                 bg=color,                 fg='white',                 padx=8,                 pady=4             )             btn.pack(side=tk.LEFT, padx=2, pady=2)<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u0435:<\/summary>\n<div class=\"spoiler__content\">\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0445\u043e\u043b\u0441\u0442 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043a\u0430\u0440\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0430\u043d\u0435\u043b\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0441 \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0442\u0438\u043b\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<p>\u041d\u0443 \u0447\u0442\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043d\u0430\u0448\u0443 \u043a\u0430\u0440\u0442\u0443 \u0441\u0445\u0435\u043c\u0443 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0430\u043c\u0438\u0445 \u043a\u0430\u0440\u0442! \u041d\u0430\u043f\u043e\u043c\u043d\u044e \u0432\u043e\u0442-\u0442\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0430\u0448\u0430 \u043a\u0430\u0440\u0442\u0430 \u0432 \u0444\u0430\u0439\u043b\u0435 map.txt:<\/p>\n<pre><code>8 WWWWWWWWWW W        W W WW  WW W W WW     W W        W W     WW W W        W WWWWWWWWWW<\/code><\/pre>\n<p>\u0418 \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u043b\u044f \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0442\u0438\u043b\u044f \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0432 <code><strong>ROOM1.map<\/strong><\/code><strong> <\/strong>!<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043f\u043e\u0439\u043b\u0435\u0440<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041a\u0430\u043a \u0432\u044b \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435 \u043f\u043e\u043d\u044f\u043b\u0438 \u044f \u043d\u0430\u0437\u0432\u0430\u043b \u0435\u0433\u043e<code><strong>ROOM1<\/strong><\/code> \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043a\u043e\u043c\u043d\u0430\u0442 \u0438 \u043c\u044b \u0434\u0430\u0436\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0446\u0435\u043b\u043e\u0435 \u043c\u0435\u043d\u044e !<\/p>\n<\/div>\n<\/details>\n<p>\u0412\u043e\u0442 \u0438 \u0441\u0430\u043c \u043a\u043e\u0434 :<\/p>\n<pre><code class=\"python\">    def init_map(self):         \"\"\"\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u043e\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u044b \u0441 \u0433\u0440\u0430\u043d\u0438\u0446\u0430\u043c\u0438\"\"\"         self.map_data = [[' ' for _ in range(self.width)] for _ in range(self.height)]                  # \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0433\u0440\u0430\u043d\u0438\u0446         for x in range(self.width):             self.map_data[0][x] = 'W'             self.map_data[-1][x] = 'W'         for y in range(self.height):             self.map_data[y][0] = 'W'             self.map_data[y][-1] = 'W'      def draw_map(self):         \"\"\"\u041e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0430 \u043a\u0430\u0440\u0442\u044b \u043d\u0430 \u0445\u043e\u043b\u0441\u0442\u0435\"\"\"         self.canvas.delete(\"all\")         cell = self.cell_size * self.zoom                  for y in range(self.height):             for x in range(self.width):                 color = self.get_color(self.map_data[y][x])                 x0 = x * cell                 y0 = y * cell                 self.canvas.create_rectangle(                     x0, y0, x0 + cell, y0 + cell,                     fill=color,                     outline='#333',                     tags=(\"cell\", f\"{x},{y}\")                 )      def get_color(self, cell):         \"\"\"\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0446\u0432\u0435\u0442 \u0434\u043b\u044f \u0442\u0438\u043f\u0430 \u044f\u0447\u0435\u0439\u043a\u0438\"\"\"         return {             'W': '#4A4A4A',  # \u0421\u0442\u0435\u043d\u0430             '.': '#6B6B6B',  # \u041f\u043e\u043b             ' ': '#202020'    # \u041f\u0443\u0441\u0442\u043e\u0442\u0430         }.get(cell, '#202020')<\/code><\/pre>\n<p>\u041d\u0443 \u0447\u0442\u043e-\u0436\u0435 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0432\u044b\u0448\u0435\u0434\u0448\u0438\u0439 \u0443 \u043d\u0430\u0441 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440! \u041d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0449\u0435 \u0447\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u043a\u043e\u0434\u0430 \u0438 \u043c\u0430\u0433\u0438\u0438 <code>\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439<\/code>!<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">    def bind_events(self):         \"\"\"\u041f\u0440\u0438\u0432\u044f\u0437\u043a\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0441\u043e\u0431\u044b\u0442\u0438\u0439\"\"\"         # \u041c\u044b\u0448\u044c         self.canvas.bind(\"&lt;Button-1&gt;\", self.draw)         self.canvas.bind(\"&lt;B1-Motion&gt;\", self.draw)         self.canvas.bind(\"&lt;Button-3&gt;\", self.erase)         self.canvas.bind(\"&lt;B3-Motion&gt;\", self.erase)                  # \u041a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u0430         self.root.bind(\"&lt;plus&gt;\", lambda e: self.change_zoom(0.1))         self.root.bind(\"&lt;minus&gt;\", lambda e: self.change_zoom(-0.1))      def draw(self, event):         \"\"\"\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u041b\u041a\u041c\"\"\"         x, y = self.get_cell_coords(event.x, event.y)         if self.is_valid_cell(x, y):             self.map_data[y][x] = 'W'             self.draw_map()      def erase(self, event):         \"\"\"\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u0442\u0438\u0440\u0430\u043d\u0438\u044f \u041f\u041a\u041c\"\"\"         x, y = self.get_cell_coords(event.x, event.y)         if self.is_valid_cell(x, y):             self.map_data[y][x] = ' '             self.draw_map()<\/code><\/pre>\n<pre><code class=\"python\">    def change_zoom(self, delta):         \"\"\"\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0430\"\"\"         self.zoom = max(0.5, min(2.0, self.zoom + delta))         self.draw_map()      def new_map(self):         \"\"\"\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u044b\"\"\"         new_width = simpledialog.askinteger(\"New Map\", \"Width:\",                                            minvalue=5, maxvalue=50)         new_height = simpledialog.askinteger(\"New Map\", \"Height:\",                                             minvalue=5, maxvalue=50)         if new_width and new_height:             self.width = new_width             self.height = new_height             self.init_map()             self.draw_map()      def save_map(self):         \"\"\"\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043a\u0430\u0440\u0442\u044b \u0432 \u0444\u0430\u0439\u043b\"\"\"         file_path = filedialog.asksaveasfilename(             defaultextension=\".map\",             filetypes=[(\"Map files\", \"*.map\")]         )         if file_path:             with open(file_path, 'w') as f:                 f.write(f\"{self.height}\\n\")                 for row in self.map_data:                     f.write(''.join(row).ljust(self.width, ' ') + '\\n')      def load_map(self):         \"\"\"\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043a\u0430\u0440\u0442\u044b \u0438\u0437 \u0444\u0430\u0439\u043b\u0430\"\"\"         file_path = filedialog.askopenfilename(             filetypes=[(\"Map files\", \"*.map\")]         )         if file_path:             with open(file_path, 'r') as f:                 lines = [line.strip() for line in f.readlines()]                 self.height = int(lines[0])                 self.map_data = [list(line.ljust(self.width, ' ')[:self.width]                                 for line in lines[1:self.height+1]]                 self.draw_map()<\/code><\/pre>\n<\/div>\n<\/details>\n<h2>\u0418\u0442\u043e\u0433!<\/h2>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0441\u0432\u043e\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0443\u0440\u043e\u0432\u043d\u0435\u0439! \u041d\u0443 \u0432\u043e\u0442 \u0438 \u0435\u0433\u043e \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>Map editor.<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width\">\n<div><figcaption>\u0412\u043e\u0442 \u043c\u043e\u044f \u043a\u0430\u0440\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<details class=\"spoiler\">\n<summary>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u044b<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><\/figure>\n<figure class=\"full-width\">\n<div><figcaption>\u0414\u0435\u043b\u0430\u044e \u043a\u0430\u0440\u0442\u0443 \ud83d\ude42<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p><strong>\u041d\u0443 \u0447\u0442\u043e-\u0436\u0435 \u0441\u043f\u0430\u0441\u0438\u0431\u043e \u0438 \u043f\u043e\u043a\u0430!!!<\/strong><\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/898960\/\" rel=\"noopener noreferrer nofollow\">&lt;- \u041f\u0420\u041e\u0428\u041b\u0410\u042f \u0421\u0422\u0410\u0422\u042c<\/a>\u042f<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><\/p>\n<div class=\"tm-article-poll-container\"><!--[--><\/p>\n<div class=\"tm-article-poll tm-article-poll_variant-bordered\">\n<div class=\"tm-notice tm-notice_positive tm-article-poll__notice\"><!----><\/p>\n<div class=\"tm-notice__inner\"><!----><\/p>\n<div class=\"tm-notice__content\" data-test-id=\"notice-content\"><!--[--><span>\u0422\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u0443\u0442 \u0443\u0447\u0430\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0432 \u043e\u043f\u0440\u043e\u0441\u0435. <a rel=\"nofollow\" href=\"\/kek\/v1\/auth\/habrahabr\/?back=\/ru\/articles\/899362\/&#038;hl=ru\">\u0412\u043e\u0439\u0434\u0438\u0442\u0435<\/a>, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430.<\/span><!--]--><\/div>\n<\/div>\n<\/div>\n<p><!--[--><\/p>\n<div class=\"tm-article-poll__header\">\u041e \u0447\u0435\u043c \u043f\u0438\u0441\u0430\u0442\u044c \u0434\u0430\u043b\u0435\u0435?<\/div>\n<div class=\"tm-article-poll__answers\"><!--[--><\/p>\n<div class=\"tm-article-poll__answer\">\n<div class=\"tm-article-poll__answer-data\"><span class=\"tm-article-poll__answer-percent\">0% <\/span><span class=\"tm-article-poll__answer-label\">\u0423\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438!<\/span><span class=\"tm-article-poll__answer-votes\">0<\/span><\/div>\n<div class=\"tm-article-poll__answer-bar\">\n<div class=\"tm-article-poll__answer-progress\" style=\"width: 0%\"><\/div>\n<\/div>\n<\/div>\n<div class=\"tm-article-poll__answer\">\n<div class=\"tm-article-poll__answer-data\"><span class=\"tm-article-poll__answer-percent\">0% <\/span><span class=\"tm-article-poll__answer-label\">\u0414\u0430 \u043d\u0438 \u043e \u0447\u0435\u043c \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0439 \u0441\u0442\u0430\u0442\u044c\u0438!<\/span><span class=\"tm-article-poll__answer-votes\">0<\/span><\/div>\n<div class=\"tm-article-poll__answer-bar\">\n<div class=\"tm-article-poll__answer-progress\" style=\"width: 0%\"><\/div>\n<\/div>\n<\/div>\n<div class=\"tm-article-poll__answer\">\n<div class=\"tm-article-poll__answer-data\"><span class=\"tm-article-poll__answer-percent\">50% <\/span><span class=\"tm-article-poll__answer-label\">\u0422\u0435\u043a\u0441\u0442\u0443\u0440\u043a\u0438!<\/span><span class=\"tm-article-poll__answer-votes\">1<\/span><\/div>\n<div class=\"tm-article-poll__answer-bar\">\n<div class=\"tm-article-poll__answer-progress\" style=\"width: 50%\"><\/div>\n<\/div>\n<\/div>\n<div class=\"tm-article-poll__answer\">\n<div class=\"tm-article-poll__answer-data\"><span class=\"tm-article-poll__answer-percent tm-article-poll__answer-percent_winning\">50% <\/span><span class=\"tm-article-poll__answer-label\">\u0415\u0449\u0435 \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u0434\u043e\u043f.\u0441\u043e\u0444\u0442!<\/span><span class=\"tm-article-poll__answer-votes\">1<\/span><\/div>\n<div class=\"tm-article-poll__answer-bar\">\n<div class=\"tm-article-poll__answer-progress tm-article-poll__answer-progress_winning\" style=\"width: 50%\"><\/div>\n<\/div>\n<\/div>\n<p><!--]--><\/div>\n<div class=\"tm-article-poll__stats\"> \u041f\u0440\u043e\u0433\u043e\u043b\u043e\u0441\u043e\u0432\u0430\u043b\u0438 2 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.    \u0412\u043e\u0437\u0434\u0435\u0440\u0436\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u043d\u0435\u0442. <\/div>\n<p><!--]--><\/div>\n<p><!--]--><\/div>\n<p> \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\/899362\/\"> https:\/\/habr.com\/ru\/articles\/899362\/<\/a><br \/><\/br><\/br><\/p>\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-455339","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/455339","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=455339"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/455339\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=455339"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=455339"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=455339"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}