doc=: 0 : 0 Globals variables (generated by run): piece : X or O (piece to insert) seq : boxed sequence of moves leading up to this point bs : board state (N by N matrix) ps : (M,N,N) of history of bs values, for X O X O ... allm : ((4*N),N,N) of all possible moves alln : move names corresponding to allm, L1 ... R1 ... T1 ... B1 ... Verbs, Adverbs, and Conjunctions: run : use as run inp where inp is an input string e.g. run '4 L1 T2 ' creates global variables as documented above, said global variables required by some of the following. moves : use as: (X or O) moves bd, generates allm (all moves) from a board ev : evaluation function, use as: (X or O) ev bd where bd is array of boards. See below. pick : adverb; picks next move according to evaluation function & piece, use as: ef pick (X or O) ump : conjunction; use as: s ex ump eo y ex is evaluation function for X eo is evaluation function for O y is integer board size or string of game history s is 1 or (default) 0; whether to display ev values and boards (instructive if 4>:n; too voluminous if n>4) Evaluation Functions applies to (M,N,N) array of boards produces a single integer for each board e.g. 'X' ev allm e.g. 'O' ev 0 4 8{allm e.g. ((i. >./) piece ev allm){allm pick the best move according to ev e.g. ((i. >./) piece ev allm){alln the move name corresp. to above ev: overall evaluation function evstraight: (# our straights) - (# their straights) evline: difference between our lines and their lines score triples for each increment to line length difference evrepeat: _1 if a board repeats a previous position of ours evcount: difference of count of pieces weighted by position ev2: uses ev to do a 2-ply search; picks a move that gives the minimum best score for the opposition eu: evaluation function that asks you for your move ) 9!:1 >.*:+/6!:0 '' NB. set random seed pr =: 1!:2&2 NB. display stuff in exec window readinp =: 1!:1 @ 1: NB. read input from "terminal" ir =: 3!:1 NB. internal representation ri =: 3!:2 NB. inverse of ir read =: 1!:1 write =: 1!:2 erase =: 1!:55 ts =: 6!:2, 7!:2@] NB. time (seconds) and space XO =: 'XO' free =: ' ' NB. free square ' ' or '.' input4 =: ' 4 L2 T2 L2 B2 R2 ' NB. sample inputs input5 =: ' 5 L2 T3 R3 L2 L2 ' input20 =: '20 L2 T2 L2 B2 R2 ' inputstra =: '4 L2 T2 L2 B2 R2 T1 ' NB. X string inputstrb =: '4 L2 T2 L2 B2 R2 T1 L3 T3 L4 T4 ' NB. X and O strings histdir =: 'temp\' checkhist =: 4 : 0 NB. see if stored history is usable if. 0 -: read :: 0: {.q q=. }.q if. n checkhist q do. n runf q else. n runc q end. puthist 0 ) runf =: 4 : 0 NB. runs from file N=: x. seq=: q=. y. NNN=: N,NN=:N,N IN4=:i.N4=: N*4 IN=: i.N IX=: <"1(N,2)$2#IN NB. indexes for all new rows for a side bs=: _1{((N,N)$free),ps sign=: 2|#ps if. #q do. ps=:ps,bs=: ((sign{XO),>{:q) Play bs end. piece=:(-.sign){XO allm=: piece moves bs NB. calculate all possible moves alln=: mnames N NB. move names corresp. to allm i.0 0 ) runc =: 4 : 0 NB. runs complete history N=: x. seq=: q=. y. NNN=: N,NN=:N,N IN4=:i.N4=: N*4 IN=: i.N IX=: <"1(N,2)$2#IN NB. indexes for all new rows for a side bs=: NN$free ps=: (0,NN)$,bs sign=:1 while. #q do. sign=:-.sign ps=:ps,bs=: ((sign{XO),>{.q) Play bs q=.}.q end. piece=:(-.sign){XO allm=: piece moves bs NB. calculate all possible moves alln=: mnames N NB. move names corresp. to allm i.0 0 ) pickrandom=: ?@# { ] pickmax =: (= >./) # i.@# pick =: 1 : '(pickrandom pickmax y. u. allm){alln' ump =: 2 : 0 NB. display ex ump eo history 0 u. ump v. y. : inp=. (":y.),' ' while. 1 do. run inp pr inp pr -/d){'XO'),' wins' return. end. if. bs e. }: ((#ps)$s|.0 1)#ps do. (s{'OX'),' loses' return. end. if. x. do. pr (<"0 piece u.`v.@.('O'&=@[) allm),(<"1 alln),:<"2 allm end. s=. -.s if. s do. inp=. inp,(t=.u. pick piece),' ' else. inp=. inp,(t=.v. pick piece),' ' end. pr piece,' ',t end. ) Play =: 4 : 0 NB. mv Play board makes one move. e.g. 'XT1' Play 5 5$' ' 'm d'=. 2{.x. i=. <:".2}.x. select. d case. 'L' do. y.i}~m LT i{y. case. 'R' do. y.i}~m LT&.|. i{y. case. 'T' do. y.j}~m LT j{y. [ j=. : @: i. flip =: 'X'&=@[ { 'XO'"_ straight =: +/"1 @: ({:@$ = +/"1 ,"1 +/"2) @: = evstraight=: straight - flip@[ straight ] evline =: +/"1 @: (* * 2&^@:|) @: (+/"1 ,"1 +/"2) @: (= - flip@[ = ]) evrepeat =: 4 : '- y. e. ((#ps)$''XO''=x.)#ps' dedge =: >: @: (+/~) @: (i. <. i.@-) count =: +/"1 @: (,"2) @: (dedge@{:@$ *"2 ]) @: = evcount =: count - flip@[ count ] ev =: evline + evcount + 1e8"_ * evrepeat + evstraight ev2a =: flip@[ ([ -@:(>./"1)@:ev moves)"2 ] ev2 =: 4 : 0 NB. 2-ply search using ev on each ply p=. x. ev y. i=. (# i.@#) (_1e6q){q,:p NB. if q is all bleak, just use p ) eu =: 4 : 0 NB. evaluation fn where you to pick your move while. 1 do. pr 'Enter your move' t=.((<"1 alln)-.&.>' ') e.