@@ -14,7 +14,7 @@ var TicTacToe4D = (function() {
1414 var plankThickness = 0.04 ; //how thick the barrier planks are
1515 var pieceColors = [ 0xFF0000 , 0x0000FF ] ;
1616 var D = 3 ; //number of dimensions
17- var S = 3 ; //side length
17+ var S = 4 ; //side length
1818 var canvSel = '#canvas' ;
1919
2020 /*************
@@ -79,6 +79,13 @@ var TicTacToe4D = (function() {
7979 parseInt ( $s ( '#z' ) . value ) ,
8080 parseInt ( $s ( '#x' ) . value )
8181 ] ) ; //axes are in this order for weird reasons...
82+
83+ var possWinner = thereIsALine ( ) ;
84+ if ( possWinner !== - 1 ) {
85+ setTimeout ( function ( ) {
86+ alert ( 'Player ' + ( possWinner + 1 ) + ' wins!' ) ;
87+ } , 10 ) ;
88+ }
8289 } ) ;
8390
8491 //initial rendering
@@ -95,6 +102,103 @@ var TicTacToe4D = (function() {
95102
96103 /********************
97104 * helper functions */
105+ function thereIsALine ( dimsIn , dimsOut ) {
106+ if ( arguments . length === 0 ) {
107+ dimsIn = [ ] ;
108+ for ( var di = 0 ; di < D ; di ++ ) dimsIn . push ( di ) ;
109+ dimsOut = { } ;
110+ }
111+ if ( dimsIn . length === 1 ) { //then just check that dim
112+ var dc = [ ] ;
113+ dc [ dimsIn [ 0 ] ] = 0 ;
114+ for ( var dim in dimsOut ) {
115+ dc [ dim ] = dimsOut [ dim ] ;
116+ }
117+ var lineOwner = accessArr ( gameState , dc ) ;
118+ if ( lineOwner === - 1 ) return - 1 ;
119+ else {
120+ for ( var si = 1 ; si < S ; si ++ ) {
121+ dc [ dimsIn [ 0 ] ] = si ;
122+ if ( lineOwner !== accessArr ( gameState , dc ) ) return - 1 ;
123+ }
124+ return lineOwner ;
125+ }
126+ } else {
127+ function getBinVectorsUpTo ( n , bits , scale ) {
128+ scale = scale || 0 ;
129+ var ret = [ ] ;
130+ for ( var ai = 0 ; ai < n ; ai ++ ) {
131+ var bin = ai . toString ( 2 ) ;
132+ var vect = [ ] ;
133+ for ( var bi = 0 ; bi < bits - bin . length ; bi ++ ) {
134+ vect . push ( 0 ) ;
135+ }
136+ for ( var bi = 0 ; bi < bin . length ; bi ++ ) {
137+ vect . push ( scale * parseInt ( bin . charAt ( bi ) ) ) ;
138+ }
139+ ret . push ( vect ) ;
140+ }
141+ return ret ;
142+ }
143+
144+ //check the long diagonals of this space
145+ var corners = getBinVectorsUpTo (
146+ Math . pow ( 2 , dimsIn . length - 1 ) , //# pairs of corners
147+ dimsIn . length , S - 1
148+ ) ;
149+ var cornerVels = [ ] ;
150+ for ( var ci = 0 ; ci < corners . length ; ci ++ ) {
151+ var vel = [ ] ;
152+ for ( var vi = 0 ; vi < corners [ ci ] . length ; vi ++ ) {
153+ vel . push ( 1 - 2 * corners [ ci ] [ vi ] / ( S - 1 ) ) ;
154+ }
155+ cornerVels . push ( vel ) ;
156+ }
157+ var baseCoords = [ ] ;
158+ for ( var dim in dimsOut ) baseCoords [ dim ] = dimsOut [ dim ] ;
159+ for ( var ci = 0 ; ci < corners . length ; ci ++ ) {
160+ var dc = baseCoords . slice ( 0 ) ; //starting cell
161+ for ( var ii = 0 ; ii < dimsIn . length ; ii ++ ) {
162+ dc [ dimsIn [ ii ] ] = corners [ ci ] [ ii ] ;
163+ }
164+ var lineOwner = accessArr ( gameState , dc ) ;
165+ if ( lineOwner !== - 1 ) {
166+ var everythingMatchedUp = true ;
167+ for ( var si = 1 ; si < S ; si ++ ) {
168+ for ( var ii = 0 ; ii < dimsIn . length ; ii ++ ) {
169+ dc [ dimsIn [ ii ] ] += cornerVels [ ci ] [ ii ] ;
170+ }
171+ if ( lineOwner !== accessArr ( gameState , dc ) ) {
172+ everythingMatchedUp = false ;
173+ break ;
174+ }
175+ }
176+ if ( everythingMatchedUp ) return lineOwner ;
177+ }
178+ }
179+
180+ //remove a dimension and check the smaller dimensional space
181+ var foundALine = false ;
182+ for ( var ii = 0 ; ii < dimsIn . length ; ii ++ ) {
183+ var dmi = [ ] ; //dimsIn without ii
184+ for ( var ai = 0 ; ai < dimsIn . length ; ai ++ ) {
185+ if ( ai !== ii ) dmi . push ( dimsIn [ ai ] ) ;
186+ }
187+ var dmo = { } ; //dimsOut with ii
188+ for ( var dim in dimsOut ) {
189+ dmo [ dim ] = dimsOut [ dim ] ;
190+ }
191+ for ( var si = 0 ; si < S ; si ++ ) {
192+ dmo [ dimsIn [ ii ] ] = si ;
193+ foundALine = thereIsALine ( dmi , dmo ) ;
194+ if ( foundALine !== - 1 ) break ;
195+ }
196+ if ( foundALine !== - 1 ) break ;
197+ }
198+ return foundALine ;
199+ }
200+ }
201+
98202 function makeMove ( coords ) {
99203 //spot not already taken
100204 if (
@@ -193,13 +297,20 @@ var TicTacToe4D = (function() {
193297 return Math . floor ( low + Math . random ( ) * ( high - low ) ) ;
194298 }
195299
300+ function accessArr ( arr , loc , idx ) {
301+ idx = idx || 0 ;
302+ if ( idx === loc . length - 1 ) return arr [ loc [ idx ] ] ;
303+ else return accessArr ( arr [ loc [ idx ] ] , loc , idx + 1 ) ;
304+ }
305+
196306 function round ( n , places ) {
197307 var mult = Math . pow ( 10 , places ) ;
198308 return Math . round ( mult * n ) / mult ;
199309 }
200310
201311 return {
202312 init : init4DTicTacToe ,
313+ thereIsALine : thereIsALine ,
203314 gameState : gameState
204315 } ;
205316} ) ( ) ;
0 commit comments