if 0 { The game of 'bridg-it' computer AI from Martin Gardener ref. models board as electrical circuit. Max voltage across resistance is computer's best move. Ver 0.2 - minor improvement to handling window close - could leave the . window running in 0.1/ } proc help {{op stdout}} { append all " Your aim is to complete a continuous line from top to bottom of the board -\n" append all " joining the blue dots.\n\n" append all " While the opponent aims to complete a continuous line from side to side,\n" append all " joining the red dots.\n\n" append all " Click to place a link between 2 blue dots.\n\n" append all " Choose a smaller or larger board with the spinbox number and 'Restart'.\n\n" append all " Once either of the players has succeeded, the other player cannot finish\n" append all " The game can only end in victory for one or other player - draw is impossible.\n\n" append all " Ref: Martin Gardner, Mathematical Puzzles and Diversions.\n" tk_messageBox -message $all puts $op $all } # the artificial intelligence solves a linear set of equations, so load:. package require math::linearalgebra # # cells # 1 n+1 2n+2 # 2 n+2.... # 3 n+3... # 4... # # # resistances - n2 = n*(n-1) number of vertical resistances # 0 n+1 2n+2 # n2 n2+n # 1 n+1.... # n2+1 n2+n+1 # 2 n+2... # n2+2 n2+n+2 # 3... # # each cell forms a closed loop of resistances and has a current flowing round it # the actual voltage across a reistance is R.(adjacent current-this current).. proc calccurr {brd nx} { ;# make the computer's move set nloops [expr {$nx*($nx-1)+1}] #puts "Computer moves for $nx size board - $nloops " # this has nx*(nx-1)+1 loops to be solved for. # we create a matrix and solve it set mt [math::linearalgebra::mkMatrix $nloops $nloops 0.0] set vc [math::linearalgebra::mkVector $nloops 0.] math::linearalgebra::setelem vc 0 1 ;# the driving voltage set i 0 set rloop 0 while {$i<$nx} { ;# consider first loop. rshared to 'lower' side only set iup [expr {$i*$nx}] ;# the shared resistor set iadj [expr {$i*($nx-1)+1}] ;# adjacent current loop set rloc [$brd getres $iup] set rloop [expr {$rloop+$rloc}] math::linearalgebra::setelem mt 0 $iadj -$rloc math::linearalgebra::setelem mt $iadj 0 -$rloc math::linearalgebra::setelem mt $iadj $iadj [expr {[math::linearalgebra::getelem $mt $iadj $iadj]+$rloc}] incr i } math::linearalgebra::setelem mt 0 0 $rloop set j 0 set iloop 0 while {$j<$nx-1} { ;# consider each loop row. Up sides already handled set i 0 while {$i<$nx} { ;# consider each loop in row. Up side already handled set iup [expr {$i*$nx+$j+1}] ;# the shared resistor set ithis [expr {$i*($nx-1)+$j+1}] ;# the local current set iadj [expr {$i*($nx-1)+$j+2}] ;# adjacent current loop set rloc [$brd getres $iup] math::linearalgebra::setelem mt $ithis $ithis [expr {[math::linearalgebra::getelem $mt $ithis $ithis]+$rloc}] if {$j<$nx-2} { ;# there is nothing beneath nx-2. math::linearalgebra::setelem mt $iadj $iadj [expr {[math::linearalgebra::getelem $mt $iadj $iadj]+$rloc}] math::linearalgebra::setelem mt $ithis $iadj -$rloc math::linearalgebra::setelem mt $iadj $ithis -$rloc } if {$i<$nx-1} { set iup [expr {$nx*$nx+$i*($nx-1)+$j }] ;# the shared resistor set iadj [expr {$ithis+($nx-1)}] ;# adjacent current loop set rloc [$brd getres $iup] # then cover right except at end of row math::linearalgebra::setelem mt $ithis $ithis [expr {[math::linearalgebra::getelem $mt $ithis $ithis]+$rloc}] math::linearalgebra::setelem mt $iadj $iadj [expr {[math::linearalgebra::getelem $mt $iadj $iadj]+$rloc}] math::linearalgebra::setelem mt $ithis $iadj -$rloc math::linearalgebra::setelem mt $iadj $ithis -$rloc } incr i incr iloop } incr j } set currs [ math::linearalgebra::solveGauss $mt $vc ] #now find voltage across each resistor - the biggest is the BEST computer move. set imax -1 set vmax 0 for {set i 0} {$i<$nx*$nx+($nx-1)*($nx-1)} { incr i} { if {[$brd getres $i]==1} { ;# not yet cut or shorted. # find shared currents. Difference is the voltage if {$i<$nx*$nx} { ;# a horizontal resistor set ix [expr {$i/$nx}] set jx [expr {$i%$nx}] set iup [expr {$jx==0?0:($i-$ix)}] set idn [expr {$jx>$nx-2?-1:$i-$ix+1}] set v [expr {$idn>0?[lindex $currs $iup]-[lindex $currs $idn]:[lindex $currs $iup]}] } else { ;# vert resist. set iii [expr {$i-$nx*$nx}] ;# which ij set ix [expr {$iii/($nx-1)}] set jx [expr {$iii%($nx-1)}] set iup [expr {$ix*($nx-1)+$jx+1}] set idn [expr {$iup+$nx-1}] set v [expr {[lindex $currs $iup]-[lindex $currs $idn]}] } if {abs($v)>abs($vmax)} { set vmax $v set imax $i } } } return [list $imax [lindex $currs 0]] } proc bridgit {w args} { ;# a game of bridgit, toplevel for the board # and allows new smooth shaped buttons. global $w.props ;# an array of options specific to the bridgit game 'class' global $w.res ;# an array of resistors for the computer move # set by .this -