Filewatcher File Search
FTP Search
  
Directory 
  
Content Search 
   
pkg://tclrobots-2.0.tar.gz:73416/tclrobots-2.0/tclrobots.tcl  downloads

#!/bin/sh
# the next line restarts using wish \
exec /usr/local/bin/wish "$0" ${1+"$@"}

set wishexec /usr/local/bin/wish

# don't fudge with the first 5 lines !!  Makefile depends on them!

# TclRobots
# Copyright 1994,1996 Tom Poindexter
# tpoindex@nyx.net
#
# version 1.0  August 1994
# version 2.0  February 1996
#

global rob1 rob2 rob3 rob4 c_tab s_tab parms nowin finish tourn_type
global running halted ticks maxticks execCmd numList tlimit bgColor

# set general tclrobots environment parameters
set parms(do_wait)	100 	;# number milliseconds robots wait on sys call
set parms(tick)		500	;# millisecond tick  
set parms(simtick)	500	;# simulation clock tick
set parms(errdist)	10	;# meters of possible error on scan resolution
set parms(sp)		10 	;# distance traveled at 100% per tick
set parms(accel)	10	;# accel/deaccel speed per tick as % speed 
set parms(mismax)	700	;# maximum range for a missle
set parms(msp)		100	;# distance missiles travel per tick
set parms(mreload)	[expr round(($parms(mismax)/$parms(msp))+0.5)] 
				;# missile reload time in ticks
set parms(lreload)	[expr $parms(mreload)*3]
				;# missile long reload time after clip
set parms(clip)		4	;# number of missiles per clip
set parms(turn,0)	100	;# max turn speed < 25 deg. delta
set parms(turn,1)	50	;#  "   "     "   " 50  "     "
set parms(turn,2)	30	;#  "   "     "   " 75  "     "
set parms(turn,3)	20	;#  "   "     "   > 75  "     "
set parms(rate,0) 	90	;# max rate of turn per tick at speed < 25
set parms(rate,1) 	60	;#  "   "   "   "    "   "   "    "   " 50
set parms(rate,2) 	40	;#  "   "   "   "    "   "   "    "   " 75
set parms(rate,3) 	30	;#  "   "   "   "    "   "   "    "   > 75
set parms(rate,4) 	20	;#  "   "   "   "    "   "   "    "   > 75
set parms(dia0)		 6	;# diameter of direct missle damage
set parms(dia1)		10	;#     "    "  maximum   "      "
set parms(dia2)		20	;#     "    "  medium    "      "
set parms(dia3)		40	;#     "    "  minimum   "      "   
set parms(hit0)		25	;# %damage within range 0
set parms(hit1)		12	;#    "       "     "   1
set parms(hit2)		7	;#    "       "     "   2
set parms(hit3)		3	;#    "       "     "   3
set parms(coll)		5	;#    "    from collision into wall 
set parms(heatsp)	35	;# %speed when heat builds
set parms(heatmax)	200	;# max heat index, sets speed to heatsp
set parms(hrate)  	10	;# inverse heating rate (greater hrate=slower)
set parms(cooling)	-25 	;# cooling rate per tick, after overheat
set parms(canheat)	20	;# cannon heating rate per shell
set parms(cancool)	-1	;# cannon cooling rate per tick
set parms(scanbad)	35	;# cannon heat index where scanner is inop

set parms(quads)  {{100 100} {600 100} {100 600} {600 600}}
set parms(shapes) {{3 12 7} {8 12 5} {11 11 3} {12 8 4}}
if {[winfo depth .] >= 4 } {
  set parms(cmodel) 1
} else {
  set parms(cmodel) 0
}
if {$parms(cmodel)} {
  set parms(colors) {SeaGreen3 IndianRed3 orchid3 SlateBlue1}
} else {
  set parms(colors) {black black black black}
}

set rob1(status) 0; set rob1(name) ""; set rob1(pid) -1
set rob2(status) 0; set rob2(name) ""; set rob2(pid) -1
set rob3(status) 0; set rob3(name) ""; set rob3(pid) -1
set rob4(status) 0; set rob4(name) ""; set rob4(pid) -1

set tlimit  10
set outfile ""

# init sin & cos tables
set pi  [expr 4*atan(1)]
set d2r [expr 180/$pi]

for {set i 0} {$i<360} {incr i} {
  set s_tab($i) [expr sin($i/$d2r)]
  set c_tab($i) [expr cos($i/$d2r)]
}


###############################################################################
#
# rand routine, scarffed from a comp.lang.tcl posting 
#    From: eichin@cygnus.com (Mark Eichin)
#

set _lastvalue [expr ([pid]*[file atime /dev/tty])%65536]

proc _rawrand {} {
    global _lastvalue
    # per Knuth 3.6:
    # 65277 mod 8 = 5 (since 65536 is a power of 2)
    # c/m = .5-(1/6)\sqrt{3}
    # c = 0.21132*m = 13849, and should be odd.
    set _lastvalue [expr (65277*$_lastvalue+13849)%65536]
    set _lastvalue [expr ($_lastvalue+65536)%65536]
    return $_lastvalue
}
proc rand {base} {
    set rr [_rawrand]
    return [expr abs(($rr*$base)/65536)]
}




###############################################################################
#
# these procs are the tclrobot's interface to the controller and other
# handy things
#

