# Models a human player or a statically controlled bot # Player.tz (c) 2010 Jacob Schrum. # See Simulation.tz for more copyright information @include "Agent.tz". # Strategies @define ALWAYS_SWING 1. #Mobile : Temp { # + to init: # self set-shape to (new Sphere init-with radius 1). # # + to iterate: # temp (string). # # temp = (self get-location). # self set-label to "$temp". #} Agent : Player { + variables: sword (object). spinning (int). iterations (int). smart-swing (int). ball (int). sword-distance (double). previous-target (vector). # Overrides method in Agent + to get-facing: if ball: return (0,0,0). else return facing. + to init: self clear-bullet. self disarm. locked = 0. spinning = 0. iterations = 0. smart-swing = ((controller get-commandline) bit-param named "smart-swing"). sword-distance = ((controller get-commandline) num-param named "sword-distance"). self set-energy to ((controller get-commandline) num-param named "player-start-energy"). facing = ((controller get-math) get-random-unit-vector). self set-appearance. # used by assist fitness self set-neighborhood-size to ((controller get-commandline) num-param named "very-close-player"). + to set-appearance: ball = (controller get-current-game-mode) == MODE_BALL. if ball : { self set-shape to ((controller get-graphics) get-ball-shape). } else { self set-shape to ((controller get-graphics) get-player-shape). self handle-collisions with-type "Monster" with-method "bump-monster". } self set-color to (controller get-bot-color). + to compare x x (double) y y (double): return (x - y). + to encircle monster m1 (object) and m2 (object): a1 (double). a2 (double). a1 = ((controller get-math) signed-angle-difference between facing and ((m1 get-location) - (self get-location))). a2 = ((controller get-math) signed-angle-difference between facing and ((m2 get-location) - (self get-location))). return (self compare x a1 y a2). + to iterate: biggestDiff (double). left (int). right (int). diff (double). loc (vector). nearest (object). i (int). i2 (int). monsters (list). strategy (int). combo (int). angle-to (double). mode (int). if (iterations == 0) : { self free-sword. } #if 1 : return. strategy = (controller get-player-strategy). combo = strategy == STRATEGY_COMBO. mode = (controller get-current-game-mode). if combo : { if (iterations % STRATEGY_SWITCH_ITERATIONS) == 0 : { if spinning == 0 : { controller catch-key-up-up. spinning = 1. } else { controller catch-key-left-up. spinning = 0. } } } if !ball : { if (strategy == STRATEGY_DODGE) && (mode == MODE_PRED) : { monsters = (controller get-monsters). sort monsters with encircle. biggestDiff = 0. for i = 0, i < |monsters|, i++ : { i2 = ((i+1)%|monsters|). loc = ((monsters{i} get-location) + (monsters{i2} get-location)) / 2. if !(self in-front-of-me location loc) : { diff = | ((monsters{i} get-location) - (monsters{i2} get-location)) |. # Bias towards current heading if (|previous-target - loc| < 1) : { diff += 1. } if (diff > biggestDiff) : { biggestDiff = diff. left = i. right = i2. } } } if (biggestDiff > 0) : { loc = ((monsters{left} get-location) + (monsters{right} get-location)) / 2. angle-to = ((controller get-math) signed-angle-difference between (- facing) and loc). # if (temp-left) : (temp-left move to (monsters{left} get-location)). # if (temp-right) : (temp-right move to (monsters{right} get-location)). # if (temp-ball) : (temp-ball move to loc). self turn-until-zero-angle current angle-to. previous-target = loc. } else { controller catch-key-left-up. controller catch-key-right-up. } nearest = (controller get-nearest-monster from (self get-location)). # Then is in front of direction of motion if !(self in-front-of-me location (nearest get-location)) : { if (self on-my-side location (nearest get-location) right 1) : { controller catch-key-left-down. } else { controller catch-key-right-down. } } #for i = 0, i < |monsters|, i++ : { # if !(self in-cone-in-front-of-me location (monsters{i} get-location) angle (2*PI - (PI / 8))) : { # controller catch-key-left-down. # } #} (controller catch-key-down-down). #(controller catch-key-up-down). } else if ((controller get-commandline) bit-param named "predator-switches-direction") && (strategy == STRATEGY_DODGE) && (mode == MODE_PREY) : { nearest = (controller get-nearest-monster from (self get-location)). if nearest : { if (self in-cone-in-front-of-me location (nearest get-location) angle (PI/3)) : { angle-to = (controller get-angle-to-nearest-monster-in-front from (self get-location) facing facing). # Arbitrary value if (angle-to == 0) : angle-to = 1. # Turn towards what is in front self turn-until-zero-angle current angle-to avoid-walls 0. if ((controller get-commandline) bit-param named "player-shoots") : { (controller catch-key-down-down). } else { (controller catch-key-up-down). } } else { angle-to = ((controller get-math) signed-angle-difference between (- facing) and ((nearest get-location) - (self get-location))). if (angle-to == 0) : angle-to = 1. # Turn towards what is in front #print (nearest get-location), angle-to, facing. self turn-until-zero-angle current (angle-to) avoid-walls 0. (controller catch-key-down-down). } } } else if (strategy == STRATEGY_AVOID_CENTER) && (mode == MODE_PRED) : { angle-to = (controller get-angle-to-monster-center from (self get-location) facing facing). # Arbitrary value if (angle-to == 0) : angle-to = 1. self turn-until-zero-angle current angle-to. (controller catch-key-down-down). } else if (strategy == STRATEGY_SMART) || (strategy == STRATEGY_AVOID_CENTER) || (strategy == STRATEGY_DODGE) : { angle-to = (controller get-angle-to-nearest-monster-in-front from (self get-location) facing facing). # Arbitrary value if (angle-to == 0) : angle-to = 1. # Turn towards what is in front if (controller anyone-in-front-of-player) : { self turn-until-zero-angle current angle-to avoid-walls (mode == MODE_PRED). } else { (controller catch-key-left-down). } if (mode == MODE_PRED) || ((controller get-commandline) bit-param named "player-shoots") : { (controller catch-key-down-down). } else if ( (mode == MODE_RAM) || (mode == MODE_BACKRAM) ) && (self ram-is-closest) : { (controller catch-key-down-down). } else { (controller catch-key-up-down). } } else if (strategy == STRATEGY_SPIN) || (combo && spinning == 1) : { controller catch-key-left-down. } else if (strategy == STRATEGY_STRAIGHT) || (combo && spinning == 0) : { if (mode == MODE_PRED) : (controller catch-key-down-down). else controller catch-key-up-down. } else if strategy == STRATEGY_BACK : { controller catch-key-down-down. } if (strategy != STRATEGY_HUMAN) : { if smart-swing : { if (controller anyone-close-to-player) && (controller anyone-in-front-of-player) : { controller catch-key-z-down. } } else if ALWAYS_SWING : controller catch-key-z-down. } } iterations++. super iterate. # monster: Monster that the Player hit + to bump-monster this monster (object): mode (int). mode = (controller get-current-game-mode). # Assures monsters get hit when they are prey self set-label to "". if (mode == MODE_PREY || mode == MODE_RAM || mode == MODE_BACKRAM) : { if !(monster is-locked): { monster repell from self. monster receive-damage-from-player of SWORD_CUT_LOSS. } } + to attack: swordStart (vector). # Can only use weapon in fight mode if (controller get-current-game-mode) == MODE_FIGHT : { # Can't attack again when still swinging if !sword: { # Materialize Sword sword = new Sword. sword set-rotation around-axis facing by (PI / 2). swordStart = cross(facing, (0,1,0)). swordStart = ( swordStart / |swordStart| ) * 2.5. sword move to ((self get-location) + (facing * sword-distance) + swordStart). # Swing Sword sword set-rotational-velocity to (-swordStart). sword set-arc-velocity to (-(swordStart * 1.9) + (facing * 2.9)). sword schedule method-call "disappear" at-time ((controller get-time) + ATTACK_DURATION). } } + to turn-until-zero-angle current angle-to (double) avoid-walls bit = 1 (int): if (bit && (self back-to-wall)) : { self back-to-wall-turn. } else if (angle-to < 0) : { (controller catch-key-right-down). } else { (controller catch-key-left-down). } + to back-to-wall-turn: if ((self back-to-upper-wall) && (facing::x < 0.0)) || ((self back-to-lower-wall) && (facing::x > 0.0)) || ((self back-to-left-wall) && (facing::z < 0.0)) || ((self back-to-right-wall) && (facing::z > 0.0)) : { (controller catch-key-left-down). } else { (controller catch-key-right-down). } + to free-sword: if sword: free sword. + to swinging: if sword: return 1. else return 0. + to ram-is-closest: nearest (object). loc (vector). ram (object). nearest = (controller get-nearest-monster from (self get-location)). if nearest : { ram = (nearest get-ram). if ram : { loc = (self get-location). return ( |loc - (nearest get-location)| > |loc - (ram get-location)| ). } } return 0. + to death: self free-sword. controller increment-deaths. controller spawn-player. } Mobile : Sword { + variables: arcVelocity (vector). + to init: arcVelocity = (0,0,0). self handle-collisions with-type "Monster" with-method "slash". self set-shape to ((controller get-graphics) get-sword-shape). self set-color to ((controller get-graphics) get-sword-color). + to set-arc-velocity to spinVector (vector): arcVelocity = spinVector. + to iterate: self set-velocity to (((controller get-player) get-velocity) + arcVelocity). + to disappear: free self. # monster: Monster being slashed by sword + to slash a monster (object): if !(monster is-locked): { # No output mode when locked monster set-label to "". monster receive-damage-from-player of SWORD_CUT_LOSS. monster repell from self. } }