about summary refs log tree commit diff stats
path: root/js/games/nluqo.github.io/~bh/v1ch6
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
committerelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
commit562a9a52d599d9a05f871404050968a5fd282640 (patch)
tree7d3305c1252c043bfe246ccc7deff0056aa6b5ab /js/games/nluqo.github.io/~bh/v1ch6
parent5d012c6c011a9dedf7d0a098e456206244eb5a0f (diff)
downloadtour-562a9a52d599d9a05f871404050968a5fd282640.tar.gz
*
Diffstat (limited to 'js/games/nluqo.github.io/~bh/v1ch6')
-rw-r--r--js/games/nluqo.github.io/~bh/v1ch6/ttt.html1409
-rw-r--r--js/games/nluqo.github.io/~bh/v1ch6/ttt.lg198
-rw-r--r--js/games/nluqo.github.io/~bh/v1ch6/v1ch6.html1409
3 files changed, 3016 insertions, 0 deletions
diff --git a/js/games/nluqo.github.io/~bh/v1ch6/ttt.html b/js/games/nluqo.github.io/~bh/v1ch6/ttt.html
new file mode 100644
index 0000000..0a86e07
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/v1ch6/ttt.html
@@ -0,0 +1,1409 @@
+<HTML>
+<HEAD>
+<TITLE>Computer Science Logo Style vol 1 ch 6: Example: Tic-Tac-Toe</TITLE>
+</HEAD>
+<BODY>
+<CITE>Computer Science Logo Style</CITE> volume 1:
+<CITE>Symbolic Computing</CITE> 2/e Copyright (C) 1997 MIT
+<H1>Example: Tic-Tac-Toe</H1>
+
+<TABLE width="100%"><TR><TD>
+<IMG SRC="../csls1.jpg" ALT="cover photo">
+<TD><TABLE>
+<TR><TD align="right"><CITE><A HREF="http://www.cs.berkeley.edu/~bh/">Brian
+Harvey</A><BR>University of California, Berkeley</CITE>
+<TR><TD align="right"><BR>
+<TR><TD align="right"><A HREF="../pdf/v1ch06.pdf">Download PDF version</A>
+<TR><TD align="right"><A HREF="../v1-toc2.html">Back to Table of Contents</A>
+<TR><TD align="right"><A HREF="../v1ch5/v1ch5.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../v1ch7/v1ch7.html"><STRONG>NEXT</STRONG></A>
+<TR><TD align="right"><A HREF="https://mitpress.mit.edu/books/computer-science-logo-style-second-edition-volume-1">MIT
+Press web page for Computer Science Logo Style</A>
+</TABLE></TABLE>
+
+<HR>
+<P>Program file for this chapter: <A HREF="ttt.lg"><CODE>ttt</CODE></A>
+
+<P>This chapter is the first application of the ideas we've explored to a
+sizable project.  The primary purpose of the chapter is to introduce
+the techniques of <EM>planning</EM> a project, especially the choice of
+how to organize the information needed by the program.  This organization is
+called the <EM>data structure</EM> of the program.  Along the way,
+we'll also see a new data type, the array, and a few other details of Logo
+programming.
+
+<P><H2>The Project</H2>
+
+<P>Tic-tac-toe is not a very challenging game for human beings.  If you're
+an enthusiast, you've probably moved from the basic game to some variant
+like three-dimensional tic-tac-toe on a larger grid.
+
+<P>If you sit down right now to play ordinary three-by-three tic-tac-toe
+with a friend, what will probably happen is that every game will come
+out a tie.  Both you and your friend can probably play perfectly,
+never making a mistake that would allow your opponent to win.
+
+<P>But can you <EM>describe</EM> how you know where to move each turn? 
+Most of the time, you probably aren't even aware of alternative possibilities;
+you just look at the board and instantly know where you want to move.
+That kind of instant knowledge is great for human beings, because
+it makes you a fast player.  But it isn't much help in writing a computer
+program.  For that, you have to know very explicitly what your strategy
+is.
+
+<P>By the way, although the example of tic-tac-toe strategy is a relatively
+trivial one, this issue of instant knowledge versus explicit rules is a hot
+one in modern psychology.  Some cognitive scientists, who think that human
+intelligence works through mechanisms similar to computer programs, maintain
+that when you know how to do something without knowing <EM>how</EM> you know,
+you have an explicit set of rules deep down inside.  It's just that the
+rules have become a habit, so you don't think about them deliberately.
+They're &quot;compiled,&quot; in the jargon of cognitive psychology.  On
+the other hand, some people think that your implicit how-to knowledge is very
+different from the sort of lists of rules that can be captured in a computer
+program.  They think that human thought is profoundly different from the way
+computers work, and that a computer cannot be programmed to simulate the
+full power of human problem-solving.  These people would say, for example,
+that when you look at a tic-tac-toe board you immediately grasp the
+strategic situation as a whole, and your eye is drawn to the best move
+without any need to examine alternatives according to a set of rules.  (You
+might like to try to be aware of your own mental processes as you play a
+game of tic-tac-toe, to try to decide which of these points of view more
+closely resembles your own experience--but on the other hand, the
+psychological validity of such introspective evidence is <EM>another</EM>
+hotly contested issue in psychology!)
+
+<P>&raquo;Before you read further, try to write down a set of strategy rules
+that, if followed consistently, will never lose a game.  Play a few
+games using your rules.  Make sure they work even if the other player
+does something bizarre.
+
+<P>I'm going to number the squares in the tic-tac-toe
+board this way:
+
+<P>
+<TABLE rules="all" frame="void" border="2" noshade><TR><TD align="center" height=30 width=30>1<TD align="center" height=30 width=30>2<TD align="center" height=30 width=30>3<TR><TD align="center" height=30 width=30>4<TD align="center" height=30 width=30>5<TD align="center" height=30 width=30>6<TR><TD align="center" height=30 width=30>7<TD align="center" height=30 width=30>8<TD align="center" height=30 width=30>9</TABLE>
+
+<P>Squares 1, 3, 7, and 9 are <EM>corner squares</EM>.  I'll call
+2, 4, 6, and 8 <EM>edge squares</EM>.  And of course number 5 is the
+<EM>center square</EM>.  I'll use the word <EM>position</EM> to mean
+a specific partly-filled-in board with X and O in certain squares, and
+other squares empty.
+
+<P>One way you might meet my challenge of describing your strategy explicitly
+is to list all the possible sequences of moves up to a certain point
+in the game, then say what move you'd make next in each situation.
+How big would the list have to be?  There are nine possibilities for
+the first move.  For each first move, there are eight possibilities
+for the second move.  If you continue this line of reasoning, you'll
+see that there are nine factorial, or 362880, possible sequences of
+moves.  Your computer may not have enough memory to list
+them all, and you certainly don't have enough patience!
+
+<P>Fortunately, not all these sequences are interesting.  Suppose you
+are describing the rules a computer should use against a human player,
+and suppose the human being moves first.  Then there are, indeed,
+nine possible first moves.  But for each of these, there is only <EM>
+one</EM> possible computer move!  After all, we're programming the computer.
+We get to decide which move it will choose.  Then there are seven
+possible responses by the opponent, and so on.  The number of sequences
+when the human being plays first is 9 times 7 times 5 times 3, or
+945.  If the computer plays first, it will presumably always make
+the single best choice.  Then there are eight possible responses,
+and so on.  In this case the number of possible game sequences is
+8 times 6 times 4 times 2, or 384.  Altogether we have 1329 cases
+to worry about, which is much better than 300,000 but still not an
+enjoyable way to write a computer program.
+
+<P>In fact, though, this number is still too big.  Not all games go for
+a full nine moves before someone wins.  Also, many moves force the
+opponent to a single possible response, even though there are other
+vacant squares on the board.  Another reduction can be achieved by
+taking advantage of <EM>symmetry</EM>.  For example, if X starts in square
+5, any game sequence in which O responds in square 1 is equivalent
+to a sequence in which O responds in square 3, with the board rotated
+90 degrees.  In fact there are only two truly different responses
+to a center-square opening: any corner square, or any edge square.
+
+<P>With all of these factors reducing the number of distinct positions,
+it would probably be possible to list all of them and write
+a strategy program that way.  I'm not sure, though, because I didn't
+want to use that technique.  I was looking for rules expressed in
+more general terms, like &quot;all else being equal, pick a corner rather
+than an edge.&quot;
+
+<P>Why should I prefer a corner?  Each corner square is part of three
+winning combinations.  For example, square 1 is part of <CODE>123</CODE>,
+<CODE>147</CODE>, and <CODE>159</CODE>.  (By expressing these winning combinations as
+three-digit numbers, I've jumped ahead a bit in the story with a preview of how
+the program I wrote represents this information.)  An edge square,
+on the other hand, is only part of two winning combinations.  For
+example, square 2 is part of <CODE>123</CODE> and <CODE>258</CODE>.  Taking a corner
+square makes three winning combinations available to me and unavailable
+to my opponent.
+
+<P>Since I've brought up the subject of winning combinations, how many
+of <EM>them</EM> are there?  Not very many: three horizontal, three vertical,
+and two diagonal.  Eight altogether.  That <EM>is</EM> a reasonable amount
+of information to include in a program, and in fact there is a list
+of the eight winning combinations in this project.
+
+<P>You might, at this point, enjoy playing a few games with the program,
+to see if you can figure out the rules it uses in its strategy.  If
+you accepted my earlier challenge to write down your own set of strategy
+rules, you can compare mine to yours.  Are they the same?  If not,
+are they equally good?
+
+<P>The top-level procedure in this project is called <CODE>ttt</CODE>.  It takes no
+inputs.  When you invoke this procedure, it will ask you if you'd
+like to play first (X) or second (O).  Then you enter moves by typing
+a digit 1-9 for the square you select.  The program draws the game
+board on the Logo graphics screen.
+
+<P>I'm about to start explaining my strategy rules, so stop reading if
+you want to work out your own and haven't done it yet.
+
+<P><H2>Strategy</H2>
+
+<P>The highest-priority and the lowest-priority rules seemed obvious
+to me right away.  The highest-priority are these:
+
+<P>
+
+<P><TABLE><TR><TH>1.&nbsp;&nbsp;<TD>If I can win on this move, do it.
+<TR><TH>2.&nbsp;&nbsp;<TD>If the other player can win on the next move, block that winning
+square.
+</TABLE>
+
+<P>Here are the lowest-priority rules, used only if there is
+nothing suggested more strongly by the board position:
+
+<P><TABLE><TR><TH><EM>n</EM>-2.&nbsp;&nbsp;<TD>Take the center square if it's free.
+<TR><TH><EM>n</EM>-1.&nbsp;&nbsp;<TD>Take a corner square if one is free.
+<TR><TH><EM>n</EM>.&nbsp;&nbsp;<TD>Take whatever is available.
+</TABLE>
+
+<P>The highest priority rules are the ones dealing with the
+most urgent situations: either I or my opponent can win on the next
+move.  The lowest priority ones deal with the least urgent situations,
+in which there is nothing special about the moves already made to
+guide me.
+
+<P>What was harder was to find the rules in between.  I knew that the
+goal of my own tic-tac-toe strategy was to set up a <EM>fork</EM>, a
+board position in which I have two winning moves, so my opponent can
+only block one of them.  Here is an example:
+
+<P>&nbsp;<TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30>o</TABLE>
+
+<P>X can win by playing in square 3 or square 4.  It's O's
+turn, but poor O can only block one of those squares at a time.  Whichever
+O picks, X will then win by picking the other one.
+
+<P>Given this concept of forking, I decided to use it as the next highest
+priority rule:
+
+<P><TABLE><TR><TH>3.&nbsp;&nbsp;<TD>If I can make a move that will set up a fork for myself, do it.
+</TABLE>
+
+<P>That was the end of the easy part.  My first attempt at
+writing the program used only these six rules.  Unfortunately, it
+lost in many different situations.  I needed to add something, but
+I had trouble finding a good rule to add.
+
+<P>My first idea was that rule 4 should be the defensive equivalent of
+rule 3, just as rule 2 is the defensive equivalent of rule 1:
+
+<P><TABLE><TR><TH>4a.&nbsp;&nbsp;<TD>If, on the next move, my opponent can set up a fork, block that
+possibility by moving into the square that is common to his two winning
+combinations.
+</TABLE>
+
+<P>In other words, apply the same search technique to the opponent's
+position that I applied to my own.
+
+<P>This strategy works well in many cases, but not all.  For example,
+here is a sequence of moves under this strategy, with the human player
+moving first:
+
+<P><PRE><TABLE><TR>
+<TD width=150 align="center" valign="bottom"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30><TD align="center" height=30 width=30>&nbsp;<TR><TD align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>&nbsp;<TR><TD align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30><TD align="center" height=30 width=30></TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TR><TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>x<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TR><TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30><TD align="center" height=30 width=30 align="center" height=30 width=30></TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30 align="center" height=30 width=30>o<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TR><TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>x<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TR><TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30><TD align="center" height=30 width=30 align="center" height=30 width=30>x</TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30 align="center" height=30 width=30>o<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TR><TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>x<TD align="center" height=30 width=30 align="center" height=30 width=30>o<TR><TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30><TD align="center" height=30 width=30 align="center" height=30 width=30>x</TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30 align="center" height=30 width=30>o<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TR><TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>x<TD align="center" height=30 width=30 align="center" height=30 width=30>o<TR><TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>x<TD align="center" height=30 width=30 align="center" height=30 width=30>x</TABLE>
+</TABLE></PRE>
+
+<P>In the fourth grid, the computer (playing O) has discovered
+that X can set up a fork by moving in square 6, between the winning
+combinations <CODE>456</CODE> and <CODE>369</CODE>.  The computer moves to block this
+fork.  Unfortunately, X can also set up a fork by moving in squares
+3, 7, or 8.  The computer's move in square 6 has blocked one combination
+of the square-3 fork, but X can still set up the other two.  In the
+fifth grid, X has moved in square 8.  This sets up the winning combinations
+<CODE>258</CODE> and <CODE>789</CODE>.  The computer can only block one of these, and
+X will win on the next move.
+
+<P>Since X has so many forks available, does this mean that the game
+was already hopeless before O moved in square 6?  No.  Here is something
+O could have done:
+
+<P><PRE><TABLE><TR>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30></TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30></TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x</TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TD align="center" height=30 width=30>x</TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TD align="center" height=30 width=30>x</TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>o<TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TD align="center" height=30 width=30>x</TABLE>
+</TABLE></PRE>
+
+<P>In this sequence, the computer's second move is in square
+7.  This move also blocks a fork, but it wasn't chosen for that reason.
+Instead, it was chosen <EM>to force X's next move</EM>.  In the fifth
+grid, X has had to move in square 4, to prevent an immediate win by
+O.  The advantage of this situation for O is that square 4 was <EM>
+not</EM> one of the ones with which X could set up a fork.  O's next move,
+in the sixth grid, is also forced.  But by then the board is too crowded
+for either player to force a win; the game ends in a tie, as usual.
+
+<P>This analysis suggests a different choice for an intermediate-level
+strategy rule, taking the offensive:
+
+<P><TABLE><TR><TH>4b.&nbsp;&nbsp;<TD>If I can make a move that will set up a winning combination
+for myself, do it.
+</TABLE>
+
+<P>Compared to my earlier try, this rule has the benefit of
+simplicity.  It's much easier for the program to look for a single
+winning combination than for a fork, which is two such combinations
+with a common square.
+
+<P>Unfortunately, this simple rule isn't quite good enough.  In the example
+just above, the computer found the winning combination <CODE>147</CODE> in
+which it already had square 1, and the other two were free.  But why
+should it choose to move in square 7 rather than square 4?  If the
+program did choose square 4, then X's move would still be forced,
+into square 7.  We would then have forced X into creating a fork,
+which would defeat the program on the next move.
+
+<P>It seems that there is no choice but to combine the ideas from rules
+4a and 4b:
+
+<P><TABLE><TR><TH>4b.&nbsp;&nbsp;<TD>If I can make a move that will set up a winning combination
+for myself, do it.  But ensure that this move does not force the opponent
+into establishing a fork.
+</TABLE>
+
+<P>What this means is that we are looking for a winning combination
+in which the computer already owns one square and the other two are empty.
+Having found such a combination, we can move in either of its empty squares.
+Whichever we choose, the opponent will be forced to choose the other one
+on the next move.  If one of the two empty squares would create a fork for
+the opponent, then the computer must choose that square and leave the other
+for the opponent.
+
+<P>What if <EM>both</EM> of the empty squares in the combination we find
+would make forks for the opponent?  In that case, we've chosen a bad
+winning combination.  It turns out that there is only one situation
+in which this can happen:
+
+<P><PRE><TABLE><TR>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30></TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30></TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x</TABLE>
+</TABLE></PRE>
+
+<P>Again, the computer is playing O.  After the third grid,
+it is looking for a possible winning combination for itself.  There
+are three possibilities: <CODE>258</CODE>, <CODE>357</CODE>, and <CODE>456</CODE>.
+So far we
+have not given the computer any reason to prefer one over another.
+But here is what happens if the program happens to choose <CODE>357</CODE>:
+
+<P><PRE><TABLE><TR>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30></TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30></TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x</TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30>o<TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x</TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30>o<TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30>x</TABLE>
+</TABLE></PRE>
+
+<P>By this choice, the computer has forced its opponent into
+a fork that will win the game for the opponent.
+If the computer chooses either of the other two possible winning combinations,
+the game ends in a tie.  (All moves after this choice turn out to
+be forced.)
+
+<P>This particular game sequence was very troublesome for me because
+it goes against most of the rules I had chosen earlier.  For one thing,
+the correct choice for the program is any edge square, while the corner
+squares must be avoided.  This is the opposite of the usual priority.
+
+<P>Another point is that this situation contradicts rule 4a (prevent
+forks for the other player) even more sharply than the example we
+considered earlier.  In that example, rule 4a wasn't enough
+guidance to ensure a correct choice, but the correct choice was at
+least <EM>consistent</EM> with the rule.  That is, just blocking a fork
+isn't enough, but threatening a win and <EM>also</EM> blocking a fork
+is better than just threatening a win alone.  This is the meaning
+of rule 4.  But in this new situation, the corner square (the move
+we have to avoid) <EM>does</EM> block a fork, while the edge square (the
+correct move) <EM>doesn't</EM> block a fork!
+
+<P>When I discovered this anomalous case, I was ready to give up on the
+idea of beautiful, general rules.  I almost decided to build into
+the program a special check for this precise board configuration.
+That would have been pretty ugly, I think.  But a shift in viewpoint
+makes this case easier to understand:  What the program must do is
+force the other player's move, and force it in a way that helps the
+computer win.  If one possible winning combination doesn't allow us to
+meet these conditions, the program should try another combination.
+My mistake was to think either about forcing alone (rule 4b) or about
+the opponent's forks alone (rule 4a).
+
+<P>As it turns out, the board situation we've been considering is the only
+one in which a possible winning combination could include two possible
+forks for the opponent.  What's more, in this board situation, it's a
+diagonal combination that gets us in trouble, while a horizontal or
+vertical combination is always okay.  Therefore, I was able to implement
+rule 4 in a way that only considers one possible winning combination by
+setting up the program's data structures so that diagonal combinations
+are the last to be chosen.  This trick makes the program's design less
+than obvious from reading the actual program, but it does save the program
+some effort.
+
+<P><H2>Program Structure and Modularity</H2>
+
+
+<P>Most game programs--in fact, most interactive programs of any
+kind--consist of an initialization section followed by a sequence
+of steps carried out repeatedly.  In the case of the tic-tac-toe game,
+the overall program structure will be something like this:
+
+<P><PRE>to ttt
+initialize
+forever [
+   if <EM>game.is.over</EM> [stop]
+   <EM>record.human.move get.human.move</EM>
+   if <EM>game.is.over</EM> [stop]
+   <EM>record.program.move compute.program.move</EM>
+]
+end
+</PRE>
+
+<P>The parts of this structure shown in <CODE><EM>italics</EM></CODE> are
+just vague ideas.  At this point in the planning, I don't know what inputs
+these procedures might need, for example.  In fact, there may not be
+procedures exactly like this in the final program.  One example is that
+the test that I've called <CODE><EM>game.is.over</EM></CODE> here will actually
+turn out to be two separate tests <CODE>already.wonp</CODE> and <CODE>tiedp</CODE> (using
+a final letter <CODE>p</CODE> to indicate a predicate, following the convention
+established by the Logo primitive predicates).
+
+<P>This half-written procedure introduces a Logo primitive we haven't used
+before: <CODE>forever</CODE>.  It takes a list of Logo instructions as its
+input, and carries out those instructions repeatedly, much as <CODE>repeat</CODE>,
+<CODE>for</CODE>, and <CODE>foreach</CODE> do.  But the number of repetitions is unlimited;
+the repetition stops only if, as in this example, the primitive <CODE>stop</CODE> or
+<CODE>output</CODE> is invoked within the repeated instructions.   <CODE>Forever</CODE> is
+useful when the ending condition can't be predicted in advance, as in a game
+situation in which a player might win at any time.
+
+<P>It may not be obvious why I've planned for one procedure to figure out the
+next move and a separate procedure to record it.  (There are two such pairs
+of procedures, one for the program's moves and the other for the human
+opponent's moves.)  For one thing, I expect that the recording of moves
+will be much the same whether it's the program or the person moving, while
+the decision about where to move will be quite different in the two cases.
+For the program's move we must apply strategy rules; for the human player's
+moves we simply ask the player.  Also, I anticipate that the selection of
+the program's moves, which will be the hardest part of the program, can be
+written in functional style.  The strategy procedure is a function that takes
+the current board position as its input, always returning the same chosen
+square for any given input position.
+
+<P>This project contains 28 procedures.  These procedures can be divided into
+related groups like this:
+
+<P><TABLE>
+<TR><TD>7<TD>overall orchestration
+<TR><TD>6<TD>initialization
+<TR><TD>2<TD>get opponent's moves
+<TR><TD>9<TD>compute program's moves
+<TR><TD>4<TD>draw moves on screen
+</TABLE>
+
+<P>As you might expect, figuring out the computer's strategy
+is the most complex part of the program's job.  But this strategic
+task is still only about a third of the complete program.
+
+<P>The five groups are quite cleanly distinguishable in this project.  There are
+relatively few procedure invocations between groups, compared to the number
+within a group.  It's easy to read the procedures within a group and
+understand how they work without having to think about other parts of the
+program at the same time.
+
+<P>
+The following diagram shows the subprocedure/superprocedure relationships
+within the program, and indicates which procedures are in each of the five
+groups listed above.  Some people find diagrams like this one very helpful in
+understanding the structure of a program.  Other people don't like these
+diagrams at all.  If you find it helpful, you may want to draw such diagrams
+for your own projects.
+
+<P>
+
+<CENTER><IMG SRC="https://people.eecs.berkeley.edu/~bh/v1ch6/tttflow.gif" ALT="figure: tttflow"></CENTER>
+
+
+
+<P>In the diagram, I've circled the names of seven procedures.  If you
+understand the purpose of each of these, then you will understand
+the general structure of the entire program.  (Don't turn to the end and
+read the actual procedures just now.  Instead, see if
+you can understand the following paragraphs just from the diagram.)
+
+<P><CODE>Ttt</CODE> is the top-level procedure for which I gave a rough outline
+earlier.  It calls initialization procedures (<CODE>draw.board</CODE> and <CODE>
+init</CODE>) to set up the game, then repeatedly alternates between the human
+opponent's moves and the program's moves.  It calls <CODE>getmove</CODE> to find
+out the next move by the opponent, <CODE>youplay</CODE> to record that move,
+then <CODE>pickmove</CODE> to compute the program's next move and <CODE>meplay</CODE>
+to record it.
+
+<P><CODE>Make.triples</CODE> translates from one representation of the board
+position to another.  The representation used within <CODE>ttt</CODE> is best
+suited for display and for user interaction, while the representation
+output by <CODE>make.triples</CODE> is best for computing the program's strategy.
+We'll look into data representation more closely later.
+
+<P><CODE>Getmove</CODE> invites the opponent to type in a move.  It ensures that
+the selected move is legal before accepting it.  The output from <CODE>
+getmove</CODE> is a number from 1 to 9 representing the chosen square.
+
+<P><CODE>Pickmove</CODE> figures out the program's next move.  It is the &quot;smartest&quot;
+procedure in the program, embodying the strategy rules I listed earlier.
+It, too, outputs a number from 1 to 9.
+
+<P><CODE>Youplay</CODE> and <CODE>meplay</CODE> are simple procedures that actually carry out
+the moves chosen by the human player and by the program, respectively.
+Each contains only two instructions.  The first invokes <CODE>draw</CODE> to draw
+the move on the screen.  The second modifies the <CODE>position</CODE> array
+to remember that the move has been made.
+
+<P><CODE>Draw</CODE> moves the turtle to the chosen square on the tic-tac-toe board.
+Then it draws either an X or an O.  (We haven't really talked about Logo's
+turtle graphics yet.  If you're not familiar with turtle graphics from
+earlier Logo experience, you can just take this part of the program on faith;
+there's nothing very interesting about it.)
+
+<P>Notice, in the diagram, that the lines representing procedure calls
+come into a box only at the top.  This is one sign of a well-organized
+program:  The dashed boxes in the diagram truly do represent distinct
+parts of the program that don't interact very much.
+
+<P><H2>Data Representation</H2>
+
+<P>I've written several tic-tac-toe programs, in different programming
+languages.  This experience has really taught me about the importance of
+picking a good data representation.  For my first tic-tac-toe
+program, several years ago, I decided without much prior thought that a
+board position should be represented as three lists of numbers, one with X's
+squares, one with O's squares, and one with the free squares.  So this board
+position
+
+<P><PRE>
+<TABLE rules="all" frame="void" border="2">
+<TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o</TABLE>
+</PRE>
+
+<P>could be represented like this:
+
+<P><PRE>make &quot;xsquares [1 4 5]
+make &quot;osquares [2 9]
+make &quot;free [3 6 7 8]
+</PRE>
+
+<P>These three variables would change in value as squares moved
+from <CODE>:free</CODE> to one of the others.  This representation was easy
+to understand, but not very helpful for writing the program!
+
+<P>What questions does a tic-tac-toe program have to answer about the board
+position?  If, for example, the program wants to print a display of the
+position, it must answer questions of the form &quot;Who's in square 4?&quot;
+With the representation shown here, that's not as easy a question as we
+might wish:
+
+<P><PRE>to occupant :square                          ;; old program
+if memberp :square :xsquares [output &quot;x]
+if memberp :square :osquares [output &quot;o]
+output &quot;free
+end
+</PRE>
+
+<P>
+<P>On the other hand, this representation isn't so bad when we're
+accepting a move from the human player and want to make sure it's a legal
+move:
+
+<P><PRE>to freep :square                             ;; old program
+output memberp :square :free
+end
+</PRE>
+
+<P>Along with this representation of the board, my first program used
+a constant list of winning combinations:
+
+<P><PRE>make &quot;wins [[1 2 3] [4 5 6] [7 8 9] [1 4 7] [2 5 8]
+            [3 6 9] [1 5 9] [3 5 7]]
+</PRE>
+
+<P>It also had a list of all possible forks.  I won't bother
+trying to reproduce this very long list for you, since it's not used
+in the current program, but the fork set up by X in the
+board position just above was represented this way:
+
+<P><PRE>[4 [1 7] [5 6]]
+</PRE>
+
+<P>This indicates that square 4 is the pivot of a fork between
+the winning combinations <CODE>[1 4 7]</CODE> and <CODE>[4 5 6]</CODE>.  Each member of the
+complete list of forks was a list like this sample.  The list of forks
+was fairly long.  Each edge square is the pivot of a fork.  Each corner
+square is the pivot of three forks.  The center square is the pivot
+of six forks.  This adds up to 22 forks altogether.
+
+<P>Each time the program wanted to choose a move, it would first check
+all eight possible winning combinations to see if two of the squares
+were occupied by the program and the third one free.  Since any of
+the three squares might be the free one, this is a fairly tricky program
+in itself:
+
+<P><PRE>to checkwin :candidate :mysquares :free      ;; old program
+if memberp first :candidate :free ~
+   [output check1 butfirst :candidate :mysquares]
+if memberp last :candidate :free ~
+   [output check1 butlast :candidate :mysquares]
+if memberp first butfirst :candidate :free ~
+   [output check1 list first :candidate last :candidate :mysquares]
+output &quot;false
+end
+
+to check1 :sublist :mysquares                ;; old program
+output and (memberp first :sublist :mysquares) ~
+           (memberp last :sublist :mysquares)
+end
+</PRE>
+
+<P>This procedure was fairly slow, especially when invoked
+eight times, once for each possible win.  But the procedure to check
+each of the possible forks was even worse!
+
+<P>In the program that I wrote for the first edition of <EM>Computer Science
+Logo Style,</EM> a very different approach is used.  This approach is based on
+the realization that, at any moment, a particular winning combination may be
+free for anyone (all three squares free), available only to one player, or
+not available to anyone.  It's silly for the program to go on checking a
+combination that can't possibly be available.  Instead of a single list of
+wins, the new program has three lists:
+
+<P>
+<TABLE>
+<TR><TD><CODE>mywins</CODE><TD width=30><TD>wins available to the computer
+<TR><TD><CODE>yourwins</CODE><TD width=30><TD>wins available to the opponent
+<TR><TD><CODE>freewins</CODE><TD width=30><TD>wins available to anyone
+</TABLE>
+
+<P>Once I decided to organize the winning combinations in this form,
+another advantage became apparent: for each possible winning combination,
+the program need only remember the squares that are free, not the
+ones that are occupied.  For example, the board position shown above
+would contain these winning combinations, supposing the computer is
+playing X:
+
+<P><PRE>make &quot;mywins [[7] [6] [3 7]]
+make &quot;yourwins [[3 6] [7 8]]
+make &quot;freewins []
+</PRE>
+
+<P>The sublist <CODE>[7]</CODE> of <CODE>:mywins</CODE> indicates that the computer can
+win simply by filling square 7.  This list represents the winning
+combination that was originally represented as <CODE>[1 4 7]</CODE>, but since
+the computer already occupies squares 1 and 4 there is no need to
+remember those numbers.
+
+<P>The process of checking for an immediate win is streamlined with this
+representation for two reasons, compared with the <CODE>checkwin</CODE> procedure
+above.  First, only those combinations in <CODE>:mywins</CODE> must
+be checked, instead of all eight every time.  Second, an immediate
+win can be recognized very simply, because it is just a list with
+one member, like <CODE>[7]</CODE> and <CODE>[6]</CODE> in the example above.  The procedure
+<CODE>single</CODE> looks for such a list:
+
+<P><PRE>to single :list                              ;; old program
+output find [equalp (count ?) 1] :list
+end
+</PRE>
+
+<P>The input to <CODE>single</CODE> is either <CODE>:mywins</CODE>, to find a winning
+move for the computer (rule 1), or <CODE>:yourwins</CODE>, to find and block a
+winning move for the opponent (rule 2).
+
+<P>Although this representation streamlines the strategy computation (the
+<CODE>pickmove</CODE> part of the program), it makes the recording of a move
+quite difficult, because combinations must be moved from one list to
+another.  That part of the program was quite intricate and hard to
+understand.
+
+<P><H2>Arrays</H2>
+
+<P>This new program uses <EM>two</EM> representations, one for the interactive
+part of the program and one for the strategy computation.  The first of these
+is simply a collection of nine words, one per square, each of which is the
+letter X, the letter O, or the number of the square.  With this
+representation, recording a move means changing one of the nine words.
+It would be possible to keep the nine words in a list, and compute a new
+list (only slightly different) after each move.  But Logo provides another
+data type, the <EM>array,</EM> which allows for changing one member
+while keeping the rest unchanged.
+
+<P>If arrays allow for easy modification and lists don't, why not always use
+arrays?  Why did I begin the book with lists?  The answer is that each
+data type has advantages and disadvantages.  The main disadvantage of an
+array is that you must decide in advance how big it will be; there aren't
+any constructors like <CODE>sentence</CODE> to lengthen an array.
+
+<P>In this case, the fixed length of an array is no problem, because a
+tic-tac-toe board has nine squares.  The <CODE>init</CODE> procedure creates
+the position array with the instruction
+
+<P><PRE>make &quot;position {1 2 3 4 5 6 7 8 9}
+</PRE>
+
+<P>The braces <CODE>{}
+</CODE> indicate an array in the same
+way that brackets indicate a list.
+
+<P>If player X moves in square 7, we can record that information
+by saying
+
+<P><PRE><CODE>setitem</CODE> 7 :position &quot;x
+</PRE>
+
+<P>(Of course, the actual instruction in procedures <CODE>meplay</CODE> and
+<CODE>youplay</CODE> uses variables instead of the specific values 7 and X.)
+<CODE>Setitem</CODE> is a command with three inputs: a number indicating which
+member of the array to change, the array itself, and the new value for
+the specified member.
+
+<P>To find out who owns a particular square, we could write this procedure:
+
+<P><PRE>to occupant :square
+output <CODE>item</CODE> :square :position
+end
+</PRE>
+
+<P>(The <CODE>item</CODE> operation can select a member of an array just as
+it can select a member of a list or of a word.)  In fact, though, it turns
+out that I don't have an <CODE>occupant</CODE> procedure in this program.  But the
+parts of the program that examine the board position do use <CODE>item</CODE> in a
+similar way, as in this example:
+
+<P><PRE>to freep :square
+output numberp item :square :position
+end
+</PRE>
+
+<P>To create an array without explicitly listing all of its members, use the
+operation <CODE>array</CODE>.  It takes a number as argument, indicating how many
+members the array should have.  It returns an array of the chosen size, in
+which each member is the empty list.  Your program can then use <CODE>setitem</CODE>
+to assign different values to the members.
+
+<P>The only primitive operation to select a member of an array is <CODE>item</CODE>.
+Word-and-list operations such as <CODE>butfirst</CODE> can't be used with arrays.
+There are operations <CODE>arraytolist</CODE> and <CODE>listtoarray</CODE> to convert
+a collection of information from one data type to the other.
+
+<P><H2>Triples</H2>
+
+<P>The position array works well as a long-term representation for the board
+position, because it's easy to update; it also works well for interaction
+with the human player, because it's easy to find out the status of a
+particular square.  But for computing the program's moves, we need a
+representation that makes it easy to ask questions such as &quot;Is there a
+winning combination for my opponent on the next move?&quot;  That's why, in
+the first edition of these books, I used the representation with three
+lists of possible winning combinations.
+
+<P>When MatthewWright and I wrote the book <EM>Simply Scheme,</EM> we
+decided that the general idea of combinations was a good one, but the three
+lists made the program more complicated than necessary.  Since there are
+only eight possible winning combinations in the first place, it's not so
+slow to keep one list of all of them, and use that list as the basis for
+all the questions we ask in working out the program's strategy.  If the
+current board position is
+
+<P><PRE>
+<TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o</TABLE>
+</PRE>
+
+<P>we represent the three horizontal winning combinations with
+the words <CODE>xo3</CODE>, <CODE>xx6</CODE>, and <CODE>78o</CODE>.  Each combination is
+represented as a three-&quot;letter&quot; word containing an <CODE>x</CODE> or an <CODE>o</CODE>
+for an occupied square, or the square's number for a free square.  By
+using words instead of lists for the combinations, we make the entire
+set of combinations more compact and easier to read.  Each of these words
+is called a <EM>triple.</EM>  The job of procedure <CODE>make.triples</CODE> is
+to combine the information in the position array with a list of the eight
+winning combinations:
+
+<P><PRE>? <U>show make.triples</U>
+[xo3 xx6 78o xx7 ox8 36o xxo 3x7]
+</PRE>
+
+<P><CODE>Make.triples</CODE> takes no inputs because the list of possible
+winning combinations is built into it, and the position array is in <CODE>
+ttt</CODE>'s local variable <CODE>position</CODE>:
+
+<P><PRE>to make.triples
+output map &quot;substitute.triple [123 456 789 147 258 369 159 357]
+end
+
+to substitute.triple :combination
+output map [item ? :position] :combination
+end
+</PRE>
+
+<P>This short subprogram will repay careful attention.  It uses
+<CODE>map</CODE> twice, once in <CODE>make.triples</CODE> to compute a function of
+each possible winning combination, and once in <CODE>substitute.triple</CODE> to
+compute a function of each square in a given combination.  (That latter
+function is the one that looks up the square in the array <CODE>:position</CODE>.)
+
+<P>Once the program can make the list of triples, we can use that to answer
+many questions about the status of the game.  For example, in the top-level
+<CODE>ttt</CODE> procedure we must check on each move whether or not a certain
+player has already won the game.  Here's how:
+
+<P><PRE>to already.wonp :player
+output memberp (word :player :player :player) (make.triples)
+end
+</PRE>
+
+<P>If we had only the <CODE>position</CODE> array to work with, it would be
+complicated to check all the possible winning combinations.  But once we've
+made the list of triples, we can just ask whether the word <CODE>xxx</CODE> or the
+word <CODE>ooo</CODE> appears in that list.
+
+<P>Here is the actual top-level procedure definition:
+
+<P><PRE>to ttt
+local [me you position]
+draw.board
+init
+if equalp :me &quot;x [meplay 5]
+forever [
+  if already.wonp :me [print [I win!] stop]
+  if tiedp [print [Tie game!] stop]
+  youplay getmove                         ;; ask person for move
+  if already.wonp :you [print [You win!] stop]
+  if tiedp [print [Tie game!] stop]
+  meplay pickmove make.triples            ;; compute program's move
+]
+end
+</PRE>
+
+<P>Notice that <CODE>position</CODE> is declared as a local variable.
+Because of Logo's dynamic scope, all of the subprocedures in this project
+can use <CODE>position</CODE> as if it were a global variable, but Logo will
+&quot;clean up&quot; after the game is over.
+
+<P>Two more such quasi-global variables are used to remember whether the
+computer or the human opponent plays first.  The value of <CODE>me</CODE> will be
+either the word <CODE>x</CODE> or the word <CODE>o</CODE>, whichever letter the program
+itself is playing.  Similarly, the value of <CODE>you</CODE> will be <CODE>x</CODE> or
+<CODE>o</CODE> to indicate the letter used by the opponent.  All of these variables
+are given their values by the initialization procedure <CODE>init</CODE>.
+
+<P>This information could have been kept in the form of a single
+<EM>flag variable,</EM> called something like <CODE>mefirst</CODE>, that would
+contain the word <CODE>true</CODE> if the computer is X, or <CODE>false</CODE> if the
+computer is O.  (A flag variable is one whose value is always <CODE>
+true</CODE> or <CODE>false</CODE>, just as a predicate is a procedure whose output is
+<CODE>true</CODE> or <CODE>false</CODE>.)  It would be used something like this:
+
+<P><PRE>if :mefirst [draw &quot;x :square] [draw &quot;o :square]
+</PRE>
+
+<P>But it turned out to be simpler to use two variables and
+just say
+
+<P><PRE>draw :me :square
+</PRE>
+
+<P>
+<P>One detail in the final program that wasn't in my first rough draft is the
+instruction
+
+<P><PRE>if equalp :me &quot;x [meplay 5]
+</PRE>
+
+<P>just before the <CODE>forever</CODE> loop.  It was easier to write the
+loop so that it always gets the human opponent's move first, and then
+computes a move for the program, rather than having two different loops
+depending on which player goes first.  If the program moves first, its
+strategy rules would tell it to choose the center square, because there is
+nothing better to do when the board is empty.  By checking for that case
+before the loop, we are ready to begin the loop with the opponent as the
+next to move.
+
+<P><H2>Variables in the Workspace</H2>
+
+
+<P>There are nine global variables that are part
+of the workspace, entered directly with top-level <CODE>make</CODE> instructions
+rather than set up by <CODE>init</CODE>, because their
+values are never changed. Their names are <CODE>box1</CODE> through <CODE>
+box9</CODE>, and their values are the coordinates on the graphics screen of
+the center of each square.  For example, <CODE>:box1</CODE> is <CODE>
+[-40 50]</CODE>.  These variables are used by <CODE>move</CODE>, a subprocedure of
+<CODE>draw</CODE>, to know where to position the turtle before drawing an X
+or an O.
+
+<P>The use of variables loaded with a workspace file, rather than given values
+by an initialization procedure, is a practice that Logo encourages in some
+ways and discourages in others.  Loading variables in a workspace file makes
+the program start up faster, because it decreases the amount of
+initialization required.  On the other hand, variables are sort of
+second-class citizens in workspace files.  In many versions of Logo the <CODE>
+load</CODE> command lists the names of the procedures in the workspace file, but
+not the names of the variables.  Similarly, <CODE>save</CODE> often reports the
+number of procedures saved, but not the number of variables.  It's easy to
+create global variables and forget that they're there.
+
+<P>Certainly preloading variables makes sense only if the variables are really
+constants; in other words, a variable whose value may change during the
+running of a program should be initialized explicitly when the program
+starts.  Otherwise, the program will probably give incorrect results if you
+run it a second time.  (One of the good ideas in the programming language
+Pascal is that there is a sort of thing in the language called a <EM>
+constant</EM>; it has a name and a value, like a variable, but you can't give
+it a new value in mid-program.  In Logo, you use a global variable to hold a
+constant, and simply refrain from changing its value.  But being able to
+<EM>say</EM> that something is a constant makes the program easier to
+understand.)
+
+<P>One reason the use of preloaded variables is sometimes questioned as a point
+of style is that when people are sloppy in their use of global variables,
+it's hard to know which are really meant to be preloaded and which are just
+left over from running the program.  That is, if you write a program, test
+it by running it, and then save it on a diskette, any global variables that
+were created during the program execution will still be in the workspace
+when you load that diskette file later.  If there are five
+intentionally-loaded variables along with 20 leftovers, it's particularly
+hard for someone to understand which are which.  This is one more reason not
+to use global variables when what you really want are variables local to the
+top-level procedure.
+
+<P><H2>The User Interface</H2>
+
+<P>The only part of the program that really interacts with the human user is
+<CODE>getmove</CODE>, the procedure that asks the user where to move.
+
+<P><PRE>to getmove
+local &quot;square
+forever [
+  type [Your move:]
+  make &quot;square readchar
+  print :square
+  if numberp :square
+     [if and (:square &gt; 0) (:square &lt; 10)
+         [if freep :square [output :square]]]
+  print [not a valid move.]
+]
+end
+</PRE>
+
+<P>There are two noteworthy things about this part of the program.  One is that
+I've chosen to use <CODE>readchar</CODE> to read what the player types.  This
+primitive operation, with no inputs, waits for the user to type any single
+character on the keyboard, and outputs whatever character the user types.
+This &quot;character at a time&quot; interaction is in contrast with the more usual
+&quot;line at a time&quot; typing, in which you can type characters, erase some if
+you make a mistake, and finally use the RETURN or ENTER key to indicate that
+the entire line you've typed should be made available to your program.
+(In Chapter 1 you met Logo's <CODE>readlist</CODE> primitive for line at a
+time typing.)  Notice that if tic-tac-toe had ten or more squares in its
+board I wouldn't have been able to make this choice, because the program
+would have to allow the entry of two-digit numbers.
+
+<P><CODE>Readchar</CODE> was meant for fast-action programs such as video games.
+It therefore does not display (or <EM>echo</EM>) the character that you type
+on the computer screen.  That's why <CODE>getmove</CODE> includes a <CODE>print</CODE>
+instruction to let the user see what she or he has typed!
+
+<P>The second point to note in <CODE>getmove</CODE> is how careful it is to allow for
+the possibility of a user error.  Ordinarily, when one procedure uses a
+value that was computed by another procedure, the programmer can assume that
+the value is a legitimate one for the intended purpose.  For example, when
+you invoke a procedure that computes a number, you assume that you can add
+the output to another number; you don't first use the <CODE>number?</CODE> 
+predicate to double-check that the result was indeed a number.  But in
+<CODE>getmove</CODE> we are dealing with a value that was typed by a human being,
+and human beings are notoriously error-prone!  The user is <EM>supposed</EM>
+to type a number between 1 and 9.  But perhaps someone's finger might slip
+and type a zero instead of a nine, or even some character that isn't a
+number at all.  Therefore, <CODE>getmove</CODE> first checks that what the user
+typed is a number.  If so, it then checks that the number is in the allowed
+range.  (We'd get a Logo error message if <CODE>getmove</CODE> used the <CODE>
+&lt;</CODE> operation with a non-numeric input.)  Only if these conditions are met
+do we use the user's number as the square-selecting input to <CODE>freep</CODE>.
+
+<P><H2>Implementing the Strategy Rules</H2>
+
+<P>To determine the program's next move, <CODE>ttt</CODE> invokes <CODE>pickmove</CODE>;
+since many of the strategy rules will involve an examination of possible
+winning combinations, <CODE>pickmove</CODE> is given the output from <CODE>
+make.triples</CODE> as its input.
+
+<P>The strategy I worked out for the program consists of several rules, in
+order of importance.  So the structure of <CODE>pickmove</CODE> should be something
+like this:
+
+<P><PRE>to pickmove :triples
+if first.rule.works [output first.rule's.square]
+if second.rule.works [output second.rule's.square]
+...
+end
+</PRE>
+
+<P>This structure would work, but it would be very inefficient,
+because the procedure to determine whether a rule is applicable does
+essentially the same work as the procedure to choose a square by following
+the rule.  For example, here's a procedure to decide whether or not the
+program can win on this move:
+
+<P><PRE>to can.i.win.now
+output not emptyp find &quot;win.nowp :triples
+end
+
+to win.nowp :triple
+output equalp (filter [not numberp ?] :triple) (word :me :me)
+end
+</PRE>
+
+<P>The subprocedure <CODE>win.nowp</CODE> decides whether or not a
+particular triple is winnable on this move, by looking for a triple
+containing one number and two letters equal to whichever of X or O
+the program is playing.  For example, <CODE>3xx</CODE> is a winnable triple
+if the program is playing X.
+
+<P>The procedure to pick a move if there is a winnable triple also must
+apply <CODE>win.nowp</CODE> to the triples:
+
+<P><PRE>to find.winning.square
+output filter &quot;numberp find &quot;win.nowp :triples
+end
+</PRE>
+
+<P>If there is a winnable triple <CODE>3xx</CODE>, then the program
+should move in square 3.  We find that out by looking for the number
+within the first winnable triple we can find.
+
+<P>It seems inelegant to find a winnable triple just to see if there are
+any, then find the same triple again to extract a number from it.
+Instead, we take advantage of the fact that the procedure I've called
+<CODE>find.winning.square</CODE> will return a distinguishable value--namely,
+an empty list--if there is no winnable triple.  We say
+
+<P><PRE>to pickmove :triples
+local &quot;try
+make &quot;try find.winning.square
+if not emptyp :try [output :try]
+...
+end
+</PRE>
+
+<P>In fact, instead of the procedure <CODE>find.winning.square</CODE> the
+actual program uses a similar <CODE>find.win</CODE> procedure that takes the
+letter X or O as an input; this allows the same procedure to check both
+rule 1 (can the computer win on this move) and rule 2 (can the opponent
+win on the following move).
+
+<P><CODE>Pickmove</CODE> checks each of the strategy rules with a similar pair of
+instructions:
+
+<P><PRE>make &quot;try something
+if not emptyp :try [output :try]
+</PRE>
+
+<P>Here is the complete procedure:
+
+<P><PRE>to pickmove :triples
+local &quot;try
+make &quot;try find.win :me                 ; rule 1: can computer win?
+if not emptyp :try [output :try]
+make &quot;try find.win :you                ; rule 2: can opponent win?
+if not emptyp :try [output :try]
+make &quot;try find.fork                    ; rule 3: can computer fork?
+if not emptyp :try [output :try]
+make &quot;try find.advance                 ; rule 4: can computer force?
+if not emptyp :try [output :try]
+output find [memberp ? :position] [5 1 3 7 9 2 4 6 8]   ; rules 5-7
+end
+</PRE>
+
+<P>The procedures that check for each rule have a common flavor:  They all
+use <CODE>filter</CODE> and <CODE>find</CODE> to select interesting triples and then
+to select an available square from the chosen triple.  I won't go through
+them in complete detail, but there's one that uses a Logo feature I haven't
+described before.  Here is <CODE>find.fork</CODE>:
+
+<P><PRE>to find.fork
+local &quot;singles
+make &quot;singles singles :me                    ; find triples like 14x, x23
+if emptyp :singles [output []]
+output repeated.number reduce &quot;word :singles ; find square in two triples
+end
+</PRE>
+
+<P>Suppose the computer is playing X and the board looks like this:
+
+<P><PRE>
+<TABLE rules="all" frame="void" border="2">
+<TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o</TABLE>
+</PRE>
+
+<P><CODE>Find.fork</CODE> calls <CODE>singles</CODE> (a straightforward procedure
+that you can read in the complete listing at the end of this chapter) to
+find all the triples containing one X and two vacant squares.  It outputs
+
+<P><PRE>[4x6 x47 3x7]
+</PRE>
+
+<P>indicating that the middle row, the left column, and one of the
+diagonals meet these conditions.  To find a fork, we must find a vacant
+square that is included in two of these triples.  The expression
+
+<P><PRE>reduce &quot;word :singles
+</PRE>
+
+<P>strings these triples together into the word <CODE>
+4x6x473x7</CODE>.  The job of <CODE>repeated.number</CODE> is to find a digit that
+occurs more than once in this word.  Here is the procedure:
+
+<P><PRE>to repeated.number :squares
+output find [memberp ? ?rest] filter &quot;numberp :squares
+end
+</PRE>
+
+<P>The expression
+
+<P><PRE>filter &quot;numberp :squares
+</PRE>
+
+<P>gives us the word <CODE>464737</CODE>, which is the input word with
+the letters removed.  We use <CODE>find</CODE> to find a repeated digit in
+this number.  The new feature is the use of <CODE>?rest</CODE> in the predicate template
+
+<P><PRE>[memberp ? ?rest]
+</PRE>
+
+<P><CODE>?rest</CODE> represents the part of the input to <CODE>find</CODE> (or any
+of the other higher-order functions that understand templates) to the right
+of the value being used as <CODE>?</CODE>.  So in this example, <CODE>find</CODE> first
+computes the value of the expression
+
+<P><PRE>memberp 4 64737
+</PRE>
+
+<P>This happens to be <CODE>true</CODE>, so <CODE>find</CODE> returns the value 4
+without looking at the remaining digits.  But if necessary, <CODE>find</CODE> would
+have gone on to compute
+
+<P><PRE>memberp 6 4737
+memberp 4 737
+memberp 7 37
+memberp 3 7
+memberp 7 "
+</PRE>
+
+<P>(using the empty word as <CODE>?rest</CODE> in the last line) until one
+of these turned out to be true.
+
+<P><H2>Further Explorations</H2>
+
+<P>The obvious first place to look for improvements to this project is
+in the strategy.
+
+<P>At the beginning of the discussion about strategy, I suggested that
+one possibility would be to make a complete list of all possible move
+sequences, with explicit next-move choices recorded for each.  How
+many such sequences are there?  If you write the program in a way
+that considers rotations of the board as equivalent, perhaps not
+very many.  For example, if the computer moves first (in the center,
+of course) there are really only two responses the opponent can make:
+a corner or an edge.  Any corner is equivalent to any other.  From
+that point on, the entire sequence of the game can be forced by the
+computer, to a tie if the opponent played a corner, or to a win if
+the opponent played an edge.  If the opponent moves first, there are
+three cases, center, corner, or edge.  And so on.
+
+<P>An intermediate possibility between the complete list of cases and
+the more general rules I used would be to keep a complete list of
+cases for, say, the first two moves.  After that, general rules could
+be used for the &quot;endgame.&quot;  This is rather like the way people,
+and some computer programs, play chess: they have the openings memorized,
+and don't really have to start thinking until several moves have passed.
+This book-opening approach is particularly appealing to me because
+it would solve the problem of the anomalous sequence that made such
+trouble for me in rule 4.
+
+<P>A completely different approach would be to have no rules at all,
+but instead to write a <EM>learning</EM> program.  The program might
+recognize an immediate win (rule 1) and the threat of an immediate
+loss (rule 2), but otherwise it would move randomly and record the
+results.  If the computer loses a game, it would remember the last
+unforced choice it made in that game, and keep a record to try something
+else in the same situation next time.  The result, after many games,
+would be a complete list of all possible sequences, as I suggested
+first, but the difference is that you wouldn't have to do the figuring
+out of each sequence.  Such learning programs are frequently used
+in the field of artificial intelligence.
+
+<P>It is possible to combine different approaches.  A famous checkers-playing
+program written by Arthur Samuel had several general rules programmed
+in, like the ones in this tic-tac-toe program.  But instead of having
+the rules arranged in a particular priority sequence, the program
+was able to learn how much weight to give each rule, by seeing which
+rules tended to win the game and which tended to lose.
+
+<P>If you're tired of tic-tac-toe, another possibility would be to write
+a program that plays some other game according to a strategy.  Don't
+start with checkers or chess!  Many people have written programs in
+which the computer acts as dealer for a game of Blackjack; you could
+reverse the roles so that you deal the cards, and the computer tries
+to bet with a winning strategy.  Another source of ideas is Martin
+Gardner, author of many books of mathematical games.
+
+<P>
+<TABLE width="100%"><TR><TD><A HREF="../v1-toc2.html">(back to Table of Contents)</A>
+<TD align="right"><A HREF="../v1ch5/v1ch5.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../v1ch7/v1ch7.html"><STRONG>NEXT</STRONG></A>
+</TABLE>
+
+<P><H2>Program Listing</H2>
+
+<PRE>
+;; Overall orchestration
+
+to ttt
+local [me you position]
+draw.board
+init
+if equalp :me "x [meplay 5]
+forever [
+  if already.wonp :me [print [I win!] stop]
+  if tiedp [print [Tie game!] stop]
+  youplay getmove                         ;; ask person for move
+  if already.wonp :you [print [You win!] stop]
+  if tiedp [print [Tie game!] stop]
+  meplay pickmove make.triples            ;; compute program's move
+]
+end
+
+to make.triples
+output map "substitute.triple [123 456 789 147 258 369 159 357]
+end
+
+to substitute.triple :combination
+output map [item ? :position] :combination
+end
+
+to already.wonp :player
+output memberp (word :player :player :player) (make.triples)
+end
+
+to tiedp
+output not reduce "or map.se "numberp arraytolist :position
+end
+
+to youplay :square
+draw :you :square
+setitem :square :position :you
+end
+
+to meplay :square
+draw :me :square
+setitem :square :position :me
+end
+
+;; Initialization
+
+to draw.board
+splitscreen clearscreen hideturtle
+drawline [-20 -50] 0 120
+drawline [20 -50] 0 120
+drawline [-60 -10] 90 120
+drawline [-60 30] 90 120
+end
+
+to drawline :pos :head :len
+penup
+setpos :pos
+setheading :head
+pendown
+forward :len
+end
+
+to init
+make "position {1 2 3 4 5 6 7 8 9}
+print [Do you want to play first (X)]
+type [or second (O)? Type X or O:]
+choose
+print [For each move, type a digit 1-9.]
+end
+
+to choose
+local "side
+forever [
+  make "side readchar
+  pr :side
+  if equalp :side "x [choosex stop]
+  if equalp :side "o [chooseo stop]
+  type [Huh? Type X or O:]
+]
+end
+
+to chooseo
+make "me "x
+make "you "o
+end
+
+to choosex
+make "me "o
+make "you "x
+end
+
+;; Get opponent's moves
+
+to getmove
+local "square
+forever [
+  type [Your move:]
+  make "square readchar
+  print :square
+  if numberp :square ~
+     [if and (:square > 0) (:square < 10)
+         [if freep :square [output :square]]]
+  print [not a valid move.]
+]
+end
+
+to freep :square
+output numberp item :square :position
+end
+
+;; Compute program's moves
+
+to pickmove :triples
+local "try
+make "try find.win :me
+if not emptyp :try [output :try]
+make "try find.win :you
+if not emptyp :try [output :try]
+make "try find.fork
+if not emptyp :try [output :try]
+make "try find.advance
+if not emptyp :try [output :try]
+output find [memberp ? :position] [5 1 3 7 9 2 4 6 8]
+end
+
+to find.win :who
+output filter "numberp find "win.nowp :triples
+end
+
+to win.nowp :triple
+output equalp (filter [not numberp ?] :triple) (word :who :who)
+end
+
+to find.fork
+local "singles
+make "singles singles :me
+if emptyp :singles [output []]
+output repeated.number reduce "word :singles
+end
+
+to singles :who
+output filter [singlep ? :who] :triples
+end
+
+to singlep :triple :who
+output equalp (filter [not numberp ?] :triple) :who
+end
+
+to repeated.number :squares
+output find [memberp ? ?rest] filter "numberp :squares
+end
+
+to find.advance
+output best.move filter "numberp find [singlep ? :me] :triples
+end
+
+to best.move :my.single
+local "your.singles
+if emptyp :my.single [output []]
+make "your.singles singles :you
+if emptyp :your.singles [output first :my.single]
+ifelse (count filter [? = first :my.single]
+                     reduce "word :your.singles) > 1 ~
+       [output first :my.single] ~
+       [output last :my.single]
+end
+
+;; Drawing moves on screen
+
+to draw :who :square
+move :square
+ifelse :who = "x [drawx] [drawo]
+end
+
+to move :square
+penup
+setpos thing word "box :square
+end
+
+to drawo
+pendown
+arc 360 18
+end
+
+to drawx
+setheading 45
+pendown
+repeat 4 [forward 25.5 back 25.5 right 90]
+end
+
+make "box1 [-40 50]
+make "box2 [0 50]
+make "box3 [40 50]
+make "box4 [-40 10]
+make "box5 [0 10]
+make "box6 [40 10]
+make "box7 [-40 -30]
+make "box8 [0 -30]
+make "box9 [40 -30]
+</PRE>
+
+<P><A HREF="../v1-toc2.html">(back to Table of Contents)</A>
+<P><A HREF="../v1ch5/v1ch5.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../v1ch7/v1ch7.html"><STRONG>NEXT</STRONG></A>
+
+<P>
+<ADDRESS>
+<A HREF="../index.html">Brian Harvey</A>, 
+<CODE>bh@cs.berkeley.edu</CODE>
+</ADDRESS>
+</BODY>
+</HTML>
diff --git a/js/games/nluqo.github.io/~bh/v1ch6/ttt.lg b/js/games/nluqo.github.io/~bh/v1ch6/ttt.lg
new file mode 100644
index 0000000..aa1c7a0
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/v1ch6/ttt.lg
@@ -0,0 +1,198 @@
+;; Overall orchestration
+
+to ttt
+local [me you position]
+draw.board
+init
+if equalp :me "x [meplay 5]
+forever [
+  if already.wonp :me [print [I win!] stop]
+  if tiedp [print [Tie game!] stop]
+  youplay getmove                         ;; ask person for move
+  if already.wonp :you [print [You win!] stop]
+  if tiedp [print [Tie game!] stop]
+  meplay pickmove make.triples            ;; compute program's move
+]
+end
+
+to make.triples
+output map "substitute.triple [123 456 789 147 258 369 159 357]
+end
+
+to substitute.triple :combination
+output map [item ? :position] :combination
+end
+
+to already.wonp :player
+output memberp (word :player :player :player) (make.triples)
+end
+
+to tiedp
+output not reduce "or map.se "numberp arraytolist :position
+end
+
+to youplay :square
+draw :you :square
+setitem :square :position :you
+end
+
+to meplay :square
+draw :me :square
+setitem :square :position :me
+end
+
+;; Initialization
+
+to draw.board
+splitscreen clearscreen hideturtle
+drawline [-20 -50] 0 120
+drawline [20 -50] 0 120
+drawline [-60 -10] 90 120
+drawline [-60 30] 90 120
+end
+
+to drawline :pos :head :len
+penup
+setpos :pos
+setheading :head
+pendown
+forward :len
+end
+
+to init
+make "position {1 2 3 4 5 6 7 8 9}
+print [Do you want to play first (X)]
+type [or second (O)? Type X or O:]
+choose
+print [For each move, type a digit 1-9.]
+end
+
+to choose
+local "side
+forever [
+  make "side readchar
+  pr :side
+  if equalp :side "x [choosex stop]
+  if equalp :side "o [chooseo stop]
+  type [Huh? Type X or O:]
+]
+end
+
+to chooseo
+make "me "x
+make "you "o
+end
+
+to choosex
+make "me "o
+make "you "x
+end
+
+;; Get opponent's moves
+
+to getmove
+local "square
+forever [
+  type [Your move:]
+  make "square readchar
+  print :square
+  if numberp :square ~
+     [if and (:square > 0) (:square < 10)
+         [if freep :square [output :square]]]
+  print [not a valid move.]
+]
+end
+
+to freep :square
+output numberp item :square :position
+end
+
+;; Compute program's moves
+
+to pickmove :triples
+local "try
+make "try find.win :me
+if not emptyp :try [output :try]
+make "try find.win :you
+if not emptyp :try [output :try]
+make "try find.fork
+if not emptyp :try [output :try]
+make "try find.advance
+if not emptyp :try [output :try]
+output find [memberp ? :position] [5 1 3 7 9 2 4 6 8]
+end
+
+to find.win :who
+output filter "numberp find "win.nowp :triples
+end
+
+to win.nowp :triple
+output equalp (filter [not numberp ?] :triple) (word :who :who)
+end
+
+to find.fork
+local "singles
+make "singles singles :me
+if emptyp :singles [output []]
+output repeated.number reduce "word :singles
+end
+
+to singles :who
+output filter [singlep ? :who] :triples
+end
+
+to singlep :triple :who
+output equalp (filter [not numberp ?] :triple) :who
+end
+
+to repeated.number :squares
+output find [memberp ? ?rest] filter "numberp :squares
+end
+
+to find.advance
+output best.move filter "numberp find [singlep ? :me] :triples
+end
+
+to best.move :my.single
+local "your.singles
+if emptyp :my.single [output []]
+make "your.singles singles :you
+if emptyp :your.singles [output first :my.single]
+ifelse (count filter [? = first :my.single]
+                     reduce "word :your.singles) > 1 ~
+       [output first :my.single] ~
+       [output last :my.single]
+end
+
+;; Drawing moves on screen
+
+to draw :who :square
+move :square
+ifelse :who = "x [drawx] [drawo]
+end
+
+to move :square
+penup
+setpos thing word "box :square
+end
+
+to drawo
+pendown
+arc 360 18
+end
+
+to drawx
+setheading 45
+pendown
+repeat 4 [forward 25.5 back 25.5 right 90]
+end
+
+make "box1 [-40 50]
+make "box2 [0 50]
+make "box3 [40 50]
+make "box4 [-40 10]
+make "box5 [0 10]
+make "box6 [40 10]
+make "box7 [-40 -30]
+make "box8 [0 -30]
+make "box9 [40 -30]
diff --git a/js/games/nluqo.github.io/~bh/v1ch6/v1ch6.html b/js/games/nluqo.github.io/~bh/v1ch6/v1ch6.html
new file mode 100644
index 0000000..0a86e07
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/v1ch6/v1ch6.html
@@ -0,0 +1,1409 @@
+<HTML>
+<HEAD>
+<TITLE>Computer Science Logo Style vol 1 ch 6: Example: Tic-Tac-Toe</TITLE>
+</HEAD>
+<BODY>
+<CITE>Computer Science Logo Style</CITE> volume 1:
+<CITE>Symbolic Computing</CITE> 2/e Copyright (C) 1997 MIT
+<H1>Example: Tic-Tac-Toe</H1>
+
+<TABLE width="100%"><TR><TD>
+<IMG SRC="../csls1.jpg" ALT="cover photo">
+<TD><TABLE>
+<TR><TD align="right"><CITE><A HREF="http://www.cs.berkeley.edu/~bh/">Brian
+Harvey</A><BR>University of California, Berkeley</CITE>
+<TR><TD align="right"><BR>
+<TR><TD align="right"><A HREF="../pdf/v1ch06.pdf">Download PDF version</A>
+<TR><TD align="right"><A HREF="../v1-toc2.html">Back to Table of Contents</A>
+<TR><TD align="right"><A HREF="../v1ch5/v1ch5.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../v1ch7/v1ch7.html"><STRONG>NEXT</STRONG></A>
+<TR><TD align="right"><A HREF="https://mitpress.mit.edu/books/computer-science-logo-style-second-edition-volume-1">MIT
+Press web page for Computer Science Logo Style</A>
+</TABLE></TABLE>
+
+<HR>
+<P>Program file for this chapter: <A HREF="ttt.lg"><CODE>ttt</CODE></A>
+
+<P>This chapter is the first application of the ideas we've explored to a
+sizable project.  The primary purpose of the chapter is to introduce
+the techniques of <EM>planning</EM> a project, especially the choice of
+how to organize the information needed by the program.  This organization is
+called the <EM>data structure</EM> of the program.  Along the way,
+we'll also see a new data type, the array, and a few other details of Logo
+programming.
+
+<P><H2>The Project</H2>
+
+<P>Tic-tac-toe is not a very challenging game for human beings.  If you're
+an enthusiast, you've probably moved from the basic game to some variant
+like three-dimensional tic-tac-toe on a larger grid.
+
+<P>If you sit down right now to play ordinary three-by-three tic-tac-toe
+with a friend, what will probably happen is that every game will come
+out a tie.  Both you and your friend can probably play perfectly,
+never making a mistake that would allow your opponent to win.
+
+<P>But can you <EM>describe</EM> how you know where to move each turn? 
+Most of the time, you probably aren't even aware of alternative possibilities;
+you just look at the board and instantly know where you want to move.
+That kind of instant knowledge is great for human beings, because
+it makes you a fast player.  But it isn't much help in writing a computer
+program.  For that, you have to know very explicitly what your strategy
+is.
+
+<P>By the way, although the example of tic-tac-toe strategy is a relatively
+trivial one, this issue of instant knowledge versus explicit rules is a hot
+one in modern psychology.  Some cognitive scientists, who think that human
+intelligence works through mechanisms similar to computer programs, maintain
+that when you know how to do something without knowing <EM>how</EM> you know,
+you have an explicit set of rules deep down inside.  It's just that the
+rules have become a habit, so you don't think about them deliberately.
+They're &quot;compiled,&quot; in the jargon of cognitive psychology.  On
+the other hand, some people think that your implicit how-to knowledge is very
+different from the sort of lists of rules that can be captured in a computer
+program.  They think that human thought is profoundly different from the way
+computers work, and that a computer cannot be programmed to simulate the
+full power of human problem-solving.  These people would say, for example,
+that when you look at a tic-tac-toe board you immediately grasp the
+strategic situation as a whole, and your eye is drawn to the best move
+without any need to examine alternatives according to a set of rules.  (You
+might like to try to be aware of your own mental processes as you play a
+game of tic-tac-toe, to try to decide which of these points of view more
+closely resembles your own experience--but on the other hand, the
+psychological validity of such introspective evidence is <EM>another</EM>
+hotly contested issue in psychology!)
+
+<P>&raquo;Before you read further, try to write down a set of strategy rules
+that, if followed consistently, will never lose a game.  Play a few
+games using your rules.  Make sure they work even if the other player
+does something bizarre.
+
+<P>I'm going to number the squares in the tic-tac-toe
+board this way:
+
+<P>
+<TABLE rules="all" frame="void" border="2" noshade><TR><TD align="center" height=30 width=30>1<TD align="center" height=30 width=30>2<TD align="center" height=30 width=30>3<TR><TD align="center" height=30 width=30>4<TD align="center" height=30 width=30>5<TD align="center" height=30 width=30>6<TR><TD align="center" height=30 width=30>7<TD align="center" height=30 width=30>8<TD align="center" height=30 width=30>9</TABLE>
+
+<P>Squares 1, 3, 7, and 9 are <EM>corner squares</EM>.  I'll call
+2, 4, 6, and 8 <EM>edge squares</EM>.  And of course number 5 is the
+<EM>center square</EM>.  I'll use the word <EM>position</EM> to mean
+a specific partly-filled-in board with X and O in certain squares, and
+other squares empty.
+
+<P>One way you might meet my challenge of describing your strategy explicitly
+is to list all the possible sequences of moves up to a certain point
+in the game, then say what move you'd make next in each situation.
+How big would the list have to be?  There are nine possibilities for
+the first move.  For each first move, there are eight possibilities
+for the second move.  If you continue this line of reasoning, you'll
+see that there are nine factorial, or 362880, possible sequences of
+moves.  Your computer may not have enough memory to list
+them all, and you certainly don't have enough patience!
+
+<P>Fortunately, not all these sequences are interesting.  Suppose you
+are describing the rules a computer should use against a human player,
+and suppose the human being moves first.  Then there are, indeed,
+nine possible first moves.  But for each of these, there is only <EM>
+one</EM> possible computer move!  After all, we're programming the computer.
+We get to decide which move it will choose.  Then there are seven
+possible responses by the opponent, and so on.  The number of sequences
+when the human being plays first is 9 times 7 times 5 times 3, or
+945.  If the computer plays first, it will presumably always make
+the single best choice.  Then there are eight possible responses,
+and so on.  In this case the number of possible game sequences is
+8 times 6 times 4 times 2, or 384.  Altogether we have 1329 cases
+to worry about, which is much better than 300,000 but still not an
+enjoyable way to write a computer program.
+
+<P>In fact, though, this number is still too big.  Not all games go for
+a full nine moves before someone wins.  Also, many moves force the
+opponent to a single possible response, even though there are other
+vacant squares on the board.  Another reduction can be achieved by
+taking advantage of <EM>symmetry</EM>.  For example, if X starts in square
+5, any game sequence in which O responds in square 1 is equivalent
+to a sequence in which O responds in square 3, with the board rotated
+90 degrees.  In fact there are only two truly different responses
+to a center-square opening: any corner square, or any edge square.
+
+<P>With all of these factors reducing the number of distinct positions,
+it would probably be possible to list all of them and write
+a strategy program that way.  I'm not sure, though, because I didn't
+want to use that technique.  I was looking for rules expressed in
+more general terms, like &quot;all else being equal, pick a corner rather
+than an edge.&quot;
+
+<P>Why should I prefer a corner?  Each corner square is part of three
+winning combinations.  For example, square 1 is part of <CODE>123</CODE>,
+<CODE>147</CODE>, and <CODE>159</CODE>.  (By expressing these winning combinations as
+three-digit numbers, I've jumped ahead a bit in the story with a preview of how
+the program I wrote represents this information.)  An edge square,
+on the other hand, is only part of two winning combinations.  For
+example, square 2 is part of <CODE>123</CODE> and <CODE>258</CODE>.  Taking a corner
+square makes three winning combinations available to me and unavailable
+to my opponent.
+
+<P>Since I've brought up the subject of winning combinations, how many
+of <EM>them</EM> are there?  Not very many: three horizontal, three vertical,
+and two diagonal.  Eight altogether.  That <EM>is</EM> a reasonable amount
+of information to include in a program, and in fact there is a list
+of the eight winning combinations in this project.
+
+<P>You might, at this point, enjoy playing a few games with the program,
+to see if you can figure out the rules it uses in its strategy.  If
+you accepted my earlier challenge to write down your own set of strategy
+rules, you can compare mine to yours.  Are they the same?  If not,
+are they equally good?
+
+<P>The top-level procedure in this project is called <CODE>ttt</CODE>.  It takes no
+inputs.  When you invoke this procedure, it will ask you if you'd
+like to play first (X) or second (O).  Then you enter moves by typing
+a digit 1-9 for the square you select.  The program draws the game
+board on the Logo graphics screen.
+
+<P>I'm about to start explaining my strategy rules, so stop reading if
+you want to work out your own and haven't done it yet.
+
+<P><H2>Strategy</H2>
+
+<P>The highest-priority and the lowest-priority rules seemed obvious
+to me right away.  The highest-priority are these:
+
+<P>
+
+<P><TABLE><TR><TH>1.&nbsp;&nbsp;<TD>If I can win on this move, do it.
+<TR><TH>2.&nbsp;&nbsp;<TD>If the other player can win on the next move, block that winning
+square.
+</TABLE>
+
+<P>Here are the lowest-priority rules, used only if there is
+nothing suggested more strongly by the board position:
+
+<P><TABLE><TR><TH><EM>n</EM>-2.&nbsp;&nbsp;<TD>Take the center square if it's free.
+<TR><TH><EM>n</EM>-1.&nbsp;&nbsp;<TD>Take a corner square if one is free.
+<TR><TH><EM>n</EM>.&nbsp;&nbsp;<TD>Take whatever is available.
+</TABLE>
+
+<P>The highest priority rules are the ones dealing with the
+most urgent situations: either I or my opponent can win on the next
+move.  The lowest priority ones deal with the least urgent situations,
+in which there is nothing special about the moves already made to
+guide me.
+
+<P>What was harder was to find the rules in between.  I knew that the
+goal of my own tic-tac-toe strategy was to set up a <EM>fork</EM>, a
+board position in which I have two winning moves, so my opponent can
+only block one of them.  Here is an example:
+
+<P>&nbsp;<TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30>o</TABLE>
+
+<P>X can win by playing in square 3 or square 4.  It's O's
+turn, but poor O can only block one of those squares at a time.  Whichever
+O picks, X will then win by picking the other one.
+
+<P>Given this concept of forking, I decided to use it as the next highest
+priority rule:
+
+<P><TABLE><TR><TH>3.&nbsp;&nbsp;<TD>If I can make a move that will set up a fork for myself, do it.
+</TABLE>
+
+<P>That was the end of the easy part.  My first attempt at
+writing the program used only these six rules.  Unfortunately, it
+lost in many different situations.  I needed to add something, but
+I had trouble finding a good rule to add.
+
+<P>My first idea was that rule 4 should be the defensive equivalent of
+rule 3, just as rule 2 is the defensive equivalent of rule 1:
+
+<P><TABLE><TR><TH>4a.&nbsp;&nbsp;<TD>If, on the next move, my opponent can set up a fork, block that
+possibility by moving into the square that is common to his two winning
+combinations.
+</TABLE>
+
+<P>In other words, apply the same search technique to the opponent's
+position that I applied to my own.
+
+<P>This strategy works well in many cases, but not all.  For example,
+here is a sequence of moves under this strategy, with the human player
+moving first:
+
+<P><PRE><TABLE><TR>
+<TD width=150 align="center" valign="bottom"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30><TD align="center" height=30 width=30>&nbsp;<TR><TD align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>&nbsp;<TR><TD align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30><TD align="center" height=30 width=30></TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TR><TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>x<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TR><TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30><TD align="center" height=30 width=30 align="center" height=30 width=30></TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30 align="center" height=30 width=30>o<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TR><TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>x<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TR><TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30><TD align="center" height=30 width=30 align="center" height=30 width=30>x</TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30 align="center" height=30 width=30>o<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TR><TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>x<TD align="center" height=30 width=30 align="center" height=30 width=30>o<TR><TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30><TD align="center" height=30 width=30 align="center" height=30 width=30>x</TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30 align="center" height=30 width=30>o<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TR><TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>x<TD align="center" height=30 width=30 align="center" height=30 width=30>o<TR><TD align="center" height=30 width=30 align="center" height=30 width=30>&nbsp;<TD align="center" height=30 width=30 align="center" height=30 width=30>x<TD align="center" height=30 width=30 align="center" height=30 width=30>x</TABLE>
+</TABLE></PRE>
+
+<P>In the fourth grid, the computer (playing O) has discovered
+that X can set up a fork by moving in square 6, between the winning
+combinations <CODE>456</CODE> and <CODE>369</CODE>.  The computer moves to block this
+fork.  Unfortunately, X can also set up a fork by moving in squares
+3, 7, or 8.  The computer's move in square 6 has blocked one combination
+of the square-3 fork, but X can still set up the other two.  In the
+fifth grid, X has moved in square 8.  This sets up the winning combinations
+<CODE>258</CODE> and <CODE>789</CODE>.  The computer can only block one of these, and
+X will win on the next move.
+
+<P>Since X has so many forks available, does this mean that the game
+was already hopeless before O moved in square 6?  No.  Here is something
+O could have done:
+
+<P><PRE><TABLE><TR>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30></TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30></TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x</TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TD align="center" height=30 width=30>x</TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TD align="center" height=30 width=30>x</TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>o<TR><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TD align="center" height=30 width=30>x</TABLE>
+</TABLE></PRE>
+
+<P>In this sequence, the computer's second move is in square
+7.  This move also blocks a fork, but it wasn't chosen for that reason.
+Instead, it was chosen <EM>to force X's next move</EM>.  In the fifth
+grid, X has had to move in square 4, to prevent an immediate win by
+O.  The advantage of this situation for O is that square 4 was <EM>
+not</EM> one of the ones with which X could set up a fork.  O's next move,
+in the sixth grid, is also forced.  But by then the board is too crowded
+for either player to force a win; the game ends in a tie, as usual.
+
+<P>This analysis suggests a different choice for an intermediate-level
+strategy rule, taking the offensive:
+
+<P><TABLE><TR><TH>4b.&nbsp;&nbsp;<TD>If I can make a move that will set up a winning combination
+for myself, do it.
+</TABLE>
+
+<P>Compared to my earlier try, this rule has the benefit of
+simplicity.  It's much easier for the program to look for a single
+winning combination than for a fork, which is two such combinations
+with a common square.
+
+<P>Unfortunately, this simple rule isn't quite good enough.  In the example
+just above, the computer found the winning combination <CODE>147</CODE> in
+which it already had square 1, and the other two were free.  But why
+should it choose to move in square 7 rather than square 4?  If the
+program did choose square 4, then X's move would still be forced,
+into square 7.  We would then have forced X into creating a fork,
+which would defeat the program on the next move.
+
+<P>It seems that there is no choice but to combine the ideas from rules
+4a and 4b:
+
+<P><TABLE><TR><TH>4b.&nbsp;&nbsp;<TD>If I can make a move that will set up a winning combination
+for myself, do it.  But ensure that this move does not force the opponent
+into establishing a fork.
+</TABLE>
+
+<P>What this means is that we are looking for a winning combination
+in which the computer already owns one square and the other two are empty.
+Having found such a combination, we can move in either of its empty squares.
+Whichever we choose, the opponent will be forced to choose the other one
+on the next move.  If one of the two empty squares would create a fork for
+the opponent, then the computer must choose that square and leave the other
+for the opponent.
+
+<P>What if <EM>both</EM> of the empty squares in the combination we find
+would make forks for the opponent?  In that case, we've chosen a bad
+winning combination.  It turns out that there is only one situation
+in which this can happen:
+
+<P><PRE><TABLE><TR>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30></TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30></TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x</TABLE>
+</TABLE></PRE>
+
+<P>Again, the computer is playing O.  After the third grid,
+it is looking for a possible winning combination for itself.  There
+are three possibilities: <CODE>258</CODE>, <CODE>357</CODE>, and <CODE>456</CODE>.
+So far we
+have not given the computer any reason to prefer one over another.
+But here is what happens if the program happens to choose <CODE>357</CODE>:
+
+<P><PRE><TABLE><TR>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30></TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30></TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x</TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30>o<TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x</TABLE>
+<TD width=150 align="center"><TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30>o<TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TD align="center" height=30 width=30>x</TABLE>
+</TABLE></PRE>
+
+<P>By this choice, the computer has forced its opponent into
+a fork that will win the game for the opponent.
+If the computer chooses either of the other two possible winning combinations,
+the game ends in a tie.  (All moves after this choice turn out to
+be forced.)
+
+<P>This particular game sequence was very troublesome for me because
+it goes against most of the rules I had chosen earlier.  For one thing,
+the correct choice for the program is any edge square, while the corner
+squares must be avoided.  This is the opposite of the usual priority.
+
+<P>Another point is that this situation contradicts rule 4a (prevent
+forks for the other player) even more sharply than the example we
+considered earlier.  In that example, rule 4a wasn't enough
+guidance to ensure a correct choice, but the correct choice was at
+least <EM>consistent</EM> with the rule.  That is, just blocking a fork
+isn't enough, but threatening a win and <EM>also</EM> blocking a fork
+is better than just threatening a win alone.  This is the meaning
+of rule 4.  But in this new situation, the corner square (the move
+we have to avoid) <EM>does</EM> block a fork, while the edge square (the
+correct move) <EM>doesn't</EM> block a fork!
+
+<P>When I discovered this anomalous case, I was ready to give up on the
+idea of beautiful, general rules.  I almost decided to build into
+the program a special check for this precise board configuration.
+That would have been pretty ugly, I think.  But a shift in viewpoint
+makes this case easier to understand:  What the program must do is
+force the other player's move, and force it in a way that helps the
+computer win.  If one possible winning combination doesn't allow us to
+meet these conditions, the program should try another combination.
+My mistake was to think either about forcing alone (rule 4b) or about
+the opponent's forks alone (rule 4a).
+
+<P>As it turns out, the board situation we've been considering is the only
+one in which a possible winning combination could include two possible
+forks for the opponent.  What's more, in this board situation, it's a
+diagonal combination that gets us in trouble, while a horizontal or
+vertical combination is always okay.  Therefore, I was able to implement
+rule 4 in a way that only considers one possible winning combination by
+setting up the program's data structures so that diagonal combinations
+are the last to be chosen.  This trick makes the program's design less
+than obvious from reading the actual program, but it does save the program
+some effort.
+
+<P><H2>Program Structure and Modularity</H2>
+
+
+<P>Most game programs--in fact, most interactive programs of any
+kind--consist of an initialization section followed by a sequence
+of steps carried out repeatedly.  In the case of the tic-tac-toe game,
+the overall program structure will be something like this:
+
+<P><PRE>to ttt
+initialize
+forever [
+   if <EM>game.is.over</EM> [stop]
+   <EM>record.human.move get.human.move</EM>
+   if <EM>game.is.over</EM> [stop]
+   <EM>record.program.move compute.program.move</EM>
+]
+end
+</PRE>
+
+<P>The parts of this structure shown in <CODE><EM>italics</EM></CODE> are
+just vague ideas.  At this point in the planning, I don't know what inputs
+these procedures might need, for example.  In fact, there may not be
+procedures exactly like this in the final program.  One example is that
+the test that I've called <CODE><EM>game.is.over</EM></CODE> here will actually
+turn out to be two separate tests <CODE>already.wonp</CODE> and <CODE>tiedp</CODE> (using
+a final letter <CODE>p</CODE> to indicate a predicate, following the convention
+established by the Logo primitive predicates).
+
+<P>This half-written procedure introduces a Logo primitive we haven't used
+before: <CODE>forever</CODE>.  It takes a list of Logo instructions as its
+input, and carries out those instructions repeatedly, much as <CODE>repeat</CODE>,
+<CODE>for</CODE>, and <CODE>foreach</CODE> do.  But the number of repetitions is unlimited;
+the repetition stops only if, as in this example, the primitive <CODE>stop</CODE> or
+<CODE>output</CODE> is invoked within the repeated instructions.   <CODE>Forever</CODE> is
+useful when the ending condition can't be predicted in advance, as in a game
+situation in which a player might win at any time.
+
+<P>It may not be obvious why I've planned for one procedure to figure out the
+next move and a separate procedure to record it.  (There are two such pairs
+of procedures, one for the program's moves and the other for the human
+opponent's moves.)  For one thing, I expect that the recording of moves
+will be much the same whether it's the program or the person moving, while
+the decision about where to move will be quite different in the two cases.
+For the program's move we must apply strategy rules; for the human player's
+moves we simply ask the player.  Also, I anticipate that the selection of
+the program's moves, which will be the hardest part of the program, can be
+written in functional style.  The strategy procedure is a function that takes
+the current board position as its input, always returning the same chosen
+square for any given input position.
+
+<P>This project contains 28 procedures.  These procedures can be divided into
+related groups like this:
+
+<P><TABLE>
+<TR><TD>7<TD>overall orchestration
+<TR><TD>6<TD>initialization
+<TR><TD>2<TD>get opponent's moves
+<TR><TD>9<TD>compute program's moves
+<TR><TD>4<TD>draw moves on screen
+</TABLE>
+
+<P>As you might expect, figuring out the computer's strategy
+is the most complex part of the program's job.  But this strategic
+task is still only about a third of the complete program.
+
+<P>The five groups are quite cleanly distinguishable in this project.  There are
+relatively few procedure invocations between groups, compared to the number
+within a group.  It's easy to read the procedures within a group and
+understand how they work without having to think about other parts of the
+program at the same time.
+
+<P>
+The following diagram shows the subprocedure/superprocedure relationships
+within the program, and indicates which procedures are in each of the five
+groups listed above.  Some people find diagrams like this one very helpful in
+understanding the structure of a program.  Other people don't like these
+diagrams at all.  If you find it helpful, you may want to draw such diagrams
+for your own projects.
+
+<P>
+
+<CENTER><IMG SRC="https://people.eecs.berkeley.edu/~bh/v1ch6/tttflow.gif" ALT="figure: tttflow"></CENTER>
+
+
+
+<P>In the diagram, I've circled the names of seven procedures.  If you
+understand the purpose of each of these, then you will understand
+the general structure of the entire program.  (Don't turn to the end and
+read the actual procedures just now.  Instead, see if
+you can understand the following paragraphs just from the diagram.)
+
+<P><CODE>Ttt</CODE> is the top-level procedure for which I gave a rough outline
+earlier.  It calls initialization procedures (<CODE>draw.board</CODE> and <CODE>
+init</CODE>) to set up the game, then repeatedly alternates between the human
+opponent's moves and the program's moves.  It calls <CODE>getmove</CODE> to find
+out the next move by the opponent, <CODE>youplay</CODE> to record that move,
+then <CODE>pickmove</CODE> to compute the program's next move and <CODE>meplay</CODE>
+to record it.
+
+<P><CODE>Make.triples</CODE> translates from one representation of the board
+position to another.  The representation used within <CODE>ttt</CODE> is best
+suited for display and for user interaction, while the representation
+output by <CODE>make.triples</CODE> is best for computing the program's strategy.
+We'll look into data representation more closely later.
+
+<P><CODE>Getmove</CODE> invites the opponent to type in a move.  It ensures that
+the selected move is legal before accepting it.  The output from <CODE>
+getmove</CODE> is a number from 1 to 9 representing the chosen square.
+
+<P><CODE>Pickmove</CODE> figures out the program's next move.  It is the &quot;smartest&quot;
+procedure in the program, embodying the strategy rules I listed earlier.
+It, too, outputs a number from 1 to 9.
+
+<P><CODE>Youplay</CODE> and <CODE>meplay</CODE> are simple procedures that actually carry out
+the moves chosen by the human player and by the program, respectively.
+Each contains only two instructions.  The first invokes <CODE>draw</CODE> to draw
+the move on the screen.  The second modifies the <CODE>position</CODE> array
+to remember that the move has been made.
+
+<P><CODE>Draw</CODE> moves the turtle to the chosen square on the tic-tac-toe board.
+Then it draws either an X or an O.  (We haven't really talked about Logo's
+turtle graphics yet.  If you're not familiar with turtle graphics from
+earlier Logo experience, you can just take this part of the program on faith;
+there's nothing very interesting about it.)
+
+<P>Notice, in the diagram, that the lines representing procedure calls
+come into a box only at the top.  This is one sign of a well-organized
+program:  The dashed boxes in the diagram truly do represent distinct
+parts of the program that don't interact very much.
+
+<P><H2>Data Representation</H2>
+
+<P>I've written several tic-tac-toe programs, in different programming
+languages.  This experience has really taught me about the importance of
+picking a good data representation.  For my first tic-tac-toe
+program, several years ago, I decided without much prior thought that a
+board position should be represented as three lists of numbers, one with X's
+squares, one with O's squares, and one with the free squares.  So this board
+position
+
+<P><PRE>
+<TABLE rules="all" frame="void" border="2">
+<TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o</TABLE>
+</PRE>
+
+<P>could be represented like this:
+
+<P><PRE>make &quot;xsquares [1 4 5]
+make &quot;osquares [2 9]
+make &quot;free [3 6 7 8]
+</PRE>
+
+<P>These three variables would change in value as squares moved
+from <CODE>:free</CODE> to one of the others.  This representation was easy
+to understand, but not very helpful for writing the program!
+
+<P>What questions does a tic-tac-toe program have to answer about the board
+position?  If, for example, the program wants to print a display of the
+position, it must answer questions of the form &quot;Who's in square 4?&quot;
+With the representation shown here, that's not as easy a question as we
+might wish:
+
+<P><PRE>to occupant :square                          ;; old program
+if memberp :square :xsquares [output &quot;x]
+if memberp :square :osquares [output &quot;o]
+output &quot;free
+end
+</PRE>
+
+<P>
+<P>On the other hand, this representation isn't so bad when we're
+accepting a move from the human player and want to make sure it's a legal
+move:
+
+<P><PRE>to freep :square                             ;; old program
+output memberp :square :free
+end
+</PRE>
+
+<P>Along with this representation of the board, my first program used
+a constant list of winning combinations:
+
+<P><PRE>make &quot;wins [[1 2 3] [4 5 6] [7 8 9] [1 4 7] [2 5 8]
+            [3 6 9] [1 5 9] [3 5 7]]
+</PRE>
+
+<P>It also had a list of all possible forks.  I won't bother
+trying to reproduce this very long list for you, since it's not used
+in the current program, but the fork set up by X in the
+board position just above was represented this way:
+
+<P><PRE>[4 [1 7] [5 6]]
+</PRE>
+
+<P>This indicates that square 4 is the pivot of a fork between
+the winning combinations <CODE>[1 4 7]</CODE> and <CODE>[4 5 6]</CODE>.  Each member of the
+complete list of forks was a list like this sample.  The list of forks
+was fairly long.  Each edge square is the pivot of a fork.  Each corner
+square is the pivot of three forks.  The center square is the pivot
+of six forks.  This adds up to 22 forks altogether.
+
+<P>Each time the program wanted to choose a move, it would first check
+all eight possible winning combinations to see if two of the squares
+were occupied by the program and the third one free.  Since any of
+the three squares might be the free one, this is a fairly tricky program
+in itself:
+
+<P><PRE>to checkwin :candidate :mysquares :free      ;; old program
+if memberp first :candidate :free ~
+   [output check1 butfirst :candidate :mysquares]
+if memberp last :candidate :free ~
+   [output check1 butlast :candidate :mysquares]
+if memberp first butfirst :candidate :free ~
+   [output check1 list first :candidate last :candidate :mysquares]
+output &quot;false
+end
+
+to check1 :sublist :mysquares                ;; old program
+output and (memberp first :sublist :mysquares) ~
+           (memberp last :sublist :mysquares)
+end
+</PRE>
+
+<P>This procedure was fairly slow, especially when invoked
+eight times, once for each possible win.  But the procedure to check
+each of the possible forks was even worse!
+
+<P>In the program that I wrote for the first edition of <EM>Computer Science
+Logo Style,</EM> a very different approach is used.  This approach is based on
+the realization that, at any moment, a particular winning combination may be
+free for anyone (all three squares free), available only to one player, or
+not available to anyone.  It's silly for the program to go on checking a
+combination that can't possibly be available.  Instead of a single list of
+wins, the new program has three lists:
+
+<P>
+<TABLE>
+<TR><TD><CODE>mywins</CODE><TD width=30><TD>wins available to the computer
+<TR><TD><CODE>yourwins</CODE><TD width=30><TD>wins available to the opponent
+<TR><TD><CODE>freewins</CODE><TD width=30><TD>wins available to anyone
+</TABLE>
+
+<P>Once I decided to organize the winning combinations in this form,
+another advantage became apparent: for each possible winning combination,
+the program need only remember the squares that are free, not the
+ones that are occupied.  For example, the board position shown above
+would contain these winning combinations, supposing the computer is
+playing X:
+
+<P><PRE>make &quot;mywins [[7] [6] [3 7]]
+make &quot;yourwins [[3 6] [7 8]]
+make &quot;freewins []
+</PRE>
+
+<P>The sublist <CODE>[7]</CODE> of <CODE>:mywins</CODE> indicates that the computer can
+win simply by filling square 7.  This list represents the winning
+combination that was originally represented as <CODE>[1 4 7]</CODE>, but since
+the computer already occupies squares 1 and 4 there is no need to
+remember those numbers.
+
+<P>The process of checking for an immediate win is streamlined with this
+representation for two reasons, compared with the <CODE>checkwin</CODE> procedure
+above.  First, only those combinations in <CODE>:mywins</CODE> must
+be checked, instead of all eight every time.  Second, an immediate
+win can be recognized very simply, because it is just a list with
+one member, like <CODE>[7]</CODE> and <CODE>[6]</CODE> in the example above.  The procedure
+<CODE>single</CODE> looks for such a list:
+
+<P><PRE>to single :list                              ;; old program
+output find [equalp (count ?) 1] :list
+end
+</PRE>
+
+<P>The input to <CODE>single</CODE> is either <CODE>:mywins</CODE>, to find a winning
+move for the computer (rule 1), or <CODE>:yourwins</CODE>, to find and block a
+winning move for the opponent (rule 2).
+
+<P>Although this representation streamlines the strategy computation (the
+<CODE>pickmove</CODE> part of the program), it makes the recording of a move
+quite difficult, because combinations must be moved from one list to
+another.  That part of the program was quite intricate and hard to
+understand.
+
+<P><H2>Arrays</H2>
+
+<P>This new program uses <EM>two</EM> representations, one for the interactive
+part of the program and one for the strategy computation.  The first of these
+is simply a collection of nine words, one per square, each of which is the
+letter X, the letter O, or the number of the square.  With this
+representation, recording a move means changing one of the nine words.
+It would be possible to keep the nine words in a list, and compute a new
+list (only slightly different) after each move.  But Logo provides another
+data type, the <EM>array,</EM> which allows for changing one member
+while keeping the rest unchanged.
+
+<P>If arrays allow for easy modification and lists don't, why not always use
+arrays?  Why did I begin the book with lists?  The answer is that each
+data type has advantages and disadvantages.  The main disadvantage of an
+array is that you must decide in advance how big it will be; there aren't
+any constructors like <CODE>sentence</CODE> to lengthen an array.
+
+<P>In this case, the fixed length of an array is no problem, because a
+tic-tac-toe board has nine squares.  The <CODE>init</CODE> procedure creates
+the position array with the instruction
+
+<P><PRE>make &quot;position {1 2 3 4 5 6 7 8 9}
+</PRE>
+
+<P>The braces <CODE>{}
+</CODE> indicate an array in the same
+way that brackets indicate a list.
+
+<P>If player X moves in square 7, we can record that information
+by saying
+
+<P><PRE><CODE>setitem</CODE> 7 :position &quot;x
+</PRE>
+
+<P>(Of course, the actual instruction in procedures <CODE>meplay</CODE> and
+<CODE>youplay</CODE> uses variables instead of the specific values 7 and X.)
+<CODE>Setitem</CODE> is a command with three inputs: a number indicating which
+member of the array to change, the array itself, and the new value for
+the specified member.
+
+<P>To find out who owns a particular square, we could write this procedure:
+
+<P><PRE>to occupant :square
+output <CODE>item</CODE> :square :position
+end
+</PRE>
+
+<P>(The <CODE>item</CODE> operation can select a member of an array just as
+it can select a member of a list or of a word.)  In fact, though, it turns
+out that I don't have an <CODE>occupant</CODE> procedure in this program.  But the
+parts of the program that examine the board position do use <CODE>item</CODE> in a
+similar way, as in this example:
+
+<P><PRE>to freep :square
+output numberp item :square :position
+end
+</PRE>
+
+<P>To create an array without explicitly listing all of its members, use the
+operation <CODE>array</CODE>.  It takes a number as argument, indicating how many
+members the array should have.  It returns an array of the chosen size, in
+which each member is the empty list.  Your program can then use <CODE>setitem</CODE>
+to assign different values to the members.
+
+<P>The only primitive operation to select a member of an array is <CODE>item</CODE>.
+Word-and-list operations such as <CODE>butfirst</CODE> can't be used with arrays.
+There are operations <CODE>arraytolist</CODE> and <CODE>listtoarray</CODE> to convert
+a collection of information from one data type to the other.
+
+<P><H2>Triples</H2>
+
+<P>The position array works well as a long-term representation for the board
+position, because it's easy to update; it also works well for interaction
+with the human player, because it's easy to find out the status of a
+particular square.  But for computing the program's moves, we need a
+representation that makes it easy to ask questions such as &quot;Is there a
+winning combination for my opponent on the next move?&quot;  That's why, in
+the first edition of these books, I used the representation with three
+lists of possible winning combinations.
+
+<P>When MatthewWright and I wrote the book <EM>Simply Scheme,</EM> we
+decided that the general idea of combinations was a good one, but the three
+lists made the program more complicated than necessary.  Since there are
+only eight possible winning combinations in the first place, it's not so
+slow to keep one list of all of them, and use that list as the basis for
+all the questions we ask in working out the program's strategy.  If the
+current board position is
+
+<P><PRE>
+<TABLE rules="all" frame="void" border="2"><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o</TABLE>
+</PRE>
+
+<P>we represent the three horizontal winning combinations with
+the words <CODE>xo3</CODE>, <CODE>xx6</CODE>, and <CODE>78o</CODE>.  Each combination is
+represented as a three-&quot;letter&quot; word containing an <CODE>x</CODE> or an <CODE>o</CODE>
+for an occupied square, or the square's number for a free square.  By
+using words instead of lists for the combinations, we make the entire
+set of combinations more compact and easier to read.  Each of these words
+is called a <EM>triple.</EM>  The job of procedure <CODE>make.triples</CODE> is
+to combine the information in the position array with a list of the eight
+winning combinations:
+
+<P><PRE>? <U>show make.triples</U>
+[xo3 xx6 78o xx7 ox8 36o xxo 3x7]
+</PRE>
+
+<P><CODE>Make.triples</CODE> takes no inputs because the list of possible
+winning combinations is built into it, and the position array is in <CODE>
+ttt</CODE>'s local variable <CODE>position</CODE>:
+
+<P><PRE>to make.triples
+output map &quot;substitute.triple [123 456 789 147 258 369 159 357]
+end
+
+to substitute.triple :combination
+output map [item ? :position] :combination
+end
+</PRE>
+
+<P>This short subprogram will repay careful attention.  It uses
+<CODE>map</CODE> twice, once in <CODE>make.triples</CODE> to compute a function of
+each possible winning combination, and once in <CODE>substitute.triple</CODE> to
+compute a function of each square in a given combination.  (That latter
+function is the one that looks up the square in the array <CODE>:position</CODE>.)
+
+<P>Once the program can make the list of triples, we can use that to answer
+many questions about the status of the game.  For example, in the top-level
+<CODE>ttt</CODE> procedure we must check on each move whether or not a certain
+player has already won the game.  Here's how:
+
+<P><PRE>to already.wonp :player
+output memberp (word :player :player :player) (make.triples)
+end
+</PRE>
+
+<P>If we had only the <CODE>position</CODE> array to work with, it would be
+complicated to check all the possible winning combinations.  But once we've
+made the list of triples, we can just ask whether the word <CODE>xxx</CODE> or the
+word <CODE>ooo</CODE> appears in that list.
+
+<P>Here is the actual top-level procedure definition:
+
+<P><PRE>to ttt
+local [me you position]
+draw.board
+init
+if equalp :me &quot;x [meplay 5]
+forever [
+  if already.wonp :me [print [I win!] stop]
+  if tiedp [print [Tie game!] stop]
+  youplay getmove                         ;; ask person for move
+  if already.wonp :you [print [You win!] stop]
+  if tiedp [print [Tie game!] stop]
+  meplay pickmove make.triples            ;; compute program's move
+]
+end
+</PRE>
+
+<P>Notice that <CODE>position</CODE> is declared as a local variable.
+Because of Logo's dynamic scope, all of the subprocedures in this project
+can use <CODE>position</CODE> as if it were a global variable, but Logo will
+&quot;clean up&quot; after the game is over.
+
+<P>Two more such quasi-global variables are used to remember whether the
+computer or the human opponent plays first.  The value of <CODE>me</CODE> will be
+either the word <CODE>x</CODE> or the word <CODE>o</CODE>, whichever letter the program
+itself is playing.  Similarly, the value of <CODE>you</CODE> will be <CODE>x</CODE> or
+<CODE>o</CODE> to indicate the letter used by the opponent.  All of these variables
+are given their values by the initialization procedure <CODE>init</CODE>.
+
+<P>This information could have been kept in the form of a single
+<EM>flag variable,</EM> called something like <CODE>mefirst</CODE>, that would
+contain the word <CODE>true</CODE> if the computer is X, or <CODE>false</CODE> if the
+computer is O.  (A flag variable is one whose value is always <CODE>
+true</CODE> or <CODE>false</CODE>, just as a predicate is a procedure whose output is
+<CODE>true</CODE> or <CODE>false</CODE>.)  It would be used something like this:
+
+<P><PRE>if :mefirst [draw &quot;x :square] [draw &quot;o :square]
+</PRE>
+
+<P>But it turned out to be simpler to use two variables and
+just say
+
+<P><PRE>draw :me :square
+</PRE>
+
+<P>
+<P>One detail in the final program that wasn't in my first rough draft is the
+instruction
+
+<P><PRE>if equalp :me &quot;x [meplay 5]
+</PRE>
+
+<P>just before the <CODE>forever</CODE> loop.  It was easier to write the
+loop so that it always gets the human opponent's move first, and then
+computes a move for the program, rather than having two different loops
+depending on which player goes first.  If the program moves first, its
+strategy rules would tell it to choose the center square, because there is
+nothing better to do when the board is empty.  By checking for that case
+before the loop, we are ready to begin the loop with the opponent as the
+next to move.
+
+<P><H2>Variables in the Workspace</H2>
+
+
+<P>There are nine global variables that are part
+of the workspace, entered directly with top-level <CODE>make</CODE> instructions
+rather than set up by <CODE>init</CODE>, because their
+values are never changed. Their names are <CODE>box1</CODE> through <CODE>
+box9</CODE>, and their values are the coordinates on the graphics screen of
+the center of each square.  For example, <CODE>:box1</CODE> is <CODE>
+[-40 50]</CODE>.  These variables are used by <CODE>move</CODE>, a subprocedure of
+<CODE>draw</CODE>, to know where to position the turtle before drawing an X
+or an O.
+
+<P>The use of variables loaded with a workspace file, rather than given values
+by an initialization procedure, is a practice that Logo encourages in some
+ways and discourages in others.  Loading variables in a workspace file makes
+the program start up faster, because it decreases the amount of
+initialization required.  On the other hand, variables are sort of
+second-class citizens in workspace files.  In many versions of Logo the <CODE>
+load</CODE> command lists the names of the procedures in the workspace file, but
+not the names of the variables.  Similarly, <CODE>save</CODE> often reports the
+number of procedures saved, but not the number of variables.  It's easy to
+create global variables and forget that they're there.
+
+<P>Certainly preloading variables makes sense only if the variables are really
+constants; in other words, a variable whose value may change during the
+running of a program should be initialized explicitly when the program
+starts.  Otherwise, the program will probably give incorrect results if you
+run it a second time.  (One of the good ideas in the programming language
+Pascal is that there is a sort of thing in the language called a <EM>
+constant</EM>; it has a name and a value, like a variable, but you can't give
+it a new value in mid-program.  In Logo, you use a global variable to hold a
+constant, and simply refrain from changing its value.  But being able to
+<EM>say</EM> that something is a constant makes the program easier to
+understand.)
+
+<P>One reason the use of preloaded variables is sometimes questioned as a point
+of style is that when people are sloppy in their use of global variables,
+it's hard to know which are really meant to be preloaded and which are just
+left over from running the program.  That is, if you write a program, test
+it by running it, and then save it on a diskette, any global variables that
+were created during the program execution will still be in the workspace
+when you load that diskette file later.  If there are five
+intentionally-loaded variables along with 20 leftovers, it's particularly
+hard for someone to understand which are which.  This is one more reason not
+to use global variables when what you really want are variables local to the
+top-level procedure.
+
+<P><H2>The User Interface</H2>
+
+<P>The only part of the program that really interacts with the human user is
+<CODE>getmove</CODE>, the procedure that asks the user where to move.
+
+<P><PRE>to getmove
+local &quot;square
+forever [
+  type [Your move:]
+  make &quot;square readchar
+  print :square
+  if numberp :square
+     [if and (:square &gt; 0) (:square &lt; 10)
+         [if freep :square [output :square]]]
+  print [not a valid move.]
+]
+end
+</PRE>
+
+<P>There are two noteworthy things about this part of the program.  One is that
+I've chosen to use <CODE>readchar</CODE> to read what the player types.  This
+primitive operation, with no inputs, waits for the user to type any single
+character on the keyboard, and outputs whatever character the user types.
+This &quot;character at a time&quot; interaction is in contrast with the more usual
+&quot;line at a time&quot; typing, in which you can type characters, erase some if
+you make a mistake, and finally use the RETURN or ENTER key to indicate that
+the entire line you've typed should be made available to your program.
+(In Chapter 1 you met Logo's <CODE>readlist</CODE> primitive for line at a
+time typing.)  Notice that if tic-tac-toe had ten or more squares in its
+board I wouldn't have been able to make this choice, because the program
+would have to allow the entry of two-digit numbers.
+
+<P><CODE>Readchar</CODE> was meant for fast-action programs such as video games.
+It therefore does not display (or <EM>echo</EM>) the character that you type
+on the computer screen.  That's why <CODE>getmove</CODE> includes a <CODE>print</CODE>
+instruction to let the user see what she or he has typed!
+
+<P>The second point to note in <CODE>getmove</CODE> is how careful it is to allow for
+the possibility of a user error.  Ordinarily, when one procedure uses a
+value that was computed by another procedure, the programmer can assume that
+the value is a legitimate one for the intended purpose.  For example, when
+you invoke a procedure that computes a number, you assume that you can add
+the output to another number; you don't first use the <CODE>number?</CODE> 
+predicate to double-check that the result was indeed a number.  But in
+<CODE>getmove</CODE> we are dealing with a value that was typed by a human being,
+and human beings are notoriously error-prone!  The user is <EM>supposed</EM>
+to type a number between 1 and 9.  But perhaps someone's finger might slip
+and type a zero instead of a nine, or even some character that isn't a
+number at all.  Therefore, <CODE>getmove</CODE> first checks that what the user
+typed is a number.  If so, it then checks that the number is in the allowed
+range.  (We'd get a Logo error message if <CODE>getmove</CODE> used the <CODE>
+&lt;</CODE> operation with a non-numeric input.)  Only if these conditions are met
+do we use the user's number as the square-selecting input to <CODE>freep</CODE>.
+
+<P><H2>Implementing the Strategy Rules</H2>
+
+<P>To determine the program's next move, <CODE>ttt</CODE> invokes <CODE>pickmove</CODE>;
+since many of the strategy rules will involve an examination of possible
+winning combinations, <CODE>pickmove</CODE> is given the output from <CODE>
+make.triples</CODE> as its input.
+
+<P>The strategy I worked out for the program consists of several rules, in
+order of importance.  So the structure of <CODE>pickmove</CODE> should be something
+like this:
+
+<P><PRE>to pickmove :triples
+if first.rule.works [output first.rule's.square]
+if second.rule.works [output second.rule's.square]
+...
+end
+</PRE>
+
+<P>This structure would work, but it would be very inefficient,
+because the procedure to determine whether a rule is applicable does
+essentially the same work as the procedure to choose a square by following
+the rule.  For example, here's a procedure to decide whether or not the
+program can win on this move:
+
+<P><PRE>to can.i.win.now
+output not emptyp find &quot;win.nowp :triples
+end
+
+to win.nowp :triple
+output equalp (filter [not numberp ?] :triple) (word :me :me)
+end
+</PRE>
+
+<P>The subprocedure <CODE>win.nowp</CODE> decides whether or not a
+particular triple is winnable on this move, by looking for a triple
+containing one number and two letters equal to whichever of X or O
+the program is playing.  For example, <CODE>3xx</CODE> is a winnable triple
+if the program is playing X.
+
+<P>The procedure to pick a move if there is a winnable triple also must
+apply <CODE>win.nowp</CODE> to the triples:
+
+<P><PRE>to find.winning.square
+output filter &quot;numberp find &quot;win.nowp :triples
+end
+</PRE>
+
+<P>If there is a winnable triple <CODE>3xx</CODE>, then the program
+should move in square 3.  We find that out by looking for the number
+within the first winnable triple we can find.
+
+<P>It seems inelegant to find a winnable triple just to see if there are
+any, then find the same triple again to extract a number from it.
+Instead, we take advantage of the fact that the procedure I've called
+<CODE>find.winning.square</CODE> will return a distinguishable value--namely,
+an empty list--if there is no winnable triple.  We say
+
+<P><PRE>to pickmove :triples
+local &quot;try
+make &quot;try find.winning.square
+if not emptyp :try [output :try]
+...
+end
+</PRE>
+
+<P>In fact, instead of the procedure <CODE>find.winning.square</CODE> the
+actual program uses a similar <CODE>find.win</CODE> procedure that takes the
+letter X or O as an input; this allows the same procedure to check both
+rule 1 (can the computer win on this move) and rule 2 (can the opponent
+win on the following move).
+
+<P><CODE>Pickmove</CODE> checks each of the strategy rules with a similar pair of
+instructions:
+
+<P><PRE>make &quot;try something
+if not emptyp :try [output :try]
+</PRE>
+
+<P>Here is the complete procedure:
+
+<P><PRE>to pickmove :triples
+local &quot;try
+make &quot;try find.win :me                 ; rule 1: can computer win?
+if not emptyp :try [output :try]
+make &quot;try find.win :you                ; rule 2: can opponent win?
+if not emptyp :try [output :try]
+make &quot;try find.fork                    ; rule 3: can computer fork?
+if not emptyp :try [output :try]
+make &quot;try find.advance                 ; rule 4: can computer force?
+if not emptyp :try [output :try]
+output find [memberp ? :position] [5 1 3 7 9 2 4 6 8]   ; rules 5-7
+end
+</PRE>
+
+<P>The procedures that check for each rule have a common flavor:  They all
+use <CODE>filter</CODE> and <CODE>find</CODE> to select interesting triples and then
+to select an available square from the chosen triple.  I won't go through
+them in complete detail, but there's one that uses a Logo feature I haven't
+described before.  Here is <CODE>find.fork</CODE>:
+
+<P><PRE>to find.fork
+local &quot;singles
+make &quot;singles singles :me                    ; find triples like 14x, x23
+if emptyp :singles [output []]
+output repeated.number reduce &quot;word :singles ; find square in two triples
+end
+</PRE>
+
+<P>Suppose the computer is playing X and the board looks like this:
+
+<P><PRE>
+<TABLE rules="all" frame="void" border="2">
+<TR><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30>o<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30>x<TD align="center" height=30 width=30><TR><TD align="center" height=30 width=30><TD align="center" height=30 width=30><TD align="center" height=30 width=30>o</TABLE>
+</PRE>
+
+<P><CODE>Find.fork</CODE> calls <CODE>singles</CODE> (a straightforward procedure
+that you can read in the complete listing at the end of this chapter) to
+find all the triples containing one X and two vacant squares.  It outputs
+
+<P><PRE>[4x6 x47 3x7]
+</PRE>
+
+<P>indicating that the middle row, the left column, and one of the
+diagonals meet these conditions.  To find a fork, we must find a vacant
+square that is included in two of these triples.  The expression
+
+<P><PRE>reduce &quot;word :singles
+</PRE>
+
+<P>strings these triples together into the word <CODE>
+4x6x473x7</CODE>.  The job of <CODE>repeated.number</CODE> is to find a digit that
+occurs more than once in this word.  Here is the procedure:
+
+<P><PRE>to repeated.number :squares
+output find [memberp ? ?rest] filter &quot;numberp :squares
+end
+</PRE>
+
+<P>The expression
+
+<P><PRE>filter &quot;numberp :squares
+</PRE>
+
+<P>gives us the word <CODE>464737</CODE>, which is the input word with
+the letters removed.  We use <CODE>find</CODE> to find a repeated digit in
+this number.  The new feature is the use of <CODE>?rest</CODE> in the predicate template
+
+<P><PRE>[memberp ? ?rest]
+</PRE>
+
+<P><CODE>?rest</CODE> represents the part of the input to <CODE>find</CODE> (or any
+of the other higher-order functions that understand templates) to the right
+of the value being used as <CODE>?</CODE>.  So in this example, <CODE>find</CODE> first
+computes the value of the expression
+
+<P><PRE>memberp 4 64737
+</PRE>
+
+<P>This happens to be <CODE>true</CODE>, so <CODE>find</CODE> returns the value 4
+without looking at the remaining digits.  But if necessary, <CODE>find</CODE> would
+have gone on to compute
+
+<P><PRE>memberp 6 4737
+memberp 4 737
+memberp 7 37
+memberp 3 7
+memberp 7 "
+</PRE>
+
+<P>(using the empty word as <CODE>?rest</CODE> in the last line) until one
+of these turned out to be true.
+
+<P><H2>Further Explorations</H2>
+
+<P>The obvious first place to look for improvements to this project is
+in the strategy.
+
+<P>At the beginning of the discussion about strategy, I suggested that
+one possibility would be to make a complete list of all possible move
+sequences, with explicit next-move choices recorded for each.  How
+many such sequences are there?  If you write the program in a way
+that considers rotations of the board as equivalent, perhaps not
+very many.  For example, if the computer moves first (in the center,
+of course) there are really only two responses the opponent can make:
+a corner or an edge.  Any corner is equivalent to any other.  From
+that point on, the entire sequence of the game can be forced by the
+computer, to a tie if the opponent played a corner, or to a win if
+the opponent played an edge.  If the opponent moves first, there are
+three cases, center, corner, or edge.  And so on.
+
+<P>An intermediate possibility between the complete list of cases and
+the more general rules I used would be to keep a complete list of
+cases for, say, the first two moves.  After that, general rules could
+be used for the &quot;endgame.&quot;  This is rather like the way people,
+and some computer programs, play chess: they have the openings memorized,
+and don't really have to start thinking until several moves have passed.
+This book-opening approach is particularly appealing to me because
+it would solve the problem of the anomalous sequence that made such
+trouble for me in rule 4.
+
+<P>A completely different approach would be to have no rules at all,
+but instead to write a <EM>learning</EM> program.  The program might
+recognize an immediate win (rule 1) and the threat of an immediate
+loss (rule 2), but otherwise it would move randomly and record the
+results.  If the computer loses a game, it would remember the last
+unforced choice it made in that game, and keep a record to try something
+else in the same situation next time.  The result, after many games,
+would be a complete list of all possible sequences, as I suggested
+first, but the difference is that you wouldn't have to do the figuring
+out of each sequence.  Such learning programs are frequently used
+in the field of artificial intelligence.
+
+<P>It is possible to combine different approaches.  A famous checkers-playing
+program written by Arthur Samuel had several general rules programmed
+in, like the ones in this tic-tac-toe program.  But instead of having
+the rules arranged in a particular priority sequence, the program
+was able to learn how much weight to give each rule, by seeing which
+rules tended to win the game and which tended to lose.
+
+<P>If you're tired of tic-tac-toe, another possibility would be to write
+a program that plays some other game according to a strategy.  Don't
+start with checkers or chess!  Many people have written programs in
+which the computer acts as dealer for a game of Blackjack; you could
+reverse the roles so that you deal the cards, and the computer tries
+to bet with a winning strategy.  Another source of ideas is Martin
+Gardner, author of many books of mathematical games.
+
+<P>
+<TABLE width="100%"><TR><TD><A HREF="../v1-toc2.html">(back to Table of Contents)</A>
+<TD align="right"><A HREF="../v1ch5/v1ch5.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../v1ch7/v1ch7.html"><STRONG>NEXT</STRONG></A>
+</TABLE>
+
+<P><H2>Program Listing</H2>
+
+<PRE>
+;; Overall orchestration
+
+to ttt
+local [me you position]
+draw.board
+init
+if equalp :me "x [meplay 5]
+forever [
+  if already.wonp :me [print [I win!] stop]
+  if tiedp [print [Tie game!] stop]
+  youplay getmove                         ;; ask person for move
+  if already.wonp :you [print [You win!] stop]
+  if tiedp [print [Tie game!] stop]
+  meplay pickmove make.triples            ;; compute program's move
+]
+end
+
+to make.triples
+output map "substitute.triple [123 456 789 147 258 369 159 357]
+end
+
+to substitute.triple :combination
+output map [item ? :position] :combination
+end
+
+to already.wonp :player
+output memberp (word :player :player :player) (make.triples)
+end
+
+to tiedp
+output not reduce "or map.se "numberp arraytolist :position
+end
+
+to youplay :square
+draw :you :square
+setitem :square :position :you
+end
+
+to meplay :square
+draw :me :square
+setitem :square :position :me
+end
+
+;; Initialization
+
+to draw.board
+splitscreen clearscreen hideturtle
+drawline [-20 -50] 0 120
+drawline [20 -50] 0 120
+drawline [-60 -10] 90 120
+drawline [-60 30] 90 120
+end
+
+to drawline :pos :head :len
+penup
+setpos :pos
+setheading :head
+pendown
+forward :len
+end
+
+to init
+make "position {1 2 3 4 5 6 7 8 9}
+print [Do you want to play first (X)]
+type [or second (O)? Type X or O:]
+choose
+print [For each move, type a digit 1-9.]
+end
+
+to choose
+local "side
+forever [
+  make "side readchar
+  pr :side
+  if equalp :side "x [choosex stop]
+  if equalp :side "o [chooseo stop]
+  type [Huh? Type X or O:]
+]
+end
+
+to chooseo
+make "me "x
+make "you "o
+end
+
+to choosex
+make "me "o
+make "you "x
+end
+
+;; Get opponent's moves
+
+to getmove
+local "square
+forever [
+  type [Your move:]
+  make "square readchar
+  print :square
+  if numberp :square ~
+     [if and (:square > 0) (:square < 10)
+         [if freep :square [output :square]]]
+  print [not a valid move.]
+]
+end
+
+to freep :square
+output numberp item :square :position
+end
+
+;; Compute program's moves
+
+to pickmove :triples
+local "try
+make "try find.win :me
+if not emptyp :try [output :try]
+make "try find.win :you
+if not emptyp :try [output :try]
+make "try find.fork
+if not emptyp :try [output :try]
+make "try find.advance
+if not emptyp :try [output :try]
+output find [memberp ? :position] [5 1 3 7 9 2 4 6 8]
+end
+
+to find.win :who
+output filter "numberp find "win.nowp :triples
+end
+
+to win.nowp :triple
+output equalp (filter [not numberp ?] :triple) (word :who :who)
+end
+
+to find.fork
+local "singles
+make "singles singles :me
+if emptyp :singles [output []]
+output repeated.number reduce "word :singles
+end
+
+to singles :who
+output filter [singlep ? :who] :triples
+end
+
+to singlep :triple :who
+output equalp (filter [not numberp ?] :triple) :who
+end
+
+to repeated.number :squares
+output find [memberp ? ?rest] filter "numberp :squares
+end
+
+to find.advance
+output best.move filter "numberp find [singlep ? :me] :triples
+end
+
+to best.move :my.single
+local "your.singles
+if emptyp :my.single [output []]
+make "your.singles singles :you
+if emptyp :your.singles [output first :my.single]
+ifelse (count filter [? = first :my.single]
+                     reduce "word :your.singles) > 1 ~
+       [output first :my.single] ~
+       [output last :my.single]
+end
+
+;; Drawing moves on screen
+
+to draw :who :square
+move :square
+ifelse :who = "x [drawx] [drawo]
+end
+
+to move :square
+penup
+setpos thing word "box :square
+end
+
+to drawo
+pendown
+arc 360 18
+end
+
+to drawx
+setheading 45
+pendown
+repeat 4 [forward 25.5 back 25.5 right 90]
+end
+
+make "box1 [-40 50]
+make "box2 [0 50]
+make "box3 [40 50]
+make "box4 [-40 10]
+make "box5 [0 10]
+make "box6 [40 10]
+make "box7 [-40 -30]
+make "box8 [0 -30]
+make "box9 [40 -30]
+</PRE>
+
+<P><A HREF="../v1-toc2.html">(back to Table of Contents)</A>
+<P><A HREF="../v1ch5/v1ch5.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../v1ch7/v1ch7.html"><STRONG>NEXT</STRONG></A>
+
+<P>
+<ADDRESS>
+<A HREF="../index.html">Brian Harvey</A>, 
+<CODE>bh@cs.berkeley.edu</CODE>
+</ADDRESS>
+</BODY>
+</HTML>