NB. TTT3D game - 3D code (OpenGL) NB. DanB 2000/09/28 NB. Last mod 2000/10/01 VERSION=: 2j3 NB. This is an add-on to the original TTT code. It must be loaded AFTER it. NB. NOTE: a lot of code was cannibalized from an APL version NB. require 'ttt3d' NB. core code require 'gl3' NB. * These are the form's callback fns ========================== wd=: 11!:0 NB. Window driver - should already be there cubeform_cube_char =: 1&SpinCube cubeform_cube_mmove=: 0: cubeform_cube_mblup=: PlaceUp cubeform_cube_mbrdown=: 0: NB. WINPOPUP not available in this version cubeform_cube_mbldown=: PlaceDown cubeform_cube_paint =: 3 : 0 cubeform_cube_size '' drawlists '' glaSwapBuffers '' ) cubeform_cube_size=: 3 : 0 wh=.glqwh '' glViewport 0 0,wh glMatrixMode GL_PROJECTION glLoadIdentity'' gluPerspective ObsDist,(%/wh),1 10 ) cubeform_Istart_button=: Istart cubeform_Ustart_button=: Ustart cubeform_L0_button=: Level@0: cubeform_L1_button=: Level@1: cubeform_L2_button=: Level@2: cubeform_L3_button=: Level@3: cubeform_ch_button=: Challenge cubeform_credits_button=: 3 : 0 NB. milinta 19990717 show the name of the person who did this t=. 'Tic-Tac-Toe 3D version ',(":VERSION),' by Dan Baronet.' t=.t,CR,'Original in 1978, APL/PC version in 1989, this version 2000.' t=.t,CR,'OpenGL by Alex Kornilovski' wdinfo t ) cubeform_huh_button=: 3 : 0 WIN_VIEWTEXT 'General help'; DESCRIBE ) cubeform_technique_button=: 3 : 0 NB. milinta 19991110 display technique used WIN_VIEWTEXT 'TTT3D Technique used'; TECHNIQUE ) drawtoken=:3 : 0 NB. ==================== NB. draw a box of color y. (could be any form) if. 1 e.y.>1 do. y.=.y.%256 end. NB. normalize color p=.CubeSizeFactor* _1 ^ #: i.8 c=.2 2 2#:2#.y. c polygon 0 1 3 2{p c polygon 0 1 5 4{p c polygon 0 2 6 4{p c polygon 4 5 7 6{p c polygon 1 3 7 5{p c polygon 2 3 7 6{p ) CubeSizeFactor=: 0.033 polygon=: 4 : 0 glColor 4{.x., 0.6 glBegin GL_POLYGON glVertex y. glEnd '' glColor Black,1 glLineWidth 0.6 glBegin GL_LINES glVertex CubeSizeFactor*CUBE glEnd '' ) NB. ==================================== draw1box=: 4 : 0 cpp=.*:cps=.4 y=.1+<.cpp%~{.y. NB. y axis offset s=.{.y.-cpp*y-1 i=.<. s%cps j=.s-cps*i mn=.(cpp*y-1)+1+(cps*i)+j glNewList (1+y.),GL_COMPILE glMatrixMode GL_MODELVIEW glPushMatrix '' glTranslate 0.2*(_1+i), (_1+j), _2+y glLoadName mn drawtoken x. NB. whatever geometric form wanted here glPopMatrix '' glEndList '' ) drawlists=:3 : 0 NB. call when moving the display glClearColor 1 1 1 0 glClear GL_COLOR_BUFFER_BIT + GL_DEPTH_BUFFER_BIT glEnable GL_DEPTH_TEST glMatrixMode GL_MODELVIEW glLoadIdentity'' glEnable GL_BLEND glBlendFunc GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA glTranslate _0.1 _0.1 _2 glRotate AxisTilt ,. 3 3 $ 1 0 0 0 glCallList each 1+i.64 ) drawnewcolor=:3 : 0 NB. call when redrawing the cube with new color glClearColor 1 1 1 0 glClear GL_COLOR_BUFFER_BIT + GL_DEPTH_BUFFER_BIT glEnable GL_DEPTH_TEST glMatrixMode GL_MODELVIEW glLoadIdentity'' glTranslate _0.1 _0.1 _2 glRotate AxisTilt ,. 3 3 $ 1 0 0 0 (X SLOTS O) draw1box each i.64 '' ) Level=: 3 : 0 if. CanChangeLevel do. Force=: y.{0 1 4 25 end. for_i. i.4 do. wd 'set L',(":i),' ',":CanChangeLevel*y.=i end. ) NB. * End of callback fns =========================== Challenge=: 3 : 0 NB. milinta 19990806 challenge user if. WIN_ASK 'Challenge!';'This will start a new game where I will play my best.',LF,'Do you wish to continue ?' do. Istart 69 ChangeLevel 0 Level 0 NB. this will remove tik marks in menu end. ) cursor=: 3 : 0 NB. milinta 20000127 set shape of cursor i.0 0 NB. until available ) draw=: 3 : 0 NB. this code is first called for every new game NB. it assumes that the canvas for drawing the cube already exists glaRC '' glSelectBuffer 100 wd 'pshow;' NB. drawlists '' drawnewcolor '' ) drawpicture=: 4 : 0 NB. this code is used to draw the picture once 'w h' =. glqwh'' glRenderMode GL_SELECT glInitNames'' glPushName _1 glMatrixMode GL_PROJECTION glLoadIdentity'' gluPickMatrix x. , (h-y.) , 0.5 0.5 , 0 0 , w , h gluPerspective ObsDist, (w%h),1 10 drawlists'' glFlush'' selbuf =: glRenderMode GL_RENDER ) newform =: 3 : 0 wd newformWD draw X=:O=:'' wd 'pshow;' ) NB. Create "ttt3d" form that can be closed with the X Windows button. NB. Coords are centered extending about 200 in each direction. newformWD=: 0 : 0 pc cubeform closeok;pn "Tic Tac Toe 3D"; rem * All menus here; menupop "New Game"; menu Istart "I start" "" "Computer starts a new game" ""; menu Ustart "You start" "" "YOU start a new game" ""; menupopz menupop "Options"; menupop "Level"; menu L0 "0" "" "computer plays at random" "easiest"; menu L1 "1" "" "computer plays at random but blocks you" "easy"; menu L2 "2" "" "computer is smarter" "tough"; menu L3 "3" "" "pretty hard to beat if you don't start" "deadly"; menupopz menu ch "Challenge" "" "Nobody's ever beaten me here!" "Unbeatable mode"; menupopz; menupop "Help"; menu huh "What IS this?" "" "Full description" "Detailed help"; menu technique "Technique" "" "How it's done" ""; menu credits "About TTT3D" "" "Who did this" ""; menupopz; rem * Status bar; sbar 1 ; sbarset status 100 "Click on an unused slot"; sbarshow; rem * The image object (a drawing surface); xywh 0 0 180 180;cc cube isigraph ws_clipchildren ws_clipsiblings rightmove bottommove; pas 0 0;pcenter; rem * Form end; ) AxisTilt=: _60 0 0 ChangeLevel=: 3 : 0 NB. milinta 20000126 set global to dis/allow to change level CanChangeLevel=:y. NB. wd 'setenable Level ',":y.>0 ) CR=: 10{a. CUBE=:24 3$1 1 1 1 1 _1 1 1 1 1 _1 1 1 1 1 _1 1 1 1 1 _1 1 _1 _1 1 1 _1 _1 1 _1 1 _1 1 1 _1 _1 1 _1 1 _1 _1 1 1 _1 _1 _1 _1 _1 _1 1 1 _1 1 _1 _1 1 1 _1 _1 1 _1 1 _1 _1 _1 _1 _1 _1 1 _1 _1 _1 DESCRIBE=: 0 : 0 3-D X and Os (Tic-Tac-Toe) The game is played in a cube 4*4*4 and we play one after the other aiming at lining up 4 slots in a row, pretty much like in the traditional 3*3 game. The cube is shown as four planes of 4 by 4 slots represented here by geometric objects (small cubes), all of the same color (white) to start with. To specify the slot you want to play simply click with the mouse on the corresponding small cube. If the location is available its colour will change to GREEN (your colour). IF YOU CAN'T REACH THE PLACE YOU WANT, ROTATE THE ENTIRE CUBE WITH THE ARROW KEYS OR BY DRAGGING THE MOUSE. To win you must line up 4 slots with your color. I, the program, am your opponent. My strength may be specified in the menu. By default I play at "Block" level, meaning that I will block your attempts at lining up 4 slots but I won't use any strategy to win. At the "Easiest" level I play randomly and I won't try to block you. At higher levels I try to foresee a winning situation. The higher the level, the better I am. In "challenge" mode I start at the highest level. You don't stand many chances. To help locating my moves I announce them in the status bar. If I am about to win I will add how many moves you have left. It will look like "I play C12..." where C is the plane's position from the top (A=top, D=bottom) and 12 means "first (closest) row, 2nd leftmost slot" Here's an example. I use 4 planes side by side but on the screen they will be stacked up of course: A B C D 4> . . . . . . . . . . . . . . . . 3> . . . . . . . . . . . . . . . . 2> . . . . . . . . . . x . . . . . 1> . o . . . . . . . . . . . . . . ^ ^ ^ ^ 1 2 3 4 Here, the 'x' is at position C23 and the 'o' at A12. Examples of winning sequences 1: A11 A12 A13 A14 Note that winning slots are 2: D14 D23 D32 D41 always either on the same plane or 3: A31 B31 C31 D31 on a different plane for each slot. 4: A41 B42 C43 D44 The same rule applies to columns 5: A44 B33 C22 D11 and rows...! A B C D 4> 4 . . 5 . 4 . . . . 4 . 2 . . 4 3> 3 . . . 3 . 5 . 3 . . . 3 2 . . 2> . . . . . . . . . 5 . . . . 2 . 1> 1 1 1 1 . . . . . . . . 5 . . 2 ^ ^ ^ ^ 1 2 3 4 You play with the green cubes and I with the blue ones. Use the arrow keys to rotate the whole cube or drag the mouse to rotate the cube and get a better view. When one of us wins I show the winning row in RED. Good luck. Dan Baronet. ) Force=: 2 LineMode=: 0 MaxTilt=: 0 0 40 MinTilt=: _90 0 _40 MDown=: 0 ObsDist=: 24 ORDER=: 48 52 56 60 49 53 57 61 50 54 58 62 51 55 59 63 32 36 40 44 33 37 41 45 34 38 42 46 35 39 43 47 16 20 24 28 17 21 25 29 18 22 26 30 19 23 27 31 0 4 8 12 1 5 9 13 2 6 10 14 3 7 11 15 PlaceDown=: 3 : 'MDown=: 2{. 0".sysdata' NB. Note where the mouse went down PlaceUp=: 3 : 0 NB. milinta 19991110 place token on screen NB. The mouse has just been clicked UP NB. We use coordinates from the top left corner. The mouse uses the BOTTOM left corner. NB. We need to adjust the mouse's position according to the height (3{sysdata) of the form. 'x y' =.pos=.--/2 2$0,1 0 3{xy=. 0 ".sysdata NB. is mouse click position over 15 pixels radius? if. 15<|j./diffxy=.-MDown-2$xy do. NB. yes, spin the cube 0 SpinCube diffxy else. NB. no, must be a selection then over=.-.+./STATE e. 0 1 2 3 10 20 30 NB. any playable slot? over=.over+.+./iu=.40 4 e. STATE NB. did user hit something? iu=. ' won. ',~,>iu#'I';'You' x drawpicture y NB. did s/he hit something? if. #selbuf do. M=:M+(2^32)*0>M=.(((#selbuf)%4),4)$selbuf p,.(ORDER{~p),.d=.WEIGHTS{~p=.<:{:|:M s=.ORDER{~t=:(([ i. >./) d){p if. over do. NB. of course, if the game is over WIN_MSG msg=.'Game over.' NB. simply display the appropriate msg wd 'set status *',iu,msg else. NB. otherwise if. SHOWn do. WIN_MSG 'hit=',":s,pos end. if. s{FREESLOTS do. NB. if the slot is free FREESLOTS=: FREESLOTS *. ALL~:s O=:O,s [ STATE=:STATE + +./"1 Lines=s NB. add to list Moves_s_=:Moves_s_,@{ RotateAngle=: 8 SpinCube=: 4 : 0 NB. SpinCube msg;key;shift;mag;orig NB. milinta 19991107 rotate cube orig=.AxisTilt NB. let's see if we'll move if. x. do. NB. a keyboard move key=.a. i. {.sysdata mag=.RotateAngle NB. magnitude of the change NB. 'key' is one of the arrow keys. AxisTilt=:AxisTilt + mag * --/2 3$166 0 165 168 0 167=key else. mag=. _1|. 0, y.%10 _10 AxisTilt=:AxisTilt + mag end. AxisTilt=:MaxTilt<.MinTilt>.AxisTilt if. -.orig-:AxisTilt do. glpaintx '' end. ) SLOTS=: 4 : 0 NB. show the color of each slot col=. 64$