set interface {
  set _resume_  0
  set _step_    0
  set _lastvalue [expr ([pid]*[file atime /dev/tty])%65536]
  proc _rawrand {} {
      global _lastvalue
      # per Knuth 3.6:
      # 65277 mod 8 = 5 (since 65536 is a power of 2)
      # c/m = .5-(1/6)\sqrt{3}
      # c = 0.21132*m = 13849, and should be odd.
      set _lastvalue [expr (65277*$_lastvalue+13849)%65536]
      set _lastvalue [expr ($_lastvalue+65536)%65536]
      return $_lastvalue
  }
  proc rand {base} {
      set rr [_rawrand]
      return [expr abs(($rr*$base)/65536)]
  }
  set _ping_proc_ ""
  set _alert_on_  0
  proc _ping_check_ {} {
    global _ping_proc_ _alert_on_
    if {!$_alert_on_} {return}
    set val 0
    catch {SEND "TCLROBOTS" do_ping HAND} val
    if {$val!=0} {
      catch {eval $_ping_proc_ $val}
    }
  }
  proc alert {procname} {
    global _ping_proc_ _alert_on_
    set _ping_proc_ $procname
    if {[string length $procname] > 0} {
      set _alert_on_ 1
    } else {
      set _alert_on_ 0
    }
  }
  proc dputs {args} {
    global _resume_
    set _resume_ 0
    catch {.d.l insert end [join $args]; .d.l yview end; UPDATE}
    DEBUG
    UPDATE
    return
  }
  proc scanner {deg res} {
    AFTER DO_WAIT
    AFTER DO_WAIT
    UPDATE
    set val -1
    catch  {SEND "TCLROBOTS" do_scanner HAND $deg $res} val 
    DEBUG
    _ping_check_
    UPDATE
    return $val
  }
  proc dsp {} {
    AFTER DO_WAIT
    UPDATE
    set val -1
    catch {SEND "TCLROBOTS" do_dsp HAND} val 
    DEBUG
    _ping_check_
    UPDATE
    return $val
  }
  proc cannon {deg range} {
    AFTER DO_WAIT
    UPDATE
    set val -1
    catch {SEND "TCLROBOTS" do_cannon HAND $deg $range} val
    DEBUG
    _ping_check_
    UPDATE
    return $val
  }
  proc drive {deg speed} {
    AFTER DO_WAIT
    UPDATE
    set val -1
    catch {SEND "TCLROBOTS" do_drive HAND $deg $speed} val
    DEBUG
    _ping_check_
    UPDATE
    return $val
  }
  proc damage {} {
    AFTER DO_WAIT
    UPDATE
    set val -1
    catch {SEND "TCLROBOTS" do_damage HAND} val
    DEBUG
    _ping_check_
    UPDATE
    return $val
  }
  proc speed {} {
    AFTER DO_WAIT
    UPDATE
    set val -1
    catch {SEND "TCLROBOTS" do_speed HAND} val
    DEBUG
    _ping_check_
    UPDATE
    return $val
  }
  proc loc_x {} {
    AFTER DO_WAIT
    UPDATE
    set val -1
    catch {SEND "TCLROBOTS" do_loc_x HAND} val
    DEBUG
    _ping_check_
    UPDATE
    return $val
  }
  proc loc_y {} {
    AFTER DO_WAIT
    UPDATE
    set val -1
    catch {SEND "TCLROBOTS" do_loc_y HAND} val
    DEBUG
    _ping_check_
    UPDATE
    return $val
  }
  proc tick {} {
    AFTER DO_WAIT
    UPDATE
    set val -1
    catch {SEND "TCLROBOTS" do_tick HAND} val
    DEBUG
    _ping_check_
    UPDATE
    return $val
  }
  proc heat {} {
    AFTER DO_WAIT
    UPDATE
    set val -1
    catch {SEND "TCLROBOTS" do_heat HAND} val
    DEBUG
    _ping_check_
    UPDATE
    return $val
  }
  proc team_declare {tname} {
    # AFTER DO_WAIT
    UPDATE
    set val -1
    catch {SEND "TCLROBOTS" do_team_declare HAND $tname} val
    DEBUG
    _ping_check_
    UPDATE
    return $val
  }
  proc team_send {args} {
    # AFTER DO_WAIT
    UPDATE
    set val -1
    catch {SEND "TCLROBOTS" do_team_send HAND "$args"} val
    DEBUG
    _ping_check_
    UPDATE
    return $val
  }
  proc team_get {} {
    # AFTER DO_WAIT
    UPDATE
    set val -1
    catch {SEND "TCLROBOTS" do_team_get HAND} val
    DEBUG
    _ping_check_
    UPDATE
    return $val
  }

}

# execute these commands on tclrobot startup
set setup {

  # setup windows, .l for file name
  frame .f
  canvas .f.c -width 20 -height 16 
  label .f.l -relief sunken -width 30  -text "(loading robot code..)" 
  label .f.s -relief sunken -width 5   -text "0%"
  pack .f.c -side left
  pack .f.s -side right
  pack .f.l -side left -expand 1 -fill both
  # .d for debug listbox and scrollbar
  frame .d
  listbox .d.l -relief sunken -yscrollcommand ".d.s set" \
                              -xscrollcommand ".d.b set"
  scrollbar .d.s -command ".d.l yview"
  scrollbar .d.b -command ".d.l xview" -orient horizontal
  pack .d.s -side right  -fill y
  pack .d.b -side bottom -fill x
  pack .d.l -side left  -expand 1 -fill both
  pack .f  -side top -fill x -ipady 5
  pack .d  -side top -expand 1 -fill both 
  wm minsize . 100 70
  update

  # disable base tk commands
  foreach p {wm frame toplevel label button message listbox scrollbar scale \
	     entry text menu menubutton canvas selection grab raise lower tk \
	     pack place focus bind winfo checkbutton radiobutton option \
             bind bindtags bell clipboard fileevent image } {
    catch {rename $p {}}
  }

  # rename these commands to their random names
  rename send SEND
  rename tkwait TKWAIT
  rename destroy DESTROY
  rename exit EXIT

  # rename after to a rand generated name, make new proc
  rename after AFTER
  proc after {args} {
    uplevel AFTER $args
  }

  # rename update to a rand generated name, make new proc
  rename update UPDATE
  proc update {args} {
    uplevel UPDATE $args
  }


  # disable base tcl commands
  foreach p {open close read gets puts eof exec cd flush pwd seek \
	     glob tell info} {

    catch {rename $p {}}
  }

  # disable base tcl library procs
  foreach p {auto_execok auto_load auto_mkindex auto_reset} {
    catch {rename $p {}}
  }

  # disable base tk library startup procs
  proc tkScreenChanged {args} {}

  # our own unknown proc
  proc unknown {name args} {
    dputs "UNKNOWN: $name"
  }

  # our own tkerror proc
  proc tkerror {args} {
    global errorInfo
    dputs $errorInfo 
    dputs "TKERROR: $args"
  }
}


###############################################################################
#
# initialize robot array, start another wish, send init code
#
#

