Index by: file name |
procedure name |
procedure call |
annotation
gscope_fourmis.tcl
(annotations | original source)
#rR gscope_fourmis.tcl sourcé par Fourmis dans gscope_atelier
proc DrawFourmis {} {
global TFB
#LoadTkAndPackages
# parametres
if { ! [info exists TFB(step) ]} { set TFB(step) 5 }
if { ! [info exists TFB(HueProche) ]} { set TFB(HueProche) 0.2 }
if { ! [info exists TFB(lenFourmi) ]} { set TFB(lenFourmi) 1 }
if { ! [info exists TFB(widFourmi) ]} { set TFB(widFourmi) 1 }
if { ! [info exists TFB(headFourmi) ]} { set TFB(headFourmi) 1 }
if { ! [info exists TFB(colTeteFourmi) ]} { set TFB(colTeteFourmi) white }
if { ! [info exists TFB(colCorpsFourmi) ]} { set TFB(colCorpsFourmi) grey }
if { ! [info exists TFB(nFourmis) ]} { set TFB(nFourmis) 5 }
if { ! [info exists TFB(rad) ]} { set TFB(rad) 10 }
if { ! [info exists TFB(nRouges) ]} { set TFB(nRouges) 30 }
if { ! [info exists TFB(nJaunes) ]} { set TFB(nJaunes) 30 }
if { ! [info exists TFB(nBleues) ]} { set TFB(nBleues) 20 }
if { ! [info exists TFB(nArcEnCiel) ]} { set TFB(nArcEnCiel) 30 }
if { ! [info exists TFB(dimX) ]} { set TFB(dimX) 1000 }
if { ! [info exists TFB(dimY) ]} { set TFB(dimY) 1000 }
if { ! [info exists TFB(mur) ]} { set TFB(mur) 1 }
return [Plateau]
}
proc Boules PAD {
return [BoulesTriColor $PAD]
}
proc MeetBall {iF bbox nbb} {
return [MeetBallTriColor $iF $bbox $nbb]
}
proc BoulesArcEnCiel {PAD} {
global TFB
# trace les boules
foreach i [NombresEntre 0 [expr $TFB(nArcEnCiel) - 1] ] {
set Hue [expr 1.0*rand()]
Espionne $Hue
set col [Nuance $Hue 0. 1.]
set ok 0
while {! $ok} {
set x [expr {round($TFB(dimX)*rand())}]
set y [expr {round($TFB(dimY)*rand())}]
set x1 [expr {$x - $TFB(rad)}]
set x2 [expr {$x + $TFB(rad)}]
set y1 [expr {$y - $TFB(rad)}]
set y2 [expr {$y + $TFB(rad)}]
# test boule sur le plateau
if {$x1 < $TFB(rad) || $y1 < $TFB(rad)} {
continue
}
if {$x2 > ($TFB(dimX)-$TFB(rad)) || $y2 > ($TFB(dimY)-$TFB(rad))} {
continue
}
# rajoute rad pour que les boules
# soitent ecartees d'une boule
set x1f [expr {$x - 2.*$TFB(rad)}]
set x2f [expr {$x + 2.*$TFB(rad)}]
set y1f [expr {$y - 2.*$TFB(rad)}]
set y2f [expr {$y + 2.*$TFB(rad)}]
if {[$PAD find overlapping $x1f $y1f $x2f $y2f] == {}} {
set ok 1
}
}
$PAD create oval \
$x1 $y1 $x2 $y2 \
-fill $col \
-outline $col \
-tags [list ball $Hue libre]
#puts "id $id $x1 $y1 $x2 $y2"
}
}
proc BoulesTriColor {PAD} {
global TFB
# trace les boules
foreach col {red yellow green} nBalls [list [set TFB(nRouges)] [set TFB(nJaunes)] [set TFB(nBleues)]] {
for {set i 0} {$i < $nBalls} {incr i} {
set ok 0
while { ! $ok} {
set x [expr {round($TFB(dimX)*rand())}]
set y [expr {round($TFB(dimY)*rand())}]
set x1 [expr {$x - $TFB(rad)}]
set x2 [expr {$x + $TFB(rad)}]
set y1 [expr {$y - $TFB(rad)}]
set y2 [expr {$y + $TFB(rad)}]
# test boule sur le plateau
if {$x1 < $TFB(rad) || $y1 < $TFB(rad)} {
continue
}
if {$x2 > ($TFB(dimX)-$TFB(rad)) || $y2 > ($TFB(dimY)-$TFB(rad))} {
continue
}
# rajoute rad pour que les boules
# soient ecartees d'une boule
set x1f [expr {$x - 2.*$TFB(rad)}]
set x2f [expr {$x + 2.*$TFB(rad)}]
set y1f [expr {$y - 2.*$TFB(rad)}]
set y2f [expr {$y + 2.*$TFB(rad)}]
if {[$PAD find overlapping $x1f $y1f $x2f $y2f] == {}} {
set ok 1
}
}
$PAD create oval \
$x1 $y1 $x2 $y2 \
-fill $col \
-outline $col \
-tags [list ball $col libre]
#puts "id $id $x1 $y1 $x2 $y2"
}
}
}
proc UnMur {PAD {Sens ""}} {
global TFB
if {$Sens=="Hori"} {
set x1 [expr {0.1 * $TFB(dimX)}]
set x2 [expr {0.3 * $TFB(dimX)}]
set y1 [expr {10}]
set y2 [expr {$y1 + 20}]
} else {
set x1 [expr {10}]
set x2 [expr {$x1 + 20}]
set y1 [expr {0.1 * $TFB(dimY)}]
set y2 [expr {0.3 * $TFB(dimY)}]
}
return [$PAD create rectangle $x1 $y1 $x2 $y2 \
-fill grey \
-outline white \
-tags [list "mur"]]
}
proc Plateau {} {
global PAD TFB
global CouleurDuFondDeUnCanva
set CouleurDuFondDeUnCanva "black"
if {0} {
set w .f
frame $w
grid $w -row 0 -column 0 -sticky news
grid columnconfig $w 0 -weight 1
grid rowconfig $w 0 -weight 1
set PAD $w.can
canvas $PAD \
-height $TFB(dimY) \
-width $TFB(dimX) \
-scrollregion [list 0 0 $TFB(dimX) $TFB(dimY)] \
-background black
grid $PAD -row 0 -column 0 -sticky news
FenetreAuCentre $w
}
set ::go 0
Espionne "$TFB(dimX) $TFB(dimY) $TFB(dimX) $TFB(dimY)"
set PAD [UnCanva $TFB(dimX) $TFB(dimY) $TFB(dimX) $TFB(dimY)]
MainLeveeSurUnCanva $PAD
Espionne $PAD
regsub "\.canvas" $PAD "" TopLev
bind $TopLev "<KeyPress-space>" GoNoGo
BoutonneLaFenetre $TopLev "Pause" "GoNoGo"
BoutonneLaFenetre $TopLev "Start" "StartFourmis"
BoutonneLaFenetre $TopLev "Fourmis" "InitFourmis"
BoutonneLaFenetre $TopLev "Boules" "Boules $PAD"
BoutonneLaFenetre $TopLev "Mur Hori" "UnMur $PAD Hori"
BoutonneLaFenetre $TopLev "Mur Vert" "UnMur $PAD Vert"
return
}
proc BougeFourmi {} {
set ::go [expr {! $::go}]
update
return
}
proc InitFourmis {} {
global TFB PAD
set taille [expr {($TFB(lenFourmi) + $TFB(headFourmi))/2}]
for {set i 0} {$i < $TFB(nFourmis)} {incr i} {
set ok 0
while {! $ok} {
set x [expr {round($TFB(dimX)*rand())}]
set y [expr {round($TFB(dimY)*rand())}]
# y a t il qq chose dans la boite
# qui va contenir la fourmi ?
set x1 [expr {$x - $taille}]
set x2 [expr {$x + $taille}]
set y1 [expr {$y - $taille}]
set y2 [expr {$y + $taille}]
if {[$PAD find overlapping $x1 $y1 $x2 $y2] == {}} {
set ok 1
}
}
if {1} {
set x1 [expr {$x - $TFB(headFourmi)/2}]
set x2 [expr {$x + $TFB(headFourmi)/2}]
set y1 [expr {$y - $TFB(headFourmi)/2}]
set y2 [expr {$y + $TFB(headFourmi)/2}]
$PAD create oval \
$x1 $y1 $x2 $y2 \
-fill $TFB(colTeteFourmi) \
-outline $TFB(colTeteFourmi) \
-tags [list fourmi tete "F$i"]
} else {
set x1 [expr {$x - $TFB(lenFourmi)/2}]
set x2 [expr {$x + $TFB(lenFourmi)/2}]
set y1 [expr {$y - $TFB(widFourmi)/2}]
set y2 [expr {$y + $TFB(widFourmi)/2}]
$PAD create polygon \
$x1 $y1 $x1 $y2 $x2 $y2 $x2 $y1 \
-fill $TFB(colCorpsFourmi) \
-outline $TFB(colCorpsFourmi) \
-tags [list fourmi corps "F$i"]
set xc $x2 ; set yc $y
set x1 [expr {$xc - $TFB(headFourmi)/2}]
set x2 [expr {$xc + $TFB(headFourmi)/2}]
set y1 [expr {$yc - $TFB(headFourmi)/2}]
set y2 [expr {$yc + $TFB(headFourmi)/2}]
$PAD create polygon \
$x1 $y1 $x2 $yc $x1 $y2 \
-fill $TFB(colTeteFourmi) \
-outline $TFB(colTeteFourmi) \
-tags [list fourmi tete "F$i"]
}
set TFB(F$i,oldAng) 0
set TFB(F$i,angle) [BonAngle [expr {359.*rand()}]]
set TFB(F$i,hasBall) 0
set TFB(F$i,lastBall) -1
set TFB(F$i,col) ""
# set TFB(F$i,angle) 45.
TourneFourmi "F$i"
OnSortPas "F$i"
lappend TFB(LFourmis) $i
}
return
}
proc GoNoGo {} {
set ::go [expr {!$::go}]
return $::go
}
proc StartFourmis {} {
global TFB PAD
set ::go 1
set iF "F0"
#$PAD moveto $iF 300 300
set TFB(F0,angle) 45.
#trace add variable TFB(F5,angle) write tangle
# bounding box du mur
lassign [$PAD bbox "mur"] x1m y1m x2m y2m
set Step 0
while {$::go} {
if {0 && [incr Step]%1000==0 && [OuiOuNon "On stoppe"]} { break }
update idletasks
# after 1
# $PAD delete marque
if {! $::go} {
after 50
update idletasks
continue
}
# select a fourmi
set ix [expr {int($TFB(nFourmis)*rand())}]
set iF "F[lindex $TFB(LFourmis) $ix]"
# puts "\nbouge $iF"
# coords de fourmis
set xadd [expr {round($TFB(step)*cos($TFB($iF,angle)*[Pi]/180.))}]
set yadd [expr {round($TFB(step)*sin($TFB($iF,angle)*[Pi]/180.))}]
# puts "xadd $xadd yadd $yadd $TFB($iF,angle)"
set bbox [$PAD bbox $iF]
lassign $bbox x1 y1 x2 y2
set xn1 [expr {$x1 + $xadd}]
set yn1 [expr {$y1 + $yadd}]
set xn2 [expr {$x2 + $xadd}]
set yn2 [expr {$y2 + $yadd}]
set nbb [list $xn1 $yn1 $xn2 $yn2]
set deplace 0
set xd 0 ; set yd 0
if {[SortiePlateau $iF $nbb]} {
TourneFourmi $iF
OnSortPas $iF
set nbb [$PAD bbox $iF]
} else {
$PAD move $iF $xadd $yadd
}
# test choc
switch [MeetBall $iF $bbox $nbb] {
"repart" {
set TFB($iF,oldAng) $TFB($iF,angle)
set TFB($iF,angle) [BonAngle [expr {359.*rand()}]]
TourneFourmi $iF
OnSortPas $iF
}
"danslemur" {
# on a la bbox avant deplacement
# on cherche de quel cote on tape
set TFB($iF,oldAng) $TFB($iF,angle)
if {$x1 < $x1m} {
# tape mur a gauche
set ang [BonAngle [expr {180.*rand() + 90.}]]
} elseif {$x2 > $x2m} {
# tape mur a droite
set ang [BonAngle [expr {-180.*rand() + 90.}]]
} elseif {$y1 < $y1m} {
# tape mur par le haut
set ang [BonAngle [expr {-180.*rand()}]]
} else {
# tape mur par le bas
set ang [BonAngle [expr {180.*rand()}]]
}
set TFB($iF,angle) $ang
TourneFourmi $iF
set deplace 1
}
"droit" {
set deplace 1
}
}
if {$deplace} {
#$PAD move $iF $xadd $yadd
}
lassign [$PAD bbox $iF] a b c d
incr a -10 ; incr b -10
incr c 10 ; incr d 10
set Lb [list $a $b $c $d]
if {0} {
$PAD create rectangle $Lb \
-width 3 \
-outline white \
-tags [list marque]
}
$PAD raise "fourmi"
$PAD raise "ball"
# $PAD raise marque
}
return
}
proc SortiePlateau {iF nbb} {
lassign $nbb x1 y1 x2 y2
set changed 0
set old $::TFB($iF,angle)
if {$x1 < 1 || $x2 > ($::TFB(dimX)-1)} {
if {$x1 < 1} {
set ang [expr {180.*rand() - 90.}]
} else {
set ang [BonAngle [expr {180.*rand() + 90.}]]
}
set ::TFB($iF,oldAng) $old
set ::TFB($iF,angle) $ang
set changed 1
}
if {$y1 < 1 || $y2 > ($::TFB(dimY)-1)} {
if {$y1 < 1} {
set ang [expr { 180.*rand()}]
} else {
set ang [expr {-180.*rand()}]
}
set ::TFB($iF,oldAng) $old
set ::TFB($iF,angle) $ang
set changed 1
}
if {$changed} {
return 1
} else {
return 0
}
}
proc MeetBallArcEnCiel {iF bbox nbb} {
global PAD TFB
set HueProche $TFB(HueProche)
set itete [$PAD find withtag "$iF && tete"]
set Lid [$PAD find overlapping {*}[$PAD bbox $itete]]
foreach tid $Lid {
set Ltags [$PAD gettags $tid]
set HueBoule [lindex $Ltags 1]
if {"$iF" in $Ltags} {
# la fourmi est contenue dans sa
# propre bounding box
continue
}
# si rencontre un mur, repart
if {"mur" in $Ltags} {
return "danslemur"
}
# si rencontre le cadre, repart
if {"Cadre" in $Ltags} {
return "danslemur"
}
# si rencontre fourmi, repart
if {"fourmi" in $Ltags} {
return "repart"
}
# boule prise
if {"pris" in $Ltags} {
continue
}
# on rencontre boule
if {! $TFB($iF,hasBall)} {
if {$TFB($iF,lastBall) != $tid} {
# fourmi n a pas de boule
# charge boule
# puts "charge $tid sur $iF"
set TFB($iF,hasBall) $tid
set TFB($iF,lastBall) $tid
# set TFB($iF,col) [$PAD itemcget $tid -fill]
set TFB($iF,hue) $HueBoule
BouleSurTete $iF $tid
if {[llength $Ltags]<3} {
Espionne "Fourmi $iF n'a que les tags $Ltags"
exit
}
lset Ltags 2 "pris"
lappend Ltags $iF
$PAD itemconfig $tid -tags $Ltags
# puts "tags $Ltags"
# parray TFB "$iF,*"
return "droit"
} else {
return "droit"
}
} else {
# depose si meme couleur
# sinon repart
set HueBoule
set HueFourmi $TFB($iF,hue)
if {$HueBoule<$HueFourmi} {
set Mi $HueBoule
set Ma $HueFourmi
} else {
set Mi $HueFourmi
set Ma $HueBoule
}
set DiffHue [expr min($Ma-$Mi, 1.0+$Mi-$Ma)]
# set DiffHue [expr min($Ma-$Mi)]
if {$DiffHue<$HueProche} {
# meme couleur, depose
# id de boule a deposer
set idd $TFB($iF,hasBall)
# puts "depose $idd de $iF"
set TFB($iF,hasBall) 0
set Ltags [$PAD gettags $idd]
if {[llength $Ltags]<3} { Espionne $Ltags ; exit }
lset Ltags 2 "libre"
set Ltags [lrange $Ltags 0 end-1]
# puts "tags $Ltags"
# parray TFB "$iF,*"
$PAD itemconfig $idd -tags $Ltags
return "repart"
} else {
return "repart"
}
}
}
return "droit"
}
proc MeetBallTriColor {iF bbox nbb} {
global PAD TFB
set itete [$PAD find withtag "$iF && tete"]
set Lid [$PAD find overlapping {*}[$PAD bbox $itete]]
foreach tid $Lid {
set Ltags [$PAD gettags $tid]
if {"$iF" in $Ltags} {
# la fourmi est contenue dans sa
# propre bounding box
continue
}
# si rencontre un mur, repart
if {"mur" in $Ltags} {
return "danslemur"
}
# si rencontre le cadre, repart
if {"Cadre" in $Ltags} {
return "danslemur"
}
# si rencontre fourmi, repart
if {"fourmi" in $Ltags} {
return "repart"
}
# boule prise
if {"pris" in $Ltags} {
continue
}
# on rencontre boule
if {! $TFB($iF,hasBall)} {
if {$TFB($iF,lastBall) != $tid} {
# fourmi n a pas de boule
# charge boule
# puts "charge $tid sur $iF"
set TFB($iF,hasBall) $tid
set TFB($iF,lastBall) $tid
set TFB($iF,col) [$PAD itemcget $tid -fill]
BouleSurTete $iF $tid
if {[llength $Ltags]<3} {
Espionne "Fourmi $iF n'a que les tags $Ltags"
}
lset Ltags 2 "pris"
lappend Ltags $iF
$PAD itemconfig $tid -tags $Ltags
# puts "tags $Ltags"
# parray TFB "$iF,*"
return "droit"
} else {
return "droit"
}
} else {
# depose si meme couleur
# sinon repart
if {$TFB($iF,col) in $Ltags} {
# meme couleur, depose
# id de boule a deposer
set idd $TFB($iF,hasBall)
# puts "depose $idd de $iF"
set TFB($iF,hasBall) 0
set Ltags [$PAD gettags $idd]
if {[llength $Ltags]<3} {
Espionne "Fourmi $iF n'a que les tags $Ltags"
exit
}
lset Ltags 2 "libre"
set Ltags [lrange $Ltags 0 end-1]
# puts "tags $Ltags"
# parray TFB "$iF,*"
$PAD itemconfig $idd -tags $Ltags
return "repart"
} else {
return "repart"
}
}
}
return "droit"
}
proc TourneListe {xr yr ang Lc} {
set cd [expr {cos($ang*[Pi]/180.)}]
set sd [expr {sin($ang*[Pi]/180.)}]
set Lout [list]
foreach {x2 y2} $Lc {
set xp [expr {$x2 - $xr}]
set yp [expr {$y2 - $yr}]
set x [expr {$xp*$cd-$yp*$sd}]
set y [expr {$xp*$sd+$yp*$cd}]
set xf [expr {round($x + $xr)}]
set yf [expr {round($y + $yr)}]
lappend Lout $xf $yf
}
return $Lout
}
proc TourneFourmi {tag} {
global PAD TFB
lassign [CentreFourmi $tag] xm ym
set ov ""
foreach elt [$PAD find withtag $tag] {
if {[$PAD type $elt] == "oval"} {
set ov $elt
continue
}
set Lc [$PAD coords $elt]
set angTot [BonAngle [expr {$TFB($tag,angle) - $TFB($tag,oldAng)}]]
set Lc [TourneListe $xm $ym $angTot $Lc]
#set Lc [TourneListe $xm $ym [expr {-1.*$TFB($tag,oldAng)}] $Lc]
#set Lc [TourneListe $xm $ym $TFB($tag,angle) $Lc]
$PAD coords $elt {*}$Lc
}
if {$ov != ""} {
BouleSurTete $tag $ov
}
set TFB($tag,oldAng) $TFB($tag,angle)
return
}
proc tangle {a b op} {
puts "[info level -1]"
puts " ang $::TFB(F5,angle)"
return
}
proc OnSortPas {tag} {
set dimX $::TFB(dimX)
set dimY $::TFB(dimY)
set xmin 1 ; set xmax [expr {$dimX - 1}]
set ymin 1 ; set ymax [expr {$dimY - 1}]
set Lc [$::PAD bbox $tag]
foreach {x y} $Lc {
if {$x < $xmin} {set xmin $x}
if {$x > $xmax} {set xmax $x}
if {$y < $ymin} {set ymin $y}
if {$y > $ymax} {set ymax $y}
}
set xd 0.0 ; set yd 0.0
if {$xmin < 1} {
set xd [expr {-1. * $xmin + 1}]
}
if {$ymin < 1} {
set yd [expr {-1. * $ymin + 1}]
}
if {$xmax > ($dimX - 1)} {
set xd [expr {-1*($xmax - $dimX + 1)}]
}
if {$ymax > ($dimY - 1)} {
set yd [expr {-1*($ymax - $dimY + 1)}]
}
if {$xd != 0.0 || $yd != 0.0} {
# puts "OnSortPas $xd $yd"
$::PAD move $tag $xd $yd
BouleSurTete $tag
}
return
}
proc BonAngle {a} {
while {$a > 180.} {
set a [expr {$a - 360.}]
}
while {$a < -180.} {
set a [expr {$a + 360.}]
}
return $a
}
proc CentreFourmi {id} {
set xm 0 ; set ym 0
set n 0
foreach e [$::PAD find withtag $id] {
if {[$::PAD type $e] == "oval"} {
foreach {x y} [$::PAD coords $e] {
set xm [expr {$xm + $x}]
set ym [expr {$ym + $y}]
incr n
}
} else {
foreach {x y} [$::PAD coords $e] {
set xm [expr {$xm + $x}]
set ym [expr {$ym + $y}]
incr n
}
}
}
set xm [expr {round($xm/$n)}]
set ym [expr {round($ym/$n)}]
#rR pourquoi des entiers pour le centre ?
return [list $xm $ym]
}
proc BouleSurTete {iF {tid ""}} {
if {$tid eq ""} {
set tid [$::PAD find withtag "$iF && ball"]
if {$tid == {} } {
return
}
}
set id [$::PAD find withtag "$iF && tete"]
set xc 0.0 ; set yc 0.0
set n 0
foreach {x y} [$::PAD coords $id] {
set xc [expr {$xc + $x}]
set yc [expr {$yc + $y}]
incr n
}
# puts "boule $tid sur $iF , corps $id"
set xc [expr {round($xc/$n)}]
set yc [expr {round($yc/$n)}]
# puts "-> $xc $yc"
lassign [$::PAD coords $tid] x1 y1 x2 y2
set xb [expr {($x1 + $x2) / 2}]
set yb [expr {($y1 + $y2) / 2}]
set vx [expr {$xc - $xb}]
set vy [expr {$yc - $yb}]
# puts "-> $vx $vy"
#$::PAD moveto $tid $xc $yc
$::PAD move $tid $vx $vy
$::PAD raise $tid
return
}
Index by: file name |
procedure name |
procedure call |
annotation
File generated 2022-04-05 at 12:55.