to snake setvars clearscreen setscreencolor :bgcolour run pick [ [maze_1] ; [maze_2] ] repeat :foodcount [makefood] setturtle 2 penup hideturtle setturtle 1 hideturtle settimer 1 1 [losetail ai turn move pixelcheck] mouseon [startdrive] [] [stopdrive] [] [] end to revive ; revives a snake which has hit a wall or tail settimer 1 1 [losetail ai turn move pixelcheck] end to pausesnake cleartimer 1 print [To resume, use revive.] end to ksnake ; EXPERIMENTAL! setvars clearscreen run pick [ [maze_1] ; [maze_2] ] repeat :foodcount [makefood] setturtle 2 penup hideturtle setturtle 1 hideturtle settimer 1 1 [losetail move pixelcheck] mouseon [startdrive] [] [stopdrive] [] [] keyboardon [kturn] setfocus [MSWLogo SCREEN] end to ai ; Simple AI to follow food if :ai_mode [ ai_main :food_points ] end to ai_main :foodpoints make "lastpos last :foodpoints make "cx first :lastpos make "cy last :lastpos make "tx xcor make "ty ycor make "x :cx - :tx make "y :cy - :ty if :y > 0 [ make "newangle arctan (:x / :y) ] if (AND (:y < 0) (:x > 0)) [ localmake "temp 0-:y make "newangle 90+arctan (:temp / :x) ] if (AND (:y < 0) (:x < 0)) [ localmake "temp 0-:y make "newangle 270+arctan (:temp / :x) ] if :newangle < 0 [ make "newangle :newangle + 360 ] if (OR (:newangle > 360) (:newangle = 360)) [ make "newangle :newangle - 360 ] ifelse (ABS (:newangle - heading)) < 160 [ setheading :newangle ][ ;ifelse (COUNT butlast :food_points) > 0 [ ; ai_main butlast :food_points ;][ setheading :newangle ;] ] end to maze_1 ; Draw a simple box around the field penup setpensize [5 5] setpencolor :wallcolour setpos [-300 -300] pendown repeat 4 [fd 600 rt 90] penup setpencolor :snakecolour setpensize [1 1] home pendown end to maze_2 local "maze_2 make "maze_2 "maze_2.bmp ; CHANGE THIS! ifelse (AND ((first (bitloadsize :maze_2)) = 600) ((last (bitloadsize :maze_2)) = 600)) [ penup setpos [-300 -300] bitload :maze_2 setpos [0 0] pendown print [Maze II loaded.] ][ print [The map needs to be 600 by 600.] ] end to pixelcheck ; Check whether we have hit our tail if (pixel = :snakecolour) [ print [You hit your own tail!] if NOT :god_mode [cleartimer 1] halt ] ; If not yet dead, check whether we have hit a wall if (pixel = :wallcolour) [ print [You have hit a wall!] if NOT :god_mode [cleartimer 1] ] ; If not yet dead, check whether we are on poison if (pixel = :poisoncolour) [ make "score :score - :poisonpenalty print (sentence [You got poisoned! Your score:] :score) make "size :size - :poisonpenalty setpensize (list :explodesize :explodesize) setpencolor :bgcolour fd 0 setpencolor :snakecolour setpensize [1 1] makepoison ] ; Check whether we're standing on food if (pixel = :foodcolour) [ make "score :score + :curspd print (sentence [You ate the food! Your score:] :score) make "size :size + (:tailgrowth*:curspd) setpensize (list :explodesize :explodesize) penerase fd 0 penpaint setpensize [1 1] makefood makepoison ] end to makefood ; Puts food onto the field setturtle 3 penup make "lastpos (list ((random :worldsize)-(:worldsize/2)) ((random :worldsize)-(:worldsize/2))) setpos :lastpos make "food_points lput :lastpos :food_points setpensize (list :foodsize :foodsize) setpencolor :foodcolour pendown fd 0 setpencolor :snakecolour setpensize [1 1] penup home pendown setturtle 1 end to makepoison ; Puts poison onto the field if (RANDOM 100) < :poisonchance [ setturtle 3 penup make "lastpos (list ((random :worldsize)-(:worldsize/2)) ((random :worldsize)-(:worldsize/2))) setpos :lastpos setpensize (list :foodsize :foodsize) setpencolor :poisoncolour pendown fd 0 setpencolor :snakecolour setpensize [1 1] penup home pendown setturtle 1 ] end to losetail if ((count :points) < :size) [ stop ] if (AND ((count :points) > :size) ((count :points) > 1)) [ while [(AND ((count :points) > :size) ((count :points) > 1))] [ make "diepoint first :points setturtle 2 setpos :diepoint setpixel :bgcolour setturtle 1 make "points butfirst :points ] ] end to move make "tx xcor make "ty ycor make "mx first mousepos make "my last mousepos make "xdist abs (:mx - :tx) make "ydist abs (:my - :ty) make "dist sqrt (:xdist*:xdist + :ydist*:ydist) if :dist < :curspd [stop] repeat :curspd [ fd 1 make "tx xcor make "ty ycor make "ax (round (:tx / 1))*1 make "ay (round (:ty / 1))*1 make "ax :tx make "ay :ty setxy :ax :ay make "points lput (list :ax :ay) :points ] end to startdrive make "curspd :curspd + :incspd end to startrev make "curspd -:incspd end to stopdrive if (OR (:curspd > :incspd) (:curspd = :incspd)) [make "curspd :curspd - :incspd] end to turn ; Normal turning procedure, guided by mouse, not by AI if :ai_mode [stop] make "cx first mousepos make "cy last mousepos make "tx xcor make "ty ycor make "x :cx - :tx make "y :cy - :ty if :y > 0 [ make "newangle arctan (:x / :y) ] if (AND (:y < 0) (:x > 0)) [ localmake "temp 0-:y make "newangle 90+arctan (:temp / :x) ] if (AND (:y < 0) (:x < 0)) [ localmake "temp 0-:y make "newangle 270+arctan (:temp / :x) ] if :newangle < 0 [ make "newangle :newangle + 360 ] if (OR (:newangle > 360) (:newangle = 360)) [ make "newangle :newangle - 360 ] setheading :newangle end to kturn make "oldheading heading if (char keyboardvalue) = "8 [make "newangle 000] if (char keyboardvalue) = "6 [make "newangle 090] if (char keyboardvalue) = "2 [make "newangle 180] if (char keyboardvalue) = "4 [make "newangle 270] if (abs (:newangle - :oldheading)) = 180 [ make "newangle :oldheading ] if namep "newangle [setheading :newangle] end to between :number :bound1 :bound2 ifelse (AND (:number > :bound1) (:number < :bound2)) [ output "true ][ output "false ] end to setvars Make "curspd 0 ; Current speed (begins at 0) Make "incspd 1 ; Speed increment when mouse is clicked Make "points [] ; List of points of the snake, DON'T CHANGE THIS! Make "food_points [] ; List of points of food (used by AI to track food), DON'T CHANGE THIS! Make "size 10 ; (starting) Size of the snake Make "tailgrowth 10 ; Growth of the tail per food bit Make "fadecount 1 ; Speed at which snake tail dies (experimental) Make "score 0 ; Current score (begins at 0) Make "worldsize 550 ; Size of the world (i.e. the boundary for food to disperse) Make "foodcount 4 ; Number of food bits on the field at any one time (not changeable during game) Make "god_mode "false ; God mode (cannot die whilst in God mode) Make "foodsize 10 ; Size of food bits Make "poisonchance 99 ; Chance of poison being created (out of 100) Make "poisonpenalty 1 ; Penalty when eating poison Make "explodesize 20 ; DIAMETER of "explosion" around food that is eaten (don't make this too big or too small) Make "snakecolour [255 255 255] ; Snake colour Make "foodcolour [253 253 253] ; Food colour Make "poisoncolour [001 001 001] ; Poison colour Make "wallcolour [128 128 128] ; Death colour Make "bgcolour [000 000 000] ; Background colour ; NB: None of these colours should be the same! ; If you want, say, all black, try 000, 001, 002, 003 Make "ai_mode "false ; If TRUE, then autopiloting (works best with a lot of food and high explosions) end