#side Frog Celestial 2 #author Devon Started 27 December 2003 #color 690 A sequel to World Toad, of normal size and without solar cells. Frogs are gatherer/fighters which retreat into a group when threatened. Thus they get the grouping advantages of a colony without giving up freedom of motion. (20040110) Added food hashing and replaced wandering/gathering code. Fixed a bug that made it keep seeking the last extra-food. #type ...goes Ribbit in the night #color c60 #hardware processor 13 radio send receive read write engine .05 shot-sensor 5 energy 400 25 food-sensor 7 4 eater 1.5 constructor 1 robot-sensor 8 4 grenades 25 8 20 armor 200 repair-rate .08 #comment Communications Frogs periodically announce their existence. Each frog listens to keep track of their collective center, and of how many combat-ready cells are in their vicinity. This tells them whether and whither to run. Frogs also call for help, and announce extra food. #code #const ribbit-ch 5 ;channel to call on (strength x y) #var next-ribbit 0 #const ribbit-period 153 ribbit: ;announce presence time next-ribbit < ifr energy armor min position 3 ribbit-ch send time ribbit-period + next-ribbit! return #vector center ;average position of all cells #var local-force-acc 0 #var total-force-acc 0 #var force-acc-time #const force-halflife 400 total-force: total-force-acc 0.5 time force-acc-time - force-halflife / exponent * return local-force: local-force-acc 0.5 time force-acc-time - force-halflife / exponent * return listen: ;listen for ribbits ribbit-ch receive nifr 2dup center population 1 - vs* v+ population vs/ center! position dist square 1 + over total-force + total-force-acc! / local-force + local-force-acc! time force-acc-time! return #const food-ch 2 ;extra food (x y time) #const target-ch 1 ;help needed (x y) announce-food: food-position-overall time 3 food-ch send return #vector best extra-food: ; (-- 0) or (-- x y 1) food-ch messages 5 - food-ch skip-messages 0 0 best! do food-ch receive while 300 + time > if 2dup position dist position best dist < best nor or and-if best! else 2drop then loop best or if best 1 else 0 then return call-for-help: ; (x y --) 2 target-ch send target-ch clear-messages return #const help-range 25 help-needed: ; (-- 0) or (x y 1) target-ch receive if 2dup position help-range in-range if 1 else 2drop 0 then else 0 then return #comment Food hashing Keep a hashtable of position -> (time, x-position) showing who claims this food. Ignore foods other people have claimed recently. (x-position is used to confirm this is the right food.) Collisions are ignored; at worst they lead to pushing matches. Food hashing was first used in YAR, a not-yet-released side by Warren. #code #const hashtable-size 100 #const hashtable-base 1 #const claim-time 240 food-hash: ;(-- hash-index) food-position + dup floor - epsilon / floor hashtable-size mod hashtable-base + return claim-food: ;(-- claimed?) food-energy 750 > if 1 return then do food-velocity or nif ;preload with (time t-addr x-pos x-addr time-threshold t-addr x-pos x-addr) time food-hash dup hashtable-size + food-position drop swap time claim-time - 2over over hashtable-size + sync read = if read > if write write 1 return else 2drop 2drop then else 2drop write write 1 return then then next-food while-loop 0 return #comment Utilities #code #vector dest ;movement destination for wandering, shot-chasing, etc. construct/repair: constructor-type if energy constructor-remaining 20 + max-energy 50 - min < 0 constructor-max-rate ifev constructor-rate! else energy max-energy 50 - > if 1 constructor-type! constructor-max-rate constructor-rate! else 0 constructor-rate! then then repair: energy 50 < 0 max-repair-rate ifev repair-rate! return help: help-needed nifr energy armor min 150 > if dest! chase& jump else 2drop then return wander: extra-food if dest! else do position swap .5 random-bool -35 35 ifev + 0 max world-width min swap .5 random-bool -35 35 ifev + 0 max world-height min dest! dest position 20 in-range while-loop then return find-robot: fire-robot-sensor sync robot-found nif 0 return then do robot-shield-fraction .3 > if 1 return then next-robot while-loop 0 return watch-for-robots: energy 20 > nifr time robot-sensor-time 43 + < ifr find-robot nifr ;If the robot is getting too close, fight or flee: robot-velocity position robot-position v- unitize dot ;closing speed robot-distance 5 < .02 .1 ifev > if rdrop enemy-seen& jump then ;Otherwise, take potshots if we're not too badly off: energy armor min 40 > shoot& ifg ;...or ignore them. return watch-for-shots: time shot-sensor-time 11 + < ifr fire-shot-sensor sync shot-found if rdrop shot-seen& jump then return shoot: robot-velocity velocity v- robot-distance grenades-speed / vs* robot-position v+ position v- rect-to-polar swap 2 max swap fire-grenade return #comment States forage eat potshot -> robot-seen shot-seen fight -> nothing-here run run-home run-away -> arrived chase-shot chase-rumor -> fight nothing-here #code #start forage: target-ch clear-messages wander do time food-sensor-time 53 + >= if fire-food-sensor sync food-found if claim-food energy 20 < or eat& ifg then then dest seek-location watch-for-robots watch-for-shots ribbit listen construct/repair help dest position 2 in-range wander& ifc forever #var last-eaten eat: food-energy 150 - food-found * 2000 > announce-food& ifc do food-position seek-location watch-for-robots watch-for-shots ribbit listen construct/repair eaten if time last-eaten! then time food-sensor-time 150 + last-eaten 30 + max < while-loop forage& jump #comment Response to enemies #code enemy-seen: robot-position call-for-help energy armor min 70 < flee-robot& fight& ifeg shot-seen: local-force 500 < flee-shot& ifg position call-for-help energy armor min 100 < flee-shot& chase-shot& ifeg #const flee-distance 12 flee-robot: total-force 3000 > if position center 10 in-range not and-if center else position robot-position v- unitize flee-distance vs* position v+ then dest! run& jump flee-shot: total-force 3000 > if position center 10 in-range not and-if center else shot-velocity unitize flee-distance vs* position v+ then dest! run& jump #const fight-distance 7 fight: shoot^ do position robot-position v- unitize fight-distance vs* robot-position v+ 1 random-angle polar-to-rect v+ ;dodge (badly) robot-velocity seek-moving-location construct/repair time robot-sensor-time grenades-reload-time + >= if find-robot forage& nifg shoot^ then energy armor min 50 > while-loop flee-robot& jump run: 0 local-force-acc! ;we're leaving dest swap 0 max world-width min swap 0 max world-height min dest! do dest seek-location construct/repair listen energy 20 > if robot-found and-if time robot-sensor-time grenades-reload-time + >= and-if find-robot shoot& ifc then position dest 2 in-range until-loop forage& jump chase-shot: shot-velocity unitize -10 vs* shot-position v+ dest! chase: do dest seek-location construct/repair time robot-sensor-time 31 + >= if find-robot enemy-seen& ifg then time shot-sensor-time 11 + >= if fire-shot-sensor sync shot-found shot-seen& ifg then dest position 3 in-range until-loop forage& jump #end