proc robot_init {robx fn x y winx winy color {sim 0}} {
  global setup interface parms wishexec nowin
  upvar #0 $robx r

  set name [file tail $fn]

  # generate a new signature
  set newsig     [rand 65535]
  set ourname    [winfo name .]

  # set robot parms
  set r(name)   ${name}_$newsig	;# window name = source.file_randnumber
  set r(num)    $newsig 	;# the rand number as digital signature
  set r(cmd)    $newsig 	;# random command names, also set below
  set r(pid)    -1		;# robot pid
  set r(status)	1 		;# robot status: 0=not used or dead, 1=running
  set r(color)	$color 		;# robot color
  set r(x) 	$x 		;# robot current x
  set r(y) 	$y		;# robot current y
  set r(orgx) 	$x 		;# robot origin  x since last heading
  set r(orgy) 	$y		;# robot origin  y   "    "     "
  set r(range)	0		;# robot current range on this heading
  set r(damage) 0		;# robot current damage
  set r(speed)	0		;# robot current speed
  set r(dspeed)	0		;# robot desired   "
  set r(hdg)	[rand 360]	;# robot current heading
  set r(dhdg)	$r(hdg)		;# robot desired   "
  set r(dir)	+		;# robot direction of turn (+/-)
  set r(sig) 	"0 0"		;# robot last scan dsp signature
  set r(mstate) 0		;# missle state: 0=avail, 1=flying
  set r(reload) 0		;# missle reload time: 0=ok, >0 = reloading
  set r(mused)  0		;# number of missles used per clip
  set r(mx)	0		;# missle current x
  set r(my)	0		;# missle current y
  set r(morgx)	0		;# missle origin  x
  set r(morgy)	0		;# missle origin  y
  set r(mhdg)	0		;# missle heading
  set r(mrange)	0		;# missle current range
  set r(mdist)	0		;# missle target distance
  set r(syscall) ""		;# last syscall & return val, for simulator
  set r(heat)	0		;# motor heat index
  set r(hflag)	0		;# overheated flag
  set r(ping)	0		;# signature of last robot to scan us
  set r(team)	""		;# declared team
  set r(data)	""		;# last team message sent
  set r(btemp)  0		;# barrel temp, affected by cannon fire

  # startup a new wish with specified name

  if {$nowin} {
    set stdinput "wm withdraw ."
  } else {
    set stdinput ""
  }
  
  catch { exec $wishexec -geom 200x115+$winx+$winy -name $r(name) \
                        << $stdinput >/dev/null 2>/dev/null & } r(pid)
  if {$r(pid) <= 0} {
    set r(pid) -1
    .l configure -text "Oops...can't find new wish, pid = $r(pid)"
    return 0
  }

  # generate new command names
  global _lastvalue
  set oldlast $_lastvalue
  if [catch {set fntime [file atime $fn]}] {set fntime [rand 255]} 
  if [catch {set fnsize [file size  $fn]}] {set fnsize [rand 255]} 
  set _lastvalue [expr ( $r(pid) * (($fntime * $fnsize)%65536) ) % 65536]
  set newcmd     [rand 65535]
  set _lastvalue $oldlast

  set r(cmd)     $newcmd

  set newdestroy _d_$newcmd
  set newafter   _a_$newcmd
  set newsend    _s_$newcmd
  set newtkwait  _t_$newcmd
  set newupdate  _u_$newcmd
  set newexit    _e_$newcmd

  if {$sim} {
    set newdebug "global _step_; if {\$_step_} {$newtkwait variable _resume_}"
  } else {
    set newdebug ""
  }

  # substitute values in generic setup and interface for this robot
  set rset $setup
  set rint $interface

  regsub -all TCLROBOTS $rint $ourname        rint
  regsub -all SEND      $rint $newsend        rint
  regsub -all AFTER     $rint $newafter       rint
  regsub -all UPDATE    $rint $newupdate      rint
  regsub -all TKWAIT    $rint $newtkwait      rint
  regsub -all DESTROY   $rint $newdestroy     rint
  regsub -all DEBUG     $rint $newdebug       rint
  regsub -all HAND      $rint $robx           rint
  regsub -all DO_WAIT   $rint $parms(do_wait) rint

  regsub -all SEND      $rset $newsend        rset
  regsub -all AFTER     $rset $newafter       rset
  regsub -all UPDATE    $rset $newupdate      rset
  regsub -all TKWAIT    $rset $newtkwait      rset
  regsub -all DESTROY   $rset $newdestroy     rset
  regsub -all EXIT      $rset $newexit        rset


  # might need to wait until new wish starts up
  set i 0
  while {[lsearch [winfo interps] $r(name)] == -1 && \
	 [incr i] < 10 && \
	 [catch {send $r(name) "expr 1+1"} result] == 1} {
    after 1000
    update
  }
  if {[catch {send $r(name) "expr 1+1"}] == 1} {
    .l configure -text "Oops...can't find new wish, pid = $r(pid)"
    return 0
  }

  # send the code
  send $r(name) $rset
  send $r(name) $rint

  if {$sim} {
    send $r(name) "set _debug 1"
  } else {
    send $r(name) "set _debug 0"
  }
  if {$parms(cmodel)} {
    send $r(name) ".f.l configure -bg $color -text $name"
  } else {
    send $r(name) ".f.l configure            -text $name"
  }
  set i [string index $robx 3]
  incr i -1
  set arrshape [lindex $parms(shapes) $i]
  send $r(name) ".f.c create line 10 12 10 7 -fill $color \
			     -arrow last -arrowshape \"$arrshape\""
  update
  send $r(name) \
    "$newafter 100 \{set _start_ 0; $newtkwait variable _start_; source $fn\}"
  return 1
}



###############################################################################
#
# start the robots!
#
#

proc start_robots {} {
  foreach robx {rob1 rob2 rob3 rob4} {
    upvar #0 $robx r
    if {$r(status)} {
      send $r(name) "_a_$r(cmd) 100 {set _start_ 1}"
    }
  }
}


###############################################################################
#
# update damage label of robot
#
#

proc up_damage {robx d} {
  global parms
  upvar #0 $robx r
  if {$d >= 100} {
    set d dead
    set c "-bg red"
  } elseif {$d >= 85} {
    set d ${d}%
    set c "-bg orange"
  } elseif {$d >= 50} {
    set d ${d}%
    set c "-bg yellow"
  } else {
    set d ${d}%
    set c ""
  }
  if {!$parms(cmodel)} {
    set c ""
  }

  catch {send -async $r(name) ".f.s configure -text $d $c; _u_$r(cmd)"}
}

###############################################################################
#
# disable robot
#
#

proc disable_robot {robx taunt} {
  upvar #0 $robx r
  # break the remote tcl interpreter by causing it to wait on .
  set insults {{junk\\ pile!} {cratered!} {scrap\\ heap!} {toast!} {face\\ plant!} {sleeps\\ with\\ PC\\ Jr.} {roasted!} {flat-liner!} {char-broiled!} {pushing\\ up\\ daisies!} {comatose!} {bits\\ busted!} {core\\ dump!} {GPF} {UAE}}
  if {$taunt} {
    set insult [lindex $insults [rand [llength $insults]]]
  } else {
    set insult ""
  }
  # break after, let the robot spin in an update cycle and wait on .
  catch {send -async $r(name) \
    "proc after {args} {}; \
     proc _ping_check_ \{\} \{while 1 \{_u_$r(cmd);_a_$r(cmd) 100\} \}" }
  catch {send -async $r(name) "_a_$r(cmd) 1 \
    \".d.l insert end $insult;.d.l yview end;_u_$r(cmd);_t_$r(cmd) window .\""}
}


###############################################################################
#
# kill robot
#
#

proc kill_robot {robx} {
  upvar #0 $robx r
  catch {send $r(name)  "rename _s_$r(cmd) send;proc _s_$r(cmd) {args} {}" }
  catch {send $r(name)  "_a_$r(cmd) 0 _e_$r(cmd)" }
  update
}


###############################################################################
#
# clean up all left overs
#
#

proc clean_up {} {
  global running
  .l configure -text "Standby, cleaning up any left overs...."
  update 
  set running 0
  foreach rr {rob1 rob2 rob3 rob4} {
    upvar #0 $rr r
    if {$r(status) || $r(pid) > 0} {
      kill_robot $rr
      after 500
      catch {exec kill $r(pid)}
      set r(pid) -1
    }
  }
}



###############################################################################
#
# update position of missiles and robots, assess damage
#
#

