{"id":116023,"date":"2020-07-29T08:00:00","date_gmt":"2020-07-29T08:00:00","guid":{"rendered":"https:\/\/fedoramagazine.org\/?p=31476"},"modified":"2020-07-29T08:00:00","modified_gmt":"2020-07-29T08:00:00","slug":"demonstrating-perl-with-tic-tac-toe-part-4","status":"publish","type":"post","link":"https:\/\/sickgaming.net\/blog\/2020\/07\/29\/demonstrating-perl-with-tic-tac-toe-part-4\/","title":{"rendered":"Demonstrating Perl with Tic-Tac-Toe, Part 4"},"content":{"rendered":"<p>This is the final article to the series demonstrating Perl with Tic-Tac-Toe. This article provides a module that can compute better game moves than the previously presented modules. For fun, the modules <em>chip1.pm<\/em> through <em>chip3.pm<\/em> can be incrementally moved out of the <em>hal<\/em> subdirectory in reverse order. With each chip that is removed, the game will become easier to play. The game must be restarted each time a chip is removed.<\/p>\n<p> <span id=\"more-31476\"><\/span> <\/p>\n<h2>An example Perl program<\/h2>\n<p>Copy and paste the below code into a plain text file and use the same one-liner that was provided in the <a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/fedoramagazine.org\/demonstrating-perl-with-tic-tac-toe-part-1\/\" target=\"_blank\" rel=\"noreferrer noopener\">the first article<\/a> of this series to strip the leading numbers. Name the version without the line numbers <em>chip3.pm<\/em> and move it into the <em>hal<\/em> subdirectory. Use the version of the game that was provided in <a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/fedoramagazine.org\/demonstrating-perl-with-tic-tac-toe-part-2\/\" target=\"_blank\" rel=\"noreferrer noopener\">the second article<\/a> so that the below chip will automatically load when placed in the <em>hal<\/em> subdirectory. Be sure to also include both <em>chip1.pm<\/em> and <em>chip2.pm<\/em> from the second <a href=\"https:\/\/fedoramagazine.org\/demonstrating-perl-with-tic-tac-toe-part-3\/\" target=\"_blank\" aria-label=\"undefined (opens in a new tab)\" rel=\"noreferrer noopener\">and third<\/a> articles, respectively, in the <em>hal<\/em> subdirectory.<\/p>\n<pre class=\"wp-block-preformatted\">00 # artificial intelligence chip\n01 02 package chip3;\n03 require chip2;\n04 require chip1;\n05 06 use strict;\n07 use warnings;\n08 09 sub moverama {\n10 my $game = shift;\n11 my @nums = $game =~ \/[1-9]\/g;\n12 my $rama = qr\/[1973]\/;\n13 my %best;\n14 15 for (@nums) {\n16 my $ra = $_;\n17 next unless $ra =~ $rama;\n18 $best{$ra} = 0;\n19 for (@nums) {\n20 my $ma = $_;\n21 next unless $ma =~ $rama;\n22 if (($ra-$ma)*(10-$ra-$ma)) {\n23 $best{$ra} += 1;\n24 }\n25 }\n26 }\n27 28 @nums = sort { $best{$b} &lt;=&gt; $best{$a} } keys %best;\n29 30 return $nums[0];\n31 }\n32 33 sub hal_move {\n34 my $game = shift;\n35 my $mark = shift;\n36 my @mark = @{ shift; };\n37 my $move;\n38 39 $move = chip2::win_move $game, $mark, \\@mark;\n40 41 if (not defined $move) {\n42 $mark = ($mark eq $mark[0]) ? $mark[1] : $mark[0];\n43 $move = chip2::win_move $game, $mark, \\@mark;\n44 }\n45 46 if (not defined $move) {\n47 $move = moverama $game;\n48 }\n49 50 if (not defined $move) {\n51 $move = chip1::hal_move $game;\n52 }\n53 54 return $move;\n55 }\n56 57 sub complain {\n58 print 'Just what do you think you\\'re doing, ',\n59 ((getpwnam($ENV{'USER'}))[6]||$ENV{'USER'}) =~ s! .*!!r, \"?\\n\";\n60 }\n61 62 sub import {\n63 no strict;\n64 no warnings;\n65 66 my $p = __PACKAGE__;\n67 my $c = caller;\n68 69 *{ $c . '::hal_move' } = \\&amp;{ $p . '::hal_move' };\n70 *{ $c . '::complain' } = \\&amp;{ $p . '::complain' };\n71 72 if (&amp;::MARKS-&gt;[0] ne &amp;::HAL9K) {\n73 @{ &amp;::MARKS } = reverse @{ &amp;::MARKS };\n74 }\n75 }\n76 77 1;\n<\/pre>\n<h2>How it works<\/h2>\n<p>Rather than making a random move or making a move based on probability, this final module to the Perl Tic-Tac-Toe game uses a more <a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/en.wikipedia.org\/wiki\/Deterministic_system\" target=\"_blank\" rel=\"noreferrer noopener\">deterministic<\/a> algorithm to calculate the best move.<\/p>\n<p>The big takeaway from this Perl module is that it is yet another example of how references can be misused or abused, and as a consequence lead to unexpected program behavior. With the addition of this chip, the computer learns to cheat. Can you figure out how it is cheating? Hints:<\/p>\n<ol>\n<li>Constants <a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/perldoc.perl.org\/5.32.0\/constant.html#TECHNICAL-NOTES\" target=\"_blank\" rel=\"noreferrer noopener\">are implemented as subroutines<\/a>.<\/li>\n<li>References allow data to be modified out of scope.<\/li>\n<\/ol>\n<h2>Final notes<\/h2>\n<p>Line 12 demonstrates that a regular expression can be <a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/perldoc.perl.org\/5.8.2\/perlretut.html#Compiling-and-saving-regular-expressions\" target=\"_blank\" rel=\"noreferrer noopener\">pre-compiled<\/a> and stored in a scalar for later use. This is useful as performance optimization when you intend to re-use the same regular expression many times over.<\/p>\n<p>Line 59 demonstrates that <a aria-label=\"undefined (opens in a new tab)\" href=\"https:\/\/perldoc.perl.org\/5.8.2\/functions\/getpwnam.html\" target=\"_blank\" rel=\"noreferrer noopener\">some system library calls<\/a> are available directly in Perl&#8217;s built-in core functionality. Using the built-in functions alleviates some overhead that would otherwise be required to launch an external program and setup the I\/O channels to communicate with it.<\/p>\n<p>Lines 72 and 73 demonstrate the use of <strong>&amp;::<\/strong> as <a href=\"https:\/\/perldoc.perl.org\/perlmod.html#Packages\" target=\"_blank\" aria-label=\"undefined (opens in a new tab)\" rel=\"noreferrer noopener\">a shorthand for <strong>&amp;main::<\/strong><\/a>.<\/p>\n<p>The full source code for this Perl game can be cloned from the git repository available here: <a href=\"https:\/\/pagure.io\/tic-tac-toe.git\" target=\"_blank\" aria-label=\"undefined (opens in a new tab)\" rel=\"noreferrer noopener\">https:\/\/pagure.io\/tic-tac-toe.git<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is the final article to the series demonstrating Perl with Tic-Tac-Toe. This article provides a module that can compute better game moves than the previously presented modules. For fun, the modules chip1.pm through chip3.pm can be incrementally moved out of the hal subdirectory in reverse order. With each chip that is removed, the game [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[48],"tags":[280,1077,135,1078,876,45,42,43,1079,46,47,921,922],"class_list":["post-116023","post","type-post","status-publish","format-standard","hentry","category-fedora-os","tag-ai","tag-array","tag-artificial-intelligence","tag-associative-array","tag-dictionary","tag-fedora","tag-for-developers","tag-for-system-administrators","tag-hash","tag-magazine","tag-news","tag-perl","tag-tic-tac-toe"],"_links":{"self":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/116023","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/comments?post=116023"}],"version-history":[{"count":0,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/116023\/revisions"}],"wp:attachment":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media?parent=116023"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/categories?post=116023"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/tags?post=116023"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}