import java.applet.Applet; import java.awt.event.*; import java.awt.*; import java.awt.geom.*; class TextCanvas extends DBCanvas { Canvas C; int panel; int toggle; int SIZE; String[] S=new String[10]; int button; Color[] COL=new Color[4]; PlayingBoard control1,control2; TextCanvas(int SIZE) { this.SIZE=SIZE; this.C=C; panel=1; for(int i=1;i<=8;++i) S[i]=""; COL[1]=Color.white; COL[2]=Color.white; } public void paint(Graphics gfx) { Graphics2D g=(Graphics2D) gfx; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); if(panel==1) { S[1]="Welcome to Lucy and Lily. Here are the parts of the game:"; S[2]=""; S[3]="-- This is the tutorial. Use the NEXT/BACK buttons to scroll."; S[4]="-- The big black windows are the playing boards."; S[5]="-- The medium-sized black windows are the view ports."; S[6]="-- The window with the buttons is the control panel."; S[7]=""; S[8]="The next few panels explain these parts in detail."; } if(panel==2) { S[1]="Playing Boards:"; S[2]=""; S[3]="Each playing board has a pentagon in it. Clicking on the Pentagon"; S[4]="causes it to flip over and occupy the position indicated by its"; S[5]="colored shadow. The initial position is marked by a blue marker."; S[6]="The pentagons in each of the two playing boards are linked together,"; S[7]="in a color coded way. A move on one forces a move on the other one."; S[8]="Try moving the pentagons around by clicking on them."; } if(panel==3) { S[1]="View Ports:"; S[2]=""; S[3]="The left/right view port records in miniature the objects"; S[4]="on the left/right playing board. The small blue square marks off the"; S[5]="visible part of the playing board. Clicking on the view port recenters"; S[6]="the blue square and thereby also recenters the playing board."; S[7]="In this way, you can move the pentagon around on a much bigger space"; S[8]="than is actually visible at any one time. Try clicking on the view ports."; } if(panel==4) { S[1]="Control Panel: "; S[2]="- The RESET button returns the pentagons to their initial positions."; S[3]="- A numbered button moves the pentagons, randomly, that many moves."; S[4]="- The HIDE button hides the objects in the playing board and view port."; S[5]=" Clicked again, the HIDE button reveals these objects."; S[6]="- The + and - buttons resize the pentagons, within limits."; S[7]="-The BUFFER button toggles the way the graphics are computed."; S[8]=" Click it only if the applet seems to be stalling."; } if(panel==5) { S[1]="How to Play the Single Game:"; S[2]="Click one of the hide buttons to cover up two of the windows,"; S[3]="then click one of the numbered buttons."; S[4]="The goal of the game is to return the pentagon to its initial position."; S[5]="How to Play the Double Game"; S[6]="Uncover all windows and then click one of the numbered buttons."; S[7]="The goal is to simultaneously return the pentagons to their initial positions."; S[8]="The Double Game has a simple winning strategy."; } if(panel==6) { S[1]="How to Win the Double Game: "; S[2]="Call the pentagon on the left Lucy."; S[3]="Call the pentagon on the right Lily"; S[4]="Lucy and Lily are the names of my daughters."; S[5]="Step 1: Move Lucy as directly as possible towards the blue marker."; S[6]="Step 2: Repeat Step 1 for Lily."; S[7]="Step 3: Repeat Step 1 for Lucy."; S[8]="And so on. After a finite number of steps, you will have won."; } if(panel==7) { S[1]="Why the Winning Strategy Works."; S[2]="When you move Lucy directly towards the origin, you do so by"; S[3]="clicking on non-adjacent colors. Here is the important point:"; S[4]="Non-adjacent colors on Lucy are adjacent on Lily and vice-versa."; S[5]="So, when Lucy is moving quickly, Lily is moving slowly,"; S[6]="in some direction or other. Thus, two steps of the strategy decrease the"; S[7]="combined distance from Lucy/Lily to the origin."; S[8]="This is half of the explanation."; } if(panel==8) { S[1]="For the other half of the explanation, we have the"; S[2]=""; S[3]="Finiteness Claim: For any N there are only finitely many positions"; S[4]="of Lucy and Lily such that the combined distance from Lucy/Lily"; S[5]="to the origin is less than N."; S[6]=""; S[7]="Assuming the Finiteness Claim, the strategy steadily reduces the number of"; S[8]="possible positions until only the winning one remains."; } if(panel==9) { S[1]="Proof of the Finiteness Claim:"; S[2]="First of all, think of the playing board as C, the complex plane."; S[3]="Define w=cos(2 Pi/5)+ i sin(2 Pi/5). Note that w^5=1;"; S[4]="Let X=Z[w], the ring of numbers of the form"; S[5]=" a0+a1*w+a2*w^2+a3*w^3+a4*w^4. Here a0,...,a4 are integers."; S[6]="When properly scaled, Lucy is always centered at a point x in X."; S[7]="When properly scaled, Lily is always centered at a y=f(x) in X."; S[8]=""; } if(panel==10) { S[1]="It turns out that the function f has the formula:"; S[2]=""; S[3]="f(a0+a1*w^1+a2*w^2+a3*w^3+a4*w^4)="; S[4]=" a0+a1*w^2+a2*w^4+a3*w^6+a4*w^8="; S[5]=" a0+a3*w^1+a1*w^2+a4*w^3+a2*w^4. (since w^5=1)"; S[6]=""; S[7]="(In technical terms, f is the restriction, to the ring of integers,"; S[8]="of the automorphism generating the Galois group of the field Q[w].)"; } if(panel==11) { S[1]="Just as with ordinary functions, one can plot the graph of f."; S[2]="That is, one can look at the set G={(x,f(x))| x in X} in the"; S[3]="4 dimensional space C^2. Amazingly, G is a 4-dimensional"; S[4]="grid of points. (This is a special case of a general result"; S[5]="about algebraic number rings.)"; S[6]="One should think of Lucy and Lily as two shadows of a"; S[7]="4-dimensional object L=(Lucy,Lily), which moves around"; S[8]="on the grid G in towards the origin."; } if(panel==12) { S[1]=""; S[2]="If the combined distance from Lucy/Lily to the origin."; S[3]="is less than N then L is contained in the ball of radius N"; S[4]="centered at the origin. In any grid there are only finitely many"; S[5]="points in any ball and so L can only be in finitely many positions."; S[6]="This proves the Finiteness Claim."; S[7]=""; S[8]=""; } g.setColor(Color.white); g.setFont(new Font("Helvetica",Font.PLAIN,12)); for(int i=1;i<=8;++i) { g.drawString(S[i],15,15+i*SIZE/25); } if(panel==1) g.drawString("1",SIZE+80,SIZE/2-8); if(panel==2) g.drawString("2",SIZE+80,SIZE/2-8); if(panel==3) g.drawString("3",SIZE+80,SIZE/2-8); if(panel==4) g.drawString("4",SIZE+80,SIZE/2-8); if(panel==5) g.drawString("5",SIZE+80,SIZE/2-8); if(panel==6) g.drawString("6",SIZE+80,SIZE/2-8); if(panel==7) g.drawString("7",SIZE+80,SIZE/2-8); if(panel==8) g.drawString("8",SIZE+80,SIZE/2-8); if(panel==9) g.drawString("9",SIZE+80,SIZE/2-8); if(panel==10) g.drawString("10",SIZE+80,SIZE/2-8); if(panel==11) g.drawString("11",SIZE+80,SIZE/2-8); if(panel==12) g.drawString("12",SIZE+80,SIZE/2-8); } TextCanvas control1(PlayingBoard X) { TextCanvas Y=this; Y.control1=X; return(Y); } TextCanvas control2(PlayingBoard X) { TextCanvas Y=this; Y.control2=X; return(Y); } }