proc update_robots {} {
  global c_tab s_tab parms ticks running finish
  update 
  incr ticks
  set num_miss 0
  set num_rob  0
  foreach robx {rob1 rob2 rob3 rob4} {
    upvar #0 $robx r

    # check all flying missiles
    if {$r(mstate)} {
      incr num_miss 
      # update location of missle
      set r(mrange) [expr $r(mrange)+$parms(msp)]
      set r(mx)    [expr ($c_tab($r(mhdg))*$r(mrange))+$r(morgx)]
      set r(my)    [expr ($s_tab($r(mhdg))*$r(mrange))+$r(morgy)]
      # check if missle reached target
      if {$r(mrange) > $r(mdist)} {
	set r(mstate) 0
        set r(mx)    [expr ($c_tab($r(mhdg))*$r(mdist))+$r(morgx)]
        set r(my)    [expr ($s_tab($r(mhdg))*$r(mdist))+$r(morgy)]
	after 1 "show_explode $robx"

	# assign damage to all within explosion ranges
	foreach robrx {rob1 rob2 rob3 rob4} {
	  upvar #0 $robrx rr
	  if {!$rr(status)} {continue}
	  set d [expr hypot($r(mx)-$rr(x),$r(my)-$rr(y))]
	  if {$d<$parms(dia3)} {
	    if {$d<$parms(dia0)} {
	      incr rr(damage) $parms(hit0)
	    } elseif {$d<$parms(dia1)} {
	      incr rr(damage) $parms(hit1)
	    } elseif {$d<$parms(dia2)} {
	      incr rr(damage) $parms(hit2)
	    } else {
	      incr rr(damage) $parms(hit3)
	    }
           up_damage $robrx $rr(damage)
	  }
	}
      }
    }

    # skip rest if robot dead
    if {!$r(status)} {continue}

    # update missle reloader
    if {$r(reload)} {incr r(reload) -1}

    # check for excessive speed, increment heat 
    if {$r(speed) > $parms(heatsp)} {
      incr r(heat) [expr round(($r(speed)-$parms(heatsp))/$parms(hrate))+1]
      if {$r(heat) >= $parms(heatmax)} {
	set r(heat) $parms(heatmax)
	set r(hflag) 1
	if {$r(dspeed) > $parms(heatsp)} {
	  set r(dspeed) $parms(heatsp)
	}
      }
    } else {
      # if overheating, apply cooling rate
      if {$r(hflag) || $r(heat) > 0} {
	incr r(heat) $parms(cooling)
	if {$r(heat) <= 0} { set r(hflag) 0; set r(heat) 0 }
      }
    }

    # check for barrel overheat, apply cooling
    if {$r(btemp)} {
      incr r(btemp) $parms(cancool)
      if {$r(btemp) < 0} { set r(btemp) 0 }
    }

    # update robot speed, moderated by acceleration
    if {$r(speed) != $r(dspeed)} {
      if {$r(speed) > $r(dspeed)} {
	incr r(speed) -$parms(accel)
	if {$r(speed) < $r(dspeed)} {
	  set r(speed) $r(dspeed)
	}
      } else {
	incr r(speed) $parms(accel)
	if {$r(speed) > $r(dspeed)} {
	  set r(speed) $r(dspeed)
	}
      }
    }

    # update robot heading, moderated by turn rates
    if {$r(hdg) != $r(dhdg)} {
      set mrate $parms(rate,[expr int($r(speed)/25)])
      set d1 [expr ($r(dhdg)-$r(hdg)+360)%360]
      set d2 [expr ($r(hdg)-$r(dhdg)+360)%360]
      set d  [expr $d1<$d2?$d1:$d2]
      if {$d<=$mrate} {
	set r(hdg) $r(dhdg)
      } else {
	set r(hdg) [expr ($r(hdg)$r(dir)$mrate+360)%360]
      }
      set r(orgx)  $r(x)
      set r(orgy)  $r(y)
      set r(range) 0
    }

    # update distance traveled on this heading
    if {$r(speed) > 0} {
      set r(range) [expr $r(range)+($r(speed)*$parms(sp)/100)]
      set r(x)     [expr round(($c_tab($r(hdg))*$r(range))+$r(orgx))]
      set r(y)     [expr round(($s_tab($r(hdg))*$r(range))+$r(orgy))]
      # check for wall collision
      if {$r(x)<0 || $r(x)>999} {
	set r(x) [expr $r(x)<0? 0 : 999]
	set r(orgx)   $r(x)
	set r(orgy)   $r(y)
	set r(range)  0
	set r(speed)  0
	set r(dspeed) 0
	incr r(damage) $parms(coll)
        up_damage $robx $r(damage)
      }
      if {$r(y)<0 || $r(y)>999} {
	set r(y) [expr $r(y)<0? 0 : 999]
	set r(orgx)   $r(x)
	set r(orgy)   $r(y)
	set r(range)  0
	set r(speed)  0
	set r(dspeed) 0
	incr r(damage) $parms(coll)
        up_damage $robx $r(damage)
      }
    }
  }

  # check for robot health
  set diffteam ""
  set num_team 0
  foreach robx {rob1 rob2 rob3 rob4} {
    upvar #0 $robx r
    if {$r(status)} {
      if {$r(damage)>=100} {
	set r(status) 0
	set r(damage) 100
        up_damage $robx $r(damage)
	disable_robot $robx 1
        append finish "$r(name) team($r(team)) dead at tick: $ticks\n"
      } else {
	incr num_rob
        if {$r(team) != ""} {
          if {[lsearch -exact $diffteam $r(team)] == -1} {
            lappend diffteam $r(team)
            incr num_team
          }
        } else {
          lappend diffteam $r(name)
          incr num_team
        }
      }
    }
  }
  
  if {($num_rob<=1 || $num_team==1) && $num_miss==0} {
    set running 0
  }
  after 1 show_robots
}


###############################################################################
#
# update canvas with position of missiles and robots
#
#

proc show_robots {} {
  global c_tab s_tab parms
  set i 0
  foreach robx {rob1 rob2 rob3 rob4} {
    upvar #0 $robx r
    # check robots
    if {$r(status)} {
      .c delete r$r(num)
      set x [expr $r(x)/2]
      set y [expr (1000-$r(y))/2]
      set arrow [lindex $parms(shapes) $i]
      .c create line $x $y \
	  [expr $x+($c_tab($r(hdg))*5)] [expr $y-($s_tab($r(hdg))*5)] \
	  -fill $r(color) -arrow last -arrowshape $arrow -tags r$r(num)
    }
    # check missiles
    if {$r(mstate)} {
      .c delete m$r(num)
      set x [expr $r(mx)/2]
      set y [expr (1000-$r(my))/2]
      .c create oval [expr $x-2] [expr $y-2] [expr $x+2] [expr $y+2] \
	  -fill black -tags m$r(num)
    }
    incr i
  }
  #delete all previous scans
  .c delete scan
  update
}



###############################################################################
#
# show scanner from a robot
#
#

proc show_scan {hand deg res} {
  global s_tab c_tab
  upvar #0 $hand r
  if {[.c find withtag s$r(num)] != ""} {
    return
  }
  set x [expr $r(x)/2]
  set y [expr (1000-$r(y))/2]
  .c create arc [expr $x-350] [expr $y-350] [expr $x+350] [expr $y+350] \
     -start [expr $deg-$res] -extent [expr 2*$res + 1] \
     -fill "" -outline $r(color) -stipple gray50 -width 1 -tags "scan s$r(num) "

  update
}




###############################################################################
#
# show explosion of missile
#
#

proc show_explode {hand} {
  global parms
  upvar #0 $hand r
  .c delete m$r(num)
  set x [expr $r(mx)/2]
  set y [expr (1000-$r(my))/2]
  if {$parms(cmodel)} {
    .c create oval [expr $x-10] [expr $y-10] [expr $x+10] [expr $y+10] \
	-outline yellow -fill yellow  -width 1 \
	-tags e$r(num)
    .c create oval [expr $x-5] [expr $y-5] [expr $x+5] [expr $y+5] \
	-outline orange -fill orange  -width 1  \
	-tags e$r(num)
    .c create oval [expr $x-3] [expr $y-3] [expr $x+3] [expr $y+3] \
	-outline red    -fill red     -width 1  \
	-tags e$r(num)
  } else {
    .c create oval [expr $x-10] [expr $y-10] [expr $x+10] [expr $y+10] \
	-outline ""    -fill black -stipple gray25  -width 1 \
	-tags e$r(num)
    .c create oval [expr $x-5] [expr $y-5] [expr $x+5] [expr $y+5] \
	-outline ""    -fill black -stipple gray50  -width 1  \
	-tags e$r(num)
    .c create oval [expr $x-3] [expr $y-3] [expr $x+3] [expr $y+3] \
	-outline ""    -fill black    -width 1  \
	-tags e$r(num)
  }
  update
  after 750 ".c delete e$r(num)"
}



