Sick Gaming
Fedora - Demonstrating Perl with Tic-Tac-Toe, Part 4 - Printable Version

+- Sick Gaming (https://www.sickgaming.net)
+-- Forum: Computers (https://www.sickgaming.net/forum-86.html)
+--- Forum: Linux, FreeBSD, and Unix types (https://www.sickgaming.net/forum-88.html)
+--- Thread: Fedora - Demonstrating Perl with Tic-Tac-Toe, Part 4 (/thread-96470.html)



Fedora - Demonstrating Perl with Tic-Tac-Toe, Part 4 - xSicKxBot - 07-30-2020

Demonstrating Perl with Tic-Tac-Toe, Part 4

<div><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>
<p> <span id="more-31476"></span> </p>
<h2>An example Perl program</h2>
<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>
<pre class="wp-block-preformatted">00 # artificial intelligence chip
01 02 package chip3;
03 require chip2;
04 require chip1;
05 06 use strict;
07 use warnings;
08 09 sub moverama {
10 my $game = shift;
11 my @nums = $game =~ /[1-9]/g;
12 my $rama = qr/[1973]/;
13 my %best;
14 15 for (@nums) {
16 my $ra = $_;
17 next unless $ra =~ $rama;
18 $best{$ra} = 0;
19 for (@nums) {
20 my $ma = $_;
21 next unless $ma =~ $rama;
22 if (($ra-$ma)*(10-$ra-$ma)) {
23 $best{$ra} += 1;
24 }
25 }
26 }
27 28 @nums = sort { $best{$b} &lt;=&gt; $best{$a} } keys %best;
29 30 return $nums[0];
31 }
32 33 sub hal_move {
34 my $game = shift;
35 my $mark = shift;
36 my @mark = @{ shift; };
37 my $move;
38 39 $move = chip2::win_move $game, $mark, \@mark;
40 41 if (not defined $move) {
42 $mark = ($mark eq $mark[0]) ? $mark[1] : $mark[0];
43 $move = chip2::win_move $game, $mark, \@mark;
44 }
45 46 if (not defined $move) {
47 $move = moverama $game;
48 }
49 50 if (not defined $move) {
51 $move = chip1::hal_move $game;
52 }
53 54 return $move;
55 }
56 57 sub complain {
58 print 'Just what do you think you\'re doing, ',
59 ((getpwnam($ENV{'USER'}))[6]||$ENV{'USER'}) =~ s! .*!!r, "?\n";
60 }
61 62 sub import {
63 no strict;
64 no warnings;
65 66 my $p = __PACKAGE__;
67 my $c = caller;
68 69 *{ $c . '::hal_move' } = \&amp;{ $p . '::hal_move' };
70 *{ $c . '::complain' } = \&amp;{ $p . '::complain' };
71 72 if (&amp;::MARKS-&gt;[0] ne &amp;::HAL9K) {
73 @{ &amp;::MARKS } = reverse @{ &amp;::MARKS };
74 }
75 }
76 77 1;
</pre>
<h2>How it works</h2>
<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>
<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>
<ol>
<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>
<li>References allow data to be modified out of scope.</li>
</ol>
<h2>Final notes</h2>
<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>
<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’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>
<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>
<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>
</div>


https://www.sickgaming.net/blog/2020/07/29/demonstrating-perl-with-tic-tac-toe-part-4/