{"id":399032,"date":"2024-06-29T14:25:49","date_gmt":"2024-06-29T14:25:49","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=399032"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=399032","title":{"rendered":"<span>Writing The Matrix in 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<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/ee9\/213\/fe2\/ee9213fe240ccc196b82685e5362e0ea.jpg\" width=\"992\" height=\"496\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ee9\/213\/fe2\/ee9213fe240ccc196b82685e5362e0ea.jpg\" data-blurred=\"true\"\/><\/figure>\n<p>There are different ways to learn new things. Some like to study theory first, and then apply it in practice. Others prefer to learn solely from examples found at Stackoverflow. And someone just downloads helicopter control skills and martial arts techniques via dedicated channel directly into the brain.<\/p>\n<p>In any case, practical exercises are indispensable. After the accelerated download of knowledge, Neo still must spar with Morpheus to learn how to put the terabytes of downloaded skills into practice. Just the exercises are different. It is one thing\u2014to fly dashingly up to the ceiling and break through the walls of the oriental gym, and quite another\u2014to methodically polish your skills for hours.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/6c9\/ccf\/7a0\/6c9ccf7a00ebf1aa9ba73b7551936918.jpg\" alt=\"Training in the Matrix\" title=\"Training in the Matrix\" width=\"1280\" height=\"720\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6c9\/ccf\/7a0\/6c9ccf7a00ebf1aa9ba73b7551936918.jpg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption><em>Training in the Matrix<\/em><\/figcaption><\/div>\n<\/figure>\n<h2>Defining the goals<\/h2>\n<p>Programming textbooks usually do not indulge us with variety of examples. There are, of course, exceptions, but in most manuals, exercises are similar to each other and not particularly interesting: create another address book, draw a circle using turtle, develop a website for a store selling some kind of &#171;necessary&#187; advertising nonsense. Too far from the authentic imitation of &#171;The Matrix&#187;. Although\u2026<\/p>\n<p>How about taking over the control and starting to invent exercises yourself?<\/p>\n<p>Would you like to write your own personal little &#171;Matrix&#187;? Of course, not the one with skyscrapers, stylish phones of the time, and the ubiquitous invincible Agent Smiths. We surely will need a couple of more months of learning for that. But any beginner programmer can write a model of the cult splash screensaver with the green streams of digits flowing down the screen. This is what we are going to do.<\/p>\n<p>It is possible to program such screensaver in almost any language. Let&#8217;s try to create it in the &#171;great and mighty&#187; Python.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b21\/397\/cd4\/b21397cd421b5aa7959ffa7828fd3e6f.png\" alt=\"Original Matrix with green hieroglyphs\" title=\"Original Matrix with green hieroglyphs\" width=\"1143\" height=\"1024\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b21\/397\/cd4\/b21397cd421b5aa7959ffa7828fd3e6f.png\"\/><\/p>\n<div><figcaption><em>Original Matrix with green hieroglyphs<\/em><\/figcaption><\/div>\n<\/figure>\n<h2>The technical requirements<\/h2>\n<p>First, we need to decide what we want to end up with. We should develop technical requirements\u2014it is always useful. Just think of &#171;The Matrix&#187; for a moment, and your memory will probably suggest a familiar image\u2014the dark console window in which streams of green numbers will flow. To make it even more interesting, let them move at different speeds. Each stream should have a beginning\u2014a bright green zero\u2014and an end. By the way, let the speeds of movement of the beginning and the end of the stream will also be different and determined randomly.<\/p>\n<p>It doesn&#8217;t sound so hard, does it? Now it&#8217;s time to just write the code. Let&#8217;s get started.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/07c\/259\/b08\/07c259b08c2eb6d84b0eabd7305121ae.jpg\" alt=\"Technical task in &quot;The Matrix&quot;\" title=\"Technical task in &quot;The Matrix&quot;\" width=\"1194\" height=\"378\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/07c\/259\/b08\/07c259b08c2eb6d84b0eabd7305121ae.jpg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption><em>Technical task in &#171;The Matrix&#187;<\/em><\/figcaption><\/div>\n<\/figure>\n<h2>Preparing the tools<\/h2>\n<p>At first we will connect all the necessary modules, starting with the standard ones:<\/p>\n<pre><code class=\"python\">import sys import random import time<\/code><\/pre>\n<p>To work with the Windows console, we need the <strong>bext<\/strong> and the <strong>colorama<\/strong> modules. How to install them using <strong>pip<\/strong>, you probably already know. You need to connect them. But let&#8217;s do it according to all the rules\u2014with a check:<\/p>\n<pre><code class=\"python\">try:     import bext, colorama except ImportError:     print ('Bext and colorama modules are required to run the program')     sys.exit ()<\/code><\/pre>\n<p>Let&#8217;s prepare the console for work:<\/p>\n<pre><code class=\"python\">bext.title ('Matrix') bext.clear () bext.hide () width, height = bext.size () width -= 1 height -= 1<\/code><\/pre>\n<p>Now it remains only to create constants with colors for the <strong>colorama<\/strong> module. We need green and dark green:<\/p>\n<pre><code class=\"python\">lgreen = colorama.Fore.LIGHTGREEN_EX green = colorama.Fore.GREEN<\/code><\/pre>\n<p>Windows is a tricky and controversial thing. The base color of green in the console is dark green.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/f30\/975\/612\/f30975612f959313720ce961752a4653.jpg\" alt=\"Standard tools in &quot;The Matrix&quot;\" title=\"Standard tools in &quot;The Matrix&quot;\" width=\"1346\" height=\"866\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f30\/975\/612\/f30975612f959313720ce961752a4653.jpg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption><em>Standard tools in &#171;The Matrix&#187;<\/em><\/figcaption><\/div>\n<\/figure>\n<h2>Inventing the antimatter<\/h2>\n<p>Now let&#8217;s think about the most important question: how can we program the flowing drops of the &#171;Matrix&#187;? Each drop is an object. All drops are different, but they behave the same. Therefore, we need to create a class in which we will describe the main actions with the drop and all its attributes.<\/p>\n<p>To make the drops flow at different speeds, let&#8217;s set a random delay timeout for each of them\u2014in steps. Some drops will move at each step of updating our picture, some\u2014less often.<\/p>\n<p>What about the upper end of the stream? It must &#171;dry&#187;, and at its own speed. Let&#8217;s not invent anything complicated. Let the upper end also be a drop, but black. Such a &#171;drop&#187; when moving will not add digits, but rather erase them. It turns out just some kind of anti-drop, anti-matter\u2014beautiful and stylish.<\/p>\n<p>Since the drop and the anti-drop behave the same, let&#8217;s program them in the same class.<\/p>\n<h2>Creating the drops<\/h2>\n<p>So, we will perform all actions with drops and anti-drops in the class methods. Let&#8217;s call it <strong>Drop<\/strong> and write a method for creating a class object:<\/p>\n<pre><code class=\"python\">def __init__ (self):     self.x = random.randint (0, width)     self.y = -1     self.drop_type = random.randint (0, 1)     self.timeout = random.randint (0, 3)     self.wait_count = random.randint (0, 3)<\/code><\/pre>\n<p>Everything is clear with the <strong>x<\/strong> and <strong>y<\/strong> attributes. The second one is &#8216;-1&#8217; so that the drop is not shown on the screen ahead of time. The timeout and wait_count attributes are needed to provide different drop rates. The first sets the constant flow rate, the second sets the iteration counter.<\/p>\n<h2>Moving the drops<\/h2>\n<p>Now let&#8217;s write a method for moving a drop, taking into account its speed.<\/p>\n<pre><code class=\"python\">def move (self):     if drop.wait_count &lt; drop.timeout:         drop.wait_count += 1         return False     else:         drop.wait_count = 0         drop.y += 1         return True<\/code><\/pre>\n<p>The method returns a boolean value\u2014the fact that the drop has moved. Or antidrops\u2014all the same.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ed8\/e9a\/389\/ed8e9a389c4fffe19973efc4f4d258ff.png\" width=\"748\" height=\"239\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ed8\/e9a\/389\/ed8e9a389c4fffe19973efc4f4d258ff.png\"\/><\/figure>\n<h2>Drawing the stream<\/h2>\n<p>Now we\u2019ve done with moving the drops. It&#8217;s time to draw!<\/p>\n<pre><code class=\"python\">def draw (self):     if self.drop_type == 1:         symbol = str (random.randint (1, 9))         con_print (self.x, self.y, green, symbol)         self.zero_draw ()     else:         con_print (self.x, self.y, green, ' ')<\/code><\/pre>\n<p>Here we call two new methods not yet written: <strong>con_print<\/strong> and <strong>zero_draw<\/strong>. The first one will output the character of the desired color to the specified location in the console window. The second will draw an extra bright zero at the beginning of the trickle.<\/p>\n<p>Here is the second method:<\/p>\n<pre><code class=\"python\">def zero_draw (self):     if (self.y &lt; height):     con_print (self.x, self.y+1, lgreen, '0')<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/22b\/69c\/796\/22b69c7965baab83198a1697a0115846.png\" alt=\"Rain in &quot;The Matrix&quot;\" title=\"Rain in &quot;The Matrix&quot;\" width=\"1000\" height=\"417\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/22b\/69c\/796\/22b69c7965baab83198a1697a0115846.png\"\/><\/p>\n<div><figcaption><em>Rain in &#171;The Matrix&#187;<\/em><\/figcaption><\/div>\n<\/figure>\n<h2>Organizing the reincarnation of the drops<\/h2>\n<p>We have already understood that what we are getting is not a simple &#171;Matrix&#187;, but a philosophical one. Therefore, when the drops and anti-drops reach the bottom edge of the screen, let&#8217;s make them reborn. They will get a new life at the upper border. This will only cost us two lines:<\/p>\n<pre><code class=\"python\">def renew (self):     self.__init__ ()<\/code><\/pre>\n<p>Now we have everything we need. The <strong>Drop<\/strong> class is ready.<\/p>\n<h2>Outputting text to the console<\/h2>\n<p>Let&#8217;s break out of the boundaries of the <strong>Drop<\/strong> class and write two functions for displaying text in the console window.<\/p>\n<p>If we try to print something in the lower right corner of the console window, then another line will automatically be added to the bottom. Nothing can be done: in this place in our ideal &#171;Matrix&#187; there will be a &#171;broken pixel&#187;:<\/p>\n<pre><code class=\"python\">def is_rb_corner (x, y):     return x==width and y==height<\/code><\/pre>\n<p>Now everything is ready to print the requested character in the right place.<\/p>\n<pre><code class=\"python\">def con_print (x, y, color, symbol):     if not is_rb_corner (x, y):         bext.goto (x, y)         sys.stdout.write (color)         print (symbol, end='')<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/49d\/cc8\/03d\/49dcc803d5a8b8fa5a5d30348d22b40b.png\" width=\"1917\" height=\"996\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/49d\/cc8\/03d\/49dcc803d5a8b8fa5a5d30348d22b40b.png\"\/><\/figure>\n<h2>Getting it all together<\/h2>\n<p>All components of our future &#171;Matrix&#187; are ready. Now it remains to put everything together and run.<\/p>\n<p>Let&#8217;s create an array of drops and antidrops (what type of object is born is a matter of chance).<\/p>\n<pre><code class=\"python\">drops = [] for i in range (1, width*2\/\/3):     drop = Drop ()     drops.append (drop)<\/code><\/pre>\n<p>And finally, the most important loop:<\/p>\n<pre><code class=\"python\">while True:     for drop in drops:         if drop.move ():             drop.draw ()             if drop.y >= height:                 drop.renew ()     key = bext.getKey (blocking = False)     if key == 'esc':         bext.clear ()         sys.exit ()     time.sleep (0.02)<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4fc\/898\/665\/4fc89866543ba2269ec56239cd47bb0b.gif\" width=\"1242\" height=\"800\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4fc\/898\/665\/4fc89866543ba2269ec56239cd47bb0b.gif\"\/><\/figure>\n<h2>The entire program<\/h2>\n<pre><code class=\"python\">import sys import random import time  try:     import bext, colorama except ImportError:     print ('Bext and colorama modules are required to run the program')     sys.exit ()  class Drop:     def __init__ (self):         self.x = random.randint (0, width)         self.y = -1         self.drop_type = random.randint (0, 1)         self.timeout = random.randint (0, 3)         self.wait_count = random.randint (0, 3)     def renew (self):         self.__init__ ()     def move (self):         if drop.wait_count &lt; drop.timeout:             drop.wait_count += 1             return False         else:             drop.wait_count = 0             drop.y += 1             return True     def draw (self):         if self.drop_type == 1:             symbol = str (random.randint (1, 9))             con_print (self.x, self.y, green, symbol)             self.zero_draw ()         else:             con_print (self.x, self.y, green, ' ')     def zero_draw (self):         if (self.y &lt; height):             con_print (self.x, self.y+1, lgreen, '0')  def is_rb_corner (x, y):     return x==width and y==height  def con_print (x, y, color, symbol):     if not is_rb_corner (x, y):         bext.goto (x, y)         sys.stdout.write (color)         print (symbol, end='')  bext.title ('Matrix') bext.clear () bext.hide () width, height = bext.size () width -= 1 height -= 1  green = colorama.Fore.GREEN lgreen = colorama.Fore.LIGHTGREEN_EX  drops = [] for i in range (1, width*2\/\/3):     drop = Drop ()     drops.append (drop)  while True:     for drop in drops:         if drop.move ():             drop.draw ()             if drop.y >= height:                 drop.renew ()     key = bext.getKey (blocking = False)     if key == 'esc':         bext.clear ()         sys.exit ()     time.sleep (0.02)<\/code><\/pre>\n<p>You can also experiment with this program. Try adding your own additional unique effects. <br \/>I wonder what your &#171;Matrix&#187; will be like.<\/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\/720452\/\"> https:\/\/habr.com\/ru\/articles\/720452\/<\/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<figure class=\"full-width\"><\/figure>\n<p>There are different ways to learn new things. Some like to study theory first, and then apply it in practice. Others prefer to learn solely from examples found at Stackoverflow. And someone just downloads helicopter control skills and martial arts techniques via dedicated channel directly into the brain.<\/p>\n<p>In any case, practical exercises are indispensable. After the accelerated download of knowledge, Neo still must spar with Morpheus to learn how to put the terabytes of downloaded skills into practice. Just the exercises are different. It is one thing\u2014to fly dashingly up to the ceiling and break through the walls of the oriental gym, and quite another\u2014to methodically polish your skills for hours.<\/p>\n<figure class=\"full-width\">\n<div><figcaption><em>Training in the Matrix<\/em><\/figcaption><\/div>\n<\/figure>\n<h2>Defining the goals<\/h2>\n<p>Programming textbooks usually do not indulge us with variety of examples. There are, of course, exceptions, but in most manuals, exercises are similar to each other and not particularly interesting: create another address book, draw a circle using turtle, develop a website for a store selling some kind of &#171;necessary&#187; advertising nonsense. Too far from the authentic imitation of &#171;The Matrix&#187;. Although\u2026<\/p>\n<p>How about taking over the control and starting to invent exercises yourself?<\/p>\n<p>Would you like to write your own personal little &#171;Matrix&#187;? Of course, not the one with skyscrapers, stylish phones of the time, and the ubiquitous invincible Agent Smiths. We surely will need a couple of more months of learning for that. But any beginner programmer can write a model of the cult splash screensaver with the green streams of digits flowing down the screen. This is what we are going to do.<\/p>\n<p>It is possible to program such screensaver in almost any language. Let&#8217;s try to create it in the &#171;great and mighty&#187; Python.<\/p>\n<figure class=\"full-width\">\n<div><figcaption><em>Original Matrix with green hieroglyphs<\/em><\/figcaption><\/div>\n<\/figure>\n<h2>The technical requirements<\/h2>\n<p>First, we need to decide what we want to end up with. We should develop technical requirements\u2014it is always useful. Just think of &#171;The Matrix&#187; for a moment, and your memory will probably suggest a familiar image\u2014the dark console window in which streams of green numbers will flow. To make it even more interesting, let them move at different speeds. Each stream should have a beginning\u2014a bright green zero\u2014and an end. By the way, let the speeds of movement of the beginning and the end of the stream will also be different and determined randomly.<\/p>\n<p>It doesn&#8217;t sound so hard, does it? Now it&#8217;s time to just write the code. Let&#8217;s get started.<\/p>\n<figure class=\"full-width\">\n<div><figcaption><em>Technical task in &#171;The Matrix&#187;<\/em><\/figcaption><\/div>\n<\/figure>\n<h2>Preparing the tools<\/h2>\n<p>At first we will connect all the necessary modules, starting with the standard ones:<\/p>\n<pre><code class=\"python\">import sys import random import time<\/code><\/pre>\n<p>To work with the Windows console, we need the <strong>bext<\/strong> and the <strong>colorama<\/strong> modules. How to install them using <strong>pip<\/strong>, you probably already know. You need to connect them. But let&#8217;s do it according to all the rules\u2014with a check:<\/p>\n<pre><code class=\"python\">try:     import bext, colorama except ImportError:     print ('Bext and colorama modules are required to run the program')     sys.exit ()<\/code><\/pre>\n<p>Let&#8217;s prepare the console for work:<\/p>\n<pre><code class=\"python\">bext.title ('Matrix') bext.clear () bext.hide () width, height = bext.size () width -= 1 height -= 1<\/code><\/pre>\n<p>Now it remains only to create constants with colors for the <strong>colorama<\/strong> module. We need green and dark green:<\/p>\n<pre><code class=\"python\">lgreen = colorama.Fore.LIGHTGREEN_EX green = colorama.Fore.GREEN<\/code><\/pre>\n<p>Windows is a tricky and controversial thing. The base color of green in the console is dark green.<\/p>\n<figure class=\"full-width\">\n<div><figcaption><em>Standard tools in &#171;The Matrix&#187;<\/em><\/figcaption><\/div>\n<\/figure>\n<h2>Inventing the antimatter<\/h2>\n<p>Now let&#8217;s think about the most important question: how can we program the flowing drops of the &#171;Matrix&#187;? Each drop is an object. All drops are different, but they behave the same. Therefore, we need to create a class in which we will describe the main actions with the drop and all its attributes.<\/p>\n<p>To make the drops flow at different speeds, let&#8217;s set a random delay timeout for each of them\u2014in steps. Some drops will move at each step of updating our picture, some\u2014less often.<\/p>\n<p>What about the upper end of the stream? It must &#171;dry&#187;, and at its own speed. Let&#8217;s not invent anything complicated. Let the upper end also be a drop, but black. Such a &#171;drop&#187; when moving will not add digits, but rather erase them. It turns out just some kind of anti-drop, anti-matter\u2014beautiful and stylish.<\/p>\n<p>Since the drop and the anti-drop behave the same, let&#8217;s program them in the same class.<\/p>\n<h2>Creating the drops<\/h2>\n<p>So, we will perform all actions with drops and anti-drops in the class methods. Let&#8217;s call it <strong>Drop<\/strong> and write a method for creating a class object:<\/p>\n<pre><code class=\"python\">def __init__ (self):     self.x = random.randint (0, width)     self.y = -1     self.drop_type = random.randint (0, 1)     self.timeout = random.randint (0, 3)     self.wait_count = random.randint (0, 3)<\/code><\/pre>\n<p>Everything is clear with the <strong>x<\/strong> and <strong>y<\/strong> attributes. The second one is &#8216;-1&#8217; so that the drop is not shown on the screen ahead of time. The timeout and wait_count attributes are needed to provide different drop rates. The first sets the constant flow rate, the second sets the iteration counter.<\/p>\n<h2>Moving the drops<\/h2>\n<p>Now let&#8217;s write a method for moving a drop, taking into account its speed.<\/p>\n<pre><code class=\"python\">def move (self):     if drop.wait_count &lt; drop.timeout:         drop.wait_count += 1         return False     else:         drop.wait_count = 0         drop.y += 1         return True<\/code><\/pre>\n<p>The method returns a boolean value\u2014the fact that the drop has moved. Or antidrops\u2014all the same.<\/p>\n<figure class=\"full-width\"><\/figure>\n<h2>Drawing the stream<\/h2>\n<p>Now we\u2019ve done with moving the drops. It&#8217;s time to draw!<\/p>\n<pre><code class=\"python\">def draw (self):     if self.drop_type == 1:         symbol = str (random.randint (1, 9))         con_print (self.x, self.y, green, symbol)         self.zero_draw ()     else:         con_print (self.x, self.y, green, ' ')<\/code><\/pre>\n<p>Here we call two new methods not yet written: <strong>con_print<\/strong> and <strong>zero_draw<\/strong>. The first one will output the character of the desired color to the specified location in the console window. The second will draw an extra bright zero at the beginning of the trickle.<\/p>\n<p>Here is the second method:<\/p>\n<pre><code class=\"python\">def zero_draw (self):     if (self.y &lt; height):     con_print (self.x, self.y+1, lgreen, '0')<\/code><\/pre>\n<figure class=\"full-width\">\n<div><figcaption><em>Rain in &#171;The Matrix&#187;<\/em><\/figcaption><\/div>\n<\/figure>\n<h2>Organizing the reincarnation of the drops<\/h2>\n<p>We have already understood that what we are getting is not a simple &#171;Matrix&#187;, but a philosophical one. Therefore, when the drops and anti-drops reach the bottom edge of the screen, let&#8217;s make them reborn. They will get a new life at the upper border. This will only cost us two lines:<\/p>\n<pre><code class=\"python\">def renew (self):     self.__init__ ()<\/code><\/pre>\n<p>Now we have everything we need. The <strong>Drop<\/strong> class is ready.<\/p>\n<h2>Outputting text to the console<\/h2>\n<p>Let&#8217;s break out of the boundaries of the <strong>Drop<\/strong> class and write two functions for displaying text in the console window.<\/p>\n<p>If we try to print something in the lower right corner of the console window, then another line will automatically be added to the bottom. Nothing can be done: in this place in our ideal &#171;Matrix&#187; there will be a &#171;broken pixel&#187;:<\/p>\n<pre><code class=\"python\">def is_rb_corner (x, y):     return x==width and y==height<\/code><\/pre>\n<p>Now everything is ready to print the requested character in the right place.<\/p>\n<pre><code class=\"python\">def con_print (x, y, color, symbol):     if not is_rb_corner (x, y):         bext.goto (x, y)         sys.stdout.write (color)         print (symbol, end='')<\/code><\/pre>\n<figure class=\"full-width\"><\/figure>\n<h2>Getting it all together<\/h2>\n<p>All components of our future &#171;Matrix&#187; are ready. Now it remains to put everything together and run.<\/p>\n<p>Let&#8217;s create an array of drops and antidrops (what type of object is born is a matter of chance).<\/p>\n<pre><code class=\"python\">drops = [] for i in range (1, width*2\/\/3):     drop = Drop ()     drops.append (drop)<\/code><\/pre>\n<p>And finally, the most important loop:<\/p>\n<pre><code class=\"python\">while True:     for drop in drops:         if drop.move ():             drop.draw ()             if drop.y >= height:                 drop.renew ()     key = bext.getKey (blocking = False)     if key == 'esc':         bext.clear ()         sys.exit ()     time.sleep (0.02)<\/code><\/pre>\n<figure class=\"full-width\"><\/figure>\n<h2>The entire program<\/h2>\n<pre><code class=\"python\">import sys import random import time  try:     import bext, colorama except ImportError:     print ('Bext and colorama modules are required to run the program')     sys.exit ()  class Drop:     def __init__ (self):         self.x = random.randint (0, width)         self.y = -1         self.drop_type = random.randint (0, 1)         self.timeout = random.randint (0, 3)         self.wait_count = random.randint (0, 3)     def renew (self):         self.__init__ ()     def move (self):         if drop.wait_count &lt; drop.timeout:             drop.wait_count += 1             return False         else:             drop.wait_count = 0             drop.y += 1             return True     def draw (self):         if self.drop_type == 1:             symbol = str (random.randint (1, 9))             con_print (self.x, self.y, green, symbol)             self.zero_draw ()         else:             con_print (self.x, self.y, green, ' ')     def zero_draw (self):         if (self.y &lt; height):             con_print (self.x, self.y+1, lgreen, '0')  def is_rb_corner (x, y):     return x==width and y==height  def con_print (x, y, color, symbol):     if not is_rb_corner (x, y):         bext.goto (x, y)         sys.stdout.write (color)         print (symbol, end='')  bext.title ('Matrix') bext.clear () bext.hide () width, height = bext.size () width -= 1 height -= 1  green = colorama.Fore.GREEN lgreen = colorama.Fore.LIGHTGREEN_EX  drops = [] for i in range (1, width*2\/\/3):     drop = Drop ()     drops.append (drop)  while True:     for drop in drops:         if drop.move ():             drop.draw ()             if drop.y >= height:                 drop.renew ()     key = bext.getKey (blocking = False)     if key == 'esc':         bext.clear ()         sys.exit ()     time.sleep (0.02)<\/code><\/pre>\n<p>You can also experiment with this program. Try adding your own additional unique effects. <br \/>I wonder what your &#171;Matrix&#187; will be like.<\/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\/720452\/\"> https:\/\/habr.com\/ru\/articles\/720452\/<\/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-399032","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/399032","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=399032"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/399032\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=399032"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=399032"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=399032"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}