###############################################################################
#
# robot interface routines - server side
#
#

proc do_scanner {hand deg res} {
  update
  global parms
  upvar #0 $hand r
  set r(syscall) "scanner $deg $res"
  if [catch {set deg [expr round($deg)]}] {append r(syscall) " (-1)";return -1}
  if [catch {set res [expr round($res)]}] {append r(syscall) " (-1)";return -1}
  if {($deg<0 || $deg>359)} {append r(syscall) " (-1)"; return  -1}
  if {($res<0 || $res>10)}  {append r(syscall) " (-1)"; return  -1}

  after 1 "show_scan $hand $deg $res"
  set dsp   0
  set dmg   0
  set near  9999
  foreach robx {rob1 rob2 rob3 rob4} {
    upvar #0 $robx rob
    if {"$hand" == "$robx" || !$rob(status)} { continue }
    set x [expr $rob(x)-$r(x)]
    set y [expr $rob(y)-$r(y)]
    set d [expr round(57.2958*atan2($y,$x))]
    if {$d<0} {incr d 360}
    set d1  [expr ($d-$deg+360)%360]
    set d2  [expr ($deg-$d+360)%360]
    set f   [expr $d1<$d2?$d1:$d2]
    if {$f<=$res} {
      set rob(ping) $r(num)
      set dist [expr round(hypot($x,$y))]
      if {$dist<$near} {
	set derr [expr $parms(errdist)*$res]
	set terr [expr ($res>0 ? 5 : 0) + [rand $derr]]
	set fud1  [expr [rand 2] ? \"-\" : \"+\"]
	set fud2  [expr [rand 2] ? \"-\" : \"+\"]
	set near [expr $dist $fud1 $terr $fud2 $r(btemp)]
	if {$near<1} {set near 1} 
	set dsp  $rob(num)
	set dmg  $rob(damage)
      }
    }
  }
  # if cannon has overheated scanner, report 0
  if {$r(btemp) >= $parms(scanbad)} {
    set r(sig) "0 0"
    set val 0
  } else {
    set r(sig) "$dsp $dmg"
    set val [expr $near==9999?0:$near]
  }
  append r(syscall) " ($val)"
  return $val
}

proc do_dsp {hand} {
  update
  upvar #0 $hand r
  set r(syscall) "dsp ($r(sig))"
  return $r(sig)
}

proc do_ping {hand} {
  update
  upvar #0 $hand r
  set val $r(ping)
  set r(ping) 0
  return $val
}

proc do_cannon {hand deg rng} {
  update
  upvar #0 $hand r
  global parms
  set r(syscall) "cannon $deg $rng"
  if {$r(mstate)} {append r(syscall) " (0)";return 0}
  if {$r(reload)} {append r(syscall) " (0)";return 0}
  if [catch {set deg [expr round($deg)]}] {append r(syscall) " (-1)";return  -1}
  if [catch {set rng [expr round($rng)]}] {append r(syscall) " (-1)";return  -1}
  if {($deg<0 || $deg>359)} {append r(syscall) " (-1)"; return  -1}
  if {($rng<0 || $rng>$parms(mismax))} {append r(syscall) " (-1)"; return  -1}
  
  set r(mhdg)   $deg
  set r(mdist)  $rng
  set r(mrange) 0
  set r(mstate) 1
  set r(morgx)  $r(x)
  set r(morgy)  $r(y)
  set r(mx)     $r(x)
  set r(my)     $r(y)
  incr r(btemp) $parms(canheat)
  incr r(mused)
  # set longer reload time if used all missiles in clip
  if {$r(mused) == $parms(clip)} {
    set r(reload) $parms(lreload)
    set r(mused) 0
  } else {
    set r(reload) $parms(mreload)
  }
  append r(syscall) " (1)"
  return 1
}

proc do_drive {hand deg spd} {
  update
  global parms
  upvar #0 $hand r
  set r(syscall) "drive $deg $spd"
  if [catch {set deg [expr round($deg)]}] {append r(syscall) " (-1)";return  -1}
  if [catch {set spd [expr round($spd)]}] {append r(syscall) " (-1)";return  -1}
  if {($deg<0 || $deg>359)} {append r(syscall) " (-1)";return  -1}
  if {($spd<0 || $spd>100)} {append r(syscall) " (-1)";return  -1}

  set d1  [expr ($r(hdg)-$deg+360)%360]
  set d2  [expr ($deg-$r(hdg)+360)%360]
  set d   [expr $d1<$d2?$d1:$d2]

  set r(dhdg)   $deg
  set r(dspeed) [expr $r(hflag) && $spd>$parms(heatsp) ? $parms(heatsp) : $spd]

  # shutdown drive if turning too fast at current speed
  set idx [expr int($d/25)] 
  if {$idx>3} {set idx 3}
  if {$r(speed)>$parms(turn,$idx)} {
    set r(dspeed) 0 
    set r(dhdg) $r(hdg)
  } else {
    set r(orgx)  $r(x)
    set r(orgy)  $r(y)
    set r(range) 0
  }
  # find direction of turn
  if {($r(hdg)+$d+360)%360==$deg} {
    set r(dir) +
  } else {
    set r(dir) -
  }
  append r(syscall) " ($r(dspeed))"
  return $r(dspeed) 
}

proc do_damage {hand} {
  update
  upvar #0 $hand r
  set r(syscall) "damage ($r(damage))"
  return $r(damage)
}

proc do_speed {hand} {
  update
  upvar #0 $hand r
  set r(syscall) "speed ($r(speed))"
  return $r(speed)
}

proc do_loc_x {hand} {
  update
  upvar #0 $hand r
  set r(syscall) "loc_x ($r(x))"
  return $r(x)
}

proc do_loc_y {hand} {
  update
  upvar #0 $hand r
  set r(syscall) "loc_y ($r(y))"
  return $r(y)
}

proc do_tick {hand} {
  update
  upvar #0 $hand r
  global ticks
  set r(syscall) "tick ($ticks)"
  return $ticks
}

proc do_heat {hand} {
  update
  upvar #0 $hand r
  set r(syscall) "heat ($r(hflag) $r(heat))"
  return "$r(hflag) $r(heat)"
}

proc do_team_declare {hand tname} {
  update
  upvar #0 $hand r
  if {$r(team) == ""} {
    set r(team) $tname
  }
  set r(syscall) "team_declare $tname ($r(team))"
  return "$r(team)"
}

proc do_team_send {hand data} {
  update
  upvar #0 $hand r
  if {$r(team) != ""} {
    set r(data) $data
  }
  set r(syscall) "team_send $data ()"
  return ""
}

proc do_team_get {hand} {
  update
  upvar #0 $hand r
  set val ""
  if {$r(team) == ""} {
    set r(syscall) "team_get ($val)"
    return ""
  }
  foreach robx {rob1 rob2 rob3 rob4} {
    upvar #0 $robx rob
    if {"$hand" == "$robx" || !$rob(status)} { continue }
    if {"$r(team)" == "$rob(team)"} {
      lappend val [list $rob(num) $rob(data)] 
    }
  }
  set r(syscall) "team_get ($val)"
  return $val
}


##############################################################################
#
# every scheduler - scarffed from a comp.lang.tcl posing
#  From: burdick@ars.rtp.nc.us (Bill Burdick)
#
#######


proc every {period cmd args} {
    if {$args == {}} {
	set test 1
    } {
      set test [lindex $args 0]
    }
    if {[uplevel #0 "expr {$test}"]} {
	uplevel #0 $cmd
	after [uplevel #0 "expr {$period}"] "every $period {$cmd} {$test}"
    }
}


###############################################################################
#
# oops - can't start or send to wish
#
#

proc oops {robx} {
 global nowin
 upvar #0 $robx r
 global wishexec
 if {$nowin} {
    puts "tclrobots: couldn't start or send to spawned wish interpreter"
    puts "'$wishexec'"
    puts "exiting tclrobots.  possible wish left running...."
    exit
 }
 if {$r(pid) > 0} {
   # bad send text
   tk_dialog2 .oops "oops!" "Couldn't find or send to a new wish,\
    bailing out!\n\nIs your X server configured for xauth style \
    security?\n\nTclRobots uses the Tk 'send' command, which \
    requires that xhost security not be used.  Use xauth \
    if possible.\n\nAlternatively,  re-compile the wish \
    executable\n'$wishexec'\nwith the \
    '-DTK_NO_SECURITY' flag." warning 0 dismiss
  } else {
    # bad wish exec
   tk_dialog2 .oops "oops!" "Couldn't start a new wish interpreter,\
    bailing out!\n\nTclRobots is expecting \n'$wishexec'\nas the \
    name of the wish executable.\nIs it in your PATH?" warning 0 dismiss
  
  }
}

###############################################################################
#
# halt a running match
#
#

proc halt {} {
  global execCmd halted running
  set running 0
  .l configure -text "Stopping battle, standby"
  update
  foreach robx {rob1 rob2 rob3 rob4} {
    upvar #0 $robx r
    if {$r(status)} {
      disable_robot $robx 0
    }
  }
  set halted 1
  set execCmd reset
  .f1.b1 configure -state normal -text "Reset"
  .f1.b2 configure -state disabled
  .f1.b3 configure -state disabled
  .f1.b4 configure -state disabled
  .f1.b5 configure -state disabled
}


###############################################################################
#
# reset to file select state
#
#

proc reset {} {
  global execCmd
  .c delete all
  set execCmd start
  .f1.b1 configure -text "Run Battle" 
  pack forget .c
  pack .f2 -side top -expand 1 -fill both
  .l configure -text "Select robot files for battle" -fg black
  .f1.b1 configure -state normal
  .f1.b2 configure -state normal
  .f1.b3 configure -state normal
  .f1.b4 configure -state normal
  .f1.b5 configure -state normal
}


###############################################################################
#
# shutdown spawned wishes and reset
#
#

proc kill_wishes {robots} {
  # shutdown all spawned wishes
  set i 1
  foreach f $robots {
    upvar #0 rob$i r
    if {$r(status)} {
      disable_robot rob$i 0
    }
    kill_robot rob$i
    incr i
  }
  reset
}


###############################################################################
#
# draw arena boundry
#
#

proc draw_arena {} {
  .c create line 0   0   0 500
  .c create line 0   0 500   0
  .c create line 500 0 500 500
  .c create line 0 500 500 500
}



###############################################################################
#
# start a match
#
#

proc start {} {
  global rob1 rob2 rob3 rob4 parms running halted ticks execCmd numList
  global finish outfile tourn_type nowin

  set finish ""
  set players "battle: "
  set running 0
  set halted  0
  set ticks   0
  set quads $parms(quads)
  set colors $parms(colors)
  set numbots 4
  .l configure -text "Initializing..."

  # clean up robots
  foreach robx {rob1 rob2 rob3 rob4} {
    upvar #0 $robx r
    set r(status) 0
    set r(mstate) 0
    set r(name)   ""
    set r(pid)    -1
  }

  # get robot filenames from window
  set robots ""
  set lst .f2.fr.l1
  for {set i 0} {$i < $numList && $i<4} {incr i} {
    lappend robots [$lst get $i]
  }

  if {[llength $robots] < 2} {
    .l configure -text "Must have at least two robots to run a battle"
    return
  }

  set dot_geom [winfo geom .]
  set dot_geom [split $dot_geom +]
  set dot_x [lindex $dot_geom 1]
  set dot_y [lindex $dot_geom 2]

  # pick random starting quadrant, colors and init robots
  set i 1
  foreach f $robots {
    set n [rand $numbots]
    set color [lindex $colors $n]
    set colors [lreplace $colors $n $n]
    set n [rand $numbots]
    set quad [lindex $quads $n]
    set quads [lreplace $quads $n $n]

    set x [expr [lindex $quad 0]+[rand 300]]
    set y [expr [lindex $quad 1]+[rand 300]]
    
    set winx [expr $dot_x+540]
    set winy [expr $dot_y+(($i-1)*145)]
    set winy [expr (($i-1)*145)]

    set rc [robot_init rob$i $f $x $y $winx $winy $color]

    if {$rc == 0} {
      oops rob$i
      clean_up
      return
    }

    upvar #0 rob$i r
    append players "$r(name) " 

    incr i
    incr numbots -1
  }

  pack forget .f2
  pack .c -side top -expand 1 -fill both
  draw_arena

  # start robots
  .l configure -text "Running"
  set execCmd halt
  .f1.b1 configure -state normal    -text "Halt"
  .f1.b2 configure -state disabled
  .f1.b3 configure -state disabled
  .f1.b4 configure -state disabled
  .f1.b5 configure -state disabled
  start_robots

  # start physics package
  show_robots
  set running 1
  every $parms(tick) update_robots {$running}

  tkwait variable running

  # find winnner
  if {$halted} {
    .l configure -text "Battle halted"
  } else {
    set alive 0
    set winner ""
    set num_team 0
    set diffteam ""
    set win_color black
    foreach robx {rob1 rob2 rob3 rob4} {
      upvar #0 $robx r
      if {$r(status)} {
        disable_robot $robx 0
	incr alive
	lappend winner $r(name)
	set win_color $r(color)
        if {$r(team) != ""} {
          if {[lsearch -exact $diffteam $r(team)] == -1} {
            lappend diffteam $r(team)
            incr num_team
          }
        } else {
          incr num_team
        }
      }
    }
    
    switch $alive {
      0 { 
        set msg "No robots left alive"
	.l configure -text $msg
      }
      1 {
        if {[string length $diffteam] > 0} {
          set diffteam "Team $diffteam"
        }
	set msg "Winner!\n\n$diffteam\n$winner"
	.l configure -text "$winner wins!" -fg $win_color
      }
      default {
        # check for teams
        if {$num_team == 1} {
	  set msg "Winner!\n\nTeam $diffteam\n$winner"
	  .l configure -text "Team: $diffteam : $winner wins!"
        } else {
	  set msg "Tie:\n\n$winner"
	  .l configure -text "Tie: $winner" 
        }
      }
    }
    if {$nowin} {
      set msg2 [join [split $msg \n] " "]
      set score "score: "
      set points 1
      foreach l [split $finish \n] {
        set n [lindex $l 0]
        if {[string length $n] == 0} {continue}
        set l [string last _ $n]
        if {$l > 0} {incr l -1; set n [string range $n 0 $l]}
        append score "$n = $points  "
        incr points
      }
      foreach n $winner {
        set l [string last _ $n]
        if {$l > 0} {incr l -1; set n [string range $n 0 $l]}
        append score "$n = $points  "
      }
      catch {write_file $outfile "$players\n$finish\n$msg2\n\n$score\n\n\n"}
    } else {
      tk_dialog2 .winner "Results" $msg "-image iconfn" 0 dismiss
    }
  }

  set execCmd "kill_wishes \"$robots\""
  .f1.b1 configure -state normal -text "Reset"

}


###############################################################################
#
# about box
#
#

proc about {} {
  tk_dialog2 .about "About TclRobots" "TclRobots\n\nCopyright 1994,1996\nTom Poindexter\ntpoindex@nyx.net\n\nVersion 2.0\nFebruary, 1996\n" "-image iconfn" 0 dismiss

}

###############################################################################
#
# set up main window
#
#

proc main_win {} {

  global execCmd numList parms

  # define our icon 

  set tr_icon {
#define tr_width 48
#define tr_height 48
static char tr_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00,
   0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x07, 0x00, 0x00,
   0x00, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x70, 0x06, 0x00, 0x00,
   0x00, 0x00, 0x38, 0x06, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x00, 0x00,
   0x00, 0x00, 0x0f, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
   0x00, 0x00, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00,
   0x80, 0x87, 0x03, 0x00, 0x07, 0x00, 0x80, 0xbf, 0x01, 0x50, 0x06, 0x00,
   0x00, 0xfc, 0x0f, 0x00, 0x06, 0x00, 0x00, 0xe0, 0x3f, 0x28, 0x06, 0x00,
   0x00, 0x80, 0x39, 0x00, 0x06, 0x00, 0x00, 0x80, 0x01, 0x14, 0x06, 0x00,
   0x00, 0x80, 0x0f, 0xc0, 0x07, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00,
   0x00, 0x00, 0xfc, 0xff, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x7f, 0x00,
   0x00, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x07, 0x00, 0x00, 0xc0, 0x01,
   0x00, 0x07, 0x00, 0x00, 0xc0, 0x01, 0x80, 0xff, 0xff, 0xff, 0xff, 0x03,
   0xc0, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0x7f, 0x30, 0x0c, 0xfc, 0x1f,
   0xf0, 0x7d, 0x30, 0x0c, 0x7c, 0x1f, 0x38, 0xe0, 0x00, 0x00, 0x0e, 0x38,
   0x38, 0xe0, 0x00, 0x00, 0x0e, 0x38, 0x3c, 0xe2, 0x01, 0x00, 0x8f, 0x78,
   0x1c, 0xc7, 0x01, 0x00, 0xc7, 0x71, 0x3c, 0xe2, 0x01, 0x00, 0x8f, 0x78,
   0x38, 0xe0, 0x00, 0x00, 0x0e, 0x38, 0x38, 0xe0, 0x00, 0x00, 0x0e, 0x38,
   0xf0, 0x7d, 0x30, 0x0c, 0x7c, 0x1f, 0xf0, 0x7f, 0x30, 0x0c, 0xfc, 0x1f,
   0xc0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01};
}

  image create bitmap iconfn -data $tr_icon -background ""

  set numList 0
  set execCmd start
  set me [winfo name .]
  if {$parms(cmodel)} {
    #option add *background        gray80
    #option add *activeBackground  gray90
    #option add *Scrollbar*background  gray80
    #option add *Scrollbar*activeBackground  gray90
  }
  option add *highlightThickness 0

  # make a toplevel icon window, iconwindow doesn't have transparent bg :-(
  catch {destroy .iconm}
  toplevel .iconm
  pack [label .iconm.i -image iconfn]

  wm title . "TclRobots"
  wm iconwindow . .iconm
  wm iconname . TclRobots
  wm protocol . WM_DELETE_WINDOW "catch {.f1.b5 invoke}"

  frame .f1
  button .f1.b1 -text "Run Battle" -width 12     -command {eval $execCmd}
  button .f1.b2 -text "Simulator.."    -command sim
  button .f1.b3 -text "Tournament.."   -command tournament
  button .f1.b4 -text "About.."        -command about 
  button .f1.b5 -text "Quit"           -command "clean_up; destroy ." 
  pack .f1.b1 .f1.b2 .f1.b3 .f1.b4 .f1.b5 -side left -expand 1 -fill both

  label .l -relief raised -text {Select robot files for battle}

  frame .f2 -width 520 -height 520 

  frame .f2.fl -relief sunken -borderwidth 3
  frame .f2.fr -relief sunken -borderwidth 3

  fileBox .f2.fl "Select" * "" [pwd] choose_file
  
  label .f2.fr.lab  -text "Robot files selected"
  listbox .f2.fr.l1 -relief sunken  -yscrollcommand ".f2.fr.s set" \
		-selectmode single
  scrollbar .f2.fr.s -command ".f2.fr.l1 yview"
  frame  .f2.fr.fb
  button .f2.fr.fb.b1 -text " Remove "     -command remove_file
  button .f2.fr.fb.b2 -text " Remove All " -command remove_all
  pack .f2.fr.fb.b1 .f2.fr.fb.b2 -side left -padx 5 -pady 5
  pack .f2.fr.lab -side top  -fill x
  pack .f2.fr.fb  -side bottom -fill x
  pack .f2.fr.s   -side right -fill y
  pack .f2.fr.l1  -side left  -expand 1 -fill both

  pack .f2.fl .f2.fr -side left -expand 1 -fill both -padx 10 -pady 10
  canvas .c -width 520 -height 520  -scrollregion "-10 -10 510 510"

  pack .f1 .l  -side top -fill both
  pack .f2 -side top -expand 1 -fill both

  wm geom . 524x574
  update
}


###############################################################################
#
# choose_file
#
proc choose_file {win filename} {
  global numList
  set listsize $numList
  .f2.fr.l1 insert end $filename
  incr numList
  set dir $filename
  for {set i 0} {$i <= $listsize} {incr i} {
    set d [.f2.fr.l1 get $i] 
    if {[string length $d] > [string length $dir]} {
      set dir  $d
    }
  }
  set idx [expr [string length [file dirname [file dirname $dir]] ]+1]
  .f2.fr.l1 xview $idx
}


###############################################################################
#
# choose_all
#
proc choose_all {} {
  global numList
  set win .f2.fl
  set lsize [$win.l.lst size]
  for {set i 0} {$i < $lsize} {incr i} {
    set f [string trim [$win.l.lst get $i]]
    if ![string match */ $f] {
      choose_file $win $f
    }
  }
  
}

###############################################################################
#
# remove_file
#
proc remove_file {} {
  global numList
  set idx -1
  catch {set idx [.f2.fr.l1 curselection]}
  if {$idx >= 0} {
    .f2.fr.l1 delete $idx
    incr  numList -1
  }
}


###############################################################################
#
# remove_all
#
proc remove_all {} {
  global numList
  set idx $numList
  if {$idx > 0} {
    .f2.fr.l1 delete 0 end
    set numList 0
  }
}


#######################################################################
# file selection box,  from my "wosql" in Oratcl
# modified not to use a toplevel
#######################################################################
# procs to support a file selection dialog box

########################
#
# fillLst
#
#    fill the fillBox listbox with selection entries
#

proc fillLst {win filt dir} {
  
  $win.l.lst delete 0 end

  cd $dir

  set dir [pwd]
  
  if {[string length $filt] == 0} {
    set filt *
  }
  set all_list [lsort [glob -nocomplain $dir/$filt]]

  set dlist  "$dir/../"
  set flist ""

  foreach f $all_list {
    if [file isfile $f] {
      lappend flist $f
    }
    if [file isdirectory $f] {
      lappend dlist ${f}/
    }
  }

  foreach d $dlist {
    $win.l.lst insert end $d
  }
  foreach f $flist {
    $win.l.lst insert end $f
  }

  $win.l.lst yview 0

  set idx [expr [string length [file dirname [file dirname $dir]] ]+1]

  $win.l.lst xview $idx
}


########################
#
# selInsert
#
#   insert into a selection entry, scroll to root name
#
proc selInsert {win pathname} {

  $win.sel delete 0 end
  $win.sel insert 0 $pathname
  set idx [expr [string length [file dirname [file dirname $pathname]] ]+1]
  $win.sel xview $idx
  $win.sel select from 0
}


########################
#
# fileOK
#
#   do the OK processing for fileBox
#

proc fileOK {win execproc} {
  
  # might not have a valid selection, so catch the selection
  # catch {  selInsert $win [lindex [selection get] 0] }
  catch {  selInsert $win [$win.l.lst get [$win.l.lst curselection]] }

  set f [lindex [$win.sel get] 0]
  if [file isdirectory $f] {
    #set f [file dirname $f]
    #set f [file dirname $f]
    cd $f
    set f [pwd]
    fillLst $win [$win.fil get] $f
  } else {
    # we don't know if a file is really there or not, let the execproc
    # figure it out.  also, window is passed if execproc wants to kill it.
    $execproc $win $f 
  }
}

########################
#
# fileBox
#
#   put up a file selection box
#    win - name of toplevel to use
#    filt - initial file selection filter 
#    initfile - initial file selection 
#    startdir - initial starting dir
#    execproc - proc to exec with selected file name
#
proc fileBox {win txt filt initfile startdir execproc} {

  if {[string length $startdir] == 0} {
    set startdir [pwd]
  }

  label $win.l1   -text "File Filter" -anchor w
  entry $win.fil  -relief sunken
  $win.fil insert 0 $filt
  label $win.l2   -text "Files" -anchor w
  frame $win.l  
  scrollbar $win.l.hor -orient horizontal -command "$win.l.lst xview" \
	    -relief sunken
  scrollbar $win.l.ver -orient vertical   -command "$win.l.lst yview" \
	    -relief sunken
  listbox $win.l.lst -yscroll "$win.l.ver set" -xscroll "$win.l.hor set" \
	    -selectmode single -relief sunken
  
  label $win.l3   -text "Selection" -anchor w
  scrollbar $win.scrl -orient horizontal -relief sunken \
                      -command "$win.sel xview"
  entry $win.sel  -relief sunken -xscroll "$win.scrl set"
  selInsert $win $initfile
  pack $win.l.ver -side right -fill y
  pack $win.l.hor -side bottom -fill x
  pack $win.l.lst -side left   -fill both  -expand 1 -ipadx 3

  frame $win.o  -relief sunken -border 1
  button $win.o.ok -text " $txt " -command "fileOK $win $execproc"
  button $win.all -text " Select All " -command "choose_all"
  button $win.filter -text " Filter " \
	  -command "fillLst $win \[$win.fil get\] \[pwd\]"

  pack $win.l1 -side top -fill x
  pack $win.fil -side top -pady 2 -fill x -ipadx 5
  pack $win.l2 -side top -fill x
  pack $win.l  -side top -fill both -expand 1
  pack $win.l3 -side top -fill x
  pack $win.sel -side top -pady 5 -fill x -ipadx 5
  pack $win.scrl -side top -fill x
  pack $win.o.ok -side left  -padx 5 -pady 5
  pack $win.o $win.all $win.filter  -side left -padx 5 -pady 10

  bind $win.fil <KeyPress-Return> "$win.filter invoke"
  bind $win.sel <KeyPress-Return> "$win.o.ok   invoke"
  bind $win.l.lst <ButtonRelease-1> \
   "+selInsert $win \[%W get \[ %W nearest %y \] \] "
  bind $win.l.lst <Double-1> \
   "selInsert $win \[%W get \[%W curselection\]\];  $win.o.ok invoke"
  bind $win <1> "$win.o.ok config -relief sunken"


  fillLst $win $filt $startdir
  selection own $win
  focus $win.sel

}

#
# end of the file selection box stuff
###########################################################################




###############################################################################
#
# step toggle
#
#

proc do_step {} {
  global rob1 parms running step
  if {$step} {
    send $rob1(name) "set _step_ 1; set _resume_ 1"
    .debug.f2.x configure -relief sunken -state normal
    .debug.f2.y configure -relief sunken -state normal
    .debug.f2.h configure -relief sunken -state normal
    .debug.fb.s configure -relief sunken -state normal
    .debug.fb.h configure -relief sunken -state normal
    .debug.fb.d configure -relief sunken -state normal
  } else {
    .debug.f2.x configure -relief flat   -state disabled
    .debug.f2.y configure -relief flat   -state disabled
    .debug.f2.h configure -relief flat   -state disabled
    .debug.fb.s configure -relief flat   -state disabled
    .debug.fb.h configure -relief flat   -state disabled
    .debug.fb.d configure -relief flat   -state disabled
    send $rob1(name) "set _step_ 0; set _resume_ 1"
    every $parms(tick) update_robots {$running && !$step }
  }
}

###############################################################################
#
# single step
#
#

proc do_single {} {
  global rob1 parms running step
  set step 1
  send $rob1(name) "set _step_ 1; set _resume_ 1"
  .debug.f2.x configure -relief sunken -state normal
  .debug.f2.y configure -relief sunken -state normal
  .debug.f2.h configure -relief sunken -state normal
  .debug.fb.s configure -relief sunken -state normal
  .debug.fb.h configure -relief sunken -state normal
  .debug.fb.d configure -relief sunken -state normal
  update_robots
}

###############################################################################
#
# examine a variable
#
#

proc examine {} {
  global rob1
  .debug.f4.val delete 0 end
  if {[catch {send $rob1(name) format \$[.debug.f4.var get]} val] == 0} {
    .debug.f4.val insert 0 $val
  } else {
    .debug.f4.val insert 0 "(not found)"
  }
}

###############################################################################
#
# set a variable
#
#

proc setval {} {
  global rob1
  catch {send $rob1(name) set [.debug.f4.var get] [list [.debug.f4.val get]]}
}


###############################################################################
#
# set heat background to indicate over heat
#
#

proc set_h_bg {args} {
  global rob1 parms bgColor
  if {$rob1(hflag)} {
    if {$parms(cmodel)} {
      .debug.f2.h configure -bg red
    } else {
      .debug.f2.h configure -bg black -fg white
    }
  } else {
    if {$parms(cmodel)} {
      .debug.f2.h configure -bg $bgColor
    } else {
      .debug.f2.h configure -bg white -fg black
    }
  }
}


#####################################
Results 1 - 1
Help - FTP Sites List - Software Dir.
Searching half a billion files worldwide
© 1997-2009 MARUHN Internet Solutions