#side Active 2 #color f08 12/31/02: Improved eat-and-move copied from haystack. A predator with active dodging. ToDo: -identify source of shots and target (cross-product trickery, similar to dodging) -missile defense -add a rat type that runs away (experimental) #type Dodger #hardware energy 400 100 armor 120 processor 35 ;to dodge in 2 frames radio send receive eater 1.2 engine 0.15 robot-sensor 11 shot-sensor 9 3 food-sensor 8 5 constructor 0.9 repair-rate 0.1 grenades 35 11 25 ;blaster 0.1 5 3 #code #const TARGET_CHANNEL 1 ;communication with Dodge-and-move: #vector desired-velocity 0 0 #var speed-slop 0.01 ;communication with Eat-and-move: #var position-slop 3 #vector desired-position random-position: 0 world-width random 0 world-height random return ;returns distance to nearest wall wall-distance: ; -> dist position min world-size position v- min min return food-sense: ;t -> food-sensor-time food-sensor-time -1000 ifev + time < if ;too old fire-food-sensor sync return else return ;previous sensing is new enough then restrict-location: ;x y -> x y world-height min 0 max swap world-width min 0 max swap return ;in: desired-position, position-slop ;out: desired-velocity, speed-slop #vector current-food #var have-current-food 0 #const MAX_SPEED 0.15 #vector wander-loc #var wander-time eat-and-move: food-sensor-time 30 + time < if position-slop 0.1 > and-if ;don't waste sensor firing if pos-slop tiny have-current-food if current-food desired-position dist position-slop < and-if current-food else desired-position position-slop food-sensor-range min 0.5 * random-angle polar-to-rect v+ ;add a little randomness then position v- rect-to-polar food-sensor-focus-direction! food-sensor-focus-distance! fire-food-sensor sync 0 have-current-food! food-found if Food-check-loop: food-position desired-position dist position-slop < if food-position current-food! 1 have-current-food! else next-food Food-check-loop& ifg then then ;food-found then ;time to fire have-current-food if current-food else position-slop food-sensor-range > if ;no point wandering if we can see it already desired-position wander-loc dist position-slop > wander-loc position 2 in-range or if position-slop random-angle polar-to-rect desired-position v+ restrict-location^ wander-loc! then wander-loc else desired-position then then position v- rect-to-polar swap 0.05 * MAX_SPEED min swap polar-to-rect desired-velocity! radius 0.05 * speed-slop! return ;end of eat-and-move #start random-position wander-loc! #const MAX_FIGHT_POSITION_SLOP 6 #const MIN_FIGHT_POSITION_SLOP 1 #const FIGHT_DISTANCE 9 #const CRUSADE_DIST 25 #const MIN_CRUSADE_DIST 12 #var have-crusade 0 #var crusade-time #vector crusade-position Begin-normaling: do energy 50 > No-target& nifg robot-sensor-time grenades-reload-time + time < if fire-robot-sensor sync robot-found if armor max-armor < if robot-position robot-sensor-time 3 TARGET_CHANNEL send then grenades-cooldown nif robot-position position v- robot-velocity time robot-sensor-time - vs* v+ ;stack: current relative position of enemy robot-velocity velocity v- robot-distance grenades-speed / vs* v+ rect-to-polar fire-grenade then position robot-position v- unitize FIGHT_DISTANCE vs* robot-position v+ desired-position! MAX_FIGHT_POSITION_SLOP energy max-energy / MAX_FIGHT_POSITION_SLOP MIN_FIGHT_POSITION_SLOP - * - position-slop! Done-targeting& jump else ;no robot found No-target& jump then ;found else Done-targeting& jump then ;time to fire No-target: have-crusade if crusade-position position robot-sensor-range 0.8 * in-range time crusade-time - 200 > or and-if 0 have-crusade! then have-crusade nif shot-found and-if shot-velocity norm and-if shot-position shot-velocity -100 vs* v+ crusade-position! shot-sensor-time crusade-time! 1 have-crusade! then have-crusade nif TARGET_CHANNEL messages 2 - 0 max 0 random-int TARGET_CHANNEL skip-messages do TARGET_CHANNEL receive while ;stack: x y t crusade-time! crusade-position! time crusade-time - 100 < if ;newish crusade-position position dist CRUSADE_DIST < and-if crusade-position position dist MIN_CRUSADE_DIST > and-if 1 have-crusade! done-chatting& jump then ;acceptable crusade loop Done-chatting: then ;have-crusade not have-crusade if energy max-energy / 0.3 > and-if armor max-armor / 0.5 > and-if crusade-position desired-position! 5 position-slop! else infinity position-slop! position desired-position! then ;have crusade Done-targeting: Dodge-and-move^ constructor-type nif 1 2 random-int constructor-type! then energy 100 > max-repair-rate 0 ifev repair-rate! max-energy 0.7 * constructor-remaining min energy < constructor-max-rate 0 ifev constructor-rate! eat-and-move^ Dodge-and-move^ shot-found if ;run away shot-velocity norm and-if energy max-energy / 0.05 > and-if energy max-energy / 0.2 < armor max-armor / 0.3 < or and-if shot-velocity 60 vs* position v+ restrict-location^ desired-position! Begin-running& jump then forever ;desired-position is set before entering running Begin-running: do energy 100 > max-repair-rate 0 ifev repair-rate! energy max-energy / 0.1 < nif robot-sensor-time grenades-reload-time + time < and-if grenades-cooldown not and-if fire-robot-sensor sync robot-found and-if robot-position position v- robot-velocity time robot-sensor-time - vs* v+ ;stack: current relative position of enemy robot-velocity velocity v- robot-distance grenades-speed / vs* v+ rect-to-polar fire-grenade then ;shooting 5 position-slop! eat-and-move^ Dodge-and-move^ desired-position position dist position-slop < if Begin-normaling& jump then forever #const Flee-angle 1.5 ;angle between shot velocity and fleeing. #const MIN_MISS_DIST 2.5 #const flee-speed 0.1 #const ASSUMED_ROBOT_SLOWDOWN_FACTOR 0.4 #const DODGE_OVERKILL_FACTOR 1.2 #var miss #vector dv #vector assumed-robot-velocity #vector go-dir ;Dodge has inputs: ;-desired-velocity, the desired medium-term engine velocity ;-speed-slop, the amount the velocity can differ before engine is used ;Dodge then sets engine-velocity and power to avoid shots. Dodge-and-move: do shot-sensor-time time 4 - < until sync loop ;do as much computation as possible before firing shot sensor to get up-to-date info energy max-energy / 2 * ; armor max-armor = 1 2 ifev * time shot-sensor-time - 20 / + energy max-energy / 6 * min armor max-armor / < Obey-user& ifg velocity ASSUMED_ROBOT_SLOWDOWN_FACTOR vs* 2dup desired-velocity dist 0.05 <= if 2drop desired-velocity else 2dup desired-velocity v- unitize -0.05 vs* v+ ;expected velocity then assumed-robot-velocity! assumed-robot-velocity rect-to-polar shot-sensor-focus-direction! 3 * shot-sensor-focus-distance! fire-shot-sensor sync shot-found Obey-User& nifg shot-process-loop: shot-velocity norm if shot-velocity assumed-robot-velocity v- dv! dv shot-position position v- dot 0 < and-if else next-shot shot-process-loop& obey-user& ifeg then dv unitize shot-position position v- cross miss! ;positive means the shot will miss to our right (when facing the incoming shot) dv angle miss 0 > Flee-angle Flee-angle negate ifev - dup 1 swap polar-to-rect go-dir! MIN_MISS_DIST miss abs - 0 max ;dist to move shot-distance 3 max / shot-velocity norm * DODGE_OVERKILL_FACTOR * ;this line: flee speed swap polar-to-rect assumed-robot-velocity v+ 2dup ;2 copies of engine-vel on stack desired-velocity v- go-dir dot ;negative if desired deviation from calculated is ok 0 < if 2drop Obey-User& jump then ;2dup angle fire-blaster engine-velocity! engine-max-power engine-power! return Obey-User: desired-velocity engine-velocity! velocity desired-velocity v- norm speed-slop < 0 engine-max-power ifev engine-power! return ;end of Dodge subroutine ;a second version of above, different strategy Dodge-and-move2: #comment #type Missile #color f00 #hardware processor 15 energy 300 300 armor 150 engine 0.15 shield 0.4 bomb 1300 robot-sensor 10 shot-sensor 8 solar-cells 0.05 #code #vector target #vector target-v #vector wander-loc #const shot-chase-distance 10 new-wander-loc: -20 world-width 20 + random -20 world-height 20 + random restrict-position^ wander-loc! return restrict-position: ; vector -> vector world-height min 0 max swap world-width min 0 max swap return set-shot-chase: ;stack: empty -> empty shot-chase-distance shot-velocity -100 vs* shot-position position v- v+ angle polar-to-rect position v+ restrict-position^ target! 0 0 target-v! return choose-next-state: ; -> robot-sensor-time 20 + time < if fire-robot-sensor fire-shot-sensor sync armor max-armor / 0.5 > if shot-found and-if shot-velocity norm and-if set-shot-chase^ drop charge& jump then robot-found 1 > robot-mass 30 > or if robot-distance 2 < if die sync then robot-position target! robot-velocity target-v! drop charge& jump then drop wander& jump then ;time to scan jump #start new-wander-loc^ begin-wandering: wander: 0 shield! wander-loc position v- rect-to-polar swap 0.05 * 0.1 min swap polar-to-rect target-v v+ engine-velocity! engine-max-power engine-power! wander-loc position dist 5 < new-wander-loc& ifc energy max-energy / 0.1 < begin-nursing& ifg wander& choose-next-state& jump begin-charging: charge: target seek-location energy 30 > max-shield 0 ifev shield! charge& choose-next-state& jump begin-nursing: 0 engine-power! 0 shield! do sync sync sync sync sync sync sync sync sync sync energy max-energy / 0.4 > begin-wandering& ifg forever #end