KnotLogo-Hubnet
Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)
VERSION
$Id: KnotLogo-Hubnet.nlogo 40114 2008-06-12 23:22:32Z tisue $
WHAT IS IT?
This Hubnet model is based off of the KnotOrNot3D NetLogo model, which is a microworld for playing with rope, thinking and learning about knots and knot theory, as well as creating virtual rope-based art and artifacts. This Hubnet version of it provides a shared virtual space where a class can interact together to engage in these activities.
HOW IT WORKS
Students have more limited control than they do in the "solo" KnotOrNot environment. They also have a different method of navigating their snakes. In the "solo" world, everything was snake-centric. In the Hubnet version, students choose absolute directions for their snake's movement (North, South, East, West, Up, and Down), and are limited to orthogonal movement (although the snake's body will still curve nicely around behind). The reason for this change is twofold.
1) I think it's good for students to have to think in multiple representations -- both from the perspective of individual agents, and from the perspective of the environment. Or, from a totally mathematical perspective, we are making them think in two different coordinate spaces.
2) In the "solo" model, each student could move the camera and position it such that they had a good view of their turtle, and could figure out which direction it was facing. In this Hubnet version, there is only one global camera, controlled by the teacher, and so viewing your turtle's heading is more difficult. It should be easier to spotting your turtle's location, and using the direction labels on the boundaries of the world, choose an appropriate direction to move.
HOW TO USE IT
The teacher should push SETUP, then GO. DON'T push SETUP again after the model is running!
Students should log in. They will each be assigned a color of snake based on their order of logging in, and they will be told (on their client screens) what color they are. Currently there are only different colors, so more than 8 clients will cause repeated colors -- and probably some confusion. More colors can be added easily by changing the COLORS and COLOR-NAMES lists that are initialized in the SETUP procedure. The trick is in choosing lots of good colors that contrast with each other.
The RESET-SNAKES button makes all the snakes only one segment long, and moves them all to the center of the world.
If desired, the teacher can also set the CAMERA-ORBIT button going, so that the viewing angle on the world will slowly rotate around. This may be useful for making the world seem more 3D, as well as moving closer and farther away from various students.
If the class creates a neat rope configuration that they'd like to save, the teacher can use the SAVE-TO-VRML button.
THINGS TO NOTICE
The student's snake bodies are limited to 40 units in length in this Hubnet version, to prevent any student from getting too carried away. Furthermore, the model runs more slowly the more segments there are in the world, and the Hubnet version in particular can really come to a crawl when the world is crowded. Thus limiting the length of snakes should be helpful for that.
THINGS TO TRY
This is a fairly open-ended participatory simulation. In general, it might work to let the class choose the direction of the activity. That said, sometimes they need more structure and guidance, so here are some ideas:
1) Can the class pair up and tie simple knots with each other?
2) Can the class form a long chain, by having each snake bite its own tail through the rings created by two other snakes?
3) Can the class cooperatively spell out a message using the snake bodies?
EXTENDING THE MODEL
Make a slider for the teacher that controls the maximum segment length for any snake.
Try adding support for teacher-controlled snakes. Or give the teacher more controls for manipulating the student's snakes.
What about giving client interfaces inputboxes, so students can ask their snakes to run any code they want? Is this safe? Probably not, students who are sufficiently savvy with NetLogo can find ways to break the model. Even so, it still could be a lot of fun, and the benefits might outweigh the drawbacks.
RELATED MODELS
KnotOrNot3D -- the solo version.
CREDITS AND REFERENCES
Model authored by Forrest Stonedahl, for an LS 426 Final Project at Northwestern University.
The basic rope simulation is adapted from the "follow the leader" algorithm proposed in this paper:
Brown, J. Latombe, J. & Montgomery, K. (2004), 'Real-time knot-tying simulation', The Visual Computer 20(2), 165--179.
Comments and Questions
extensions [ vrml ] globals [ headlist jigglers jiggler-patches first-mover ; for keeping track of which snakesegment initiates motion, ; whenever a snake movement occurs colors color-names ] breed [snakesegments snakesegment] snakesegments-own [ prev next snake-id tempdx tempdy tempdz ] ; for hubnet handling breed [students student] students-own [ my-hubnet-id my-snake-id move-snake? ] to startup hubnet-set-client-interface "COMPUTER" [] hubnet-reset setup-vars end ;; initialize global variables to setup-vars set colors (list red brown green yellow violet (sky + 1) pink (blue - 1)) set color-names ["red" "brown" "green" "yellow" "purple" "light blue" "pink" "dark blue"] end to-report get-color [ id ] report (item (id mod (length colors)) colors) end to-report get-color-name [ id ] report (item (id mod (length color-names)) color-names) end to setup clear-patches reset-perspective set headlist [] set first-mover nobody ask patch 0 0 (max-pzcor - 2) [ set plabel "UP" ] ask patch 0 0 (min-pzcor + 2) [ set plabel "DOWN" ] ask patch 0 (max-pycor - 2) 0 [ set plabel "NORTH" ] ask patch 0 (min-pycor + 2) 0 [ set plabel "SOUTH" ] ask patch (max-pxcor - 2) 0 0 [ set plabel "EAST" ] ask patch (min-pxcor + 2) 0 0 [ set plabel "WEST" ] orbit-down 45 orbit-left 30 zoom 20 end to go listen-clients forward-all 0.1 end to reset-snakes ask snakes [ repeat 39 [ snake-shrink ] setxyz 0 0 0 set heading 360 * snake-id / (count snakes) ] end to update-appearance ifelse (is-head? and not looped?) [ set shape "default" set size 2 ] [ set shape "circle" set size 1 ] set color (get-color snake-id) - 1 if (is-head?) [ set color color + 2 ] end to-report snake [ n ] if (n < 0 or n >= length headlist or (item n headlist) = nobody ) [ user-message (word "Snake " n " doesn't exist!") report nobody ] report item n headlist end to-report snakes report turtle-set headlist end to-report is-head? report self = snake snake-id end to-report is-tail? report (next = nobody) or ([is-head?] of next) end to-report get-head report (snake snake-id) end to-report get-tail ifelse (is-tail?) [ report self ] [ report [get-tail] of next ] end to-report make-snake [ x y z ] if (not is-list? headlist ) [ set headlist [] ] let nextid position nobody headlist ; reuse snake-ids if (nextid = false) [ set nextid length headlist ] let temp nobody create-snakesegments 1 [ setxyz x y z set pitch random 360 set prev nobody set next nobody set temp self set snake-id nextid ] ifelse (nextid = length headlist) [ set headlist lput temp headlist ] [ set headlist replace-item nextid headlist temp ] ask temp [ update-appearance ] report temp end to snake-grow ; impose a limit of 40 segments, to prevent any student ; from going too crazy about snake-length. if (count snakesegments with [ snake-id = [snake-id] of myself ] < 40) [ let temp next hatch 1 [ set next temp set prev myself set temp self update-appearance ] if (not is-tail?) [ ask next [ set prev temp ] ] set next temp fd 0.55 ] end to snake-shrink ask get-head [ if (not is-tail?) [ let temp self face next move-to next rt 180 ask next [ if (next != nobody) [ ask next [ set prev temp set temp self ] ] die ] set next temp ] ] end to snake-die ask snakesegments with [ snake-id = [snake-id] of myself ] [ die ] end to-report looped? report [ prev != nobody ] of get-head end to snake-loop ask get-head [ let mytail get-tail set prev mytail ask mytail [ set next myself ] face mytail update-appearance ] end to snake-unloop ask get-head [ let mytail get-tail set prev nobody ask mytail [ set next nobody ] face next rt 180 update-appearance ] end to snake-reverse ask get-head [ snake-reverse-helper update-appearance ] end to snake-reverse-helper let temp next set next prev set prev temp ifelse (prev = nobody or ([is-head?] of prev)) [ set headlist replace-item snake-id headlist self update-appearance if (not is-tail?) [ face next ] right 180 ] [ ask prev [ snake-reverse-helper] ] end ; neat little utility function, to get every snakesegment ; in the snake to run some code. to snake-map [ str ] run str if (not is-tail?) [ ask next [ snake-map str ] ] end to snake-move [ dist ] let distprev world-width ; big number let mystep dist ifelse (self = first-mover) [ fd dist ] [ face prev set distprev (distance prev) ; we allow them to step up to 25% farther than the ; head moved, to allow them to "catch up" if necessary ; we don't allow them to move *too* close to ; the snakesegment ahead of them. set mystep min list (dist * 1.25) (distprev - 0.55) if (mystep != 0 ) [ fd mystep ] ] if (next != nobody and next != first-mover) [ ask next [ snake-move dist ] ] end to snake-move-bk [ dist ] let distnext world-width ; big number let mystep dist ifelse (self = first-mover) [ fd dist ] [ face next set distnext (distance next) ; we allow them to step up to 25% farther than the ; head moved, to allow them to "catch up" if necessary ; we don't allow them to move *too* close to ; the snakesegment ahead of them. set mystep min list (dist * 1.25) (distnext - 0.55) if (mystep != 0 ) [ fd mystep ] ] if (prev != nobody and prev != first-mover) [ ask prev [ snake-move-bk dist ] ] end to snake-forward [ dist ] if ([move-snake?] of one-of students with [ my-snake-id = [snake-id] of myself ]) [ repeat round (dist / 0.1) [ ; even if you ask a snakesegment in the middle ; of the snake to move, we move the head anyway ask get-head [ update-appearance set first-mover self ifelse (looped?) [ face prev snake-move 0.1 ] [ snake-move 0.1 ] ] collision-detection display ] ] end to snake-step snake-forward 1 end to forward-all [ dist ] repeat round (dist / 0.1) [ ask snakes [ if ([move-snake?] of one-of students with [ my-snake-id = [snake-id] of myself ]) [ set first-mover self ifelse (looped?) [ face prev snake-move 0.1 ] [ snake-move 0.1 ] ] ] collision-detection display ] end to collision-detection let clist [] ask snakesegments [ set tempdx 0 set tempdy 0 set tempdz 0 let pushx 0 let pushy 0 let pushz 0 let myx xcor let myy ycor let myz zcor let nearbys snakesegments in-radius 1.0 set nearbys nearbys with [prev != myself and next != myself and self != myself] ; print count nearbys if (any? nearbys) [ ask nearbys [ let dist distance myself if (dist = 0) [ fd 0.001 set dist 0.001 ] let push (1.0 - dist) / 2 + 0.02 let ddx myx - xcor if (ddx < 0 - world-width / 2) [ set ddx ddx + world-width ] if (ddx > world-width / 2) [ set ddx ddx - world-width ] let ddy myy - ycor if (ddy < 0 - world-height / 2) [ set ddy ddy + world-height ] if (ddy > world-height / 2) [ set ddy ddy - world-height ] let ddz myz - zcor if (ddz < 0 - world-depth / 2) [ set ddz ddz + world-depth ] if (ddz > world-depth / 2) [ set ddz ddz - world-depth ] set pushx pushx + ddx / dist * push set pushy pushy + ddy / dist * push set pushz pushz + ddz / dist * push ] set tempdx pushx / count nearbys + random-float 0.01 set tempdy pushy / count nearbys + random-float 0.01 set tempdz pushz / count nearbys + random-float 0.01 set clist fput self clist ;show (list tempdx tempdy tempdz) ; show (list tempdx tempdy tempdz) ; if (tempdx != 0) ; [ print word "moo: " (list tempdx tempdy tempdz) ] ] ] foreach clist [ ask ? [ set xcor xcor + tempdx set ycor ycor + tempdy set zcor zcor + tempdz ] ] end to tighten-all ask snakes [ snake-reverse ] forward-all 0.5 ask snakes [ snake-reverse ] forward-all 0.5 end to snake-tighten snake-reverse snake-forward 0.5 snake-reverse snake-forward 0.5 end to jiggle-snakes if (not is-list? jigglers or member? nobody jigglers or random 100 < 1) [ set jigglers [self] of (n-of 2 snakesegments) set jiggler-patches [self] of (n-of 2 patches ) ] (foreach jigglers jiggler-patches [ let j ?1 let jp ?2 ask j [ ;let nearbys (snakesegments in-radius 2.0) with [prev != myself and next != myself and self != myself] ;ifelse any? nearbys ;[ face one-of nearbys ] ;[ face one-of patches ] face jp set first-mover self forward 0.05 if (next != nobody) [ ask next [ snake-move 0.1 ] ] if (prev != nobody) [ ask prev [ snake-move-bk 0.1 ] ] ] ]) collision-detection display end to save-to-vrml let filename user-new-file if (filename != false) [ vrml:clear-scene ask snakesegments [ let mycolor extract-rgb color ; make the head the same color as the body ; in the vrml export if (is-head?) [ set mycolor extract-rgb (color - 2) ] vrml:set-color (item 0 mycolor) (item 1 mycolor) (item 2 mycolor) vrml:add-sphere xcor ycor zcor 0.5 ] vrml:save-scene filename ] end ; returns the head of the most recently created snake to-report newest-snake report snake ((length headlist) - 1) end ;;; HUBNET procedures ;; determines which client sent a command, and what the command was to listen-clients while [ hubnet-message-waiting? ] [ hubnet-fetch-message ifelse hubnet-enter-message? [ create-new-student ] [ ifelse hubnet-exit-message? [ remove-student ] [ ask students with [ my-hubnet-id = hubnet-message-source ] [ execute-command hubnet-message-tag ] ] ] ] end to execute-command [command] if command = "move-snake?" [ set move-snake? hubnet-message stop ] if command = "north" [ ask snake my-snake-id [ rt 90 fd 0.03 set pitch 0 set heading 0 ] stop ] if command = "south" [ ask snake my-snake-id [ rt 90 fd 0.03 set pitch 0 set heading 180 ] stop ] if command = "east" [ ask snake my-snake-id [ rt 90 fd 0.03 set pitch 0 set heading 90 ] stop ] if command = "west" [ ask snake my-snake-id [ rt 90 fd 0.03 set pitch 0 set heading 270 ] stop ] if command = "up" [ ask snake my-snake-id [ rt 90 fd 0.03 set pitch 90 ] stop ] if command = "down" [ ask snake my-snake-id [ rt 90 fd 0.03 set pitch -90 ] stop ] ask snake my-snake-id [ run command stop ] end to create-new-student let newsnake (make-snake random-pxcor random-pycor random-pzcor) create-students 1 [ ht set my-hubnet-id hubnet-message-source set my-snake-id [snake-id] of newsnake set move-snake? false hubnet-send my-hubnet-id "my-snake-color" get-color-name my-snake-id ] end to remove-student ask students with [my-hubnet-id = hubnet-message-source] [ ask snake my-snake-id [ snake-die ] die ] end
There is only one version of this model, created over 14 years ago by Uri Wilensky.
Attached files
No files
This model does not have any ancestors.
This model does not have any descendants.