# Generic Agent class for Simulation # Agent.tz (c) 2010 Jacob Schrum. # See Simulation.tz for more copyright information @use Mobile. Mobile : Agent { + variables: facing (vector). forward-coeff (double). turn-angle (double). energy (double). locked (int). speed-boost (double). armed (int). firing (int). bullet (object). just-hit-wall (int). walls-exist (int). wrap (int). math (object). + to init: wrap = ((controller get-commandline) bit-param named "wrap"). walls-exist = ((controller get-commandline) bit-param named "use-walls"). if walls-exist : { self handle-collisions with-type "Wall" with-method "bounce". } forward-coeff = 0. turn-angle = 0. just-hit-wall = 0. speed-boost = 1.0. if !facing : facing = (1,0,0). #Overrides + to point vertex theVertex (vector) at theLocation (vector): facing = theLocation. super point vertex theVertex at theLocation. + to get-math: if !math : math = (controller get-math). return math. + to iterate: loc (vector). # Adjust movement direction self set-velocity to (facing * forward-coeff * speed-boost). self turn. self point vertex (0, 1, 0) at facing. if wrap : { loc = self get-location. if (|loc::x| > (HALF_WALL_LENGTH + WRAP_BUFFER)) : self move to (-loc::x, loc::y, loc::z). else if (|loc::z| > (HALF_WALL_LENGTH + WRAP_BUFFER)) : self move to (-loc::x, loc::y, -loc::z). } if energy <= 0: self death. # Shoot + to fire: if ( !firing ) : { firing = 1. bullet = (new Bullet). bullet create at ((self get-location) + facing) direction facing from self. self schedule method-call "clear-bullet" at-time ((controller get-time) + BULLET_TIME). } + to clear-bullet: firing = 0. + to is-armed: return armed. + to arm: armed = 1. self schedule method-call "disarm" at-time ((controller get-time) + GUN_TIME). + to disarm: armed = 0. # Speed Boost + to get-speed-boost-value: return speed-boost. + to boost-speed: speed-boost = 2.0. self schedule method-call "lose-speed-boost" at-time ((controller get-time) + SPEED_BOOST_DURATION). + to lose-speed-boost: speed-boost = 1.0. # Locking + to lock: locked = 1. turn-angle = 0. self schedule method-call "unlock" at-time ((controller get-time) + RECOVERY_TIME). + to unlock: forward-coeff = 0. turn-angle = 0. locked = 0. + to is-locked: return locked. # Wall # wall : a Wall object that the Agent has collided with + to bounce off wall (object): pos (vector). angle-diff (double). just-hit-wall = 1. pos = self get-location. if(|pos::x| >= |pos::z|) : { if pos::x < 0 : { angle-diff = ((self get-math) signed-angle-difference between facing and (-1, facing::y, 0)). self move to (pos::x + RICOCHET_SPACING, pos::y, pos::z). } else { angle-diff = ((self get-math) signed-angle-difference between facing and (1, facing::y, 0)). self move to (pos::x - RICOCHET_SPACING, pos::y, pos::z). } self ricochet by-angle (PI - (2 * angle-diff)). } if |pos::z| > |pos::x| : { if pos::z < 0 : { angle-diff = ((self get-math) signed-angle-difference between facing and (0, facing::y, -1)). self move to (pos::x, pos::y, pos::z + RICOCHET_SPACING). } else { angle-diff = ((self get-math) signed-angle-difference between facing and (0, facing::y, 1)). self move to (pos::x, pos::y, pos::z - RICOCHET_SPACING). } self ricochet by-angle (PI - (2 * angle-diff)). } # radians: -2*PI <= radians <= 2*PI + to ricochet by-angle radians (double): facing = ((self get-math) get-turn-matrix with-angle radians) * facing. # Turn + to turn: facing = ((self get-math) get-turn-matrix with-angle turn-angle) * facing. # Assignment # value: new vector direction in which to face + to set-facing to value (vector): facing = value. # value: new forward coefficient + to set-forward-coeff to value (double): forward-coeff = value. # value: new turn angle + to set-turn-angle to value (double): turn-angle = value. # value: new energy value + to set-energy to value (double): energy = value. # Accessor + to get-facing: return facing. + to get-facing-x: return (facing::x). + to get-facing-z: return (facing::z). + to get-forward-coeff: return forward-coeff. + to get-turn-angle: return turn-angle. + to get-energy: return energy. # Walls # Facing + to facing-wall: if walls-exist : return ((self facing-upper-wall) + (self facing-lower-wall) + (self facing-left-wall) + (self facing-right-wall)). else return 0. + to facing-upper-wall: if (((self upper-wall-close) > 0) && (facing::z > 0.0)): return 1.0. else return 0.0. + to facing-lower-wall: if (((self lower-wall-close) > 0) && (facing::z < 0.0)) : return 1.0. else return 0.0. + to facing-left-wall: if (((self left-wall-close) > 0) && (facing::x < 0.0)) : return 1.0. else return 0.0. + to facing-right-wall: if (((self right-wall-close) > 0) && (facing::x > 0.0)) : return 1.0. else return 0.0. # Back + to back-to-wall: if walls-exist : return ((self back-to-upper-wall) + (self back-to-lower-wall) + (self back-to-left-wall) + (self back-to-right-wall)). else return 0. + to back-to-upper-wall: if (((self upper-wall-close) > 0) && (facing::z < 0.0)) : return 1.0. else return 0.0. + to back-to-lower-wall: if (((self lower-wall-close) > 0) && (facing::z > 0.0)) : return 1.0. else return 0.0. + to back-to-left-wall: if (((self left-wall-close) > 0) && (facing::x > 0.0)) : return 1.0. else return 0.0. + to back-to-right-wall: if (((self right-wall-close) > 0) && (facing::x < 0.0)) : return 1.0. else return 0.0. # Close + to left-wall-close: if (self get-left-wall-distance) < ((controller get-commandline) num-param named "very-close-wall") : return 1.0. else return 0.0. + to right-wall-close: if (self get-right-wall-distance) < ((controller get-commandline) num-param named "very-close-wall") : return 1.0. else return 0.0. + to lower-wall-close: if (self get-lower-wall-distance) < ((controller get-commandline) num-param named "very-close-wall") : return 1.0. else return 0.0. + to upper-wall-close: if (self get-upper-wall-distance) < ((controller get-commandline) num-param named "very-close-wall") : return 1.0. else return 0.0. + to wall-close: if walls-exist : return ((self left-wall-close) + (self right-wall-close) + (self lower-wall-close) + (self upper-wall-close)). else return 0. + to get-left-wall-distance: return (HALF_WALL_LENGTH + ((self get-location)::x)). + to get-right-wall-distance: return (HALF_WALL_LENGTH - ((self get-location)::x)). + to get-upper-wall-distance: return (HALF_WALL_LENGTH - ((self get-location)::z)). + to get-lower-wall-distance: return (HALF_WALL_LENGTH + ((self get-location)::z)). # Death + to death: self unlock. + to in-front-of-me location loc (vector): return (self in-cone-in-front-of-me location loc angle (PI/2)). + to in-cone-in-front-of-me location loc (vector) angle a (double): angle-between (double). angle-between = | (angle((loc - (self get-location)), facing)) |. if angle-between < a : { return 1. } else return 0. + to on-my-side location loc (vector) right bit (int): angle-between (double). angle-between = ((self get-math) signed-angle-difference between facing and (loc - (self get-location))). return (bit && (angle-between > 0)) || (!bit && (angle-between < 0)). }